if_bwn.c revision 204081
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 204081 2010-02-19 03:36:02Z 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);
539
540static struct resource_spec bwn_res_spec_legacy[] = {
541	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
542	{ -1,			0,		0 }
543};
544
545static struct resource_spec bwn_res_spec_msi[] = {
546	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
547	{ -1,			0,		0 }
548};
549
550static const struct bwn_channelinfo bwn_chantable_bg = {
551	.channels = {
552		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
553		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
554		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
555		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
556		{ 2472, 13, 30 }, { 2484, 14, 30 } },
557	.nchannels = 14
558};
559
560static const struct bwn_channelinfo bwn_chantable_a = {
561	.channels = {
562		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
563		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
564		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
565		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
566		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
567		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
568		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
569		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
570		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
571		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
572		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
573		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
574		{ 6080, 216, 30 } },
575	.nchannels = 37
576};
577
578static const struct bwn_channelinfo bwn_chantable_n = {
579	.channels = {
580		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
581		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
582		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
583		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
584		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
585		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
586		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
587		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
588		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
589		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
590		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
591		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
592		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
593		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
594		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
595		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
596		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
597		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
598		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
599		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
600		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
601		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
602		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
603		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
604		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
605		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
606		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
607		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
608		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
609		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
610		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
611		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
612		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
613		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
614		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
615		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
616		{ 6130, 226, 30 }, { 6140, 228, 30 } },
617	.nchannels = 110
618};
619
620static const uint8_t bwn_b2063_chantable_data[33][12] = {
621	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
627	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
634	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
654};
655
656static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
657	{ 1, 2412, bwn_b2063_chantable_data[0] },
658	{ 2, 2417, bwn_b2063_chantable_data[0] },
659	{ 3, 2422, bwn_b2063_chantable_data[0] },
660	{ 4, 2427, bwn_b2063_chantable_data[1] },
661	{ 5, 2432, bwn_b2063_chantable_data[1] },
662	{ 6, 2437, bwn_b2063_chantable_data[1] },
663	{ 7, 2442, bwn_b2063_chantable_data[1] },
664	{ 8, 2447, bwn_b2063_chantable_data[1] },
665	{ 9, 2452, bwn_b2063_chantable_data[2] },
666	{ 10, 2457, bwn_b2063_chantable_data[2] },
667	{ 11, 2462, bwn_b2063_chantable_data[3] },
668	{ 12, 2467, bwn_b2063_chantable_data[3] },
669	{ 13, 2472, bwn_b2063_chantable_data[3] },
670	{ 14, 2484, bwn_b2063_chantable_data[4] },
671	{ 34, 5170, bwn_b2063_chantable_data[5] },
672	{ 36, 5180, bwn_b2063_chantable_data[6] },
673	{ 38, 5190, bwn_b2063_chantable_data[7] },
674	{ 40, 5200, bwn_b2063_chantable_data[8] },
675	{ 42, 5210, bwn_b2063_chantable_data[9] },
676	{ 44, 5220, bwn_b2063_chantable_data[10] },
677	{ 46, 5230, bwn_b2063_chantable_data[11] },
678	{ 48, 5240, bwn_b2063_chantable_data[12] },
679	{ 52, 5260, bwn_b2063_chantable_data[13] },
680	{ 56, 5280, bwn_b2063_chantable_data[14] },
681	{ 60, 5300, bwn_b2063_chantable_data[14] },
682	{ 64, 5320, bwn_b2063_chantable_data[15] },
683	{ 100, 5500, bwn_b2063_chantable_data[16] },
684	{ 104, 5520, bwn_b2063_chantable_data[17] },
685	{ 108, 5540, bwn_b2063_chantable_data[18] },
686	{ 112, 5560, bwn_b2063_chantable_data[19] },
687	{ 116, 5580, bwn_b2063_chantable_data[20] },
688	{ 120, 5600, bwn_b2063_chantable_data[21] },
689	{ 124, 5620, bwn_b2063_chantable_data[21] },
690	{ 128, 5640, bwn_b2063_chantable_data[22] },
691	{ 132, 5660, bwn_b2063_chantable_data[22] },
692	{ 136, 5680, bwn_b2063_chantable_data[22] },
693	{ 140, 5700, bwn_b2063_chantable_data[23] },
694	{ 149, 5745, bwn_b2063_chantable_data[23] },
695	{ 153, 5765, bwn_b2063_chantable_data[23] },
696	{ 157, 5785, bwn_b2063_chantable_data[23] },
697	{ 161, 5805, bwn_b2063_chantable_data[23] },
698	{ 165, 5825, bwn_b2063_chantable_data[23] },
699	{ 184, 4920, bwn_b2063_chantable_data[24] },
700	{ 188, 4940, bwn_b2063_chantable_data[25] },
701	{ 192, 4960, bwn_b2063_chantable_data[26] },
702	{ 196, 4980, bwn_b2063_chantable_data[27] },
703	{ 200, 5000, bwn_b2063_chantable_data[28] },
704	{ 204, 5020, bwn_b2063_chantable_data[29] },
705	{ 208, 5040, bwn_b2063_chantable_data[30] },
706	{ 212, 5060, bwn_b2063_chantable_data[31] },
707	{ 216, 5080, bwn_b2063_chantable_data[32] }
708};
709
710static const uint8_t bwn_b2062_chantable_data[22][12] = {
711	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
712	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
732	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
733};
734
735static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
736	{ 1, 2412, bwn_b2062_chantable_data[0] },
737	{ 2, 2417, bwn_b2062_chantable_data[0] },
738	{ 3, 2422, bwn_b2062_chantable_data[0] },
739	{ 4, 2427, bwn_b2062_chantable_data[0] },
740	{ 5, 2432, bwn_b2062_chantable_data[0] },
741	{ 6, 2437, bwn_b2062_chantable_data[0] },
742	{ 7, 2442, bwn_b2062_chantable_data[0] },
743	{ 8, 2447, bwn_b2062_chantable_data[0] },
744	{ 9, 2452, bwn_b2062_chantable_data[0] },
745	{ 10, 2457, bwn_b2062_chantable_data[0] },
746	{ 11, 2462, bwn_b2062_chantable_data[0] },
747	{ 12, 2467, bwn_b2062_chantable_data[0] },
748	{ 13, 2472, bwn_b2062_chantable_data[0] },
749	{ 14, 2484, bwn_b2062_chantable_data[0] },
750	{ 34, 5170, bwn_b2062_chantable_data[1] },
751	{ 38, 5190, bwn_b2062_chantable_data[2] },
752	{ 42, 5210, bwn_b2062_chantable_data[2] },
753	{ 46, 5230, bwn_b2062_chantable_data[3] },
754	{ 36, 5180, bwn_b2062_chantable_data[4] },
755	{ 40, 5200, bwn_b2062_chantable_data[5] },
756	{ 44, 5220, bwn_b2062_chantable_data[6] },
757	{ 48, 5240, bwn_b2062_chantable_data[3] },
758	{ 52, 5260, bwn_b2062_chantable_data[3] },
759	{ 56, 5280, bwn_b2062_chantable_data[3] },
760	{ 60, 5300, bwn_b2062_chantable_data[7] },
761	{ 64, 5320, bwn_b2062_chantable_data[8] },
762	{ 100, 5500, bwn_b2062_chantable_data[9] },
763	{ 104, 5520, bwn_b2062_chantable_data[10] },
764	{ 108, 5540, bwn_b2062_chantable_data[10] },
765	{ 112, 5560, bwn_b2062_chantable_data[10] },
766	{ 116, 5580, bwn_b2062_chantable_data[11] },
767	{ 120, 5600, bwn_b2062_chantable_data[12] },
768	{ 124, 5620, bwn_b2062_chantable_data[12] },
769	{ 128, 5640, bwn_b2062_chantable_data[12] },
770	{ 132, 5660, bwn_b2062_chantable_data[12] },
771	{ 136, 5680, bwn_b2062_chantable_data[12] },
772	{ 140, 5700, bwn_b2062_chantable_data[12] },
773	{ 149, 5745, bwn_b2062_chantable_data[12] },
774	{ 153, 5765, bwn_b2062_chantable_data[12] },
775	{ 157, 5785, bwn_b2062_chantable_data[12] },
776	{ 161, 5805, bwn_b2062_chantable_data[12] },
777	{ 165, 5825, bwn_b2062_chantable_data[12] },
778	{ 184, 4920, bwn_b2062_chantable_data[13] },
779	{ 188, 4940, bwn_b2062_chantable_data[14] },
780	{ 192, 4960, bwn_b2062_chantable_data[15] },
781	{ 196, 4980, bwn_b2062_chantable_data[16] },
782	{ 200, 5000, bwn_b2062_chantable_data[17] },
783	{ 204, 5020, bwn_b2062_chantable_data[18] },
784	{ 208, 5040, bwn_b2062_chantable_data[19] },
785	{ 212, 5060, bwn_b2062_chantable_data[20] },
786	{ 216, 5080, bwn_b2062_chantable_data[21] }
787};
788
789/* for LP PHY */
790static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
791	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
792	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
793	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
794	{ 13, -66, 13 }, { 14, -66, 13 },
795};
796
797/* for LP PHY */
798static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
799	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
800	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
801	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
802	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
803	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
804	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
805	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
806	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
807	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
808	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
809	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
810	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
811	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
812};
813
814static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
815
816static const uint8_t bwn_tab_sigsq_tbl[] = {
817	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
818	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
819	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
822	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
823};
824
825static const uint8_t bwn_tab_pllfrac_tbl[] = {
826	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
828};
829
830static const uint16_t bwn_tabl_iqlocal_tbl[] = {
831	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
832	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
835	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
836	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843};
844
845static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
846static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
847static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
848static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
849static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
850const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
851
852#define	VENDOR_LED_ACT(vendor)				\
853{							\
854	.vid = PCI_VENDOR_##vendor,			\
855	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
856}
857
858static const struct {
859	uint16_t	vid;
860	uint8_t		led_act[BWN_LED_MAX];
861} bwn_vendor_led_act[] = {
862	VENDOR_LED_ACT(COMPAQ),
863	VENDOR_LED_ACT(ASUSTEK)
864};
865
866static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
867	{ BWN_VENDOR_LED_ACT_DEFAULT };
868
869#undef VENDOR_LED_ACT
870
871static const struct {
872	int		on_dur;
873	int		off_dur;
874} bwn_led_duration[109] = {
875	[0]	= { 400, 100 },
876	[2]	= { 150, 75 },
877	[4]	= { 90, 45 },
878	[11]	= { 66, 34 },
879	[12]	= { 53, 26 },
880	[18]	= { 42, 21 },
881	[22]	= { 35, 17 },
882	[24]	= { 32, 16 },
883	[36]	= { 21, 10 },
884	[48]	= { 16, 8 },
885	[72]	= { 11, 5 },
886	[96]	= { 9, 4 },
887	[108]	= { 7, 3 }
888};
889
890static const uint16_t bwn_wme_shm_offsets[] = {
891	[0] = BWN_WME_BESTEFFORT,
892	[1] = BWN_WME_BACKGROUND,
893	[2] = BWN_WME_VOICE,
894	[3] = BWN_WME_VIDEO,
895};
896
897static const struct siba_devid bwn_devs[] = {
898	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
899	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
900	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
901	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
902	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
903	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
904	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
905	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
906	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
907};
908
909static int
910bwn_probe(device_t dev)
911{
912	struct siba_dev_softc *sd = device_get_ivars(dev);
913	int i;
914
915	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
916		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
917		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
918		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
919			return (BUS_PROBE_DEFAULT);
920	}
921
922	return (ENXIO);
923}
924
925static int
926bwn_attach(device_t dev)
927{
928	struct bwn_mac *mac;
929	struct bwn_softc *sc = device_get_softc(dev);
930	struct siba_dev_softc *sd = device_get_ivars(dev);
931	struct siba_softc *siba = sd->sd_bus;
932	int error, i, msic, reg;
933
934	sc->sc_dev = dev;
935	sc->sc_sd = sd;
936#ifdef BWN_DEBUG
937	sc->sc_debug = bwn_debug;
938#endif
939
940	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
941		error = bwn_attach_pre(sc);
942		if (error != 0)
943			return (error);
944		bwn_sprom_bugfixes(sd->sd_bus);
945		sc->sc_flags |= BWN_FLAG_ATTACHED;
946	}
947
948	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
949		if (siba->siba_pci_did != 0x4313 &&
950		    siba->siba_pci_did != 0x431a &&
951		    siba->siba_pci_did != 0x4321) {
952			device_printf(sc->sc_dev,
953			    "skip 802.11 cores\n");
954			return (ENODEV);
955		}
956	}
957
958	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
959	    M_NOWAIT | M_ZERO);
960	if (mac == NULL)
961		return (ENOMEM);
962	mac->mac_sc = sc;
963	mac->mac_sd = sd;
964	mac->mac_status = BWN_MAC_STATUS_UNINIT;
965	if (bwn_bfp != 0)
966		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
967
968	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
969	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
970	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
971
972	error = bwn_attach_core(mac);
973	if (error)
974		goto fail0;
975	bwn_led_attach(mac);
976
977	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
978	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
979	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
980	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
981	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
982	    mac->mac_phy.rf_rev);
983	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
984		device_printf(sc->sc_dev, "DMA (%d bits)\n",
985		    mac->mac_method.dma.dmatype);
986	else
987		device_printf(sc->sc_dev, "PIO\n");
988
989	/*
990	 * setup PCI resources and interrupt.
991	 */
992	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
993		msic = pci_msi_count(dev);
994		if (bootverbose)
995			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
996	} else
997		msic = 0;
998
999	mac->mac_intr_spec = bwn_res_spec_legacy;
1000	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1001		if (pci_alloc_msi(dev, &msic) == 0) {
1002			device_printf(sc->sc_dev,
1003			    "Using %d MSI messages\n", msic);
1004			mac->mac_intr_spec = bwn_res_spec_msi;
1005			mac->mac_msi = 1;
1006		}
1007	}
1008
1009	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1010	    mac->mac_res_irq);
1011	if (error) {
1012		device_printf(sc->sc_dev,
1013		    "couldn't allocate IRQ resources (%d)\n", error);
1014		goto fail1;
1015	}
1016
1017	if (mac->mac_msi == 0)
1018		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1019		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1020		    &mac->mac_intrhand[0]);
1021	else {
1022		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1023			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1024			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1025			    &mac->mac_intrhand[i]);
1026			if (error != 0) {
1027				device_printf(sc->sc_dev,
1028				    "couldn't setup interrupt (%d)\n", error);
1029				break;
1030			}
1031		}
1032	}
1033
1034	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1035
1036	/*
1037	 * calls attach-post routine
1038	 */
1039	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1040		bwn_attach_post(sc);
1041
1042	return (0);
1043fail1:
1044	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1045		pci_release_msi(dev);
1046fail0:
1047	free(mac, M_DEVBUF);
1048	return (error);
1049}
1050
1051static int
1052bwn_is_valid_ether_addr(uint8_t *addr)
1053{
1054	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1055
1056	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1057		return (FALSE);
1058
1059	return (TRUE);
1060}
1061
1062static int
1063bwn_attach_post(struct bwn_softc *sc)
1064{
1065	struct ieee80211com *ic;
1066	struct ifnet *ifp = sc->sc_ifp;
1067	struct siba_dev_softc *sd = sc->sc_sd;
1068	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1069#ifdef BWN_DEBUG
1070	device_t dev = sc->sc_dev;
1071#endif
1072
1073	ic = ifp->if_l2com;
1074	ic->ic_ifp = ifp;
1075	/* XXX not right but it's not used anywhere important */
1076	ic->ic_phytype = IEEE80211_T_OFDM;
1077	ic->ic_opmode = IEEE80211_M_STA;
1078	ic->ic_caps =
1079		  IEEE80211_C_STA		/* station mode supported */
1080		| IEEE80211_C_MONITOR		/* monitor mode */
1081		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1082		| IEEE80211_C_SHSLOT		/* short slot time supported */
1083		| IEEE80211_C_WME		/* WME/WMM supported */
1084		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1085		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1086		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1087		;
1088
1089	/* call MI attach routine. */
1090	ieee80211_ifattach(ic,
1091	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1092	    sprom->mac_80211bg);
1093
1094	ic->ic_headroom = sizeof(struct bwn_txhdr);
1095
1096	/* override default methods */
1097	ic->ic_raw_xmit = bwn_raw_xmit;
1098	ic->ic_newassoc = bwn_newassoc;
1099	ic->ic_updateslot = bwn_updateslot;
1100	ic->ic_update_promisc = bwn_update_promisc;
1101	ic->ic_wme.wme_update = bwn_wme_update;
1102
1103	ic->ic_node_alloc = bwn_node_alloc;
1104	sc->sc_node_cleanup = ic->ic_node_cleanup;
1105	ic->ic_node_cleanup = bwn_node_cleanup;
1106
1107	ic->ic_scan_start = bwn_scan_start;
1108	ic->ic_scan_end = bwn_scan_end;
1109	ic->ic_set_channel = bwn_set_channel;
1110
1111	ic->ic_vap_create = bwn_vap_create;
1112	ic->ic_vap_delete = bwn_vap_delete;
1113
1114	ieee80211_radiotap_attach(ic,
1115	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1116	    BWN_TX_RADIOTAP_PRESENT,
1117	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1118	    BWN_RX_RADIOTAP_PRESENT);
1119
1120#ifdef BWN_DEBUG
1121	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1122	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1123	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
1124#endif
1125
1126	if (bootverbose)
1127		ieee80211_announce(ic);
1128	return (0);
1129}
1130
1131static void
1132bwn_phy_detach(struct bwn_mac *mac)
1133{
1134
1135	if (mac->mac_phy.detach != NULL)
1136		mac->mac_phy.detach(mac);
1137}
1138
1139static int
1140bwn_detach(device_t dev)
1141{
1142	struct bwn_softc *sc = device_get_softc(dev);
1143	struct bwn_mac *mac = sc->sc_curmac;
1144	struct ifnet *ifp = sc->sc_ifp;
1145	struct ieee80211com *ic = ifp->if_l2com;
1146	int i;
1147
1148	sc->sc_flags |= BWN_FLAG_INVALID;
1149
1150	if (device_is_attached(sc->sc_dev)) {
1151		bwn_stop(sc, 1);
1152		bwn_dma_free(mac);
1153		callout_drain(&sc->sc_led_blink_ch);
1154		callout_drain(&sc->sc_rfswitch_ch);
1155		callout_drain(&sc->sc_task_ch);
1156		callout_drain(&sc->sc_watchdog_ch);
1157		bwn_phy_detach(mac);
1158		if (ifp != NULL) {
1159			ieee80211_draintask(ic, &mac->mac_hwreset);
1160			ieee80211_draintask(ic, &mac->mac_txpower);
1161			ieee80211_ifdetach(ic);
1162			if_free(ifp);
1163		}
1164	}
1165	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1166	taskqueue_free(sc->sc_tq);
1167
1168	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1169		if (mac->mac_intrhand[i] != NULL) {
1170			bus_teardown_intr(dev, mac->mac_res_irq[i],
1171			    mac->mac_intrhand[i]);
1172			mac->mac_intrhand[i] = NULL;
1173		}
1174	}
1175	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1176	if (mac->mac_msi != 0)
1177		pci_release_msi(dev);
1178
1179	BWN_LOCK_DESTROY(sc);
1180	return (0);
1181}
1182
1183static int
1184bwn_attach_pre(struct bwn_softc *sc)
1185{
1186	struct ifnet *ifp;
1187	int error = 0;
1188
1189	BWN_LOCK_INIT(sc);
1190	TAILQ_INIT(&sc->sc_maclist);
1191	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1192	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1193	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1194
1195	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1196		taskqueue_thread_enqueue, &sc->sc_tq);
1197	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1198		"%s taskq", device_get_nameunit(sc->sc_dev));
1199
1200	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1201	if (ifp == NULL) {
1202		device_printf(sc->sc_dev, "can not if_alloc()\n");
1203		error = ENOSPC;
1204		goto fail;
1205	}
1206
1207	/* set these up early for if_printf use */
1208	if_initname(ifp, device_get_name(sc->sc_dev),
1209	    device_get_unit(sc->sc_dev));
1210
1211	ifp->if_softc = sc;
1212	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1213	ifp->if_init = bwn_init;
1214	ifp->if_ioctl = bwn_ioctl;
1215	ifp->if_start = bwn_start;
1216	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1217	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1218	IFQ_SET_READY(&ifp->if_snd);
1219
1220	return (0);
1221
1222fail:	BWN_LOCK_DESTROY(sc);
1223	return (error);
1224}
1225
1226static void
1227bwn_sprom_bugfixes(struct siba_softc *siba)
1228{
1229#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1230	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1231	 (siba->siba_pci_did == _device) &&				\
1232	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1233	 (siba->siba_pci_subdid == _subdevice))
1234
1235	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1236	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1237		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1238	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1239	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1240		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1241	if (siba->siba_type == SIBA_TYPE_PCI) {
1242		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1243		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1244		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1245		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1246		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1247		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1248		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1249			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1250	}
1251#undef	BWN_ISDEV
1252}
1253
1254static int
1255bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1256{
1257#define	IS_RUNNING(ifp) \
1258	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1259	struct bwn_softc *sc = ifp->if_softc;
1260	struct ieee80211com *ic = ifp->if_l2com;
1261	struct ifreq *ifr = (struct ifreq *)data;
1262	int error = 0, startall;
1263
1264	switch (cmd) {
1265	case SIOCSIFFLAGS:
1266		startall = 0;
1267		if (IS_RUNNING(ifp)) {
1268			bwn_update_promisc(ifp);
1269		} else if (ifp->if_flags & IFF_UP) {
1270			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1271				bwn_init(sc);
1272				startall = 1;
1273			}
1274		} else
1275			bwn_stop(sc, 1);
1276		if (startall)
1277			ieee80211_start_all(ic);
1278		break;
1279	case SIOCGIFMEDIA:
1280		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1281		break;
1282	case SIOCGIFADDR:
1283		error = ether_ioctl(ifp, cmd, data);
1284		break;
1285	default:
1286		error = EINVAL;
1287		break;
1288	}
1289	return (error);
1290}
1291
1292static void
1293bwn_start(struct ifnet *ifp)
1294{
1295	struct bwn_softc *sc = ifp->if_softc;
1296
1297	BWN_LOCK(sc);
1298	bwn_start_locked(ifp);
1299	BWN_UNLOCK(sc);
1300}
1301
1302static void
1303bwn_start_locked(struct ifnet *ifp)
1304{
1305	struct bwn_softc *sc = ifp->if_softc;
1306	struct bwn_mac *mac = sc->sc_curmac;
1307	struct ieee80211_frame *wh;
1308	struct ieee80211_node *ni;
1309	struct ieee80211_key *k;
1310	struct mbuf *m;
1311
1312	BWN_ASSERT_LOCKED(sc);
1313
1314	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1315	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1316		return;
1317
1318	for (;;) {
1319		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1320		if (m == NULL)
1321			break;
1322
1323		if (bwn_tx_isfull(sc, m))
1324			break;
1325		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1326		if (ni == NULL) {
1327			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1328			m_freem(m);
1329			ifp->if_oerrors++;
1330			continue;
1331		}
1332		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1333		wh = mtod(m, struct ieee80211_frame *);
1334		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1335			k = ieee80211_crypto_encap(ni, m);
1336			if (k == NULL) {
1337				ieee80211_free_node(ni);
1338				m_freem(m);
1339				ifp->if_oerrors++;
1340				continue;
1341			}
1342		}
1343		wh = NULL;	/* Catch any invalid use */
1344
1345		if (bwn_tx_start(sc, ni, m) != 0) {
1346			if (ni != NULL)
1347				ieee80211_free_node(ni);
1348			ifp->if_oerrors++;
1349			continue;
1350		}
1351
1352		sc->sc_watchdog_timer = 5;
1353	}
1354}
1355
1356static int
1357bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1358{
1359	struct bwn_dma_ring *dr;
1360	struct bwn_mac *mac = sc->sc_curmac;
1361	struct bwn_pio_txqueue *tq;
1362	struct ifnet *ifp = sc->sc_ifp;
1363	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1364
1365	BWN_ASSERT_LOCKED(sc);
1366
1367	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1368		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1369		if (dr->dr_stop == 1 ||
1370		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1371			dr->dr_stop = 1;
1372			goto full;
1373		}
1374	} else {
1375		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1376		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1377		    pktlen > (tq->tq_size - tq->tq_used)) {
1378			tq->tq_stop = 1;
1379			goto full;
1380		}
1381	}
1382	return (0);
1383full:
1384	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1385	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1386	return (1);
1387}
1388
1389static int
1390bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1391{
1392	struct bwn_mac *mac = sc->sc_curmac;
1393	int error;
1394
1395	BWN_ASSERT_LOCKED(sc);
1396
1397	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1398		m_freem(m);
1399		return (ENXIO);
1400	}
1401
1402	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1403	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1404	if (error) {
1405		m_freem(m);
1406		return (error);
1407	}
1408	return (0);
1409}
1410
1411static int
1412bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1413{
1414	struct bwn_pio_txpkt *tp;
1415	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1416	struct bwn_softc *sc = mac->mac_sc;
1417	struct bwn_txhdr txhdr;
1418	struct mbuf *m_new;
1419	uint32_t ctl32;
1420	int error;
1421	uint16_t ctl16;
1422
1423	BWN_ASSERT_LOCKED(sc);
1424
1425	/* XXX TODO send packets after DTIM */
1426
1427	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1428	tp = TAILQ_FIRST(&tq->tq_pktlist);
1429	tp->tp_ni = ni;
1430	tp->tp_m = m;
1431
1432	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1433	if (error) {
1434		device_printf(sc->sc_dev, "tx fail\n");
1435		return (error);
1436	}
1437
1438	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1439	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1440	tq->tq_free--;
1441
1442	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1443		/*
1444		 * XXX please removes m_defrag(9)
1445		 */
1446		m_new = m_defrag(m, M_DONTWAIT);
1447		if (m_new == NULL) {
1448			device_printf(sc->sc_dev,
1449			    "%s: can't defrag TX buffer\n",
1450			    __func__);
1451			return (ENOBUFS);
1452		}
1453		if (m_new->m_next != NULL)
1454			device_printf(sc->sc_dev,
1455			    "TODO: fragmented packets for PIO\n");
1456		tp->tp_m = m_new;
1457
1458		/* send HEADER */
1459		ctl32 = bwn_pio_write_multi_4(mac, tq,
1460		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1461			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1462		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1463		/* send BODY */
1464		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1465		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1466		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1467		    ctl32 | BWN_PIO8_TXCTL_EOF);
1468	} else {
1469		ctl16 = bwn_pio_write_multi_2(mac, tq,
1470		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1471			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1472		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1473		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1474		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1475		    ctl16 | BWN_PIO_TXCTL_EOF);
1476	}
1477
1478	return (0);
1479}
1480
1481static struct bwn_pio_txqueue *
1482bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1483{
1484
1485	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1486		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1487
1488	switch (prio) {
1489	case 0:
1490		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1491	case 1:
1492		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1493	case 2:
1494		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1495	case 3:
1496		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1497	}
1498	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1499}
1500
1501static int
1502bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1503{
1504#define	BWN_GET_TXHDRCACHE(slot)					\
1505	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1506	struct bwn_dma *dma = &mac->mac_method.dma;
1507	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1508	struct bwn_dmadesc_generic *desc;
1509	struct bwn_dmadesc_meta *mt;
1510	struct bwn_softc *sc = mac->mac_sc;
1511	struct ifnet *ifp = sc->sc_ifp;
1512	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1513	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1514
1515	BWN_ASSERT_LOCKED(sc);
1516	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1517
1518	/* XXX send after DTIM */
1519
1520	slot = bwn_dma_getslot(dr);
1521	dr->getdesc(dr, slot, &desc, &mt);
1522	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1523	    ("%s:%d: fail", __func__, __LINE__));
1524
1525	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1526	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1527	    BWN_DMA_COOKIE(dr, slot));
1528	if (error)
1529		goto fail;
1530	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1531	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1532	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1533	if (error) {
1534		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1535		    __func__, error);
1536		goto fail;
1537	}
1538	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1539	    BUS_DMASYNC_PREWRITE);
1540	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1541	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1542	    BUS_DMASYNC_PREWRITE);
1543
1544	slot = bwn_dma_getslot(dr);
1545	dr->getdesc(dr, slot, &desc, &mt);
1546	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1547	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1548	mt->mt_m = m;
1549	mt->mt_ni = ni;
1550
1551	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1552	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1553	if (error && error != EFBIG) {
1554		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1555		    __func__, error);
1556		goto fail;
1557	}
1558	if (error) {    /* error == EFBIG */
1559		struct mbuf *m_new;
1560
1561		m_new = m_defrag(m, M_DONTWAIT);
1562		if (m_new == NULL) {
1563			if_printf(ifp, "%s: can't defrag TX buffer\n",
1564			    __func__);
1565			error = ENOBUFS;
1566			goto fail;
1567		} else {
1568			m = m_new;
1569		}
1570
1571		mt->mt_m = m;
1572		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1573		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1574		if (error) {
1575			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1576			    __func__, error);
1577			goto fail;
1578		}
1579	}
1580	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1581	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1582	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1583	    BUS_DMASYNC_PREWRITE);
1584
1585	/* XXX send after DTIM */
1586
1587	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1588	return (0);
1589fail:
1590	dr->dr_curslot = backup[0];
1591	dr->dr_usedslot = backup[1];
1592	return (error);
1593#undef BWN_GET_TXHDRCACHE
1594}
1595
1596static void
1597bwn_watchdog(void *arg)
1598{
1599	struct bwn_softc *sc = arg;
1600	struct ifnet *ifp = sc->sc_ifp;
1601
1602	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1603		if_printf(ifp, "device timeout\n");
1604		ifp->if_oerrors++;
1605	}
1606	callout_schedule(&sc->sc_watchdog_ch, hz);
1607}
1608
1609static int
1610bwn_attach_core(struct bwn_mac *mac)
1611{
1612	struct bwn_softc *sc = mac->mac_sc;
1613	struct siba_dev_softc *sd = mac->mac_sd;
1614	struct siba_softc *siba = sd->sd_bus;
1615	int error, have_bg = 0, have_a = 0;
1616	uint32_t high;
1617
1618	KASSERT(sd->sd_id.sd_rev >= 5,
1619	    ("unsupported revision %d", sd->sd_id.sd_rev));
1620
1621	siba_powerup(siba, 0);
1622
1623	high = siba_read_4(sd, SIBA_TGSHIGH);
1624	bwn_reset_core(mac,
1625	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1626	error = bwn_phy_getinfo(mac, high);
1627	if (error)
1628		goto fail;
1629
1630	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1631	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1632	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1633	    siba->siba_pci_did != 0x4324) {
1634		have_a = have_bg = 0;
1635		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1636			have_a = 1;
1637		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1638		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1639		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1640			have_bg = 1;
1641		else
1642			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1643			    mac->mac_phy.type));
1644	}
1645	/* XXX turns off PHY A because it's not supported */
1646	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1647	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1648		have_a = 0;
1649		have_bg = 1;
1650	}
1651
1652	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1653		mac->mac_phy.attach = bwn_phy_g_attach;
1654		mac->mac_phy.detach = bwn_phy_g_detach;
1655		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1656		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1657		mac->mac_phy.init = bwn_phy_g_init;
1658		mac->mac_phy.exit = bwn_phy_g_exit;
1659		mac->mac_phy.phy_read = bwn_phy_g_read;
1660		mac->mac_phy.phy_write = bwn_phy_g_write;
1661		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1662		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1663		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1664		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1665		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1666		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1667		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1668		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1669		mac->mac_phy.set_im = bwn_phy_g_im;
1670		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1671		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1672		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1673		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1674	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1675		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1676		mac->mac_phy.init = bwn_phy_lp_init;
1677		mac->mac_phy.phy_read = bwn_phy_lp_read;
1678		mac->mac_phy.phy_write = bwn_phy_lp_write;
1679		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1680		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1681		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1682		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1683		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1684		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1685		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1686		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1687		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1688	} else {
1689		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1690		    mac->mac_phy.type);
1691		error = ENXIO;
1692		goto fail;
1693	}
1694
1695	mac->mac_phy.gmode = have_bg;
1696	if (mac->mac_phy.attach != NULL) {
1697		error = mac->mac_phy.attach(mac);
1698		if (error) {
1699			device_printf(sc->sc_dev, "failed\n");
1700			goto fail;
1701		}
1702	}
1703
1704	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1705
1706	error = bwn_chiptest(mac);
1707	if (error)
1708		goto fail;
1709	error = bwn_setup_channels(mac, have_bg, have_a);
1710	if (error) {
1711		device_printf(sc->sc_dev, "failed to setup channels\n");
1712		goto fail;
1713	}
1714
1715	if (sc->sc_curmac == NULL)
1716		sc->sc_curmac = mac;
1717
1718	error = bwn_dma_attach(mac);
1719	if (error != 0) {
1720		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1721		goto fail;
1722	}
1723
1724	mac->mac_phy.switch_analog(mac, 0);
1725
1726	siba_dev_down(sd, 0);
1727fail:
1728	siba_powerdown(siba);
1729	return (error);
1730}
1731
1732static void
1733bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1734{
1735	struct siba_dev_softc *sd = mac->mac_sd;
1736	uint32_t low, ctl;
1737
1738	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1739
1740	siba_dev_up(sd, flags);
1741	DELAY(2000);
1742
1743	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1744	    ~BWN_TGSLOW_PHYRESET;
1745	siba_write_4(sd, SIBA_TGSLOW, low);
1746	siba_read_4(sd, SIBA_TGSLOW);
1747	DELAY(1000);
1748	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1749	siba_read_4(sd, SIBA_TGSLOW);
1750	DELAY(1000);
1751
1752	if (mac->mac_phy.switch_analog != NULL)
1753		mac->mac_phy.switch_analog(mac, 1);
1754
1755	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1756	if (flags & BWN_TGSLOW_SUPPORT_G)
1757		ctl |= BWN_MACCTL_GMODE;
1758	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1759}
1760
1761static int
1762bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1763{
1764	struct bwn_phy *phy = &mac->mac_phy;
1765	struct bwn_softc *sc = mac->mac_sc;
1766	struct siba_dev_softc *sd = mac->mac_sd;
1767	struct siba_softc *siba = sd->sd_bus;
1768	uint32_t tmp;
1769
1770	/* PHY */
1771	tmp = BWN_READ_2(mac, BWN_PHYVER);
1772	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1773	phy->rf_on = 1;
1774	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1775	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1776	phy->rev = (tmp & BWN_PHYVER_VERSION);
1777	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1778	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1779		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1780	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1781	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1782	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1783		goto unsupphy;
1784
1785	/* RADIO */
1786	if (siba->siba_chipid == 0x4317) {
1787		if (siba->siba_chiprev == 0)
1788			tmp = 0x3205017f;
1789		else if (siba->siba_chiprev == 1)
1790			tmp = 0x4205017f;
1791		else
1792			tmp = 0x5205017f;
1793	} else {
1794		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1795		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1796		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1797		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1798	}
1799	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1800	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1801	phy->rf_manuf = (tmp & 0x00000fff);
1802	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1803		goto unsupradio;
1804	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1805	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1806	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1807	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1808	    (phy->type == BWN_PHYTYPE_N &&
1809	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1810	    (phy->type == BWN_PHYTYPE_LP &&
1811	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1812		goto unsupradio;
1813
1814	return (0);
1815unsupphy:
1816	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1817	    "analog %#x)\n",
1818	    phy->type, phy->rev, phy->analog);
1819	return (ENXIO);
1820unsupradio:
1821	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1822	    "rev %#x)\n",
1823	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1824	return (ENXIO);
1825}
1826
1827static int
1828bwn_chiptest(struct bwn_mac *mac)
1829{
1830#define	TESTVAL0	0x55aaaa55
1831#define	TESTVAL1	0xaa5555aa
1832	struct bwn_softc *sc = mac->mac_sc;
1833	struct siba_dev_softc *sd = mac->mac_sd;
1834	uint32_t v, backup;
1835
1836	BWN_LOCK(sc);
1837
1838	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1839
1840	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1841	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1842		goto error;
1843	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1844	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1845		goto error;
1846
1847	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1848
1849	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1850		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1851		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1852		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1853			goto error;
1854		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1855			goto error;
1856	}
1857	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1858
1859	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1860	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1861		goto error;
1862
1863	BWN_UNLOCK(sc);
1864	return (0);
1865error:
1866	BWN_UNLOCK(sc);
1867	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1868	return (ENODEV);
1869}
1870
1871#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1872#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1873
1874static int
1875bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1876{
1877	struct bwn_softc *sc = mac->mac_sc;
1878	struct ifnet *ifp = sc->sc_ifp;
1879	struct ieee80211com *ic = ifp->if_l2com;
1880
1881	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1882	ic->ic_nchans = 0;
1883
1884	if (have_bg)
1885		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1887	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1888		if (have_a)
1889			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1890			    &ic->ic_nchans, &bwn_chantable_n,
1891			    IEEE80211_CHAN_HTA);
1892	} else {
1893		if (have_a)
1894			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1895			    &ic->ic_nchans, &bwn_chantable_a,
1896			    IEEE80211_CHAN_A);
1897	}
1898
1899	mac->mac_phy.supports_2ghz = have_bg;
1900	mac->mac_phy.supports_5ghz = have_a;
1901
1902	return (ic->ic_nchans == 0 ? ENXIO : 0);
1903}
1904
1905static uint32_t
1906bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1907{
1908	struct bwn_softc *sc = mac->mac_sc;
1909	uint32_t ret;
1910
1911	BWN_ASSERT_LOCKED(sc);
1912
1913	if (way == BWN_SHARED) {
1914		KASSERT((offset & 0x0001) == 0,
1915		    ("%s:%d warn", __func__, __LINE__));
1916		if (offset & 0x0003) {
1917			bwn_shm_ctlword(mac, way, offset >> 2);
1918			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1919			ret <<= 16;
1920			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1921			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1922			goto out;
1923		}
1924		offset >>= 2;
1925	}
1926	bwn_shm_ctlword(mac, way, offset);
1927	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1928out:
1929	return (ret);
1930}
1931
1932static uint16_t
1933bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1934{
1935	struct bwn_softc *sc = mac->mac_sc;
1936	uint16_t ret;
1937
1938	BWN_ASSERT_LOCKED(sc);
1939
1940	if (way == BWN_SHARED) {
1941		KASSERT((offset & 0x0001) == 0,
1942		    ("%s:%d warn", __func__, __LINE__));
1943		if (offset & 0x0003) {
1944			bwn_shm_ctlword(mac, way, offset >> 2);
1945			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1946			goto out;
1947		}
1948		offset >>= 2;
1949	}
1950	bwn_shm_ctlword(mac, way, offset);
1951	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1952out:
1953
1954	return (ret);
1955}
1956
1957static void
1958bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1959    uint16_t offset)
1960{
1961	uint32_t control;
1962
1963	control = way;
1964	control <<= 16;
1965	control |= offset;
1966	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1967}
1968
1969static void
1970bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1971    uint32_t value)
1972{
1973	struct bwn_softc *sc = mac->mac_sc;
1974
1975	BWN_ASSERT_LOCKED(sc);
1976
1977	if (way == BWN_SHARED) {
1978		KASSERT((offset & 0x0001) == 0,
1979		    ("%s:%d warn", __func__, __LINE__));
1980		if (offset & 0x0003) {
1981			bwn_shm_ctlword(mac, way, offset >> 2);
1982			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1983				    (value >> 16) & 0xffff);
1984			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1985			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1986			return;
1987		}
1988		offset >>= 2;
1989	}
1990	bwn_shm_ctlword(mac, way, offset);
1991	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1992}
1993
1994static void
1995bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1996    uint16_t value)
1997{
1998	struct bwn_softc *sc = mac->mac_sc;
1999
2000	BWN_ASSERT_LOCKED(sc);
2001
2002	if (way == BWN_SHARED) {
2003		KASSERT((offset & 0x0001) == 0,
2004		    ("%s:%d warn", __func__, __LINE__));
2005		if (offset & 0x0003) {
2006			bwn_shm_ctlword(mac, way, offset >> 2);
2007			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
2008			return;
2009		}
2010		offset >>= 2;
2011	}
2012	bwn_shm_ctlword(mac, way, offset);
2013	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2014}
2015
2016static void
2017bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2018    int txpow)
2019{
2020
2021	c->ic_freq = freq;
2022	c->ic_flags = flags;
2023	c->ic_ieee = ieee;
2024	c->ic_minpower = 0;
2025	c->ic_maxpower = 2 * txpow;
2026	c->ic_maxregpower = txpow;
2027}
2028
2029static void
2030bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2031    const struct bwn_channelinfo *ci, int flags)
2032{
2033	struct ieee80211_channel *c;
2034	int i;
2035
2036	c = &chans[*nchans];
2037
2038	for (i = 0; i < ci->nchannels; i++) {
2039		const struct bwn_channel *hc;
2040
2041		hc = &ci->channels[i];
2042		if (*nchans >= maxchans)
2043			break;
2044		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2045		c++, (*nchans)++;
2046		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2047			/* g channel have a separate b-only entry */
2048			if (*nchans >= maxchans)
2049				break;
2050			c[0] = c[-1];
2051			c[-1].ic_flags = IEEE80211_CHAN_B;
2052			c++, (*nchans)++;
2053		}
2054		if (flags == IEEE80211_CHAN_HTG) {
2055			/* HT g channel have a separate g-only entry */
2056			if (*nchans >= maxchans)
2057				break;
2058			c[-1].ic_flags = IEEE80211_CHAN_G;
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		if (flags == IEEE80211_CHAN_HTA) {
2065			/* HT a channel have a separate a-only entry */
2066			if (*nchans >= maxchans)
2067				break;
2068			c[-1].ic_flags = IEEE80211_CHAN_A;
2069			c[0] = c[-1];
2070			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2071			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2072			c++, (*nchans)++;
2073		}
2074	}
2075}
2076
2077static int
2078bwn_phy_g_attach(struct bwn_mac *mac)
2079{
2080	struct bwn_softc *sc = mac->mac_sc;
2081	struct bwn_phy *phy = &mac->mac_phy;
2082	struct bwn_phy_g *pg = &phy->phy_g;
2083	struct siba_dev_softc *sd = mac->mac_sd;
2084	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2085	unsigned int i;
2086	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2087	    pab2 = (int16_t)(sprom->pa0b2);
2088	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2089	int8_t bg = (int8_t)sprom->tssi_bg;
2090
2091	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2092		device_printf(sc->sc_dev, "not supported anymore\n");
2093
2094	pg->pg_flags = 0;
2095	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2096	    pab2 == -1) {
2097		pg->pg_idletssi = 52;
2098		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2099		return (0);
2100	}
2101
2102	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2103	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2104	if (pg->pg_tssi2dbm == NULL) {
2105		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2106		return (ENOMEM);
2107	}
2108	for (i = 0; i < 64; i++) {
2109		int32_t m1, m2, f, q, delta;
2110		int8_t j = 0;
2111
2112		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2113		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2114		f = 256;
2115
2116		do {
2117			if (j > 15) {
2118				device_printf(sc->sc_dev,
2119				    "failed to generate tssi2dBm\n");
2120				free(pg->pg_tssi2dbm, M_DEVBUF);
2121				return (ENOMEM);
2122			}
2123			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2124			    f, 2048);
2125			delta = abs(q - f);
2126			f = q;
2127			j++;
2128		} while (delta >= 2);
2129
2130		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2131		    128);
2132	}
2133
2134	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2135	return (0);
2136}
2137
2138static void
2139bwn_phy_g_detach(struct bwn_mac *mac)
2140{
2141	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2142
2143	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2144		free(pg->pg_tssi2dbm, M_DEVBUF);
2145		pg->pg_tssi2dbm = NULL;
2146	}
2147	pg->pg_flags = 0;
2148}
2149
2150static void
2151bwn_phy_g_init_pre(struct bwn_mac *mac)
2152{
2153	struct bwn_phy *phy = &mac->mac_phy;
2154	struct bwn_phy_g *pg = &phy->phy_g;
2155	void *tssi2dbm;
2156	int idletssi;
2157	unsigned int i;
2158
2159	tssi2dbm = pg->pg_tssi2dbm;
2160	idletssi = pg->pg_idletssi;
2161
2162	memset(pg, 0, sizeof(*pg));
2163
2164	pg->pg_tssi2dbm = tssi2dbm;
2165	pg->pg_idletssi = idletssi;
2166
2167	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2168
2169	for (i = 0; i < N(pg->pg_nrssi); i++)
2170		pg->pg_nrssi[i] = -1000;
2171	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2172		pg->pg_nrssi_lt[i] = i;
2173	pg->pg_lofcal = 0xffff;
2174	pg->pg_initval = 0xffff;
2175	pg->pg_immode = BWN_IMMODE_NONE;
2176	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2177	pg->pg_avgtssi = 0xff;
2178
2179	pg->pg_loctl.tx_bias = 0xff;
2180	TAILQ_INIT(&pg->pg_loctl.calib_list);
2181}
2182
2183static int
2184bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2185{
2186	struct bwn_phy *phy = &mac->mac_phy;
2187	struct bwn_phy_g *pg = &phy->phy_g;
2188	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2189	struct siba_softc *bus = mac->mac_sd->sd_bus;
2190	static const struct bwn_rfatt rfatt0[] = {
2191		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2192		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2193		{ 3, 1 }, { 4, 1 }
2194	};
2195	static const struct bwn_rfatt rfatt1[] = {
2196		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2197		{ 14, 1 }
2198	};
2199	static const struct bwn_rfatt rfatt2[] = {
2200		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2201		{ 9, 1 }
2202	};
2203	static const struct bwn_bbatt bbatt_0[] = {
2204		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2205	};
2206
2207	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2208
2209	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2210		pg->pg_bbatt.att = 0;
2211	else
2212		pg->pg_bbatt.att = 2;
2213
2214	/* prepare Radio Attenuation */
2215	pg->pg_rfatt.padmix = 0;
2216
2217	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2218	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2219		if (bus->siba_board_rev < 0x43) {
2220			pg->pg_rfatt.att = 2;
2221			goto done;
2222		} else if (bus->siba_board_rev < 0x51) {
2223			pg->pg_rfatt.att = 3;
2224			goto done;
2225		}
2226	}
2227
2228	if (phy->type == BWN_PHYTYPE_A) {
2229		pg->pg_rfatt.att = 0x60;
2230		goto done;
2231	}
2232
2233	switch (phy->rf_ver) {
2234	case 0x2050:
2235		switch (phy->rf_rev) {
2236		case 0:
2237			pg->pg_rfatt.att = 5;
2238			goto done;
2239		case 1:
2240			if (phy->type == BWN_PHYTYPE_G) {
2241				if (bus->siba_board_vendor ==
2242				    SIBA_BOARDVENDOR_BCM &&
2243				    bus->siba_board_type ==
2244				    SIBA_BOARD_BCM4309G &&
2245				    bus->siba_board_rev >= 30)
2246					pg->pg_rfatt.att = 3;
2247				else if (bus->siba_board_vendor ==
2248				    SIBA_BOARDVENDOR_BCM &&
2249				    bus->siba_board_type == SIBA_BOARD_BU4306)
2250					pg->pg_rfatt.att = 3;
2251				else
2252					pg->pg_rfatt.att = 1;
2253			} else {
2254				if (bus->siba_board_vendor ==
2255				    SIBA_BOARDVENDOR_BCM &&
2256				    bus->siba_board_type ==
2257				    SIBA_BOARD_BCM4309G &&
2258				    bus->siba_board_rev >= 30)
2259					pg->pg_rfatt.att = 7;
2260				else
2261					pg->pg_rfatt.att = 6;
2262			}
2263			goto done;
2264		case 2:
2265			if (phy->type == BWN_PHYTYPE_G) {
2266				if (bus->siba_board_vendor ==
2267				    SIBA_BOARDVENDOR_BCM &&
2268				    bus->siba_board_type ==
2269				    SIBA_BOARD_BCM4309G &&
2270				    bus->siba_board_rev >= 30)
2271					pg->pg_rfatt.att = 3;
2272				else if (bus->siba_board_vendor ==
2273				    SIBA_BOARDVENDOR_BCM &&
2274				    bus->siba_board_type == SIBA_BOARD_BU4306)
2275					pg->pg_rfatt.att = 5;
2276				else if (bus->siba_chipid == 0x4320)
2277					pg->pg_rfatt.att = 4;
2278				else
2279					pg->pg_rfatt.att = 3;
2280			} else
2281				pg->pg_rfatt.att = 6;
2282			goto done;
2283		case 3:
2284			pg->pg_rfatt.att = 5;
2285			goto done;
2286		case 4:
2287		case 5:
2288			pg->pg_rfatt.att = 1;
2289			goto done;
2290		case 6:
2291		case 7:
2292			pg->pg_rfatt.att = 5;
2293			goto done;
2294		case 8:
2295			pg->pg_rfatt.att = 0xa;
2296			pg->pg_rfatt.padmix = 1;
2297			goto done;
2298		case 9:
2299		default:
2300			pg->pg_rfatt.att = 5;
2301			goto done;
2302		}
2303		break;
2304	case 0x2053:
2305		switch (phy->rf_rev) {
2306		case 1:
2307			pg->pg_rfatt.att = 6;
2308			goto done;
2309		}
2310		break;
2311	}
2312	pg->pg_rfatt.att = 5;
2313done:
2314	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2315
2316	if (!bwn_has_hwpctl(mac)) {
2317		lo->rfatt.array = rfatt0;
2318		lo->rfatt.len = N(rfatt0);
2319		lo->rfatt.min = 0;
2320		lo->rfatt.max = 9;
2321		goto genbbatt;
2322	}
2323	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2324		lo->rfatt.array = rfatt1;
2325		lo->rfatt.len = N(rfatt1);
2326		lo->rfatt.min = 0;
2327		lo->rfatt.max = 14;
2328		goto genbbatt;
2329	}
2330	lo->rfatt.array = rfatt2;
2331	lo->rfatt.len = N(rfatt2);
2332	lo->rfatt.min = 0;
2333	lo->rfatt.max = 9;
2334genbbatt:
2335	lo->bbatt.array = bbatt_0;
2336	lo->bbatt.len = N(bbatt_0);
2337	lo->bbatt.min = 0;
2338	lo->bbatt.max = 8;
2339
2340	BWN_READ_4(mac, BWN_MACCTL);
2341	if (phy->rev == 1) {
2342		phy->gmode = 0;
2343		bwn_reset_core(mac, 0);
2344		bwn_phy_g_init_sub(mac);
2345		phy->gmode = 1;
2346		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2347	}
2348	return (0);
2349}
2350
2351static uint16_t
2352bwn_phy_g_txctl(struct bwn_mac *mac)
2353{
2354	struct bwn_phy *phy = &mac->mac_phy;
2355
2356	if (phy->rf_ver != 0x2050)
2357		return (0);
2358	if (phy->rf_rev == 1)
2359		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2360	if (phy->rf_rev < 6)
2361		return (BWN_TXCTL_PA2DB);
2362	if (phy->rf_rev == 8)
2363		return (BWN_TXCTL_TXMIX);
2364	return (0);
2365}
2366
2367static int
2368bwn_phy_g_init(struct bwn_mac *mac)
2369{
2370
2371	bwn_phy_g_init_sub(mac);
2372	return (0);
2373}
2374
2375static void
2376bwn_phy_g_exit(struct bwn_mac *mac)
2377{
2378	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2379	struct bwn_lo_calib *cal, *tmp;
2380
2381	if (lo == NULL)
2382		return;
2383	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2384		TAILQ_REMOVE(&lo->calib_list, cal, list);
2385		free(cal, M_DEVBUF);
2386	}
2387}
2388
2389static uint16_t
2390bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2391{
2392
2393	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2394	return (BWN_READ_2(mac, BWN_PHYDATA));
2395}
2396
2397static void
2398bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2399{
2400
2401	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2402	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2403}
2404
2405static uint16_t
2406bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2407{
2408
2409	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2410	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2411	return (BWN_READ_2(mac, BWN_RFDATALO));
2412}
2413
2414static void
2415bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2416{
2417
2418	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2419	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2420	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2421}
2422
2423static int
2424bwn_phy_g_hwpctl(struct bwn_mac *mac)
2425{
2426
2427	return (mac->mac_phy.rev >= 6);
2428}
2429
2430static void
2431bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2432{
2433	struct bwn_phy *phy = &mac->mac_phy;
2434	struct bwn_phy_g *pg = &phy->phy_g;
2435	unsigned int channel;
2436	uint16_t rfover, rfoverval;
2437
2438	if (on) {
2439		if (phy->rf_on)
2440			return;
2441
2442		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2443		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2444		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2445		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2446			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2447			    pg->pg_radioctx_over);
2448			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2449			    pg->pg_radioctx_overval);
2450			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2451		}
2452		channel = phy->chan;
2453		bwn_phy_g_switch_chan(mac, 6, 1);
2454		bwn_phy_g_switch_chan(mac, channel, 0);
2455		return;
2456	}
2457
2458	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2459	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2460	pg->pg_radioctx_over = rfover;
2461	pg->pg_radioctx_overval = rfoverval;
2462	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2463	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2464	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2465}
2466
2467static int
2468bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2469{
2470
2471	if ((newchan < 1) || (newchan > 14))
2472		return (EINVAL);
2473	bwn_phy_g_switch_chan(mac, newchan, 0);
2474
2475	return (0);
2476}
2477
2478static uint32_t
2479bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2480{
2481
2482	return (1);
2483}
2484
2485static void
2486bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2487{
2488	struct bwn_phy *phy = &mac->mac_phy;
2489	uint64_t hf;
2490	int autodiv = 0;
2491	uint16_t tmp;
2492
2493	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2494		autodiv = 1;
2495
2496	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2497	bwn_hf_write(mac, hf);
2498
2499	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2500	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2501	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2502		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2503
2504	if (autodiv) {
2505		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2506		if (antenna == BWN_ANTAUTO1)
2507			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2508		else
2509			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2510		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2511	}
2512	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2513	if (autodiv)
2514		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2515	else
2516		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2517	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2518	if (phy->rev >= 2) {
2519		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2520		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2521		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2522		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2523		    0x15);
2524		if (phy->rev == 2)
2525			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2526		else
2527			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2528			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2529			    8);
2530	}
2531	if (phy->rev >= 6)
2532		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2533
2534	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2535	bwn_hf_write(mac, hf);
2536}
2537
2538static int
2539bwn_phy_g_im(struct bwn_mac *mac, int mode)
2540{
2541	struct bwn_phy *phy = &mac->mac_phy;
2542	struct bwn_phy_g *pg = &phy->phy_g;
2543
2544	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2545	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2546
2547	if (phy->rev == 0 || !phy->gmode)
2548		return (ENODEV);
2549
2550	pg->pg_aci_wlan_automatic = 0;
2551	return (0);
2552}
2553
2554static int
2555bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2556{
2557	struct bwn_phy *phy = &mac->mac_phy;
2558	struct bwn_phy_g *pg = &phy->phy_g;
2559	struct bwn_softc *sc = mac->mac_sc;
2560	struct siba_softc *siba = mac->mac_sd->sd_bus;
2561	unsigned int tssi;
2562	int cck, ofdm;
2563	int power;
2564	int rfatt, bbatt;
2565	unsigned int max;
2566
2567	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2568
2569	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2570	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2571	if (cck < 0 && ofdm < 0) {
2572		if (ignore_tssi == 0)
2573			return (BWN_TXPWR_RES_DONE);
2574		cck = 0;
2575		ofdm = 0;
2576	}
2577	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2578	if (pg->pg_avgtssi != 0xff)
2579		tssi = (tssi + pg->pg_avgtssi) / 2;
2580	pg->pg_avgtssi = tssi;
2581	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2582
2583	max = siba->siba_sprom.maxpwr_bg;
2584	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2585		max -= 3;
2586	if (max >= 120) {
2587		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2588		siba->siba_sprom.maxpwr_bg = max = 80;
2589	}
2590
2591	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2592	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2593	     tssi, 0x00), 0x3f)]);
2594	if (power == 0)
2595		return (BWN_TXPWR_RES_DONE);
2596
2597	rfatt = -((power + 7) / 8);
2598	bbatt = (-(power / 2)) - (4 * rfatt);
2599	if ((rfatt == 0) && (bbatt == 0))
2600		return (BWN_TXPWR_RES_DONE);
2601	pg->pg_bbatt_delta = bbatt;
2602	pg->pg_rfatt_delta = rfatt;
2603	return (BWN_TXPWR_RES_NEED_ADJUST);
2604}
2605
2606static void
2607bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2608{
2609	struct bwn_phy *phy = &mac->mac_phy;
2610	struct bwn_phy_g *pg = &phy->phy_g;
2611	struct bwn_softc *sc = mac->mac_sc;
2612	int rfatt, bbatt;
2613	uint8_t txctl;
2614
2615	bwn_mac_suspend(mac);
2616
2617	BWN_ASSERT_LOCKED(sc);
2618
2619	bbatt = pg->pg_bbatt.att;
2620	bbatt += pg->pg_bbatt_delta;
2621	rfatt = pg->pg_rfatt.att;
2622	rfatt += pg->pg_rfatt_delta;
2623
2624	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2625	txctl = pg->pg_txctl;
2626	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2627		if (rfatt <= 1) {
2628			if (txctl == 0) {
2629				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2630				rfatt += 2;
2631				bbatt += 2;
2632			} else if (mac->mac_sd->sd_bus->siba_sprom.
2633				   bf_lo &
2634				   BWN_BFL_PACTRL) {
2635				bbatt += 4 * (rfatt - 2);
2636				rfatt = 2;
2637			}
2638		} else if (rfatt > 4 && txctl) {
2639			txctl = 0;
2640			if (bbatt < 3) {
2641				rfatt -= 3;
2642				bbatt += 2;
2643			} else {
2644				rfatt -= 2;
2645				bbatt -= 2;
2646			}
2647		}
2648	}
2649	pg->pg_txctl = txctl;
2650	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2651	pg->pg_rfatt.att = rfatt;
2652	pg->pg_bbatt.att = bbatt;
2653
2654	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2655
2656	bwn_phy_lock(mac);
2657	bwn_rf_lock(mac);
2658	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2659	    pg->pg_txctl);
2660	bwn_rf_unlock(mac);
2661	bwn_phy_unlock(mac);
2662
2663	bwn_mac_enable(mac);
2664}
2665
2666static void
2667bwn_phy_g_task_15s(struct bwn_mac *mac)
2668{
2669	struct bwn_phy *phy = &mac->mac_phy;
2670	struct bwn_phy_g *pg = &phy->phy_g;
2671	struct bwn_softc *sc = mac->mac_sc;
2672	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2673	unsigned long expire, now;
2674	struct bwn_lo_calib *cal, *tmp;
2675	uint8_t expired = 0;
2676
2677	bwn_mac_suspend(mac);
2678
2679	if (lo == NULL)
2680		goto fail;
2681
2682	BWN_GETTIME(now);
2683	if (bwn_has_hwpctl(mac)) {
2684		expire = now - BWN_LO_PWRVEC_EXPIRE;
2685		if (time_before(lo->pwr_vec_read_time, expire)) {
2686			bwn_lo_get_powervector(mac);
2687			bwn_phy_g_dc_lookup_init(mac, 0);
2688		}
2689		goto fail;
2690	}
2691
2692	expire = now - BWN_LO_CALIB_EXPIRE;
2693	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2694		if (!time_before(cal->calib_time, expire))
2695			continue;
2696		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2697		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2698			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2699			expired = 1;
2700		}
2701
2702		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2703		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2704		    cal->ctl.i, cal->ctl.q);
2705
2706		TAILQ_REMOVE(&lo->calib_list, cal, list);
2707		free(cal, M_DEVBUF);
2708	}
2709	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2710		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2711		    &pg->pg_rfatt);
2712		if (cal == NULL) {
2713			device_printf(sc->sc_dev,
2714			    "failed to recalibrate LO\n");
2715			goto fail;
2716		}
2717		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2718		bwn_lo_write(mac, &cal->ctl);
2719	}
2720
2721fail:
2722	bwn_mac_enable(mac);
2723}
2724
2725static void
2726bwn_phy_g_task_60s(struct bwn_mac *mac)
2727{
2728	struct bwn_phy *phy = &mac->mac_phy;
2729	uint8_t old = phy->chan;
2730
2731	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2732		return;
2733
2734	bwn_mac_suspend(mac);
2735	bwn_nrssi_slope_11g(mac);
2736	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2737		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2738		bwn_switch_channel(mac, old);
2739	}
2740	bwn_mac_enable(mac);
2741}
2742
2743static void
2744bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2745{
2746
2747	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2748}
2749
2750static int
2751bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2752	const struct ieee80211_bpf_params *params)
2753{
2754	struct ieee80211com *ic = ni->ni_ic;
2755	struct ifnet *ifp = ic->ic_ifp;
2756	struct bwn_softc *sc = ifp->if_softc;
2757	struct bwn_mac *mac = sc->sc_curmac;
2758
2759	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2760	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2761		ieee80211_free_node(ni);
2762		m_freem(m);
2763		return (ENETDOWN);
2764	}
2765
2766	BWN_LOCK(sc);
2767	if (bwn_tx_isfull(sc, m)) {
2768		ieee80211_free_node(ni);
2769		m_freem(m);
2770		ifp->if_oerrors++;
2771		BWN_UNLOCK(sc);
2772		return (ENOBUFS);
2773	}
2774
2775	if (bwn_tx_start(sc, ni, m) != 0) {
2776		if (ni != NULL)
2777			ieee80211_free_node(ni);
2778		ifp->if_oerrors++;
2779	}
2780	sc->sc_watchdog_timer = 5;
2781	BWN_UNLOCK(sc);
2782	return (0);
2783}
2784
2785/*
2786 * Setup driver-specific state for a newly associated node.
2787 * Note that we're called also on a re-associate, the isnew
2788 * param tells us if this is the first time or not.
2789 */
2790static void
2791bwn_newassoc(struct ieee80211_node *ni, int isnew)
2792{
2793	struct ieee80211vap *vap = ni->ni_vap;
2794
2795	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2796	    &BWN_NODE(ni)->bn_amn, ni);
2797}
2798
2799/*
2800 * Callback from the 802.11 layer to update the slot time
2801 * based on the current setting.  We use it to notify the
2802 * firmware of ERP changes and the f/w takes care of things
2803 * like slot time and preamble.
2804 */
2805static void
2806bwn_updateslot(struct ifnet *ifp)
2807{
2808	struct bwn_softc *sc = ifp->if_softc;
2809	struct ieee80211com *ic = ifp->if_l2com;
2810	struct bwn_mac *mac;
2811
2812	BWN_LOCK(sc);
2813	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2814		mac = (struct bwn_mac *)sc->sc_curmac;
2815		bwn_set_slot_time(mac,
2816		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2817	}
2818	BWN_UNLOCK(sc);
2819}
2820
2821/*
2822 * Callback from the 802.11 layer after a promiscuous mode change.
2823 * Note this interface does not check the operating mode as this
2824 * is an internal callback and we are expected to honor the current
2825 * state (e.g. this is used for setting the interface in promiscuous
2826 * mode when operating in hostap mode to do ACS).
2827 */
2828static void
2829bwn_update_promisc(struct ifnet *ifp)
2830{
2831	struct bwn_softc *sc = ifp->if_softc;
2832	struct bwn_mac *mac = sc->sc_curmac;
2833
2834	BWN_LOCK(sc);
2835	mac = sc->sc_curmac;
2836	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2837		if (ifp->if_flags & IFF_PROMISC)
2838			sc->sc_filters |= BWN_MACCTL_PROMISC;
2839		else
2840			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2841		bwn_set_opmode(mac);
2842	}
2843	BWN_UNLOCK(sc);
2844}
2845
2846/*
2847 * Callback from the 802.11 layer to update WME parameters.
2848 */
2849static int
2850bwn_wme_update(struct ieee80211com *ic)
2851{
2852	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2853	struct bwn_mac *mac = sc->sc_curmac;
2854	struct wmeParams *wmep;
2855	int i;
2856
2857	BWN_LOCK(sc);
2858	mac = sc->sc_curmac;
2859	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2860		bwn_mac_suspend(mac);
2861		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2862			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2863			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2864		}
2865		bwn_mac_enable(mac);
2866	}
2867	BWN_UNLOCK(sc);
2868	return (0);
2869}
2870
2871static struct ieee80211_node *
2872bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2873{
2874	struct ieee80211com *ic = vap->iv_ic;
2875	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2876	const size_t space = sizeof(struct bwn_node);
2877	struct bwn_node *bn;
2878
2879	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2880	if (bn == NULL) {
2881		/* XXX stat+msg */
2882		return (NULL);
2883	}
2884	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2885	return (&bn->bn_node);
2886}
2887
2888static void
2889bwn_node_cleanup(struct ieee80211_node *ni)
2890{
2891	struct ieee80211com *ic = ni->ni_ic;
2892	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2893
2894	sc->sc_node_cleanup(ni);
2895}
2896
2897static void
2898bwn_scan_start(struct ieee80211com *ic)
2899{
2900	struct ifnet *ifp = ic->ic_ifp;
2901	struct bwn_softc *sc = ifp->if_softc;
2902	struct bwn_mac *mac;
2903
2904	BWN_LOCK(sc);
2905	mac = sc->sc_curmac;
2906	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2907		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2908		bwn_set_opmode(mac);
2909		/* disable CFP update during scan */
2910		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2911	}
2912	BWN_UNLOCK(sc);
2913}
2914
2915static void
2916bwn_scan_end(struct ieee80211com *ic)
2917{
2918	struct ifnet *ifp = ic->ic_ifp;
2919	struct bwn_softc *sc = ifp->if_softc;
2920	struct bwn_mac *mac;
2921
2922	BWN_LOCK(sc);
2923	mac = sc->sc_curmac;
2924	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2925		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2926		bwn_set_opmode(mac);
2927		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2928	}
2929	BWN_UNLOCK(sc);
2930}
2931
2932static void
2933bwn_set_channel(struct ieee80211com *ic)
2934{
2935	struct ifnet *ifp = ic->ic_ifp;
2936	struct bwn_softc *sc = ifp->if_softc;
2937	struct bwn_mac *mac = sc->sc_curmac;
2938	struct bwn_phy *phy = &mac->mac_phy;
2939	int chan, error;
2940
2941	BWN_LOCK(sc);
2942
2943	error = bwn_switch_band(sc, ic->ic_curchan);
2944	if (error)
2945		goto fail;;
2946	bwn_mac_suspend(mac);
2947	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2948	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2949	if (chan != phy->chan)
2950		bwn_switch_channel(mac, chan);
2951
2952	/* TX power level */
2953	if (ic->ic_curchan->ic_maxpower != 0 &&
2954	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2955		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2956		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2957		    BWN_TXPWR_IGNORE_TSSI);
2958	}
2959
2960	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2961	if (phy->set_antenna)
2962		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2963
2964	if (sc->sc_rf_enabled != phy->rf_on) {
2965		if (sc->sc_rf_enabled) {
2966			bwn_rf_turnon(mac);
2967			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2968				device_printf(sc->sc_dev,
2969				    "please turns on the RF switch\n");
2970		} else
2971			bwn_rf_turnoff(mac);
2972	}
2973
2974	bwn_mac_enable(mac);
2975
2976fail:
2977	/*
2978	 * Setup radio tap channel freq and flags
2979	 */
2980	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2981		htole16(ic->ic_curchan->ic_freq);
2982	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2983		htole16(ic->ic_curchan->ic_flags & 0xffff);
2984
2985	BWN_UNLOCK(sc);
2986}
2987
2988static struct ieee80211vap *
2989bwn_vap_create(struct ieee80211com *ic,
2990	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2991	const uint8_t bssid[IEEE80211_ADDR_LEN],
2992	const uint8_t mac0[IEEE80211_ADDR_LEN])
2993{
2994	struct ifnet *ifp = ic->ic_ifp;
2995	struct bwn_softc *sc = ifp->if_softc;
2996	struct ieee80211vap *vap;
2997	struct bwn_vap *bvp;
2998	uint8_t mac[IEEE80211_ADDR_LEN];
2999
3000	IEEE80211_ADDR_COPY(mac, mac0);
3001	switch (opmode) {
3002	case IEEE80211_M_HOSTAP:
3003	case IEEE80211_M_MBSS:
3004	case IEEE80211_M_STA:
3005	case IEEE80211_M_WDS:
3006	case IEEE80211_M_MONITOR:
3007	case IEEE80211_M_IBSS:
3008	case IEEE80211_M_AHDEMO:
3009		break;
3010	default:
3011		return (NULL);
3012	}
3013
3014	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3015
3016	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3017	    M_80211_VAP, M_NOWAIT | M_ZERO);
3018	if (bvp == NULL) {
3019		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3020		return (NULL);
3021	}
3022	vap = &bvp->bv_vap;
3023	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3024	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3025	/* override with driver methods */
3026	bvp->bv_newstate = vap->iv_newstate;
3027	vap->iv_newstate = bwn_newstate;
3028
3029	/* override max aid so sta's cannot assoc when we're out of sta id's */
3030	vap->iv_max_aid = BWN_STAID_MAX;
3031
3032	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3033	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3034	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3035	    500 /*ms*/);
3036
3037	/* complete setup */
3038	ieee80211_vap_attach(vap, ieee80211_media_change,
3039	    ieee80211_media_status);
3040	return (vap);
3041}
3042
3043static void
3044bwn_vap_delete(struct ieee80211vap *vap)
3045{
3046	struct bwn_vap *bvp = BWN_VAP(vap);
3047
3048	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3049	ieee80211_vap_detach(vap);
3050	free(bvp, M_80211_VAP);
3051}
3052
3053static void
3054bwn_init(void *arg)
3055{
3056	struct bwn_softc *sc = arg;
3057	struct ifnet *ifp = sc->sc_ifp;
3058	struct ieee80211com *ic = ifp->if_l2com;
3059	int error = 0;
3060
3061	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3062		__func__, ifp->if_flags);
3063
3064	BWN_LOCK(sc);
3065	error = bwn_init_locked(sc);
3066	BWN_UNLOCK(sc);
3067
3068	if (error == 0)
3069		ieee80211_start_all(ic);	/* start all vap's */
3070}
3071
3072static int
3073bwn_init_locked(struct bwn_softc *sc)
3074{
3075	struct bwn_mac *mac;
3076	struct ifnet *ifp = sc->sc_ifp;
3077	int error;
3078
3079	BWN_ASSERT_LOCKED(sc);
3080
3081	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3082	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3083	sc->sc_filters = 0;
3084	bwn_wme_clear(sc);
3085	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3086	sc->sc_rf_enabled = 1;
3087
3088	mac = sc->sc_curmac;
3089	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3090		error = bwn_core_init(mac);
3091		if (error != 0)
3092			return (error);
3093	}
3094	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3095		bwn_core_start(mac);
3096
3097	bwn_set_opmode(mac);
3098	bwn_set_pretbtt(mac);
3099	bwn_spu_setdelay(mac, 0);
3100	bwn_set_macaddr(mac);
3101
3102	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3103	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3104	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3105
3106	return (0);
3107}
3108
3109static void
3110bwn_stop(struct bwn_softc *sc, int statechg)
3111{
3112
3113	BWN_LOCK(sc);
3114	bwn_stop_locked(sc, statechg);
3115	BWN_UNLOCK(sc);
3116}
3117
3118static void
3119bwn_stop_locked(struct bwn_softc *sc, int statechg)
3120{
3121	struct bwn_mac *mac = sc->sc_curmac;
3122	struct ifnet *ifp = sc->sc_ifp;
3123
3124	BWN_ASSERT_LOCKED(sc);
3125
3126	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3127		/* XXX FIXME opmode not based on VAP */
3128		bwn_set_opmode(mac);
3129		bwn_set_macaddr(mac);
3130	}
3131
3132	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3133		bwn_core_stop(mac);
3134
3135	callout_stop(&sc->sc_led_blink_ch);
3136	sc->sc_led_blinking = 0;
3137
3138	bwn_core_exit(mac);
3139	sc->sc_rf_enabled = 0;
3140
3141	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3142}
3143
3144static void
3145bwn_wme_clear(struct bwn_softc *sc)
3146{
3147#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3148	struct wmeParams *p;
3149	unsigned int i;
3150
3151	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3152	    ("%s:%d: fail", __func__, __LINE__));
3153
3154	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3155		p = &(sc->sc_wmeParams[i]);
3156
3157		switch (bwn_wme_shm_offsets[i]) {
3158		case BWN_WME_VOICE:
3159			p->wmep_txopLimit = 0;
3160			p->wmep_aifsn = 2;
3161			/* XXX FIXME: log2(cwmin) */
3162			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3163			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3164			break;
3165		case BWN_WME_VIDEO:
3166			p->wmep_txopLimit = 0;
3167			p->wmep_aifsn = 2;
3168			/* XXX FIXME: log2(cwmin) */
3169			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3170			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3171			break;
3172		case BWN_WME_BESTEFFORT:
3173			p->wmep_txopLimit = 0;
3174			p->wmep_aifsn = 3;
3175			/* XXX FIXME: log2(cwmin) */
3176			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3177			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3178			break;
3179		case BWN_WME_BACKGROUND:
3180			p->wmep_txopLimit = 0;
3181			p->wmep_aifsn = 7;
3182			/* XXX FIXME: log2(cwmin) */
3183			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3184			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3185			break;
3186		default:
3187			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3188		}
3189	}
3190}
3191
3192static int
3193bwn_core_init(struct bwn_mac *mac)
3194{
3195#ifdef BWN_DEBUG
3196	struct bwn_softc *sc = mac->mac_sc;
3197#endif
3198	struct siba_dev_softc *sd = mac->mac_sd;
3199	struct siba_softc *siba = sd->sd_bus;
3200	struct siba_sprom *sprom = &siba->siba_sprom;
3201	uint64_t hf;
3202	int error;
3203
3204	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3205	    ("%s:%d: fail", __func__, __LINE__));
3206
3207	siba_powerup(siba, 0);
3208	if (!siba_dev_isup(sd))
3209		bwn_reset_core(mac,
3210		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3211
3212	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3213	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3214	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3215	BWN_GETTIME(mac->mac_phy.nexttime);
3216	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3217	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3218	mac->mac_stats.link_noise = -95;
3219	mac->mac_reason_intr = 0;
3220	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3221	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3222#ifdef BWN_DEBUG
3223	if (sc->sc_debug & BWN_DEBUG_XMIT)
3224		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3225#endif
3226	mac->mac_suspended = 1;
3227	mac->mac_task_state = 0;
3228	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3229
3230	mac->mac_phy.init_pre(mac);
3231
3232	siba_pcicore_intr(&siba->siba_pci, sd);
3233
3234	bwn_fix_imcfglobug(mac);
3235	bwn_bt_disable(mac);
3236	if (mac->mac_phy.prepare_hw) {
3237		error = mac->mac_phy.prepare_hw(mac);
3238		if (error)
3239			goto fail0;
3240	}
3241	error = bwn_chip_init(mac);
3242	if (error)
3243		goto fail0;
3244	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3245	    mac->mac_sd->sd_id.sd_rev);
3246	hf = bwn_hf_read(mac);
3247	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3248		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3249		if (sprom->bf_lo & BWN_BFL_PACTRL)
3250			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3251		if (mac->mac_phy.rev == 1)
3252			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3253	}
3254	if (mac->mac_phy.rf_ver == 0x2050) {
3255		if (mac->mac_phy.rf_rev < 6)
3256			hf |= BWN_HF_FORCE_VCO_RECALC;
3257		if (mac->mac_phy.rf_rev == 6)
3258			hf |= BWN_HF_4318_TSSI;
3259	}
3260	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3261		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3262	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3263	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3264		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3265	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3266	bwn_hf_write(mac, hf);
3267
3268	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3269	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3270	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3271	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3272
3273	bwn_rate_init(mac);
3274	bwn_set_phytxctl(mac);
3275
3276	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3277	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3278	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3279
3280	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3281		bwn_pio_init(mac);
3282	else
3283		bwn_dma_init(mac);
3284	if (error)
3285		goto fail1;
3286	bwn_wme_init(mac);
3287	bwn_spu_setdelay(mac, 1);
3288	bwn_bt_enable(mac);
3289
3290	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3291	bwn_set_macaddr(mac);
3292	bwn_crypt_init(mac);
3293
3294	/* XXX LED initializatin */
3295
3296	mac->mac_status = BWN_MAC_STATUS_INITED;
3297
3298	return (error);
3299
3300fail1:
3301	bwn_chip_exit(mac);
3302fail0:
3303	siba_powerdown(siba);
3304	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3305	    ("%s:%d: fail", __func__, __LINE__));
3306	return (error);
3307}
3308
3309static void
3310bwn_core_start(struct bwn_mac *mac)
3311{
3312	struct bwn_softc *sc = mac->mac_sc;
3313	uint32_t tmp;
3314
3315	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3316	    ("%s:%d: fail", __func__, __LINE__));
3317
3318	if (mac->mac_sd->sd_id.sd_rev < 5)
3319		return;
3320
3321	while (1) {
3322		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3323		if (!(tmp & 0x00000001))
3324			break;
3325		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3326	}
3327
3328	bwn_mac_enable(mac);
3329	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3330	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3331
3332	mac->mac_status = BWN_MAC_STATUS_STARTED;
3333}
3334
3335static void
3336bwn_core_exit(struct bwn_mac *mac)
3337{
3338	struct bwn_softc *sc = mac->mac_sc;
3339	uint32_t macctl;
3340
3341	BWN_ASSERT_LOCKED(sc);
3342
3343	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3344	    ("%s:%d: fail", __func__, __LINE__));
3345
3346	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3347		return;
3348	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3349
3350	macctl = BWN_READ_4(mac, BWN_MACCTL);
3351	macctl &= ~BWN_MACCTL_MCODE_RUN;
3352	macctl |= BWN_MACCTL_MCODE_JMP0;
3353	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3354
3355	bwn_dma_stop(mac);
3356	bwn_pio_stop(mac);
3357	bwn_chip_exit(mac);
3358	mac->mac_phy.switch_analog(mac, 0);
3359	siba_dev_down(mac->mac_sd, 0);
3360	siba_powerdown(mac->mac_sd->sd_bus);
3361}
3362
3363static void
3364bwn_fix_imcfglobug(struct bwn_mac *mac)
3365{
3366	struct siba_dev_softc *sd = mac->mac_sd;
3367	struct siba_softc *siba = sd->sd_bus;
3368	uint32_t tmp;
3369
3370	if (siba->siba_pci.spc_dev == NULL)
3371		return;
3372	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3373	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3374		return;
3375
3376	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3377	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3378	switch (siba->siba_type) {
3379	case SIBA_TYPE_PCI:
3380	case SIBA_TYPE_PCMCIA:
3381		tmp |= 0x32;
3382		break;
3383	case SIBA_TYPE_SSB:
3384		tmp |= 0x53;
3385		break;
3386	}
3387	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3388}
3389
3390static void
3391bwn_bt_disable(struct bwn_mac *mac)
3392{
3393	struct bwn_softc *sc = mac->mac_sc;
3394
3395	(void)sc;
3396	/* XXX do nothing yet */
3397}
3398
3399static int
3400bwn_chip_init(struct bwn_mac *mac)
3401{
3402	struct bwn_phy *phy = &mac->mac_phy;
3403	uint32_t macctl;
3404	int error;
3405
3406	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3407	if (phy->gmode)
3408		macctl |= BWN_MACCTL_GMODE;
3409	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3410
3411	error = bwn_fw_fillinfo(mac);
3412	if (error)
3413		return (error);
3414	error = bwn_fw_loaducode(mac);
3415	if (error)
3416		return (error);
3417
3418	error = bwn_gpio_init(mac);
3419	if (error)
3420		return (error);
3421
3422	error = bwn_fw_loadinitvals(mac);
3423	if (error) {
3424		bwn_gpio_cleanup(mac);
3425		return (error);
3426	}
3427	phy->switch_analog(mac, 1);
3428	error = bwn_phy_init(mac);
3429	if (error) {
3430		bwn_gpio_cleanup(mac);
3431		return (error);
3432	}
3433	if (phy->set_im)
3434		phy->set_im(mac, BWN_IMMODE_NONE);
3435	if (phy->set_antenna)
3436		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3437	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3438
3439	if (phy->type == BWN_PHYTYPE_B)
3440		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3441	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3442	if (mac->mac_sd->sd_id.sd_rev < 5)
3443		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3444
3445	BWN_WRITE_4(mac, BWN_MACCTL,
3446	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3447	BWN_WRITE_4(mac, BWN_MACCTL,
3448	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3449	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3450
3451	bwn_set_opmode(mac);
3452	if (mac->mac_sd->sd_id.sd_rev < 3) {
3453		BWN_WRITE_2(mac, 0x060e, 0x0000);
3454		BWN_WRITE_2(mac, 0x0610, 0x8000);
3455		BWN_WRITE_2(mac, 0x0604, 0x0000);
3456		BWN_WRITE_2(mac, 0x0606, 0x0200);
3457	} else {
3458		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3459		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3460	}
3461	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3462	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3463	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3464	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3465	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3466	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3467	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3468	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3469	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3470	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3471	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3472	return (error);
3473}
3474
3475/* read hostflags */
3476static uint64_t
3477bwn_hf_read(struct bwn_mac *mac)
3478{
3479	uint64_t ret;
3480
3481	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3482	ret <<= 16;
3483	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3484	ret <<= 16;
3485	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3486	return (ret);
3487}
3488
3489static void
3490bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3491{
3492
3493	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3494	    (value & 0x00000000ffffull));
3495	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3496	    (value & 0x0000ffff0000ull) >> 16);
3497	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3498	    (value & 0xffff00000000ULL) >> 32);
3499}
3500
3501static void
3502bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3503{
3504
3505	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3506	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3507}
3508
3509static void
3510bwn_rate_init(struct bwn_mac *mac)
3511{
3512
3513	switch (mac->mac_phy.type) {
3514	case BWN_PHYTYPE_A:
3515	case BWN_PHYTYPE_G:
3516	case BWN_PHYTYPE_LP:
3517	case BWN_PHYTYPE_N:
3518		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3519		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3520		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3521		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3522		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3523		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3524		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3525		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3526			break;
3527		/* FALLTHROUGH */
3528	case BWN_PHYTYPE_B:
3529		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3530		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3531		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3532		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3533		break;
3534	default:
3535		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3536	}
3537}
3538
3539static void
3540bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3541{
3542	uint16_t offset;
3543
3544	if (ofdm) {
3545		offset = 0x480;
3546		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3547	} else {
3548		offset = 0x4c0;
3549		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3550	}
3551	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3552	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3553}
3554
3555static uint8_t
3556bwn_plcp_getcck(const uint8_t bitrate)
3557{
3558
3559	switch (bitrate) {
3560	case BWN_CCK_RATE_1MB:
3561		return (0x0a);
3562	case BWN_CCK_RATE_2MB:
3563		return (0x14);
3564	case BWN_CCK_RATE_5MB:
3565		return (0x37);
3566	case BWN_CCK_RATE_11MB:
3567		return (0x6e);
3568	}
3569	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3570	return (0);
3571}
3572
3573static uint8_t
3574bwn_plcp_getofdm(const uint8_t bitrate)
3575{
3576
3577	switch (bitrate) {
3578	case BWN_OFDM_RATE_6MB:
3579		return (0xb);
3580	case BWN_OFDM_RATE_9MB:
3581		return (0xf);
3582	case BWN_OFDM_RATE_12MB:
3583		return (0xa);
3584	case BWN_OFDM_RATE_18MB:
3585		return (0xe);
3586	case BWN_OFDM_RATE_24MB:
3587		return (0x9);
3588	case BWN_OFDM_RATE_36MB:
3589		return (0xd);
3590	case BWN_OFDM_RATE_48MB:
3591		return (0x8);
3592	case BWN_OFDM_RATE_54MB:
3593		return (0xc);
3594	}
3595	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3596	return (0);
3597}
3598
3599static void
3600bwn_set_phytxctl(struct bwn_mac *mac)
3601{
3602	uint16_t ctl;
3603
3604	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3605	    BWN_TX_PHY_TXPWR);
3606	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3607	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3608	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3609}
3610
3611static void
3612bwn_pio_init(struct bwn_mac *mac)
3613{
3614	struct bwn_pio *pio = &mac->mac_method.pio;
3615
3616	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3617	    & ~BWN_MACCTL_BIGENDIAN);
3618	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3619
3620	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3621	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3622	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3623	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3624	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3625	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3626}
3627
3628static void
3629bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3630    int index)
3631{
3632	struct bwn_pio_txpkt *tp;
3633	unsigned int i;
3634
3635	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3636	tq->tq_index = index;
3637
3638	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3639	if (mac->mac_sd->sd_id.sd_rev >= 8)
3640		tq->tq_size = 1920;
3641	else {
3642		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3643		tq->tq_size -= 80;
3644	}
3645
3646	TAILQ_INIT(&tq->tq_pktlist);
3647	for (i = 0; i < N(tq->tq_pkts); i++) {
3648		tp = &(tq->tq_pkts[i]);
3649		tp->tp_index = i;
3650		tp->tp_queue = tq;
3651		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3652	}
3653}
3654
3655static uint16_t
3656bwn_pio_idx2base(struct bwn_mac *mac, int index)
3657{
3658	struct bwn_softc *sc = mac->mac_sc;
3659	static const uint16_t bases[] = {
3660		BWN_PIO_BASE0,
3661		BWN_PIO_BASE1,
3662		BWN_PIO_BASE2,
3663		BWN_PIO_BASE3,
3664		BWN_PIO_BASE4,
3665		BWN_PIO_BASE5,
3666		BWN_PIO_BASE6,
3667		BWN_PIO_BASE7,
3668	};
3669	static const uint16_t bases_rev11[] = {
3670		BWN_PIO11_BASE0,
3671		BWN_PIO11_BASE1,
3672		BWN_PIO11_BASE2,
3673		BWN_PIO11_BASE3,
3674		BWN_PIO11_BASE4,
3675		BWN_PIO11_BASE5,
3676	};
3677
3678	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3679		if (index >= N(bases_rev11))
3680			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3681		return (bases_rev11[index]);
3682	}
3683	if (index >= N(bases))
3684		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3685	return (bases[index]);
3686}
3687
3688static void
3689bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3690    int index)
3691{
3692
3693	prq->prq_mac = mac;
3694	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3695	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3696	bwn_dma_rxdirectfifo(mac, index, 1);
3697}
3698
3699static void
3700bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3701{
3702	if (tq == NULL)
3703		return;
3704	bwn_pio_cancel_tx_packets(tq);
3705}
3706
3707static void
3708bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3709{
3710
3711	bwn_destroy_pioqueue_tx(pio);
3712}
3713
3714static uint16_t
3715bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3716    uint16_t offset)
3717{
3718
3719	return (BWN_READ_2(mac, tq->tq_base + offset));
3720}
3721
3722static void
3723bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3724{
3725	uint32_t ctl;
3726	int type;
3727	uint16_t base;
3728
3729	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3730	base = bwn_dma_base(type, idx);
3731	if (type == BWN_DMA_64BIT) {
3732		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3733		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3734		if (enable)
3735			ctl |= BWN_DMA64_RXDIRECTFIFO;
3736		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3737	} else {
3738		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3739		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3740		if (enable)
3741			ctl |= BWN_DMA32_RXDIRECTFIFO;
3742		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3743	}
3744}
3745
3746static uint64_t
3747bwn_dma_mask(struct bwn_mac *mac)
3748{
3749	uint32_t tmp;
3750	uint16_t base;
3751
3752	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3753	if (tmp & SIBA_TGSHIGH_DMA64)
3754		return (BWN_DMA_BIT_MASK(64));
3755	base = bwn_dma_base(0, 0);
3756	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3757	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3758	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3759		return (BWN_DMA_BIT_MASK(32));
3760
3761	return (BWN_DMA_BIT_MASK(30));
3762}
3763
3764static int
3765bwn_dma_mask2type(uint64_t dmamask)
3766{
3767
3768	if (dmamask == BWN_DMA_BIT_MASK(30))
3769		return (BWN_DMA_30BIT);
3770	if (dmamask == BWN_DMA_BIT_MASK(32))
3771		return (BWN_DMA_32BIT);
3772	if (dmamask == BWN_DMA_BIT_MASK(64))
3773		return (BWN_DMA_64BIT);
3774	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3775	return (BWN_DMA_30BIT);
3776}
3777
3778static void
3779bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3780{
3781	struct bwn_pio_txpkt *tp;
3782	unsigned int i;
3783
3784	for (i = 0; i < N(tq->tq_pkts); i++) {
3785		tp = &(tq->tq_pkts[i]);
3786		if (tp->tp_m) {
3787			m_freem(tp->tp_m);
3788			tp->tp_m = NULL;
3789		}
3790	}
3791}
3792
3793static uint16_t
3794bwn_dma_base(int type, int controller_idx)
3795{
3796	static const uint16_t map64[] = {
3797		BWN_DMA64_BASE0,
3798		BWN_DMA64_BASE1,
3799		BWN_DMA64_BASE2,
3800		BWN_DMA64_BASE3,
3801		BWN_DMA64_BASE4,
3802		BWN_DMA64_BASE5,
3803	};
3804	static const uint16_t map32[] = {
3805		BWN_DMA32_BASE0,
3806		BWN_DMA32_BASE1,
3807		BWN_DMA32_BASE2,
3808		BWN_DMA32_BASE3,
3809		BWN_DMA32_BASE4,
3810		BWN_DMA32_BASE5,
3811	};
3812
3813	if (type == BWN_DMA_64BIT) {
3814		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3815		    ("%s:%d: fail", __func__, __LINE__));
3816		return (map64[controller_idx]);
3817	}
3818	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3819	    ("%s:%d: fail", __func__, __LINE__));
3820	return (map32[controller_idx]);
3821}
3822
3823static void
3824bwn_dma_init(struct bwn_mac *mac)
3825{
3826	struct bwn_dma *dma = &mac->mac_method.dma;
3827
3828	/* setup TX DMA channels. */
3829	bwn_dma_setup(dma->wme[WME_AC_BK]);
3830	bwn_dma_setup(dma->wme[WME_AC_BE]);
3831	bwn_dma_setup(dma->wme[WME_AC_VI]);
3832	bwn_dma_setup(dma->wme[WME_AC_VO]);
3833	bwn_dma_setup(dma->mcast);
3834	/* setup RX DMA channel. */
3835	bwn_dma_setup(dma->rx);
3836}
3837
3838static struct bwn_dma_ring *
3839bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3840    int for_tx, int type)
3841{
3842	struct bwn_dma *dma = &mac->mac_method.dma;
3843	struct bwn_dma_ring *dr;
3844	struct bwn_dmadesc_generic *desc;
3845	struct bwn_dmadesc_meta *mt;
3846	struct bwn_softc *sc = mac->mac_sc;
3847	int error, i;
3848
3849	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3850	if (dr == NULL)
3851		goto out;
3852	dr->dr_numslots = BWN_RXRING_SLOTS;
3853	if (for_tx)
3854		dr->dr_numslots = BWN_TXRING_SLOTS;
3855
3856	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3857	    M_DEVBUF, M_NOWAIT | M_ZERO);
3858	if (dr->dr_meta == NULL)
3859		goto fail0;
3860
3861	dr->dr_type = type;
3862	dr->dr_mac = mac;
3863	dr->dr_base = bwn_dma_base(type, controller_index);
3864	dr->dr_index = controller_index;
3865	if (type == BWN_DMA_64BIT) {
3866		dr->getdesc = bwn_dma_64_getdesc;
3867		dr->setdesc = bwn_dma_64_setdesc;
3868		dr->start_transfer = bwn_dma_64_start_transfer;
3869		dr->suspend = bwn_dma_64_suspend;
3870		dr->resume = bwn_dma_64_resume;
3871		dr->get_curslot = bwn_dma_64_get_curslot;
3872		dr->set_curslot = bwn_dma_64_set_curslot;
3873	} else {
3874		dr->getdesc = bwn_dma_32_getdesc;
3875		dr->setdesc = bwn_dma_32_setdesc;
3876		dr->start_transfer = bwn_dma_32_start_transfer;
3877		dr->suspend = bwn_dma_32_suspend;
3878		dr->resume = bwn_dma_32_resume;
3879		dr->get_curslot = bwn_dma_32_get_curslot;
3880		dr->set_curslot = bwn_dma_32_set_curslot;
3881	}
3882	if (for_tx) {
3883		dr->dr_tx = 1;
3884		dr->dr_curslot = -1;
3885	} else {
3886		if (dr->dr_index == 0) {
3887			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3888			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3889		} else
3890			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3891	}
3892
3893	error = bwn_dma_allocringmemory(dr);
3894	if (error)
3895		goto fail2;
3896
3897	if (for_tx) {
3898		/*
3899		 * Assumption: BWN_TXRING_SLOTS can be divided by
3900		 * BWN_TX_SLOTS_PER_FRAME
3901		 */
3902		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3903		    ("%s:%d: fail", __func__, __LINE__));
3904
3905		dr->dr_txhdr_cache =
3906		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3907			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3908		KASSERT(dr->dr_txhdr_cache != NULL,
3909		    ("%s:%d: fail", __func__, __LINE__));
3910
3911		/*
3912		 * Create TX ring DMA stuffs
3913		 */
3914		error = bus_dma_tag_create(dma->parent_dtag,
3915				    BWN_ALIGN, 0,
3916				    BUS_SPACE_MAXADDR,
3917				    BUS_SPACE_MAXADDR,
3918				    NULL, NULL,
3919				    BWN_HDRSIZE(mac),
3920				    1,
3921				    BUS_SPACE_MAXSIZE_32BIT,
3922				    0,
3923				    NULL, NULL,
3924				    &dr->dr_txring_dtag);
3925		if (error) {
3926			device_printf(sc->sc_dev,
3927			    "can't create TX ring DMA tag: TODO frees\n");
3928			goto fail1;
3929		}
3930
3931		for (i = 0; i < dr->dr_numslots; i += 2) {
3932			dr->getdesc(dr, i, &desc, &mt);
3933
3934			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3935			mt->mt_m = NULL;
3936			mt->mt_ni = NULL;
3937			mt->mt_islast = 0;
3938			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3939			    &mt->mt_dmap);
3940			if (error) {
3941				device_printf(sc->sc_dev,
3942				     "can't create RX buf DMA map\n");
3943				goto fail1;
3944			}
3945
3946			dr->getdesc(dr, i + 1, &desc, &mt);
3947
3948			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3949			mt->mt_m = NULL;
3950			mt->mt_ni = NULL;
3951			mt->mt_islast = 1;
3952			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3953			    &mt->mt_dmap);
3954			if (error) {
3955				device_printf(sc->sc_dev,
3956				     "can't create RX buf DMA map\n");
3957				goto fail1;
3958			}
3959		}
3960	} else {
3961		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3962		    &dr->dr_spare_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
3969		for (i = 0; i < dr->dr_numslots; i++) {
3970			dr->getdesc(dr, i, &desc, &mt);
3971
3972			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3973			    &mt->mt_dmap);
3974			if (error) {
3975				device_printf(sc->sc_dev,
3976				    "can't create RX buf DMA map\n");
3977				goto out;	/* XXX wrong! */
3978			}
3979			error = bwn_dma_newbuf(dr, desc, mt, 1);
3980			if (error) {
3981				device_printf(sc->sc_dev,
3982				    "failed to allocate RX buf\n");
3983				goto out;	/* XXX wrong! */
3984			}
3985		}
3986
3987		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3988		    BUS_DMASYNC_PREWRITE);
3989
3990		dr->dr_usedslot = dr->dr_numslots;
3991	}
3992
3993      out:
3994	return (dr);
3995
3996fail2:
3997	free(dr->dr_txhdr_cache, M_DEVBUF);
3998fail1:
3999	free(dr->dr_meta, M_DEVBUF);
4000fail0:
4001	free(dr, M_DEVBUF);
4002	return (NULL);
4003}
4004
4005static void
4006bwn_dma_ringfree(struct bwn_dma_ring **dr)
4007{
4008
4009	if (dr == NULL)
4010		return;
4011
4012	bwn_dma_free_descbufs(*dr);
4013	bwn_dma_free_ringmemory(*dr);
4014
4015	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4016	free((*dr)->dr_meta, M_DEVBUF);
4017	free(*dr, M_DEVBUF);
4018
4019	*dr = NULL;
4020}
4021
4022static void
4023bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4024    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4025{
4026	struct bwn_dmadesc32 *desc;
4027
4028	*meta = &(dr->dr_meta[slot]);
4029	desc = dr->dr_ring_descbase;
4030	desc = &(desc[slot]);
4031
4032	*gdesc = (struct bwn_dmadesc_generic *)desc;
4033}
4034
4035static void
4036bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4037    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4038    int start, int end, int irq)
4039{
4040	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4041	uint32_t addr, addrext, ctl;
4042	int slot;
4043
4044	slot = (int)(&(desc->dma.dma32) - descbase);
4045	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4046	    ("%s:%d: fail", __func__, __LINE__));
4047
4048	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4049	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4050	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4051	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4052	if (slot == dr->dr_numslots - 1)
4053		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4054	if (start)
4055		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4056	if (end)
4057		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4058	if (irq)
4059		ctl |= BWN_DMA32_DCTL_IRQ;
4060	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4061	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4062
4063	desc->dma.dma32.control = htole32(ctl);
4064	desc->dma.dma32.address = htole32(addr);
4065}
4066
4067static void
4068bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4069{
4070
4071	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4072	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4073}
4074
4075static void
4076bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4077{
4078
4079	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4080	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4081}
4082
4083static void
4084bwn_dma_32_resume(struct bwn_dma_ring *dr)
4085{
4086
4087	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4088	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4089}
4090
4091static int
4092bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4093{
4094	uint32_t val;
4095
4096	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4097	val &= BWN_DMA32_RXDPTR;
4098
4099	return (val / sizeof(struct bwn_dmadesc32));
4100}
4101
4102static void
4103bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4104{
4105
4106	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4107	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4108}
4109
4110static void
4111bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4112    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4113{
4114	struct bwn_dmadesc64 *desc;
4115
4116	*meta = &(dr->dr_meta[slot]);
4117	desc = dr->dr_ring_descbase;
4118	desc = &(desc[slot]);
4119
4120	*gdesc = (struct bwn_dmadesc_generic *)desc;
4121}
4122
4123static void
4124bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4125    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4126    int start, int end, int irq)
4127{
4128	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4129	int slot;
4130	uint32_t ctl0 = 0, ctl1 = 0;
4131	uint32_t addrlo, addrhi;
4132	uint32_t addrext;
4133
4134	slot = (int)(&(desc->dma.dma64) - descbase);
4135	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4136	    ("%s:%d: fail", __func__, __LINE__));
4137
4138	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4139	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4140	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4141	    30;
4142	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4143	if (slot == dr->dr_numslots - 1)
4144		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4145	if (start)
4146		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4147	if (end)
4148		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4149	if (irq)
4150		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4151	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4152	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4153	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4154
4155	desc->dma.dma64.control0 = htole32(ctl0);
4156	desc->dma.dma64.control1 = htole32(ctl1);
4157	desc->dma.dma64.address_low = htole32(addrlo);
4158	desc->dma.dma64.address_high = htole32(addrhi);
4159}
4160
4161static void
4162bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4163{
4164
4165	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4166	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4167}
4168
4169static void
4170bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4171{
4172
4173	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4174	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4175}
4176
4177static void
4178bwn_dma_64_resume(struct bwn_dma_ring *dr)
4179{
4180
4181	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4182	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4183}
4184
4185static int
4186bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4187{
4188	uint32_t val;
4189
4190	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4191	val &= BWN_DMA64_RXSTATDPTR;
4192
4193	return (val / sizeof(struct bwn_dmadesc64));
4194}
4195
4196static void
4197bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4198{
4199
4200	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4201	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4202}
4203
4204static int
4205bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4206{
4207	struct bwn_mac *mac = dr->dr_mac;
4208	struct bwn_dma *dma = &mac->mac_method.dma;
4209	struct bwn_softc *sc = mac->mac_sc;
4210	int error;
4211
4212	error = bus_dma_tag_create(dma->parent_dtag,
4213			    BWN_ALIGN, 0,
4214			    BUS_SPACE_MAXADDR,
4215			    BUS_SPACE_MAXADDR,
4216			    NULL, NULL,
4217			    BWN_DMA_RINGMEMSIZE,
4218			    1,
4219			    BUS_SPACE_MAXSIZE_32BIT,
4220			    0,
4221			    NULL, NULL,
4222			    &dr->dr_ring_dtag);
4223	if (error) {
4224		device_printf(sc->sc_dev,
4225		    "can't create TX ring DMA tag: TODO frees\n");
4226		return (-1);
4227	}
4228
4229	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4230	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4231	    &dr->dr_ring_dmap);
4232	if (error) {
4233		device_printf(sc->sc_dev,
4234		    "can't allocate DMA mem: TODO frees\n");
4235		return (-1);
4236	}
4237	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4238	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4239	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4240	if (error) {
4241		device_printf(sc->sc_dev,
4242		    "can't load DMA mem: TODO free\n");
4243		return (-1);
4244	}
4245
4246	return (0);
4247}
4248
4249static void
4250bwn_dma_setup(struct bwn_dma_ring *dr)
4251{
4252	uint64_t ring64;
4253	uint32_t addrext, ring32, value;
4254	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4255
4256	if (dr->dr_tx) {
4257		dr->dr_curslot = -1;
4258
4259		if (dr->dr_type == BWN_DMA_64BIT) {
4260			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4261			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4262			    >> 30;
4263			value = BWN_DMA64_TXENABLE;
4264			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4265			    & BWN_DMA64_TXADDREXT_MASK;
4266			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4267			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4268			    (ring64 & 0xffffffff));
4269			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4270			    ((ring64 >> 32) &
4271			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4272		} else {
4273			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4274			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4275			value = BWN_DMA32_TXENABLE;
4276			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4277			    & BWN_DMA32_TXADDREXT_MASK;
4278			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4279			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4280			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4281		}
4282		return;
4283	}
4284
4285	/*
4286	 * set for RX
4287	 */
4288	dr->dr_usedslot = dr->dr_numslots;
4289
4290	if (dr->dr_type == BWN_DMA_64BIT) {
4291		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4292		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4293		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4294		value |= BWN_DMA64_RXENABLE;
4295		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4296		    & BWN_DMA64_RXADDREXT_MASK;
4297		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4298		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4299		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4300		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4301		    | (trans << 1));
4302		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4303		    sizeof(struct bwn_dmadesc64));
4304	} else {
4305		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4306		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4307		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4308		value |= BWN_DMA32_RXENABLE;
4309		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4310		    & BWN_DMA32_RXADDREXT_MASK;
4311		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4312		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4313		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4314		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4315		    sizeof(struct bwn_dmadesc32));
4316	}
4317}
4318
4319static void
4320bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4321{
4322
4323	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4324	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4325	    dr->dr_ring_dmap);
4326}
4327
4328static void
4329bwn_dma_cleanup(struct bwn_dma_ring *dr)
4330{
4331
4332	if (dr->dr_tx) {
4333		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4334		if (dr->dr_type == BWN_DMA_64BIT) {
4335			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4336			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4337		} else
4338			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4339	} else {
4340		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4341		if (dr->dr_type == BWN_DMA_64BIT) {
4342			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4343			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4344		} else
4345			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4346	}
4347}
4348
4349static void
4350bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4351{
4352	struct bwn_dmadesc_generic *desc;
4353	struct bwn_dmadesc_meta *meta;
4354	struct bwn_mac *mac = dr->dr_mac;
4355	struct bwn_dma *dma = &mac->mac_method.dma;
4356	struct bwn_softc *sc = mac->mac_sc;
4357	int i;
4358
4359	if (!dr->dr_usedslot)
4360		return;
4361	for (i = 0; i < dr->dr_numslots; i++) {
4362		dr->getdesc(dr, i, &desc, &meta);
4363
4364		if (meta->mt_m == NULL) {
4365			if (!dr->dr_tx)
4366				device_printf(sc->sc_dev, "%s: not TX?\n",
4367				    __func__);
4368			continue;
4369		}
4370		if (dr->dr_tx) {
4371			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4372				bus_dmamap_unload(dr->dr_txring_dtag,
4373				    meta->mt_dmap);
4374			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4375				bus_dmamap_unload(dma->txbuf_dtag,
4376				    meta->mt_dmap);
4377		} else
4378			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4379		bwn_dma_free_descbuf(dr, meta);
4380	}
4381}
4382
4383static int
4384bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4385    int type)
4386{
4387	struct bwn_softc *sc = mac->mac_sc;
4388	uint32_t value;
4389	int i;
4390	uint16_t offset;
4391
4392	for (i = 0; i < 10; i++) {
4393		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4394		    BWN_DMA32_TXSTATUS;
4395		value = BWN_READ_4(mac, base + offset);
4396		if (type == BWN_DMA_64BIT) {
4397			value &= BWN_DMA64_TXSTAT;
4398			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4399			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4400			    value == BWN_DMA64_TXSTAT_STOPPED)
4401				break;
4402		} else {
4403			value &= BWN_DMA32_TXSTATE;
4404			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4405			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4406			    value == BWN_DMA32_TXSTAT_STOPPED)
4407				break;
4408		}
4409		DELAY(1000);
4410	}
4411	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4412	BWN_WRITE_4(mac, base + offset, 0);
4413	for (i = 0; i < 10; i++) {
4414		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4415						   BWN_DMA32_TXSTATUS;
4416		value = BWN_READ_4(mac, base + offset);
4417		if (type == BWN_DMA_64BIT) {
4418			value &= BWN_DMA64_TXSTAT;
4419			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4420				i = -1;
4421				break;
4422			}
4423		} else {
4424			value &= BWN_DMA32_TXSTATE;
4425			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4426				i = -1;
4427				break;
4428			}
4429		}
4430		DELAY(1000);
4431	}
4432	if (i != -1) {
4433		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4434		return (ENODEV);
4435	}
4436	DELAY(1000);
4437
4438	return (0);
4439}
4440
4441static int
4442bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4443    int type)
4444{
4445	struct bwn_softc *sc = mac->mac_sc;
4446	uint32_t value;
4447	int i;
4448	uint16_t offset;
4449
4450	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4451	BWN_WRITE_4(mac, base + offset, 0);
4452	for (i = 0; i < 10; i++) {
4453		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4454		    BWN_DMA32_RXSTATUS;
4455		value = BWN_READ_4(mac, base + offset);
4456		if (type == BWN_DMA_64BIT) {
4457			value &= BWN_DMA64_RXSTAT;
4458			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4459				i = -1;
4460				break;
4461			}
4462		} else {
4463			value &= BWN_DMA32_RXSTATE;
4464			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4465				i = -1;
4466				break;
4467			}
4468		}
4469		DELAY(1000);
4470	}
4471	if (i != -1) {
4472		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4473		return (ENODEV);
4474	}
4475
4476	return (0);
4477}
4478
4479static void
4480bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4481    struct bwn_dmadesc_meta *meta)
4482{
4483
4484	if (meta->mt_m != NULL) {
4485		m_freem(meta->mt_m);
4486		meta->mt_m = NULL;
4487	}
4488	if (meta->mt_ni != NULL) {
4489		ieee80211_free_node(meta->mt_ni);
4490		meta->mt_ni = NULL;
4491	}
4492}
4493
4494static void
4495bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4496{
4497	struct bwn_rxhdr4 *rxhdr;
4498	unsigned char *frame;
4499
4500	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4501	rxhdr->frame_len = 0;
4502
4503	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4504	    sizeof(struct bwn_plcp6) + 2,
4505	    ("%s:%d: fail", __func__, __LINE__));
4506	frame = mtod(m, char *) + dr->dr_frameoffset;
4507	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4508}
4509
4510static uint8_t
4511bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4512{
4513	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4514
4515	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4516	    == 0xff);
4517}
4518
4519static void
4520bwn_wme_init(struct bwn_mac *mac)
4521{
4522
4523	bwn_wme_load(mac);
4524
4525	/* enable WME support. */
4526	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4527	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4528	    BWN_IFSCTL_USE_EDCF);
4529}
4530
4531static void
4532bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4533{
4534	struct bwn_softc *sc = mac->mac_sc;
4535	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4536	uint16_t delay;	/* microsec */
4537
4538	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4539	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4540		delay = 500;
4541	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4542		delay = max(delay, (uint16_t)2400);
4543
4544	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4545}
4546
4547static void
4548bwn_bt_enable(struct bwn_mac *mac)
4549{
4550	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4551	uint64_t hf;
4552
4553	if (bwn_bluetooth == 0)
4554		return;
4555	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4556		return;
4557	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4558		return;
4559
4560	hf = bwn_hf_read(mac);
4561	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4562		hf |= BWN_HF_BT_COEXISTALT;
4563	else
4564		hf |= BWN_HF_BT_COEXIST;
4565	bwn_hf_write(mac, hf);
4566}
4567
4568static void
4569bwn_set_macaddr(struct bwn_mac *mac)
4570{
4571
4572	bwn_mac_write_bssid(mac);
4573	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4574}
4575
4576static void
4577bwn_clear_keys(struct bwn_mac *mac)
4578{
4579	int i;
4580
4581	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4582		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4583		    ("%s:%d: fail", __func__, __LINE__));
4584
4585		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4586		    NULL, BWN_SEC_KEYSIZE, NULL);
4587		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4588			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4589			    NULL, BWN_SEC_KEYSIZE, NULL);
4590		}
4591		mac->mac_key[i].keyconf = NULL;
4592	}
4593}
4594
4595static void
4596bwn_crypt_init(struct bwn_mac *mac)
4597{
4598
4599	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4600	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4601	    ("%s:%d: fail", __func__, __LINE__));
4602	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4603	mac->mac_ktp *= 2;
4604	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4605		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4606		    mac->mac_max_nr_keys - 8);
4607	}
4608	bwn_clear_keys(mac);
4609}
4610
4611static void
4612bwn_chip_exit(struct bwn_mac *mac)
4613{
4614
4615	bwn_phy_exit(mac);
4616	bwn_gpio_cleanup(mac);
4617}
4618
4619static int
4620bwn_fw_fillinfo(struct bwn_mac *mac)
4621{
4622	int error;
4623
4624	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4625	if (error == 0)
4626		return (0);
4627	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4628	if (error == 0)
4629		return (0);
4630	return (error);
4631}
4632
4633static int
4634bwn_gpio_init(struct bwn_mac *mac)
4635{
4636	struct siba_softc *bus = mac->mac_sd->sd_bus;
4637	struct siba_dev_softc *sd;
4638	uint32_t mask = 0x0000001f, set = 0x0000000f;
4639
4640	BWN_WRITE_4(mac, BWN_MACCTL,
4641	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4642	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4643	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4644
4645	if (bus->siba_chipid == 0x4301) {
4646		mask |= 0x0060;
4647		set |= 0x0060;
4648	}
4649	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4650		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4651		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4652		mask |= 0x0200;
4653		set |= 0x0200;
4654	}
4655	if (mac->mac_sd->sd_id.sd_rev >= 2)
4656		mask |= 0x0010;
4657	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4658	    bus->siba_pci.spc_dev;
4659	if (sd == NULL)
4660		return (0);
4661	siba_write_4(sd, BWN_GPIOCTL,
4662	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4663
4664	return (0);
4665}
4666
4667static int
4668bwn_fw_loadinitvals(struct bwn_mac *mac)
4669{
4670#define	GETFWOFFSET(fwp, offset)				\
4671	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4672	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4673	const struct bwn_fwhdr *hdr;
4674	struct bwn_fw *fw = &mac->mac_fw;
4675	int error;
4676
4677	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4678	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4679	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4680	if (error)
4681		return (error);
4682	if (fw->initvals_band.fw) {
4683		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4684		error = bwn_fwinitvals_write(mac,
4685		    GETFWOFFSET(fw->initvals_band, hdr_len),
4686		    be32toh(hdr->size),
4687		    fw->initvals_band.fw->datasize - hdr_len);
4688	}
4689	return (error);
4690#undef GETFWOFFSET
4691}
4692
4693static int
4694bwn_phy_init(struct bwn_mac *mac)
4695{
4696	struct bwn_softc *sc = mac->mac_sc;
4697	int error;
4698
4699	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4700	mac->mac_phy.rf_onoff(mac, 1);
4701	error = mac->mac_phy.init(mac);
4702	if (error) {
4703		device_printf(sc->sc_dev, "PHY init failed\n");
4704		goto fail0;
4705	}
4706	error = bwn_switch_channel(mac,
4707	    mac->mac_phy.get_default_chan(mac));
4708	if (error) {
4709		device_printf(sc->sc_dev,
4710		    "failed to switch default channel\n");
4711		goto fail1;
4712	}
4713	return (0);
4714fail1:
4715	if (mac->mac_phy.exit)
4716		mac->mac_phy.exit(mac);
4717fail0:
4718	mac->mac_phy.rf_onoff(mac, 0);
4719
4720	return (error);
4721}
4722
4723static void
4724bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4725{
4726	uint16_t ant;
4727	uint16_t tmp;
4728
4729	ant = bwn_ant2phy(antenna);
4730
4731	/* For ACK/CTS */
4732	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4733	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4734	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4735	/* For Probe Resposes */
4736	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4737	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4738	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4739}
4740
4741static void
4742bwn_set_opmode(struct bwn_mac *mac)
4743{
4744	struct bwn_softc *sc = mac->mac_sc;
4745	struct ifnet *ifp = sc->sc_ifp;
4746	struct ieee80211com *ic = ifp->if_l2com;
4747	uint32_t ctl;
4748	uint16_t cfp_pretbtt;
4749
4750	ctl = BWN_READ_4(mac, BWN_MACCTL);
4751	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4752	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4753	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4754	ctl |= BWN_MACCTL_STA;
4755
4756	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4757	    ic->ic_opmode == IEEE80211_M_MBSS)
4758		ctl |= BWN_MACCTL_HOSTAP;
4759	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4760		ctl &= ~BWN_MACCTL_STA;
4761	ctl |= sc->sc_filters;
4762
4763	if (mac->mac_sd->sd_id.sd_rev <= 4)
4764		ctl |= BWN_MACCTL_PROMISC;
4765
4766	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4767
4768	cfp_pretbtt = 2;
4769	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4770		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4771		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4772			cfp_pretbtt = 100;
4773		else
4774			cfp_pretbtt = 50;
4775	}
4776	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4777}
4778
4779static void
4780bwn_gpio_cleanup(struct bwn_mac *mac)
4781{
4782	struct siba_softc *bus = mac->mac_sd->sd_bus;
4783	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4784
4785	pcidev = bus->siba_pci.spc_dev;
4786	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4787	if (!gpiodev)
4788		return;
4789	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4790}
4791
4792static int
4793bwn_dma_gettype(struct bwn_mac *mac)
4794{
4795	uint32_t tmp;
4796	uint16_t base;
4797
4798	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4799	if (tmp & SIBA_TGSHIGH_DMA64)
4800		return (BWN_DMA_64BIT);
4801	base = bwn_dma_base(0, 0);
4802	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4803	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4804	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4805		return (BWN_DMA_32BIT);
4806
4807	return (BWN_DMA_30BIT);
4808}
4809
4810static void
4811bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4812{
4813	if (!error) {
4814		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4815		*((bus_addr_t *)arg) = seg->ds_addr;
4816	}
4817}
4818
4819static void
4820bwn_phy_g_init_sub(struct bwn_mac *mac)
4821{
4822	struct bwn_phy *phy = &mac->mac_phy;
4823	struct bwn_phy_g *pg = &phy->phy_g;
4824	uint16_t i, tmp;
4825
4826	if (phy->rev == 1)
4827		bwn_phy_init_b5(mac);
4828	else
4829		bwn_phy_init_b6(mac);
4830
4831	if (phy->rev >= 2 || phy->gmode)
4832		bwn_phy_init_a(mac);
4833
4834	if (phy->rev >= 2) {
4835		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4836		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4837	}
4838	if (phy->rev == 2) {
4839		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4840		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4841	}
4842	if (phy->rev > 5) {
4843		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4844		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4845	}
4846	if (phy->gmode || phy->rev >= 2) {
4847		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4848		tmp &= BWN_PHYVER_VERSION;
4849		if (tmp == 3 || tmp == 5) {
4850			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4851			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4852		}
4853		if (tmp == 5) {
4854			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4855			    0x1f00);
4856		}
4857	}
4858	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4859		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4860	if (phy->rf_rev == 8) {
4861		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4862		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4863	}
4864	if (BWN_HAS_LOOPBACK(phy))
4865		bwn_loopback_calcgain(mac);
4866
4867	if (phy->rf_rev != 8) {
4868		if (pg->pg_initval == 0xffff)
4869			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4870		else
4871			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4872	}
4873	bwn_lo_g_init(mac);
4874	if (BWN_HAS_TXMAG(phy)) {
4875		BWN_RF_WRITE(mac, 0x52,
4876		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4877		    | pg->pg_loctl.tx_bias |
4878		    pg->pg_loctl.tx_magn);
4879	} else {
4880		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4881	}
4882	if (phy->rev >= 6) {
4883		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4884		    (pg->pg_loctl.tx_bias << 12));
4885	}
4886	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4887		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4888	else
4889		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4890	if (phy->rev < 2)
4891		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4892	else
4893		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4894	if (phy->gmode || phy->rev >= 2) {
4895		bwn_lo_g_adjust(mac);
4896		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4897	}
4898
4899	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4900		for (i = 0; i < 64; i++) {
4901			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4902			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4903			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4904			    -32), 31));
4905		}
4906		bwn_nrssi_threshold(mac);
4907	} else if (phy->gmode || phy->rev >= 2) {
4908		if (pg->pg_nrssi[0] == -1000) {
4909			KASSERT(pg->pg_nrssi[1] == -1000,
4910			    ("%s:%d: fail", __func__, __LINE__));
4911			bwn_nrssi_slope_11g(mac);
4912		} else
4913			bwn_nrssi_threshold(mac);
4914	}
4915	if (phy->rf_rev == 8)
4916		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4917	bwn_phy_hwpctl_init(mac);
4918	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4919	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4920		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4921		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4922	}
4923}
4924
4925static uint8_t
4926bwn_has_hwpctl(struct bwn_mac *mac)
4927{
4928
4929	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4930		return (0);
4931	return (mac->mac_phy.use_hwpctl(mac));
4932}
4933
4934static void
4935bwn_phy_init_b5(struct bwn_mac *mac)
4936{
4937	struct siba_softc *bus = mac->mac_sd->sd_bus;
4938	struct bwn_phy *phy = &mac->mac_phy;
4939	struct bwn_phy_g *pg = &phy->phy_g;
4940	uint16_t offset, value;
4941	uint8_t old_channel;
4942
4943	if (phy->analog == 1)
4944		BWN_RF_SET(mac, 0x007a, 0x0050);
4945	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4946	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4947		value = 0x2120;
4948		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4949			BWN_PHY_WRITE(mac, offset, value);
4950			value += 0x202;
4951		}
4952	}
4953	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4954	if (phy->rf_ver == 0x2050)
4955		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4956
4957	if (phy->gmode || phy->rev >= 2) {
4958		if (phy->rf_ver == 0x2050) {
4959			BWN_RF_SET(mac, 0x007a, 0x0020);
4960			BWN_RF_SET(mac, 0x0051, 0x0004);
4961		}
4962		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4963
4964		BWN_PHY_SET(mac, 0x0802, 0x0100);
4965		BWN_PHY_SET(mac, 0x042b, 0x2000);
4966
4967		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4968
4969		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4970		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4971		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4972	}
4973
4974	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4975		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4976
4977	if (phy->analog == 1) {
4978		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4979		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4980		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4981		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4982		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4983	} else
4984		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4985	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4986	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4987
4988	if (phy->analog == 1)
4989		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4990	else
4991		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4992
4993	if (phy->analog == 0)
4994		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4995
4996	old_channel = phy->chan;
4997	bwn_phy_g_switch_chan(mac, 7, 0);
4998
4999	if (phy->rf_ver != 0x2050) {
5000		BWN_RF_WRITE(mac, 0x0075, 0x0080);
5001		BWN_RF_WRITE(mac, 0x0079, 0x0081);
5002	}
5003
5004	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5005	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5006
5007	if (phy->rf_ver == 0x2050) {
5008		BWN_RF_WRITE(mac, 0x0050, 0x0020);
5009		BWN_RF_WRITE(mac, 0x005a, 0x0070);
5010	}
5011
5012	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5013	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5014	BWN_RF_SET(mac, 0x007a, 0x0007);
5015
5016	bwn_phy_g_switch_chan(mac, old_channel, 0);
5017	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5018	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5019	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5020
5021	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5022	    pg->pg_txctl);
5023
5024	if (phy->rf_ver == 0x2050)
5025		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5026
5027	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5028}
5029
5030static void
5031bwn_loopback_calcgain(struct bwn_mac *mac)
5032{
5033	struct bwn_phy *phy = &mac->mac_phy;
5034	struct bwn_phy_g *pg = &phy->phy_g;
5035	uint16_t backup_phy[16] = { 0 };
5036	uint16_t backup_radio[3];
5037	uint16_t backup_bband;
5038	uint16_t i, j, loop_i_max;
5039	uint16_t trsw_rx;
5040	uint16_t loop1_outer_done, loop1_inner_done;
5041
5042	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5043	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5044	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5045	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5046	if (phy->rev != 1) {
5047		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5048		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5049	}
5050	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5051	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5052	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5053	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5054	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5055	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5056	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5057	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5058	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5059	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5060	backup_bband = pg->pg_bbatt.att;
5061	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5062	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5063	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5064
5065	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5066	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5067	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5068	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5069	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5070	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5071	if (phy->rev != 1) {
5072		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5073		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5074		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5075		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5076	}
5077	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5078	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5079	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5080	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5081
5082	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5083	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5084	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5085
5086	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5087	if (phy->rev != 1) {
5088		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5089		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5090	}
5091	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5092
5093	if (phy->rf_rev == 8)
5094		BWN_RF_WRITE(mac, 0x43, 0x000f);
5095	else {
5096		BWN_RF_WRITE(mac, 0x52, 0);
5097		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5098	}
5099	bwn_phy_g_set_bbatt(mac, 11);
5100
5101	if (phy->rev >= 3)
5102		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5103	else
5104		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5105	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5106
5107	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5108	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5109
5110	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5111	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5112
5113	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5114		if (phy->rev >= 7) {
5115			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5116			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5117		}
5118	}
5119	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5120
5121	j = 0;
5122	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5123	for (i = 0; i < loop_i_max; i++) {
5124		for (j = 0; j < 16; j++) {
5125			BWN_RF_WRITE(mac, 0x43, i);
5126			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5127			    (j << 8));
5128			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5129			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5130			DELAY(20);
5131			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5132				goto done0;
5133		}
5134	}
5135done0:
5136	loop1_outer_done = i;
5137	loop1_inner_done = j;
5138	if (j >= 8) {
5139		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5140		trsw_rx = 0x1b;
5141		for (j = j - 8; j < 16; j++) {
5142			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5143			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5144			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5145			DELAY(20);
5146			trsw_rx -= 3;
5147			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5148				goto done1;
5149		}
5150	} else
5151		trsw_rx = 0x18;
5152done1:
5153
5154	if (phy->rev != 1) {
5155		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5156		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5157	}
5158	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5159	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5160	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5161	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5162	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5163	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5164	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5165	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5166	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5167
5168	bwn_phy_g_set_bbatt(mac, backup_bband);
5169
5170	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5171	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5172	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5173
5174	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5175	DELAY(10);
5176	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5177	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5178	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5179	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5180
5181	pg->pg_max_lb_gain =
5182	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5183	pg->pg_trsw_rx_gain = trsw_rx * 2;
5184}
5185
5186static uint16_t
5187bwn_rf_init_bcm2050(struct bwn_mac *mac)
5188{
5189	struct bwn_phy *phy = &mac->mac_phy;
5190	uint32_t tmp1 = 0, tmp2 = 0;
5191	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5192	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5193	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5194	static const uint8_t rcc_table[] = {
5195		0x02, 0x03, 0x01, 0x0f,
5196		0x06, 0x07, 0x05, 0x0f,
5197		0x0a, 0x0b, 0x09, 0x0f,
5198		0x0e, 0x0f, 0x0d, 0x0f,
5199	};
5200
5201	radio0 = BWN_RF_READ(mac, 0x43);
5202	radio1 = BWN_RF_READ(mac, 0x51);
5203	radio2 = BWN_RF_READ(mac, 0x52);
5204	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5205	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5206	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5207	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5208
5209	if (phy->type == BWN_PHYTYPE_B) {
5210		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5211		reg0 = BWN_READ_2(mac, 0x3ec);
5212
5213		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5214		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5215	} else if (phy->gmode || phy->rev >= 2) {
5216		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5217		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5218		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5219		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5220		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5221		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5222
5223		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5224		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5225		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5226		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5227		if (BWN_HAS_LOOPBACK(phy)) {
5228			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5229			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5230			if (phy->rev >= 3)
5231				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5232			else
5233				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5234			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5235		}
5236
5237		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5239			BWN_LPD(0, 1, 1)));
5240		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5241		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5242	}
5243	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5244
5245	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5246	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5247	reg1 = BWN_READ_2(mac, 0x3e6);
5248	reg2 = BWN_READ_2(mac, 0x3f4);
5249
5250	if (phy->analog == 0)
5251		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5252	else {
5253		if (phy->analog >= 2)
5254			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5255		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5256		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5257	}
5258
5259	reg = BWN_RF_READ(mac, 0x60);
5260	index = (reg & 0x001e) >> 1;
5261	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5262
5263	if (phy->type == BWN_PHYTYPE_B)
5264		BWN_RF_WRITE(mac, 0x78, 0x26);
5265	if (phy->gmode || phy->rev >= 2) {
5266		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5267		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5268			BWN_LPD(0, 1, 1)));
5269	}
5270	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5271	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5272	if (phy->gmode || phy->rev >= 2) {
5273		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5274		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5275			BWN_LPD(0, 0, 1)));
5276	}
5277	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5278	BWN_RF_SET(mac, 0x51, 0x0004);
5279	if (phy->rf_rev == 8)
5280		BWN_RF_WRITE(mac, 0x43, 0x1f);
5281	else {
5282		BWN_RF_WRITE(mac, 0x52, 0);
5283		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5284	}
5285	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5286
5287	for (i = 0; i < 16; i++) {
5288		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5289		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5290		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5291		if (phy->gmode || phy->rev >= 2) {
5292			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5293			    bwn_rf_2050_rfoverval(mac,
5294				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5295		}
5296		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5297		DELAY(10);
5298		if (phy->gmode || phy->rev >= 2) {
5299			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5300			    bwn_rf_2050_rfoverval(mac,
5301				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5302		}
5303		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5304		DELAY(10);
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, 0)));
5309		}
5310		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5311		DELAY(20);
5312		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5313		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5314		if (phy->gmode || phy->rev >= 2) {
5315			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5316			    bwn_rf_2050_rfoverval(mac,
5317				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5318		}
5319		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5320	}
5321	DELAY(10);
5322
5323	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5324	tmp1++;
5325	tmp1 >>= 9;
5326
5327	for (i = 0; i < 16; i++) {
5328		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5329		BWN_RF_WRITE(mac, 0x78, radio78);
5330		DELAY(10);
5331		for (j = 0; j < 16; j++) {
5332			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5333			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5334			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5335			if (phy->gmode || phy->rev >= 2) {
5336				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5337				    bwn_rf_2050_rfoverval(mac,
5338					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5339			}
5340			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5341			DELAY(10);
5342			if (phy->gmode || phy->rev >= 2) {
5343				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5344				    bwn_rf_2050_rfoverval(mac,
5345					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5346			}
5347			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5348			DELAY(10);
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, 0)));
5353			}
5354			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5355			DELAY(10);
5356			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5357			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5358			if (phy->gmode || phy->rev >= 2) {
5359				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5360				    bwn_rf_2050_rfoverval(mac,
5361					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5362			}
5363			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5364		}
5365		tmp2++;
5366		tmp2 >>= 8;
5367		if (tmp1 < tmp2)
5368			break;
5369	}
5370
5371	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5372	BWN_RF_WRITE(mac, 0x51, radio1);
5373	BWN_RF_WRITE(mac, 0x52, radio2);
5374	BWN_RF_WRITE(mac, 0x43, radio0);
5375	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5376	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5377	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5378	BWN_WRITE_2(mac, 0x3e6, reg1);
5379	if (phy->analog != 0)
5380		BWN_WRITE_2(mac, 0x3f4, reg2);
5381	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5382	bwn_spu_workaround(mac, phy->chan);
5383	if (phy->type == BWN_PHYTYPE_B) {
5384		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5385		BWN_WRITE_2(mac, 0x3ec, reg0);
5386	} else if (phy->gmode) {
5387		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5388			    BWN_READ_2(mac, BWN_PHY_RADIO)
5389			    & 0x7fff);
5390		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5391		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5392		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5393		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5394			      analogoverval);
5395		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5396		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5397		if (BWN_HAS_LOOPBACK(phy)) {
5398			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5399			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5400		}
5401	}
5402
5403	return ((i > 15) ? radio78 : rcc);
5404}
5405
5406static void
5407bwn_phy_init_b6(struct bwn_mac *mac)
5408{
5409	struct bwn_phy *phy = &mac->mac_phy;
5410	struct bwn_phy_g *pg = &phy->phy_g;
5411	uint16_t offset, val;
5412	uint8_t old_channel;
5413
5414	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5415	    ("%s:%d: fail", __func__, __LINE__));
5416
5417	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5418	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5419	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5420		BWN_RF_WRITE(mac, 0x51, 0x37);
5421		BWN_RF_WRITE(mac, 0x52, 0x70);
5422		BWN_RF_WRITE(mac, 0x53, 0xb3);
5423		BWN_RF_WRITE(mac, 0x54, 0x9b);
5424		BWN_RF_WRITE(mac, 0x5a, 0x88);
5425		BWN_RF_WRITE(mac, 0x5b, 0x88);
5426		BWN_RF_WRITE(mac, 0x5d, 0x88);
5427		BWN_RF_WRITE(mac, 0x5e, 0x88);
5428		BWN_RF_WRITE(mac, 0x7d, 0x88);
5429		bwn_hf_write(mac,
5430		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5431	}
5432	if (phy->rf_rev == 8) {
5433		BWN_RF_WRITE(mac, 0x51, 0);
5434		BWN_RF_WRITE(mac, 0x52, 0x40);
5435		BWN_RF_WRITE(mac, 0x53, 0xb7);
5436		BWN_RF_WRITE(mac, 0x54, 0x98);
5437		BWN_RF_WRITE(mac, 0x5a, 0x88);
5438		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5439		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5440		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5441			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5442			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5443		} else {
5444			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5445			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5446		}
5447		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5448		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5449		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5450		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5451	}
5452	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5453		BWN_PHY_WRITE(mac, offset, val);
5454		val -= 0x0202;
5455	}
5456	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5457		BWN_PHY_WRITE(mac, offset, val);
5458		val -= 0x0202;
5459	}
5460	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5461		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5462		val += 0x0202;
5463	}
5464	if (phy->type == BWN_PHYTYPE_G) {
5465		BWN_RF_SET(mac, 0x007a, 0x0020);
5466		BWN_RF_SET(mac, 0x0051, 0x0004);
5467		BWN_PHY_SET(mac, 0x0802, 0x0100);
5468		BWN_PHY_SET(mac, 0x042b, 0x2000);
5469		BWN_PHY_WRITE(mac, 0x5b, 0);
5470		BWN_PHY_WRITE(mac, 0x5c, 0);
5471	}
5472
5473	old_channel = phy->chan;
5474	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5475
5476	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5477	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5478	DELAY(40);
5479	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5480		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5481		BWN_RF_WRITE(mac, 0x50, 0x20);
5482	}
5483	if (phy->rf_rev <= 2) {
5484		BWN_RF_WRITE(mac, 0x7c, 0x20);
5485		BWN_RF_WRITE(mac, 0x5a, 0x70);
5486		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5487		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5488	}
5489	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5490
5491	bwn_phy_g_switch_chan(mac, old_channel, 0);
5492
5493	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5494	if (phy->rf_rev >= 6)
5495		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5496	else
5497		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5498	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5499	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5500	    pg->pg_txctl);
5501	if (phy->rf_rev <= 5)
5502		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5503	if (phy->rf_rev <= 2)
5504		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5505
5506	if (phy->analog == 4) {
5507		BWN_WRITE_2(mac, 0x3e4, 9);
5508		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5509	} else
5510		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5511	if (phy->type == BWN_PHYTYPE_B)
5512		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5513	else if (phy->type == BWN_PHYTYPE_G)
5514		BWN_WRITE_2(mac, 0x03e6, 0x0);
5515}
5516
5517static void
5518bwn_phy_init_a(struct bwn_mac *mac)
5519{
5520	struct bwn_phy *phy = &mac->mac_phy;
5521
5522	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5523	    ("%s:%d: fail", __func__, __LINE__));
5524
5525	if (phy->rev >= 6) {
5526		if (phy->type == BWN_PHYTYPE_A)
5527			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5528		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5529			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5530		else
5531			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5532	}
5533
5534	bwn_wa_init(mac);
5535
5536	if (phy->type == BWN_PHYTYPE_G &&
5537	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5538		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5539}
5540
5541static void
5542bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5543{
5544	int i;
5545
5546	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5547		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5548}
5549
5550static void
5551bwn_wa_agc(struct bwn_mac *mac)
5552{
5553	struct bwn_phy *phy = &mac->mac_phy;
5554
5555	if (phy->rev == 1) {
5556		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5560		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5561		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5562		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5563		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5564		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5565	} else {
5566		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5567		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5568		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5569		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5570	}
5571
5572	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5573	    0x5700);
5574	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5577	BWN_RF_SET(mac, 0x7a, 0x0008);
5578	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5579	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5582	if (phy->rev == 1)
5583		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5584	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5585	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5586	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5587	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5588	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5589	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5590	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5591	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5592	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5593	if (phy->rev == 1) {
5594		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5595		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5596	} else {
5597		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5598		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5599		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5600		if (phy->rev >= 6) {
5601			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5602			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5603			    (uint16_t)~0xf000, 0x3000);
5604		}
5605	}
5606	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5607	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5608	if (phy->rev == 1) {
5609		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5610		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5611		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5612		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5613		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5614		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5615		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5616		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5617	} else {
5618		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5619		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5620		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5621		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5622	}
5623	if (phy->rev >= 6) {
5624		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5625		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5626	}
5627	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5628}
5629
5630static void
5631bwn_wa_grev1(struct bwn_mac *mac)
5632{
5633	struct bwn_phy *phy = &mac->mac_phy;
5634	int i;
5635	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5636	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5637	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5638
5639	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5640
5641	/* init CRSTHRES and ANTDWELL */
5642	if (phy->rev == 1) {
5643		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5644	} else if (phy->rev == 2) {
5645		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5646		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5647		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5648	} else {
5649		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5650		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5651		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5652		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5653	}
5654	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5655	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5656	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5657
5658	/* XXX support PHY-A??? */
5659	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5660		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5661		    bwn_tab_finefreqg[i]);
5662
5663	/* XXX support PHY-A??? */
5664	if (phy->rev == 1)
5665		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5666			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5667			    bwn_tab_noise_g1[i]);
5668	else
5669		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5670			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5671			    bwn_tab_noise_g2[i]);
5672
5673
5674	for (i = 0; i < N(bwn_tab_rotor); i++)
5675		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5676		    bwn_tab_rotor[i]);
5677
5678	/* XXX support PHY-A??? */
5679	if (phy->rev >= 6) {
5680		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5681		    BWN_PHY_ENCORE_EN)
5682			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5683		else
5684			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5685	} else
5686		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5687
5688	for (i = 0; i < N(bwn_tab_retard); i++)
5689		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5690		    bwn_tab_retard[i]);
5691
5692	if (phy->rev == 1) {
5693		for (i = 0; i < 16; i++)
5694			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5695			    i, 0x0020);
5696	} else {
5697		for (i = 0; i < 32; i++)
5698			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5699	}
5700
5701	bwn_wa_agc(mac);
5702}
5703
5704static void
5705bwn_wa_grev26789(struct bwn_mac *mac)
5706{
5707	struct bwn_phy *phy = &mac->mac_phy;
5708	int i;
5709	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5710	uint16_t ofdmrev;
5711
5712	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5713
5714	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5715
5716	/* init CRSTHRES and ANTDWELL */
5717	if (phy->rev == 1)
5718		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5719	else if (phy->rev == 2) {
5720		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5721		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5722		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5723	} else {
5724		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5725		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5726		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5727		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5728	}
5729
5730	for (i = 0; i < 64; i++)
5731		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5732
5733	/* XXX support PHY-A??? */
5734	if (phy->rev == 1)
5735		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5736			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5737			    bwn_tab_noise_g1[i]);
5738	else
5739		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5740			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5741			    bwn_tab_noise_g2[i]);
5742
5743	/* XXX support PHY-A??? */
5744	if (phy->rev >= 6) {
5745		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5746		    BWN_PHY_ENCORE_EN)
5747			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5748		else
5749			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5750	} else
5751		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5752
5753	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5754		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5755		    bwn_tab_sigmasqr2[i]);
5756
5757	if (phy->rev == 1) {
5758		for (i = 0; i < 16; i++)
5759			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5760			    0x0020);
5761	} else {
5762		for (i = 0; i < 32; i++)
5763			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5764	}
5765
5766	bwn_wa_agc(mac);
5767
5768	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5769	if (ofdmrev > 2) {
5770		if (phy->type == BWN_PHYTYPE_A)
5771			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5772		else
5773			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5774	} else {
5775		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5776		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5777		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5778	}
5779
5780	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5781	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5782}
5783
5784static void
5785bwn_wa_init(struct bwn_mac *mac)
5786{
5787	struct bwn_phy *phy = &mac->mac_phy;
5788	struct siba_softc *bus = mac->mac_sd->sd_bus;
5789
5790	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5791
5792	switch (phy->rev) {
5793	case 1:
5794		bwn_wa_grev1(mac);
5795		break;
5796	case 2:
5797	case 6:
5798	case 7:
5799	case 8:
5800	case 9:
5801		bwn_wa_grev26789(mac);
5802		break;
5803	default:
5804		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5805	}
5806
5807	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5808	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5809	    bus->siba_board_rev != 0x17) {
5810		if (phy->rev < 2) {
5811			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5812			    0x0002);
5813			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5814			    0x0001);
5815		} else {
5816			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5817			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5818			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5819			    (phy->rev >= 7)) {
5820				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5821				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5822				    0x0020, 0x0001);
5823				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5824				    0x0021, 0x0001);
5825				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5826				    0x0022, 0x0001);
5827				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5828				    0x0023, 0x0000);
5829				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5830				    0x0000, 0x0000);
5831				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5832				    0x0003, 0x0002);
5833			}
5834		}
5835	}
5836	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5837		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5838		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5839	}
5840
5841	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5842	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5843}
5844
5845static void
5846bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5847    uint16_t value)
5848{
5849	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5850	uint16_t addr;
5851
5852	addr = table + offset;
5853	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5854	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5855		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5856		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5857	}
5858	pg->pg_ofdmtab_addr = addr;
5859	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5860}
5861
5862static void
5863bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5864    uint32_t value)
5865{
5866	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5867	uint16_t addr;
5868
5869	addr = table + offset;
5870	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5871	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5872		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5873		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5874	}
5875	pg->pg_ofdmtab_addr = addr;
5876
5877	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5878	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5879}
5880
5881static void
5882bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5883    uint16_t value)
5884{
5885
5886	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5887	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5888}
5889
5890static void
5891bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5892{
5893	struct bwn_phy *phy = &mac->mac_phy;
5894	struct bwn_softc *sc = mac->mac_sc;
5895	unsigned int i, max_loop;
5896	uint16_t value;
5897	uint32_t buffer[5] = {
5898		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5899	};
5900
5901	if (ofdm) {
5902		max_loop = 0x1e;
5903		buffer[0] = 0x000201cc;
5904	} else {
5905		max_loop = 0xfa;
5906		buffer[0] = 0x000b846e;
5907	}
5908
5909	BWN_ASSERT_LOCKED(sc);
5910
5911	for (i = 0; i < 5; i++)
5912		bwn_ram_write(mac, i * 4, buffer[i]);
5913
5914	BWN_WRITE_2(mac, 0x0568, 0x0000);
5915	BWN_WRITE_2(mac, 0x07c0,
5916	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5917	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5918	BWN_WRITE_2(mac, 0x050c, value);
5919	if (phy->type == BWN_PHYTYPE_LP)
5920		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5921	BWN_WRITE_2(mac, 0x0508, 0x0000);
5922	BWN_WRITE_2(mac, 0x050a, 0x0000);
5923	BWN_WRITE_2(mac, 0x054c, 0x0000);
5924	BWN_WRITE_2(mac, 0x056a, 0x0014);
5925	BWN_WRITE_2(mac, 0x0568, 0x0826);
5926	BWN_WRITE_2(mac, 0x0500, 0x0000);
5927	if (phy->type == BWN_PHYTYPE_LP)
5928		BWN_WRITE_2(mac, 0x0502, 0x0050);
5929	else
5930		BWN_WRITE_2(mac, 0x0502, 0x0030);
5931
5932	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5933		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5934	for (i = 0x00; i < max_loop; i++) {
5935		value = BWN_READ_2(mac, 0x050e);
5936		if (value & 0x0080)
5937			break;
5938		DELAY(10);
5939	}
5940	for (i = 0x00; i < 0x0a; i++) {
5941		value = BWN_READ_2(mac, 0x050e);
5942		if (value & 0x0400)
5943			break;
5944		DELAY(10);
5945	}
5946	for (i = 0x00; i < 0x19; i++) {
5947		value = BWN_READ_2(mac, 0x0690);
5948		if (!(value & 0x0100))
5949			break;
5950		DELAY(10);
5951	}
5952	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5953		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5954}
5955
5956static void
5957bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5958{
5959	uint32_t macctl;
5960
5961	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5962
5963	macctl = BWN_READ_4(mac, BWN_MACCTL);
5964	if (macctl & BWN_MACCTL_BIGENDIAN)
5965		printf("TODO: need swap\n");
5966
5967	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5968	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5969	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5970}
5971
5972static void
5973bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5974{
5975	struct bwn_phy *phy = &mac->mac_phy;
5976	uint16_t value;
5977
5978	KASSERT(phy->type == BWN_PHYTYPE_G,
5979	    ("%s:%d: fail", __func__, __LINE__));
5980
5981	value = (uint8_t) (ctl->q);
5982	value |= ((uint8_t) (ctl->i)) << 8;
5983	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5984}
5985
5986static uint16_t
5987bwn_lo_calcfeed(struct bwn_mac *mac,
5988    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5989{
5990	struct bwn_phy *phy = &mac->mac_phy;
5991	uint16_t rfover;
5992	uint16_t feedthrough;
5993
5994	if (phy->gmode) {
5995		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5996		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5997
5998		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5999		    ("%s:%d: fail", __func__, __LINE__));
6000		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
6001		    ("%s:%d: fail", __func__, __LINE__));
6002
6003		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
6004
6005		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
6006		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
6007		    && phy->rev > 6)
6008			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
6009
6010		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6011		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6012		DELAY(10);
6013		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6014		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6015		DELAY(10);
6016		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6017		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6018		DELAY(10);
6019		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6020	} else {
6021		pga |= BWN_PHY_PGACTL_UNKNOWN;
6022		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6023		DELAY(10);
6024		pga |= BWN_PHY_PGACTL_LOWBANDW;
6025		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6026		DELAY(10);
6027		pga |= BWN_PHY_PGACTL_LPF;
6028		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6029	}
6030	DELAY(21);
6031	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6032
6033	return (feedthrough);
6034}
6035
6036static uint16_t
6037bwn_lo_txctl_regtable(struct bwn_mac *mac,
6038    uint16_t *value, uint16_t *pad_mix_gain)
6039{
6040	struct bwn_phy *phy = &mac->mac_phy;
6041	uint16_t reg, v, padmix;
6042
6043	if (phy->type == BWN_PHYTYPE_B) {
6044		v = 0x30;
6045		if (phy->rf_rev <= 5) {
6046			reg = 0x43;
6047			padmix = 0;
6048		} else {
6049			reg = 0x52;
6050			padmix = 5;
6051		}
6052	} else {
6053		if (phy->rev >= 2 && phy->rf_rev == 8) {
6054			reg = 0x43;
6055			v = 0x10;
6056			padmix = 2;
6057		} else {
6058			reg = 0x52;
6059			v = 0x30;
6060			padmix = 5;
6061		}
6062	}
6063	if (value)
6064		*value = v;
6065	if (pad_mix_gain)
6066		*pad_mix_gain = padmix;
6067
6068	return (reg);
6069}
6070
6071static void
6072bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6073{
6074	struct bwn_phy *phy = &mac->mac_phy;
6075	struct bwn_phy_g *pg = &phy->phy_g;
6076	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6077	uint16_t reg, mask;
6078	uint16_t trsw_rx, pga;
6079	uint16_t rf_pctl_reg;
6080
6081	static const uint8_t tx_bias_values[] = {
6082		0x09, 0x08, 0x0a, 0x01, 0x00,
6083		0x02, 0x05, 0x04, 0x06,
6084	};
6085	static const uint8_t tx_magn_values[] = {
6086		0x70, 0x40,
6087	};
6088
6089	if (!BWN_HAS_LOOPBACK(phy)) {
6090		rf_pctl_reg = 6;
6091		trsw_rx = 2;
6092		pga = 0;
6093	} else {
6094		int lb_gain;
6095
6096		trsw_rx = 0;
6097		lb_gain = pg->pg_max_lb_gain / 2;
6098		if (lb_gain > 10) {
6099			rf_pctl_reg = 0;
6100			pga = abs(10 - lb_gain) / 6;
6101			pga = MIN(MAX(pga, 0), 15);
6102		} else {
6103			int cmp_val;
6104			int tmp;
6105
6106			pga = 0;
6107			cmp_val = 0x24;
6108			if ((phy->rev >= 2) &&
6109			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6110				cmp_val = 0x3c;
6111			tmp = lb_gain;
6112			if ((10 - lb_gain) < cmp_val)
6113				tmp = (10 - lb_gain);
6114			if (tmp < 0)
6115				tmp += 6;
6116			else
6117				tmp += 3;
6118			cmp_val /= 4;
6119			tmp /= 4;
6120			if (tmp >= cmp_val)
6121				rf_pctl_reg = cmp_val;
6122			else
6123				rf_pctl_reg = tmp;
6124		}
6125	}
6126	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6127	bwn_phy_g_set_bbatt(mac, 2);
6128
6129	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6130	mask = ~mask;
6131	BWN_RF_MASK(mac, reg, mask);
6132
6133	if (BWN_HAS_TXMAG(phy)) {
6134		int i, j;
6135		int feedthrough;
6136		int min_feedth = 0xffff;
6137		uint8_t tx_magn, tx_bias;
6138
6139		for (i = 0; i < N(tx_magn_values); i++) {
6140			tx_magn = tx_magn_values[i];
6141			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6142			for (j = 0; j < N(tx_bias_values); j++) {
6143				tx_bias = tx_bias_values[j];
6144				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6145				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6146				    trsw_rx);
6147				if (feedthrough < min_feedth) {
6148					lo->tx_bias = tx_bias;
6149					lo->tx_magn = tx_magn;
6150					min_feedth = feedthrough;
6151				}
6152				if (lo->tx_bias == 0)
6153					break;
6154			}
6155			BWN_RF_WRITE(mac, 0x52,
6156					  (BWN_RF_READ(mac, 0x52)
6157					   & 0xff00) | lo->tx_bias | lo->
6158					  tx_magn);
6159		}
6160	} else {
6161		lo->tx_magn = 0;
6162		lo->tx_bias = 0;
6163		BWN_RF_MASK(mac, 0x52, 0xfff0);
6164	}
6165
6166	BWN_GETTIME(lo->txctl_measured_time);
6167}
6168
6169static void
6170bwn_lo_get_powervector(struct bwn_mac *mac)
6171{
6172	struct bwn_phy *phy = &mac->mac_phy;
6173	struct bwn_phy_g *pg = &phy->phy_g;
6174	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6175	int i;
6176	uint64_t tmp;
6177	uint64_t power_vector = 0;
6178
6179	for (i = 0; i < 8; i += 2) {
6180		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6181		power_vector |= (tmp << (i * 8));
6182		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6183	}
6184	if (power_vector)
6185		lo->power_vector = power_vector;
6186
6187	BWN_GETTIME(lo->pwr_vec_read_time);
6188}
6189
6190static void
6191bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6192    int use_trsw_rx)
6193{
6194	struct bwn_phy *phy = &mac->mac_phy;
6195	struct bwn_phy_g *pg = &phy->phy_g;
6196	uint16_t tmp;
6197
6198	if (max_rx_gain < 0)
6199		max_rx_gain = 0;
6200
6201	if (BWN_HAS_LOOPBACK(phy)) {
6202		int trsw_rx = 0;
6203		int trsw_rx_gain;
6204
6205		if (use_trsw_rx) {
6206			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6207			if (max_rx_gain >= trsw_rx_gain) {
6208				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6209				trsw_rx = 0x20;
6210			}
6211		} else
6212			trsw_rx_gain = max_rx_gain;
6213		if (trsw_rx_gain < 9) {
6214			pg->pg_lna_lod_gain = 0;
6215		} else {
6216			pg->pg_lna_lod_gain = 1;
6217			trsw_rx_gain -= 8;
6218		}
6219		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6220		pg->pg_pga_gain = trsw_rx_gain / 3;
6221		if (pg->pg_pga_gain >= 5) {
6222			pg->pg_pga_gain -= 5;
6223			pg->pg_lna_gain = 2;
6224		} else
6225			pg->pg_lna_gain = 0;
6226	} else {
6227		pg->pg_lna_gain = 0;
6228		pg->pg_trsw_rx_gain = 0x20;
6229		if (max_rx_gain >= 0x14) {
6230			pg->pg_lna_lod_gain = 1;
6231			pg->pg_pga_gain = 2;
6232		} else if (max_rx_gain >= 0x12) {
6233			pg->pg_lna_lod_gain = 1;
6234			pg->pg_pga_gain = 1;
6235		} else if (max_rx_gain >= 0xf) {
6236			pg->pg_lna_lod_gain = 1;
6237			pg->pg_pga_gain = 0;
6238		} else {
6239			pg->pg_lna_lod_gain = 0;
6240			pg->pg_pga_gain = 0;
6241		}
6242	}
6243
6244	tmp = BWN_RF_READ(mac, 0x7a);
6245	if (pg->pg_lna_lod_gain == 0)
6246		tmp &= ~0x0008;
6247	else
6248		tmp |= 0x0008;
6249	BWN_RF_WRITE(mac, 0x7a, tmp);
6250}
6251
6252static void
6253bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6254{
6255	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6256	struct bwn_phy *phy = &mac->mac_phy;
6257	struct bwn_phy_g *pg = &phy->phy_g;
6258	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6259	struct timespec ts;
6260	uint16_t tmp;
6261
6262	if (bwn_has_hwpctl(mac)) {
6263		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6264		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6265		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6266		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6267		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6268
6269		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6270		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6271		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6272		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6273	}
6274	if (phy->type == BWN_PHYTYPE_B &&
6275	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6276		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6277		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6278	}
6279	if (phy->rev >= 2) {
6280		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6281		sav->phy_analogoverval =
6282		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6283		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6284		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6285		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6286		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6287		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6288
6289		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6290		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6291		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6292		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6293		if (phy->type == BWN_PHYTYPE_G) {
6294			if ((phy->rev >= 7) &&
6295			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6296				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6297			} else {
6298				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6299			}
6300		} else {
6301			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6302		}
6303		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6304	}
6305	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6306	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6307	sav->rf0 = BWN_RF_READ(mac, 0x43);
6308	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6309	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6310	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6311	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6312	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6313
6314	if (!BWN_HAS_TXMAG(phy)) {
6315		sav->rf2 = BWN_RF_READ(mac, 0x52);
6316		sav->rf2 &= 0x00f0;
6317	}
6318	if (phy->type == BWN_PHYTYPE_B) {
6319		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6320		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6321		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6322		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6323	} else {
6324		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6325			    | 0x8000);
6326	}
6327	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6328		    & 0xf000);
6329
6330	tmp =
6331	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6332	BWN_PHY_WRITE(mac, tmp, 0x007f);
6333
6334	tmp = sav->phy_syncctl;
6335	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6336	tmp = sav->rf1;
6337	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6338
6339	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6340	if (phy->type == BWN_PHYTYPE_G ||
6341	    (phy->type == BWN_PHYTYPE_B &&
6342	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6343		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6344	} else
6345		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6346	if (phy->rev >= 2)
6347		bwn_dummy_transmission(mac, 0, 1);
6348	bwn_phy_g_switch_chan(mac, 6, 0);
6349	BWN_RF_READ(mac, 0x51);
6350	if (phy->type == BWN_PHYTYPE_G)
6351		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6352
6353	nanouptime(&ts);
6354	if (time_before(lo->txctl_measured_time,
6355	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6356		bwn_lo_measure_txctl_values(mac);
6357
6358	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6359		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6360	else {
6361		if (phy->type == BWN_PHYTYPE_B)
6362			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6363		else
6364			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6365	}
6366}
6367
6368static void
6369bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6370{
6371	struct bwn_phy *phy = &mac->mac_phy;
6372	struct bwn_phy_g *pg = &phy->phy_g;
6373	uint16_t tmp;
6374
6375	if (phy->rev >= 2) {
6376		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6377		tmp = (pg->pg_pga_gain << 8);
6378		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6379		DELAY(5);
6380		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6381		DELAY(2);
6382		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6383	} else {
6384		tmp = (pg->pg_pga_gain | 0xefa0);
6385		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6386	}
6387	if (phy->type == BWN_PHYTYPE_G) {
6388		if (phy->rev >= 3)
6389			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6390		else
6391			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6392		if (phy->rev >= 2)
6393			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6394		else
6395			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6396	}
6397	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6398	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6399	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6400	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6401	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6402	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6403	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6404	if (!BWN_HAS_TXMAG(phy)) {
6405		tmp = sav->rf2;
6406		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6407	}
6408	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6409	if (phy->type == BWN_PHYTYPE_B &&
6410	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6411		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6412		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6413	}
6414	if (phy->rev >= 2) {
6415		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6416		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6417			      sav->phy_analogoverval);
6418		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6419		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6420		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6421		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6422		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6423	}
6424	if (bwn_has_hwpctl(mac)) {
6425		tmp = (sav->phy_lomask & 0xbfff);
6426		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6427		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6428		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6429		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6430		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6431	}
6432	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6433}
6434
6435static int
6436bwn_lo_probe_loctl(struct bwn_mac *mac,
6437    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6438{
6439	struct bwn_phy *phy = &mac->mac_phy;
6440	struct bwn_phy_g *pg = &phy->phy_g;
6441	struct bwn_loctl orig, test;
6442	struct bwn_loctl prev = { -100, -100 };
6443	static const struct bwn_loctl modifiers[] = {
6444		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6445		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6446	};
6447	int begin, end, lower = 0, i;
6448	uint16_t feedth;
6449
6450	if (d->curstate == 0) {
6451		begin = 1;
6452		end = 8;
6453	} else if (d->curstate % 2 == 0) {
6454		begin = d->curstate - 1;
6455		end = d->curstate + 1;
6456	} else {
6457		begin = d->curstate - 2;
6458		end = d->curstate + 2;
6459	}
6460	if (begin < 1)
6461		begin += 8;
6462	if (end > 8)
6463		end -= 8;
6464
6465	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6466	i = begin;
6467	d->curstate = i;
6468	while (1) {
6469		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6470		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6471		test.i += modifiers[i - 1].i * d->multipler;
6472		test.q += modifiers[i - 1].q * d->multipler;
6473		if ((test.i != prev.i || test.q != prev.q) &&
6474		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6475			bwn_lo_write(mac, &test);
6476			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6477			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6478			if (feedth < d->feedth) {
6479				memcpy(probe, &test,
6480				    sizeof(struct bwn_loctl));
6481				lower = 1;
6482				d->feedth = feedth;
6483				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6484					break;
6485			}
6486		}
6487		memcpy(&prev, &test, sizeof(prev));
6488		if (i == end)
6489			break;
6490		if (i == 8)
6491			i = 1;
6492		else
6493			i++;
6494		d->curstate = i;
6495	}
6496
6497	return (lower);
6498}
6499
6500static void
6501bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6502{
6503	struct bwn_phy *phy = &mac->mac_phy;
6504	struct bwn_phy_g *pg = &phy->phy_g;
6505	struct bwn_lo_g_sm d;
6506	struct bwn_loctl probe;
6507	int lower, repeat, cnt = 0;
6508	uint16_t feedth;
6509
6510	d.nmeasure = 0;
6511	d.multipler = 1;
6512	if (BWN_HAS_LOOPBACK(phy))
6513		d.multipler = 3;
6514
6515	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6516	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6517
6518	do {
6519		bwn_lo_write(mac, &d.loctl);
6520		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6521		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6522		if (feedth < 0x258) {
6523			if (feedth >= 0x12c)
6524				*rxgain += 6;
6525			else
6526				*rxgain += 3;
6527			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6528			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6529		}
6530		d.feedth = feedth;
6531		d.curstate = 0;
6532		do {
6533			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6534			    ("%s:%d: fail", __func__, __LINE__));
6535			memcpy(&probe, &d.loctl,
6536			       sizeof(struct bwn_loctl));
6537			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6538			if (!lower)
6539				break;
6540			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6541				break;
6542			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6543			d.nmeasure++;
6544		} while (d.nmeasure < 24);
6545		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6546
6547		if (BWN_HAS_LOOPBACK(phy)) {
6548			if (d.feedth > 0x1194)
6549				*rxgain -= 6;
6550			else if (d.feedth < 0x5dc)
6551				*rxgain += 3;
6552			if (cnt == 0) {
6553				if (d.feedth <= 0x5dc) {
6554					d.multipler = 1;
6555					cnt++;
6556				} else
6557					d.multipler = 2;
6558			} else if (cnt == 2)
6559				d.multipler = 1;
6560		}
6561		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6562	} while (++cnt < repeat);
6563}
6564
6565static struct bwn_lo_calib *
6566bwn_lo_calibset(struct bwn_mac *mac,
6567    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6568{
6569	struct bwn_phy *phy = &mac->mac_phy;
6570	struct bwn_phy_g *pg = &phy->phy_g;
6571	struct bwn_loctl loctl = { 0, 0 };
6572	struct bwn_lo_calib *cal;
6573	struct bwn_lo_g_value sval;
6574	int rxgain;
6575	uint16_t pad, reg, value;
6576
6577	sval.old_channel = phy->chan;
6578	bwn_mac_suspend(mac);
6579	bwn_lo_save(mac, &sval);
6580
6581	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6582	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6583	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6584
6585	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6586	if (rfatt->padmix)
6587		rxgain -= pad;
6588	if (BWN_HAS_LOOPBACK(phy))
6589		rxgain += pg->pg_max_lb_gain;
6590	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6591	bwn_phy_g_set_bbatt(mac, bbatt->att);
6592	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6593
6594	bwn_lo_restore(mac, &sval);
6595	bwn_mac_enable(mac);
6596
6597	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6598	if (!cal) {
6599		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6600		return (NULL);
6601	}
6602	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6603	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6604	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6605
6606	BWN_GETTIME(cal->calib_time);
6607
6608	return (cal);
6609}
6610
6611static struct bwn_lo_calib *
6612bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6613    const struct bwn_rfatt *rfatt)
6614{
6615	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6616	struct bwn_lo_calib *c;
6617
6618	TAILQ_FOREACH(c, &lo->calib_list, list) {
6619		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6620			continue;
6621		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6622			continue;
6623		return (c);
6624	}
6625
6626	c = bwn_lo_calibset(mac, bbatt, rfatt);
6627	if (!c)
6628		return (NULL);
6629	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6630
6631	return (c);
6632}
6633
6634static void
6635bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6636{
6637	struct bwn_phy *phy = &mac->mac_phy;
6638	struct bwn_phy_g *pg = &phy->phy_g;
6639	struct bwn_softc *sc = mac->mac_sc;
6640	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6641	const struct bwn_rfatt *rfatt;
6642	const struct bwn_bbatt *bbatt;
6643	uint64_t pvector;
6644	int i;
6645	int rf_offset, bb_offset;
6646	uint8_t changed = 0;
6647
6648	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6649	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6650	    ("%s:%d: fail", __func__, __LINE__));
6651
6652	pvector = lo->power_vector;
6653	if (!update && !pvector)
6654		return;
6655
6656	bwn_mac_suspend(mac);
6657
6658	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6659		struct bwn_lo_calib *cal;
6660		int idx;
6661		uint16_t val;
6662
6663		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6664			continue;
6665		bb_offset = i / lo->rfatt.len;
6666		rf_offset = i % lo->rfatt.len;
6667		bbatt = &(lo->bbatt.array[bb_offset]);
6668		rfatt = &(lo->rfatt.array[rf_offset]);
6669
6670		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6671		if (!cal) {
6672			device_printf(sc->sc_dev, "LO: Could not "
6673			    "calibrate DC table entry\n");
6674			continue;
6675		}
6676		val = (uint8_t)(cal->ctl.q);
6677		val |= ((uint8_t)(cal->ctl.i)) << 4;
6678		free(cal, M_DEVBUF);
6679
6680		idx = i / 2;
6681		if (i % 2)
6682			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6683			    | ((val & 0x00ff) << 8);
6684		else
6685			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6686			    | (val & 0x00ff);
6687		changed = 1;
6688	}
6689	if (changed) {
6690		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6691			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6692	}
6693	bwn_mac_enable(mac);
6694}
6695
6696static void
6697bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6698{
6699
6700	if (!rf->padmix)
6701		return;
6702	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6703		rf->att = 4;
6704}
6705
6706static void
6707bwn_lo_g_adjust(struct bwn_mac *mac)
6708{
6709	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6710	struct bwn_lo_calib *cal;
6711	struct bwn_rfatt rf;
6712
6713	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6714	bwn_lo_fixup_rfatt(&rf);
6715
6716	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6717	if (!cal)
6718		return;
6719	bwn_lo_write(mac, &cal->ctl);
6720}
6721
6722static void
6723bwn_lo_g_init(struct bwn_mac *mac)
6724{
6725
6726	if (!bwn_has_hwpctl(mac))
6727		return;
6728
6729	bwn_lo_get_powervector(mac);
6730	bwn_phy_g_dc_lookup_init(mac, 1);
6731}
6732
6733static void
6734bwn_mac_suspend(struct bwn_mac *mac)
6735{
6736	struct bwn_softc *sc = mac->mac_sc;
6737	int i;
6738	uint32_t tmp;
6739
6740	KASSERT(mac->mac_suspended >= 0,
6741	    ("%s:%d: fail", __func__, __LINE__));
6742
6743	if (mac->mac_suspended == 0) {
6744		bwn_psctl(mac, BWN_PS_AWAKE);
6745		BWN_WRITE_4(mac, BWN_MACCTL,
6746			    BWN_READ_4(mac, BWN_MACCTL)
6747			    & ~BWN_MACCTL_ON);
6748		BWN_READ_4(mac, BWN_MACCTL);
6749		for (i = 35; i; i--) {
6750			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6751			if (tmp & BWN_INTR_MAC_SUSPENDED)
6752				goto out;
6753			DELAY(10);
6754		}
6755		for (i = 40; i; i--) {
6756			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6757			if (tmp & BWN_INTR_MAC_SUSPENDED)
6758				goto out;
6759			DELAY(1000);
6760		}
6761		device_printf(sc->sc_dev, "MAC suspend failed\n");
6762	}
6763out:
6764	mac->mac_suspended++;
6765}
6766
6767static void
6768bwn_mac_enable(struct bwn_mac *mac)
6769{
6770	struct bwn_softc *sc = mac->mac_sc;
6771	uint16_t state;
6772
6773	state = bwn_shm_read_2(mac, BWN_SHARED,
6774	    BWN_SHARED_UCODESTAT);
6775	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6776	    state != BWN_SHARED_UCODESTAT_SLEEP)
6777		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6778
6779	mac->mac_suspended--;
6780	KASSERT(mac->mac_suspended >= 0,
6781	    ("%s:%d: fail", __func__, __LINE__));
6782	if (mac->mac_suspended == 0) {
6783		BWN_WRITE_4(mac, BWN_MACCTL,
6784		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6785		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6786		BWN_READ_4(mac, BWN_MACCTL);
6787		BWN_READ_4(mac, BWN_INTR_REASON);
6788		bwn_psctl(mac, 0);
6789	}
6790}
6791
6792static void
6793bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6794{
6795	int i;
6796	uint16_t ucstat;
6797
6798	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6799	    ("%s:%d: fail", __func__, __LINE__));
6800	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6801	    ("%s:%d: fail", __func__, __LINE__));
6802
6803	/* XXX forcibly awake and hwps-off */
6804
6805	BWN_WRITE_4(mac, BWN_MACCTL,
6806	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6807	    ~BWN_MACCTL_HWPS);
6808	BWN_READ_4(mac, BWN_MACCTL);
6809	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6810		for (i = 0; i < 100; i++) {
6811			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6812			    BWN_SHARED_UCODESTAT);
6813			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6814				break;
6815			DELAY(10);
6816		}
6817	}
6818}
6819
6820static int16_t
6821bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6822{
6823
6824	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6825	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6826}
6827
6828static void
6829bwn_nrssi_threshold(struct bwn_mac *mac)
6830{
6831	struct bwn_phy *phy = &mac->mac_phy;
6832	struct bwn_phy_g *pg = &phy->phy_g;
6833	struct siba_softc *siba = mac->mac_sd->sd_bus;
6834	int32_t a, b;
6835	int16_t tmp16;
6836	uint16_t tmpu16;
6837
6838	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6839
6840	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6841		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6842			a = 0x13;
6843			b = 0x12;
6844		} else {
6845			a = 0xe;
6846			b = 0x11;
6847		}
6848
6849		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6850		a += (pg->pg_nrssi[0] << 6);
6851		a += (a < 32) ? 31 : 32;
6852		a = a >> 6;
6853		a = MIN(MAX(a, -31), 31);
6854
6855		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6856		b += (pg->pg_nrssi[0] << 6);
6857		if (b < 32)
6858			b += 31;
6859		else
6860			b += 32;
6861		b = b >> 6;
6862		b = MIN(MAX(b, -31), 31);
6863
6864		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6865		tmpu16 |= ((uint32_t)b & 0x0000003f);
6866		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6867		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6868		return;
6869	}
6870
6871	tmp16 = bwn_nrssi_read(mac, 0x20);
6872	if (tmp16 >= 0x20)
6873		tmp16 -= 0x40;
6874	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6875}
6876
6877static void
6878bwn_nrssi_slope_11g(struct bwn_mac *mac)
6879{
6880#define	SAVE_RF_MAX		3
6881#define	SAVE_PHY_COMM_MAX	4
6882#define	SAVE_PHY3_MAX		8
6883	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6884		{ 0x7a, 0x52, 0x43 };
6885	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6886		{ 0x15, 0x5a, 0x59, 0x58 };
6887	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6888		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6889		0x0801, 0x0060, 0x0014, 0x0478
6890	};
6891	struct bwn_phy *phy = &mac->mac_phy;
6892	struct bwn_phy_g *pg = &phy->phy_g;
6893	int32_t i, tmp32, phy3_idx = 0;
6894	uint16_t delta, tmp;
6895	uint16_t save_rf[SAVE_RF_MAX];
6896	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6897	uint16_t save_phy3[SAVE_PHY3_MAX];
6898	uint16_t ant_div, phy0, chan_ex;
6899	int16_t nrssi0, nrssi1;
6900
6901	KASSERT(phy->type == BWN_PHYTYPE_G,
6902	    ("%s:%d: fail", __func__, __LINE__));
6903
6904	if (phy->rf_rev >= 9)
6905		return;
6906	if (phy->rf_rev == 8)
6907		bwn_nrssi_offset(mac);
6908
6909	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6910	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6911
6912	/*
6913	 * Save RF/PHY registers for later restoration
6914	 */
6915	ant_div = BWN_READ_2(mac, 0x03e2);
6916	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6917	for (i = 0; i < SAVE_RF_MAX; ++i)
6918		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6919	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6920		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6921
6922	phy0 = BWN_READ_2(mac, BWN_PHY0);
6923	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6924	if (phy->rev >= 3) {
6925		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6926			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6927		BWN_PHY_WRITE(mac, 0x002e, 0);
6928		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6929		switch (phy->rev) {
6930		case 4:
6931		case 6:
6932		case 7:
6933			BWN_PHY_SET(mac, 0x0478, 0x0100);
6934			BWN_PHY_SET(mac, 0x0801, 0x0040);
6935			break;
6936		case 3:
6937		case 5:
6938			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6939			break;
6940		}
6941		BWN_PHY_SET(mac, 0x0060, 0x0040);
6942		BWN_PHY_SET(mac, 0x0014, 0x0200);
6943	}
6944	/*
6945	 * Calculate nrssi0
6946	 */
6947	BWN_RF_SET(mac, 0x007a, 0x0070);
6948	bwn_set_all_gains(mac, 0, 8, 0);
6949	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6950	if (phy->rev >= 2) {
6951		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6952		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6953	}
6954	BWN_RF_SET(mac, 0x007a, 0x0080);
6955	DELAY(20);
6956
6957	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6958	if (nrssi0 >= 0x0020)
6959		nrssi0 -= 0x0040;
6960
6961	/*
6962	 * Calculate nrssi1
6963	 */
6964	BWN_RF_MASK(mac, 0x007a, 0x007f);
6965	if (phy->rev >= 2)
6966		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6967
6968	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6969	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6970	BWN_RF_SET(mac, 0x007a, 0x000f);
6971	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6972	if (phy->rev >= 2) {
6973		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6974		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6975	}
6976
6977	bwn_set_all_gains(mac, 3, 0, 1);
6978	if (phy->rf_rev == 8) {
6979		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6980	} else {
6981		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6982		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6983		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6984		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6985	}
6986	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6987	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6988	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6989	DELAY(20);
6990	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6991
6992	/*
6993	 * Install calculated narrow RSSI values
6994	 */
6995	if (nrssi1 >= 0x0020)
6996		nrssi1 -= 0x0040;
6997	if (nrssi0 == nrssi1)
6998		pg->pg_nrssi_slope = 0x00010000;
6999	else
7000		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
7001	if (nrssi0 >= -4) {
7002		pg->pg_nrssi[0] = nrssi1;
7003		pg->pg_nrssi[1] = nrssi0;
7004	}
7005
7006	/*
7007	 * Restore saved RF/PHY registers
7008	 */
7009	if (phy->rev >= 3) {
7010		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7011			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7012			    save_phy3[phy3_idx]);
7013		}
7014	}
7015	if (phy->rev >= 2) {
7016		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7017		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7018	}
7019
7020	for (i = 0; i < SAVE_RF_MAX; ++i)
7021		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7022
7023	BWN_WRITE_2(mac, 0x03e2, ant_div);
7024	BWN_WRITE_2(mac, 0x03e6, phy0);
7025	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7026
7027	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7028		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7029
7030	bwn_spu_workaround(mac, phy->chan);
7031	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7032	bwn_set_original_gains(mac);
7033	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7034	if (phy->rev >= 3) {
7035		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7036			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7037			    save_phy3[phy3_idx]);
7038		}
7039	}
7040
7041	delta = 0x1f - pg->pg_nrssi[0];
7042	for (i = 0; i < 64; i++) {
7043		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7044		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7045		pg->pg_nrssi_lt[i] = tmp32;
7046	}
7047
7048	bwn_nrssi_threshold(mac);
7049#undef SAVE_RF_MAX
7050#undef SAVE_PHY_COMM_MAX
7051#undef SAVE_PHY3_MAX
7052}
7053
7054static void
7055bwn_nrssi_offset(struct bwn_mac *mac)
7056{
7057#define	SAVE_RF_MAX		2
7058#define	SAVE_PHY_COMM_MAX	10
7059#define	SAVE_PHY6_MAX		8
7060	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7061		{ 0x7a, 0x43 };
7062	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7063		0x0001, 0x0811, 0x0812, 0x0814,
7064		0x0815, 0x005a, 0x0059, 0x0058,
7065		0x000a, 0x0003
7066	};
7067	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7068		0x002e, 0x002f, 0x080f, 0x0810,
7069		0x0801, 0x0060, 0x0014, 0x0478
7070	};
7071	struct bwn_phy *phy = &mac->mac_phy;
7072	int i, phy6_idx = 0;
7073	uint16_t save_rf[SAVE_RF_MAX];
7074	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7075	uint16_t save_phy6[SAVE_PHY6_MAX];
7076	int16_t nrssi;
7077	uint16_t saved = 0xffff;
7078
7079	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7080		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7081	for (i = 0; i < SAVE_RF_MAX; ++i)
7082		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7083
7084	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7085	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7086	BWN_PHY_SET(mac, 0x0811, 0x000c);
7087	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7088	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7089	if (phy->rev >= 6) {
7090		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7091			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7092
7093		BWN_PHY_WRITE(mac, 0x002e, 0);
7094		BWN_PHY_WRITE(mac, 0x002f, 0);
7095		BWN_PHY_WRITE(mac, 0x080f, 0);
7096		BWN_PHY_WRITE(mac, 0x0810, 0);
7097		BWN_PHY_SET(mac, 0x0478, 0x0100);
7098		BWN_PHY_SET(mac, 0x0801, 0x0040);
7099		BWN_PHY_SET(mac, 0x0060, 0x0040);
7100		BWN_PHY_SET(mac, 0x0014, 0x0200);
7101	}
7102	BWN_RF_SET(mac, 0x007a, 0x0070);
7103	BWN_RF_SET(mac, 0x007a, 0x0080);
7104	DELAY(30);
7105
7106	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7107	if (nrssi >= 0x20)
7108		nrssi -= 0x40;
7109	if (nrssi == 31) {
7110		for (i = 7; i >= 4; i--) {
7111			BWN_RF_WRITE(mac, 0x007b, i);
7112			DELAY(20);
7113			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7114			    0x003f);
7115			if (nrssi >= 0x20)
7116				nrssi -= 0x40;
7117			if (nrssi < 31 && saved == 0xffff)
7118				saved = i;
7119		}
7120		if (saved == 0xffff)
7121			saved = 4;
7122	} else {
7123		BWN_RF_MASK(mac, 0x007a, 0x007f);
7124		if (phy->rev != 1) {
7125			BWN_PHY_SET(mac, 0x0814, 0x0001);
7126			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7127		}
7128		BWN_PHY_SET(mac, 0x0811, 0x000c);
7129		BWN_PHY_SET(mac, 0x0812, 0x000c);
7130		BWN_PHY_SET(mac, 0x0811, 0x0030);
7131		BWN_PHY_SET(mac, 0x0812, 0x0030);
7132		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7133		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7134		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7135		if (phy->rev == 0)
7136			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7137		else
7138			BWN_PHY_SET(mac, 0x000a, 0x2000);
7139		if (phy->rev != 1) {
7140			BWN_PHY_SET(mac, 0x0814, 0x0004);
7141			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7142		}
7143		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7144		BWN_RF_SET(mac, 0x007a, 0x000f);
7145		bwn_set_all_gains(mac, 3, 0, 1);
7146		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7147		DELAY(30);
7148		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7149		if (nrssi >= 0x20)
7150			nrssi -= 0x40;
7151		if (nrssi == -32) {
7152			for (i = 0; i < 4; i++) {
7153				BWN_RF_WRITE(mac, 0x007b, i);
7154				DELAY(20);
7155				nrssi = (int16_t)((BWN_PHY_READ(mac,
7156				    0x047f) >> 8) & 0x003f);
7157				if (nrssi >= 0x20)
7158					nrssi -= 0x40;
7159				if (nrssi > -31 && saved == 0xffff)
7160					saved = i;
7161			}
7162			if (saved == 0xffff)
7163				saved = 3;
7164		} else
7165			saved = 0;
7166	}
7167	BWN_RF_WRITE(mac, 0x007b, saved);
7168
7169	/*
7170	 * Restore saved RF/PHY registers
7171	 */
7172	if (phy->rev >= 6) {
7173		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7174			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7175			    save_phy6[phy6_idx]);
7176		}
7177	}
7178	if (phy->rev != 1) {
7179		for (i = 3; i < 5; i++)
7180			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7181			    save_phy_comm[i]);
7182	}
7183	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7184		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7185
7186	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7187		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7188
7189	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7190	BWN_PHY_SET(mac, 0x0429, 0x8000);
7191	bwn_set_original_gains(mac);
7192	if (phy->rev >= 6) {
7193		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7194			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7195			    save_phy6[phy6_idx]);
7196		}
7197	}
7198
7199	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7200	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7201	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7202}
7203
7204static void
7205bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7206    int16_t third)
7207{
7208	struct bwn_phy *phy = &mac->mac_phy;
7209	uint16_t i;
7210	uint16_t start = 0x08, end = 0x18;
7211	uint16_t tmp;
7212	uint16_t table;
7213
7214	if (phy->rev <= 1) {
7215		start = 0x10;
7216		end = 0x20;
7217	}
7218
7219	table = BWN_OFDMTAB_GAINX;
7220	if (phy->rev <= 1)
7221		table = BWN_OFDMTAB_GAINX_R1;
7222	for (i = 0; i < 4; i++)
7223		bwn_ofdmtab_write_2(mac, table, i, first);
7224
7225	for (i = start; i < end; i++)
7226		bwn_ofdmtab_write_2(mac, table, i, second);
7227
7228	if (third != -1) {
7229		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7230		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7231		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7232		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7233	}
7234	bwn_dummy_transmission(mac, 0, 1);
7235}
7236
7237static void
7238bwn_set_original_gains(struct bwn_mac *mac)
7239{
7240	struct bwn_phy *phy = &mac->mac_phy;
7241	uint16_t i, tmp;
7242	uint16_t table;
7243	uint16_t start = 0x0008, end = 0x0018;
7244
7245	if (phy->rev <= 1) {
7246		start = 0x0010;
7247		end = 0x0020;
7248	}
7249
7250	table = BWN_OFDMTAB_GAINX;
7251	if (phy->rev <= 1)
7252		table = BWN_OFDMTAB_GAINX_R1;
7253	for (i = 0; i < 4; i++) {
7254		tmp = (i & 0xfffc);
7255		tmp |= (i & 0x0001) << 1;
7256		tmp |= (i & 0x0002) >> 1;
7257
7258		bwn_ofdmtab_write_2(mac, table, i, tmp);
7259	}
7260
7261	for (i = start; i < end; i++)
7262		bwn_ofdmtab_write_2(mac, table, i, i - start);
7263
7264	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7265	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7266	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7267	bwn_dummy_transmission(mac, 0, 1);
7268}
7269
7270static void
7271bwn_phy_hwpctl_init(struct bwn_mac *mac)
7272{
7273	struct siba_softc *bus = mac->mac_sd->sd_bus;
7274	struct bwn_phy *phy = &mac->mac_phy;
7275	struct bwn_phy_g *pg = &phy->phy_g;
7276	struct bwn_rfatt old_rfatt, rfatt;
7277	struct bwn_bbatt old_bbatt, bbatt;
7278	uint8_t old_txctl = 0;
7279
7280	KASSERT(phy->type == BWN_PHYTYPE_G,
7281	    ("%s:%d: fail", __func__, __LINE__));
7282
7283	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7284	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7285		return;
7286
7287	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7288
7289	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7290
7291	if (!phy->gmode)
7292		return;
7293	bwn_hwpctl_early_init(mac);
7294	if (pg->pg_curtssi == 0) {
7295		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7296			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7297		} else {
7298			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7299			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7300			old_txctl = pg->pg_txctl;
7301
7302			bbatt.att = 11;
7303			if (phy->rf_rev == 8) {
7304				rfatt.att = 15;
7305				rfatt.padmix = 1;
7306			} else {
7307				rfatt.att = 9;
7308				rfatt.padmix = 0;
7309			}
7310			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7311		}
7312		bwn_dummy_transmission(mac, 0, 1);
7313		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7314		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7315			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7316		else
7317			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7318			    &old_rfatt, old_txctl);
7319	}
7320	bwn_hwpctl_init_gphy(mac);
7321
7322	/* clear TSSI */
7323	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7324	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7325	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7326	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7327}
7328
7329static void
7330bwn_hwpctl_early_init(struct bwn_mac *mac)
7331{
7332	struct bwn_phy *phy = &mac->mac_phy;
7333
7334	if (!bwn_has_hwpctl(mac)) {
7335		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7336		return;
7337	}
7338
7339	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7340	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7341	BWN_PHY_SET(mac, 0x047c, 0x0002);
7342	BWN_PHY_SET(mac, 0x047a, 0xf000);
7343	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7344		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7345		BWN_PHY_SET(mac, 0x005d, 0x8000);
7346		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7347		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7348		BWN_PHY_SET(mac, 0x0036, 0x0400);
7349	} else {
7350		BWN_PHY_SET(mac, 0x0036, 0x0200);
7351		BWN_PHY_SET(mac, 0x0036, 0x0400);
7352		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7353		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7354		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7355		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7356		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7357	}
7358}
7359
7360static void
7361bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7362{
7363	struct bwn_phy *phy = &mac->mac_phy;
7364	struct bwn_phy_g *pg = &phy->phy_g;
7365	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7366	int i;
7367	uint16_t nr_written = 0, tmp, value;
7368	uint8_t rf, bb;
7369
7370	if (!bwn_has_hwpctl(mac)) {
7371		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7372		return;
7373	}
7374
7375	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7376	    (pg->pg_idletssi - pg->pg_curtssi));
7377	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7378	    (pg->pg_idletssi - pg->pg_curtssi));
7379
7380	for (i = 0; i < 32; i++)
7381		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7382	for (i = 32; i < 64; i++)
7383		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7384	for (i = 0; i < 64; i += 2) {
7385		value = (uint16_t) pg->pg_tssi2dbm[i];
7386		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7387		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7388	}
7389
7390	for (rf = 0; rf < lo->rfatt.len; rf++) {
7391		for (bb = 0; bb < lo->bbatt.len; bb++) {
7392			if (nr_written >= 0x40)
7393				return;
7394			tmp = lo->bbatt.array[bb].att;
7395			tmp <<= 8;
7396			if (phy->rf_rev == 8)
7397				tmp |= 0x50;
7398			else
7399				tmp |= 0x40;
7400			tmp |= lo->rfatt.array[rf].att;
7401			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7402			nr_written++;
7403		}
7404	}
7405
7406	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7407	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7408
7409	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7410	BWN_PHY_SET(mac, 0x0478, 0x0800);
7411	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7412	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7413
7414	bwn_phy_g_dc_lookup_init(mac, 1);
7415	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7416}
7417
7418static void
7419bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7420{
7421	struct siba_softc *siba = mac->mac_sd->sd_bus;
7422
7423	if (spu != 0)
7424		bwn_spu_workaround(mac, channel);
7425
7426	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7427
7428	if (channel == 14) {
7429		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7430			bwn_hf_write(mac,
7431			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7432		else
7433			bwn_hf_write(mac,
7434			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7435		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7436		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7437		return;
7438	}
7439
7440	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7441	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7442}
7443
7444static uint16_t
7445bwn_phy_g_chan2freq(uint8_t channel)
7446{
7447	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7448
7449	KASSERT(channel >= 1 && channel <= 14,
7450	    ("%s:%d: fail", __func__, __LINE__));
7451
7452	return (bwn_phy_g_rf_channels[channel - 1]);
7453}
7454
7455static void
7456bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7457    const struct bwn_rfatt *rfatt, uint8_t txctl)
7458{
7459	struct bwn_phy *phy = &mac->mac_phy;
7460	struct bwn_phy_g *pg = &phy->phy_g;
7461	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7462	uint16_t bb, rf;
7463	uint16_t tx_bias, tx_magn;
7464
7465	bb = bbatt->att;
7466	rf = rfatt->att;
7467	tx_bias = lo->tx_bias;
7468	tx_magn = lo->tx_magn;
7469	if (tx_bias == 0xff)
7470		tx_bias = 0;
7471
7472	pg->pg_txctl = txctl;
7473	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7474	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7475	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7476	bwn_phy_g_set_bbatt(mac, bb);
7477	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7478	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7479		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7480	else {
7481		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7482		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7483	}
7484	if (BWN_HAS_TXMAG(phy))
7485		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7486	else
7487		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7488	bwn_lo_g_adjust(mac);
7489}
7490
7491static void
7492bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7493    uint16_t bbatt)
7494{
7495	struct bwn_phy *phy = &mac->mac_phy;
7496
7497	if (phy->analog == 0) {
7498		BWN_WRITE_2(mac, BWN_PHY0,
7499		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7500		return;
7501	}
7502	if (phy->analog > 1) {
7503		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7504		return;
7505	}
7506	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7507}
7508
7509static uint16_t
7510bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7511{
7512	struct bwn_phy *phy = &mac->mac_phy;
7513	struct bwn_phy_g *pg = &phy->phy_g;
7514	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7515	int max_lb_gain;
7516	uint16_t extlna;
7517	uint16_t i;
7518
7519	if (phy->gmode == 0)
7520		return (0);
7521
7522	if (BWN_HAS_LOOPBACK(phy)) {
7523		max_lb_gain = pg->pg_max_lb_gain;
7524		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7525		if (max_lb_gain >= 0x46) {
7526			extlna = 0x3000;
7527			max_lb_gain -= 0x46;
7528		} else if (max_lb_gain >= 0x3a) {
7529			extlna = 0x1000;
7530			max_lb_gain -= 0x3a;
7531		} else if (max_lb_gain >= 0x2e) {
7532			extlna = 0x2000;
7533			max_lb_gain -= 0x2e;
7534		} else {
7535			extlna = 0;
7536			max_lb_gain -= 0x10;
7537		}
7538
7539		for (i = 0; i < 16; i++) {
7540			max_lb_gain -= (i * 6);
7541			if (max_lb_gain < 6)
7542				break;
7543		}
7544
7545		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7546			if (reg == BWN_PHY_RFOVER) {
7547				return (0x1b3);
7548			} else if (reg == BWN_PHY_RFOVERVAL) {
7549				extlna |= (i << 8);
7550				switch (lpd) {
7551				case BWN_LPD(0, 1, 1):
7552					return (0x0f92);
7553				case BWN_LPD(0, 0, 1):
7554				case BWN_LPD(1, 0, 1):
7555					return (0x0092 | extlna);
7556				case BWN_LPD(1, 0, 0):
7557					return (0x0093 | extlna);
7558				}
7559				KASSERT(0 == 1,
7560				    ("%s:%d: fail", __func__, __LINE__));
7561			}
7562			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7563		} else {
7564			if (reg == BWN_PHY_RFOVER)
7565				return (0x9b3);
7566			if (reg == BWN_PHY_RFOVERVAL) {
7567				if (extlna)
7568					extlna |= 0x8000;
7569				extlna |= (i << 8);
7570				switch (lpd) {
7571				case BWN_LPD(0, 1, 1):
7572					return (0x8f92);
7573				case BWN_LPD(0, 0, 1):
7574					return (0x8092 | extlna);
7575				case BWN_LPD(1, 0, 1):
7576					return (0x2092 | extlna);
7577				case BWN_LPD(1, 0, 0):
7578					return (0x2093 | extlna);
7579				}
7580				KASSERT(0 == 1,
7581				    ("%s:%d: fail", __func__, __LINE__));
7582			}
7583			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7584		}
7585		return (0);
7586	}
7587
7588	if ((phy->rev < 7) ||
7589	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7590		if (reg == BWN_PHY_RFOVER) {
7591			return (0x1b3);
7592		} else if (reg == BWN_PHY_RFOVERVAL) {
7593			switch (lpd) {
7594			case BWN_LPD(0, 1, 1):
7595				return (0x0fb2);
7596			case BWN_LPD(0, 0, 1):
7597				return (0x00b2);
7598			case BWN_LPD(1, 0, 1):
7599				return (0x30b2);
7600			case BWN_LPD(1, 0, 0):
7601				return (0x30b3);
7602			}
7603			KASSERT(0 == 1,
7604			    ("%s:%d: fail", __func__, __LINE__));
7605		}
7606		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7607	} else {
7608		if (reg == BWN_PHY_RFOVER) {
7609			return (0x9b3);
7610		} else if (reg == BWN_PHY_RFOVERVAL) {
7611			switch (lpd) {
7612			case BWN_LPD(0, 1, 1):
7613				return (0x8fb2);
7614			case BWN_LPD(0, 0, 1):
7615				return (0x80b2);
7616			case BWN_LPD(1, 0, 1):
7617				return (0x20b2);
7618			case BWN_LPD(1, 0, 0):
7619				return (0x20b3);
7620			}
7621			KASSERT(0 == 1,
7622			    ("%s:%d: fail", __func__, __LINE__));
7623		}
7624		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7625	}
7626	return (0);
7627}
7628
7629static void
7630bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7631{
7632
7633	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7634		return;
7635	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7636	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7637	DELAY(1000);
7638	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7639}
7640
7641static int
7642bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7643{
7644	struct bwn_softc *sc = mac->mac_sc;
7645	struct bwn_fw *fw = &mac->mac_fw;
7646	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7647	const char *filename;
7648	uint32_t high;
7649	int error;
7650
7651	/* microcode */
7652	if (rev >= 5 && rev <= 10)
7653		filename = "ucode5";
7654	else if (rev >= 11 && rev <= 12)
7655		filename = "ucode11";
7656	else if (rev == 13)
7657		filename = "ucode13";
7658	else if (rev == 14)
7659		filename = "ucode14";
7660	else if (rev >= 15)
7661		filename = "ucode15";
7662	else {
7663		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7664		bwn_release_firmware(mac);
7665		return (EOPNOTSUPP);
7666	}
7667	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7668	if (error) {
7669		bwn_release_firmware(mac);
7670		return (error);
7671	}
7672
7673	/* PCM */
7674	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7675	if (rev >= 5 && rev <= 10) {
7676		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7677		if (error == ENOENT)
7678			fw->no_pcmfile = 1;
7679		else if (error) {
7680			bwn_release_firmware(mac);
7681			return (error);
7682		}
7683	} else if (rev < 11) {
7684		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7685		return (EOPNOTSUPP);
7686	}
7687
7688	/* initvals */
7689	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7690	switch (mac->mac_phy.type) {
7691	case BWN_PHYTYPE_A:
7692		if (rev < 5 || rev > 10)
7693			goto fail1;
7694		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7695			filename = "a0g1initvals5";
7696		else
7697			filename = "a0g0initvals5";
7698		break;
7699	case BWN_PHYTYPE_G:
7700		if (rev >= 5 && rev <= 10)
7701			filename = "b0g0initvals5";
7702		else if (rev >= 13)
7703			filename = "b0g0initvals13";
7704		else
7705			goto fail1;
7706		break;
7707	case BWN_PHYTYPE_LP:
7708		if (rev == 13)
7709			filename = "lp0initvals13";
7710		else if (rev == 14)
7711			filename = "lp0initvals14";
7712		else if (rev >= 15)
7713			filename = "lp0initvals15";
7714		else
7715			goto fail1;
7716		break;
7717	case BWN_PHYTYPE_N:
7718		if (rev >= 11 && rev <= 12)
7719			filename = "n0initvals11";
7720		else
7721			goto fail1;
7722		break;
7723	default:
7724		goto fail1;
7725	}
7726	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7727	if (error) {
7728		bwn_release_firmware(mac);
7729		return (error);
7730	}
7731
7732	/* bandswitch initvals */
7733	switch (mac->mac_phy.type) {
7734	case BWN_PHYTYPE_A:
7735		if (rev >= 5 && rev <= 10) {
7736			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7737				filename = "a0g1bsinitvals5";
7738			else
7739				filename = "a0g0bsinitvals5";
7740		} else if (rev >= 11)
7741			filename = NULL;
7742		else
7743			goto fail1;
7744		break;
7745	case BWN_PHYTYPE_G:
7746		if (rev >= 5 && rev <= 10)
7747			filename = "b0g0bsinitvals5";
7748		else if (rev >= 11)
7749			filename = NULL;
7750		else
7751			goto fail1;
7752		break;
7753	case BWN_PHYTYPE_LP:
7754		if (rev == 13)
7755			filename = "lp0bsinitvals13";
7756		else if (rev == 14)
7757			filename = "lp0bsinitvals14";
7758		else if (rev >= 15)
7759			filename = "lp0bsinitvals15";
7760		else
7761			goto fail1;
7762		break;
7763	case BWN_PHYTYPE_N:
7764		if (rev >= 11 && rev <= 12)
7765			filename = "n0bsinitvals11";
7766		else
7767			goto fail1;
7768		break;
7769	default:
7770		goto fail1;
7771	}
7772	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7773	if (error) {
7774		bwn_release_firmware(mac);
7775		return (error);
7776	}
7777	return (0);
7778fail1:
7779	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7780	bwn_release_firmware(mac);
7781	return (EOPNOTSUPP);
7782}
7783
7784static int
7785bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7786    const char *name, struct bwn_fwfile *bfw)
7787{
7788	const struct bwn_fwhdr *hdr;
7789	struct bwn_softc *sc = mac->mac_sc;
7790	const struct firmware *fw;
7791	char namebuf[64];
7792
7793	if (name == NULL) {
7794		bwn_do_release_fw(bfw);
7795		return (0);
7796	}
7797	if (bfw->filename != NULL) {
7798		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7799			return (0);
7800		bwn_do_release_fw(bfw);
7801	}
7802
7803	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s",
7804	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", name);
7805	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7806	fw = firmware_get(namebuf);
7807	if (fw == NULL) {
7808		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7809		    namebuf);
7810		return (ENOENT);
7811	}
7812	if (fw->datasize < sizeof(struct bwn_fwhdr))
7813		goto fail;
7814	hdr = (const struct bwn_fwhdr *)(fw->data);
7815	switch (hdr->type) {
7816	case BWN_FWTYPE_UCODE:
7817	case BWN_FWTYPE_PCM:
7818		if (be32toh(hdr->size) !=
7819		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7820			goto fail;
7821		/* FALLTHROUGH */
7822	case BWN_FWTYPE_IV:
7823		if (hdr->ver != 1)
7824			goto fail;
7825		break;
7826	default:
7827		goto fail;
7828	}
7829	bfw->filename = name;
7830	bfw->fw = fw;
7831	bfw->type = type;
7832	return (0);
7833fail:
7834	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7835	if (fw != NULL)
7836		firmware_put(fw, FIRMWARE_UNLOAD);
7837	return (EPROTO);
7838}
7839
7840static void
7841bwn_release_firmware(struct bwn_mac *mac)
7842{
7843
7844	bwn_do_release_fw(&mac->mac_fw.ucode);
7845	bwn_do_release_fw(&mac->mac_fw.pcm);
7846	bwn_do_release_fw(&mac->mac_fw.initvals);
7847	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7848}
7849
7850static void
7851bwn_do_release_fw(struct bwn_fwfile *bfw)
7852{
7853
7854	if (bfw->fw != NULL)
7855		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7856	bfw->fw = NULL;
7857	bfw->filename = NULL;
7858}
7859
7860static int
7861bwn_fw_loaducode(struct bwn_mac *mac)
7862{
7863#define	GETFWOFFSET(fwp, offset)	\
7864	((const uint32_t *)((const char *)fwp.fw->data + offset))
7865#define	GETFWSIZE(fwp, offset)	\
7866	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7867	struct bwn_softc *sc = mac->mac_sc;
7868	const uint32_t *data;
7869	unsigned int i;
7870	uint32_t ctl;
7871	uint16_t date, fwcaps, time;
7872	int error = 0;
7873
7874	ctl = BWN_READ_4(mac, BWN_MACCTL);
7875	ctl |= BWN_MACCTL_MCODE_JMP0;
7876	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7877	    __LINE__));
7878	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7879	for (i = 0; i < 64; i++)
7880		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7881	for (i = 0; i < 4096; i += 2)
7882		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7883
7884	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7885	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7886	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7887	     i++) {
7888		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7889		DELAY(10);
7890	}
7891
7892	if (mac->mac_fw.pcm.fw) {
7893		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7894		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7895		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7896		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7897		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7898		    sizeof(struct bwn_fwhdr)); i++) {
7899			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7900			DELAY(10);
7901		}
7902	}
7903
7904	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7905	BWN_WRITE_4(mac, BWN_MACCTL,
7906	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7907	    BWN_MACCTL_MCODE_RUN);
7908
7909	for (i = 0; i < 21; i++) {
7910		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7911			break;
7912		if (i >= 20) {
7913			device_printf(sc->sc_dev, "ucode timeout\n");
7914			error = ENXIO;
7915			goto error;
7916		}
7917		DELAY(50000);
7918	}
7919	BWN_READ_4(mac, BWN_INTR_REASON);
7920
7921	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7922	if (mac->mac_fw.rev <= 0x128) {
7923		device_printf(sc->sc_dev, "the firmware is too old\n");
7924		error = EOPNOTSUPP;
7925		goto error;
7926	}
7927	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7928	    BWN_SHARED_UCODE_PATCH);
7929	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7930	mac->mac_fw.opensource = (date == 0xffff);
7931	if (bwn_wme != 0)
7932		mac->mac_flags |= BWN_MAC_FLAG_WME;
7933	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7934
7935	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7936	if (mac->mac_fw.opensource == 0) {
7937		device_printf(sc->sc_dev,
7938		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7939		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7940		if (mac->mac_fw.no_pcmfile)
7941			device_printf(sc->sc_dev,
7942			    "no HW crypto acceleration due to pcm5\n");
7943	} else {
7944		mac->mac_fw.patch = time;
7945		fwcaps = bwn_fwcaps_read(mac);
7946		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7947			device_printf(sc->sc_dev,
7948			    "disabling HW crypto acceleration\n");
7949			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7950		}
7951		if (!(fwcaps & BWN_FWCAPS_WME)) {
7952			device_printf(sc->sc_dev, "disabling WME support\n");
7953			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7954		}
7955	}
7956
7957	if (BWN_ISOLDFMT(mac))
7958		device_printf(sc->sc_dev, "using old firmware image\n");
7959
7960	return (0);
7961
7962error:
7963	BWN_WRITE_4(mac, BWN_MACCTL,
7964	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7965	    BWN_MACCTL_MCODE_JMP0);
7966
7967	return (error);
7968#undef GETFWSIZE
7969#undef GETFWOFFSET
7970}
7971
7972/* OpenFirmware only */
7973static uint16_t
7974bwn_fwcaps_read(struct bwn_mac *mac)
7975{
7976
7977	KASSERT(mac->mac_fw.opensource == 1,
7978	    ("%s:%d: fail", __func__, __LINE__));
7979	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7980}
7981
7982static int
7983bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7984    size_t count, size_t array_size)
7985{
7986#define	GET_NEXTIV16(iv)						\
7987	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7988	    sizeof(uint16_t) + sizeof(uint16_t)))
7989#define	GET_NEXTIV32(iv)						\
7990	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7991	    sizeof(uint16_t) + sizeof(uint32_t)))
7992	struct bwn_softc *sc = mac->mac_sc;
7993	const struct bwn_fwinitvals *iv;
7994	uint16_t offset;
7995	size_t i;
7996	uint8_t bit32;
7997
7998	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7999	    ("%s:%d: fail", __func__, __LINE__));
8000	iv = ivals;
8001	for (i = 0; i < count; i++) {
8002		if (array_size < sizeof(iv->offset_size))
8003			goto fail;
8004		array_size -= sizeof(iv->offset_size);
8005		offset = be16toh(iv->offset_size);
8006		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
8007		offset &= BWN_FWINITVALS_OFFSET_MASK;
8008		if (offset >= 0x1000)
8009			goto fail;
8010		if (bit32) {
8011			if (array_size < sizeof(iv->data.d32))
8012				goto fail;
8013			array_size -= sizeof(iv->data.d32);
8014			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8015			iv = GET_NEXTIV32(iv);
8016		} else {
8017
8018			if (array_size < sizeof(iv->data.d16))
8019				goto fail;
8020			array_size -= sizeof(iv->data.d16);
8021			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8022
8023			iv = GET_NEXTIV16(iv);
8024		}
8025	}
8026	if (array_size != 0)
8027		goto fail;
8028	return (0);
8029fail:
8030	device_printf(sc->sc_dev, "initvals: invalid format\n");
8031	return (EPROTO);
8032#undef GET_NEXTIV16
8033#undef GET_NEXTIV32
8034}
8035
8036static int
8037bwn_switch_channel(struct bwn_mac *mac, int chan)
8038{
8039	struct bwn_phy *phy = &(mac->mac_phy);
8040	struct bwn_softc *sc = mac->mac_sc;
8041	struct ifnet *ifp = sc->sc_ifp;
8042	struct ieee80211com *ic = ifp->if_l2com;
8043	uint16_t channelcookie, savedcookie;
8044	int error;
8045
8046	if (chan == 0xffff)
8047		chan = phy->get_default_chan(mac);
8048
8049	channelcookie = chan;
8050	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8051		channelcookie |= 0x100;
8052	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8053	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8054	error = phy->switch_channel(mac, chan);
8055	if (error)
8056		goto fail;
8057
8058	mac->mac_phy.chan = chan;
8059	DELAY(8000);
8060	return (0);
8061fail:
8062	device_printf(sc->sc_dev, "failed to switch channel\n");
8063	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8064	return (error);
8065}
8066
8067static uint16_t
8068bwn_ant2phy(int antenna)
8069{
8070
8071	switch (antenna) {
8072	case BWN_ANT0:
8073		return (BWN_TX_PHY_ANT0);
8074	case BWN_ANT1:
8075		return (BWN_TX_PHY_ANT1);
8076	case BWN_ANT2:
8077		return (BWN_TX_PHY_ANT2);
8078	case BWN_ANT3:
8079		return (BWN_TX_PHY_ANT3);
8080	case BWN_ANTAUTO:
8081		return (BWN_TX_PHY_ANT01AUTO);
8082	}
8083	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8084	return (0);
8085}
8086
8087static void
8088bwn_wme_load(struct bwn_mac *mac)
8089{
8090	struct bwn_softc *sc = mac->mac_sc;
8091	int i;
8092
8093	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8094	    ("%s:%d: fail", __func__, __LINE__));
8095
8096	bwn_mac_suspend(mac);
8097	for (i = 0; i < N(sc->sc_wmeParams); i++)
8098		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8099		    bwn_wme_shm_offsets[i]);
8100	bwn_mac_enable(mac);
8101}
8102
8103static void
8104bwn_wme_loadparams(struct bwn_mac *mac,
8105    const struct wmeParams *p, uint16_t shm_offset)
8106{
8107#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8108	struct bwn_softc *sc = mac->mac_sc;
8109	uint16_t params[BWN_NR_WMEPARAMS];
8110	int slot, tmp;
8111	unsigned int i;
8112
8113	slot = BWN_READ_2(mac, BWN_RNG) &
8114	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8115
8116	memset(&params, 0, sizeof(params));
8117
8118	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8119	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8120	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8121
8122	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8123	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8124	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8125	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8126	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8127	params[BWN_WMEPARAM_BSLOTS] = slot;
8128	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8129
8130	for (i = 0; i < N(params); i++) {
8131		if (i == BWN_WMEPARAM_STATUS) {
8132			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8133			    shm_offset + (i * 2));
8134			tmp |= 0x100;
8135			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8136			    tmp);
8137		} else {
8138			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8139			    params[i]);
8140		}
8141	}
8142}
8143
8144static void
8145bwn_mac_write_bssid(struct bwn_mac *mac)
8146{
8147	struct bwn_softc *sc = mac->mac_sc;
8148	uint32_t tmp;
8149	int i;
8150	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8151
8152	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8153	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8154	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8155	    IEEE80211_ADDR_LEN);
8156
8157	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8158		tmp = (uint32_t) (mac_bssid[i + 0]);
8159		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8160		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8161		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8162		bwn_ram_write(mac, 0x20 + i, tmp);
8163	}
8164}
8165
8166static void
8167bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8168    const uint8_t *macaddr)
8169{
8170	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8171	uint16_t data;
8172
8173	if (!mac)
8174		macaddr = zero;
8175
8176	offset |= 0x0020;
8177	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8178
8179	data = macaddr[0];
8180	data |= macaddr[1] << 8;
8181	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8182	data = macaddr[2];
8183	data |= macaddr[3] << 8;
8184	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8185	data = macaddr[4];
8186	data |= macaddr[5] << 8;
8187	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8188}
8189
8190static void
8191bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8192    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8193{
8194	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8195	uint8_t per_sta_keys_start = 8;
8196
8197	if (BWN_SEC_NEWAPI(mac))
8198		per_sta_keys_start = 4;
8199
8200	KASSERT(index < mac->mac_max_nr_keys,
8201	    ("%s:%d: fail", __func__, __LINE__));
8202	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8203	    ("%s:%d: fail", __func__, __LINE__));
8204
8205	if (index >= per_sta_keys_start)
8206		bwn_key_macwrite(mac, index, NULL);
8207	if (key)
8208		memcpy(buf, key, key_len);
8209	bwn_key_write(mac, index, algorithm, buf);
8210	if (index >= per_sta_keys_start)
8211		bwn_key_macwrite(mac, index, mac_addr);
8212
8213	mac->mac_key[index].algorithm = algorithm;
8214}
8215
8216static void
8217bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8218{
8219	uint32_t addrtmp[2] = { 0, 0 };
8220	uint8_t start = 8;
8221
8222	if (BWN_SEC_NEWAPI(mac))
8223		start = 4;
8224
8225	KASSERT(index >= start,
8226	    ("%s:%d: fail", __func__, __LINE__));
8227	index -= start;
8228
8229	if (addr) {
8230		addrtmp[0] = addr[0];
8231		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8232		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8233		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8234		addrtmp[1] = addr[4];
8235		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8236	}
8237
8238	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8239		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8240		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8241	} else {
8242		if (index >= 8) {
8243			bwn_shm_write_4(mac, BWN_SHARED,
8244			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8245			bwn_shm_write_2(mac, BWN_SHARED,
8246			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8247		}
8248	}
8249}
8250
8251static void
8252bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8253    const uint8_t *key)
8254{
8255	unsigned int i;
8256	uint32_t offset;
8257	uint16_t kidx, value;
8258
8259	kidx = BWN_SEC_KEY2FW(mac, index);
8260	bwn_shm_write_2(mac, BWN_SHARED,
8261	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8262
8263	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8264	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8265		value = key[i];
8266		value |= (uint16_t)(key[i + 1]) << 8;
8267		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8268	}
8269}
8270
8271static void
8272bwn_phy_exit(struct bwn_mac *mac)
8273{
8274
8275	mac->mac_phy.rf_onoff(mac, 0);
8276	if (mac->mac_phy.exit != NULL)
8277		mac->mac_phy.exit(mac);
8278}
8279
8280static void
8281bwn_dma_free(struct bwn_mac *mac)
8282{
8283	struct bwn_dma *dma;
8284
8285	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8286		return;
8287	dma = &mac->mac_method.dma;
8288
8289	bwn_dma_ringfree(&dma->rx);
8290	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8291	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8292	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8293	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8294	bwn_dma_ringfree(&dma->mcast);
8295}
8296
8297static void
8298bwn_core_stop(struct bwn_mac *mac)
8299{
8300	struct bwn_softc *sc = mac->mac_sc;
8301
8302	BWN_ASSERT_LOCKED(sc);
8303
8304	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8305		return;
8306
8307	callout_stop(&sc->sc_rfswitch_ch);
8308	callout_stop(&sc->sc_task_ch);
8309	callout_stop(&sc->sc_watchdog_ch);
8310	sc->sc_watchdog_timer = 0;
8311	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8312	BWN_READ_4(mac, BWN_INTR_MASK);
8313	bwn_mac_suspend(mac);
8314
8315	mac->mac_status = BWN_MAC_STATUS_INITED;
8316}
8317
8318static int
8319bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8320{
8321	struct bwn_mac *up_dev = NULL;
8322	struct bwn_mac *down_dev;
8323	struct bwn_mac *mac;
8324	int err, status;
8325	uint8_t gmode;
8326
8327	BWN_ASSERT_LOCKED(sc);
8328
8329	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8330		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8331		    mac->mac_phy.supports_2ghz) {
8332			up_dev = mac;
8333			gmode = 1;
8334		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8335		    mac->mac_phy.supports_5ghz) {
8336			up_dev = mac;
8337			gmode = 0;
8338		} else {
8339			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8340			return (EINVAL);
8341		}
8342		if (up_dev != NULL)
8343			break;
8344	}
8345	if (up_dev == NULL) {
8346		device_printf(sc->sc_dev, "Could not find a device\n");
8347		return (ENODEV);
8348	}
8349	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8350		return (0);
8351
8352	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8353	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8354
8355	down_dev = sc->sc_curmac;;
8356	status = down_dev->mac_status;
8357	if (status >= BWN_MAC_STATUS_STARTED)
8358		bwn_core_stop(down_dev);
8359	if (status >= BWN_MAC_STATUS_INITED)
8360		bwn_core_exit(down_dev);
8361
8362	if (down_dev != up_dev)
8363		bwn_phy_reset(down_dev);
8364
8365	up_dev->mac_phy.gmode = gmode;
8366	if (status >= BWN_MAC_STATUS_INITED) {
8367		err = bwn_core_init(up_dev);
8368		if (err) {
8369			device_printf(sc->sc_dev,
8370			    "fatal: failed to initialize for %s-GHz\n",
8371			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8372			goto fail;
8373		}
8374	}
8375	if (status >= BWN_MAC_STATUS_STARTED)
8376		bwn_core_start(up_dev);
8377	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8378	sc->sc_curmac = up_dev;
8379
8380	return (0);
8381fail:
8382	sc->sc_curmac = NULL;
8383	return (err);
8384}
8385
8386static void
8387bwn_rf_turnon(struct bwn_mac *mac)
8388{
8389
8390	bwn_mac_suspend(mac);
8391	mac->mac_phy.rf_onoff(mac, 1);
8392	mac->mac_phy.rf_on = 1;
8393	bwn_mac_enable(mac);
8394}
8395
8396static void
8397bwn_rf_turnoff(struct bwn_mac *mac)
8398{
8399
8400	bwn_mac_suspend(mac);
8401	mac->mac_phy.rf_onoff(mac, 0);
8402	mac->mac_phy.rf_on = 0;
8403	bwn_mac_enable(mac);
8404}
8405
8406static void
8407bwn_phy_reset(struct bwn_mac *mac)
8408{
8409	struct siba_dev_softc *sd = mac->mac_sd;
8410
8411	siba_write_4(sd, SIBA_TGSLOW,
8412	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8413	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8414	DELAY(1000);
8415	siba_write_4(sd, SIBA_TGSLOW,
8416	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8417	    BWN_TGSLOW_PHYRESET);
8418	DELAY(1000);
8419}
8420
8421static int
8422bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8423{
8424	struct bwn_vap *bvp = BWN_VAP(vap);
8425	struct ieee80211com *ic= vap->iv_ic;
8426	struct ifnet *ifp = ic->ic_ifp;
8427	enum ieee80211_state ostate = vap->iv_state;
8428	struct bwn_softc *sc = ifp->if_softc;
8429	struct bwn_mac *mac = sc->sc_curmac;
8430	int error;
8431
8432	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8433	    ieee80211_state_name[vap->iv_state],
8434	    ieee80211_state_name[nstate]);
8435
8436	error = bvp->bv_newstate(vap, nstate, arg);
8437	if (error != 0)
8438		return (error);
8439
8440	BWN_LOCK(sc);
8441
8442	bwn_led_newstate(mac, nstate);
8443
8444	/*
8445	 * Clear the BSSID when we stop a STA
8446	 */
8447	if (vap->iv_opmode == IEEE80211_M_STA) {
8448		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8449			/*
8450			 * Clear out the BSSID.  If we reassociate to
8451			 * the same AP, this will reinialize things
8452			 * correctly...
8453			 */
8454			if (ic->ic_opmode == IEEE80211_M_STA &&
8455			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8456				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8457				bwn_set_macaddr(mac);
8458			}
8459		}
8460	}
8461
8462	if (vap->iv_opmode == IEEE80211_M_MONITOR) {
8463		/* XXX nothing to do? */
8464	} else if (nstate == IEEE80211_S_RUN) {
8465		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8466		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8467		bwn_set_opmode(mac);
8468		bwn_set_pretbtt(mac);
8469		bwn_spu_setdelay(mac, 0);
8470		bwn_set_macaddr(mac);
8471	}
8472
8473	BWN_UNLOCK(sc);
8474
8475	return (error);
8476}
8477
8478static void
8479bwn_set_pretbtt(struct bwn_mac *mac)
8480{
8481	struct bwn_softc *sc = mac->mac_sc;
8482	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8483	uint16_t pretbtt;
8484
8485	if (ic->ic_opmode == IEEE80211_M_IBSS)
8486		pretbtt = 2;
8487	else
8488		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8489	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8490	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8491}
8492
8493static int
8494bwn_intr(void *arg)
8495{
8496	struct bwn_mac *mac = arg;
8497	struct bwn_softc *sc = mac->mac_sc;
8498	struct siba_softc *siba = mac->mac_sd->sd_bus;
8499	uint32_t reason;
8500
8501	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8502		return (FILTER_STRAY);
8503
8504	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8505	if (reason == 0xffffffff)	/* shared IRQ */
8506		return (FILTER_STRAY);
8507	reason &= mac->mac_intr_mask;
8508	if (reason == 0)
8509		return (FILTER_HANDLED);
8510
8511	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8512	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8513	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8514	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8515	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8516	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8517	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8518	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8519	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8520	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8521	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8522
8523	/* Disable interrupts. */
8524	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8525
8526	mac->mac_reason_intr = reason;
8527
8528	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8529	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8530
8531	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8532	return (FILTER_HANDLED);
8533}
8534
8535static void
8536bwn_intrtask(void *arg, int npending)
8537{
8538	struct bwn_mac *mac = arg;
8539	struct bwn_softc *sc = mac->mac_sc;
8540	struct ifnet *ifp = sc->sc_ifp;
8541	struct siba_softc *siba = mac->mac_sd->sd_bus;
8542	uint32_t merged = 0;
8543	int i, tx = 0, rx = 0;
8544
8545	BWN_LOCK(sc);
8546	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8547		BWN_UNLOCK(sc);
8548		return;
8549	}
8550
8551	for (i = 0; i < N(mac->mac_reason); i++)
8552		merged |= mac->mac_reason[i];
8553
8554	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8555		device_printf(sc->sc_dev, "MAC trans error\n");
8556
8557	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8558		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8559		mac->mac_phy.txerrors--;
8560		if (mac->mac_phy.txerrors == 0) {
8561			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8562			bwn_restart(mac, "PHY TX errors");
8563		}
8564	}
8565
8566	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8567		if (merged & BWN_DMAINTR_FATALMASK) {
8568			device_printf(sc->sc_dev,
8569			    "Fatal 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			bwn_restart(mac, "DMA error");
8574			BWN_UNLOCK(sc);
8575			return;
8576		}
8577		if (merged & BWN_DMAINTR_NONFATALMASK) {
8578			device_printf(sc->sc_dev,
8579			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8580			    mac->mac_reason[0], mac->mac_reason[1],
8581			    mac->mac_reason[2], mac->mac_reason[3],
8582			    mac->mac_reason[4], mac->mac_reason[5]);
8583		}
8584	}
8585
8586	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8587		bwn_intr_ucode_debug(mac);
8588	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8589		bwn_intr_tbtt_indication(mac);
8590	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8591		bwn_intr_atim_end(mac);
8592	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8593		bwn_intr_beacon(mac);
8594	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8595		bwn_intr_pmq(mac);
8596	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8597		bwn_intr_noise(mac);
8598
8599	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8600		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8601			bwn_dma_rx(mac->mac_method.dma.rx);
8602			rx = 1;
8603		}
8604	} else
8605		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8606
8607	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8608	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8609	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8610	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8611	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8612
8613	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8614		bwn_intr_txeof(mac);
8615		tx = 1;
8616	}
8617
8618	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8619
8620	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8621		int evt = BWN_LED_EVENT_NONE;
8622
8623		if (tx && rx) {
8624			if (sc->sc_rx_rate > sc->sc_tx_rate)
8625				evt = BWN_LED_EVENT_RX;
8626			else
8627				evt = BWN_LED_EVENT_TX;
8628		} else if (tx) {
8629			evt = BWN_LED_EVENT_TX;
8630		} else if (rx) {
8631			evt = BWN_LED_EVENT_RX;
8632		} else if (rx == 0) {
8633			evt = BWN_LED_EVENT_POLL;
8634		}
8635
8636		if (evt != BWN_LED_EVENT_NONE)
8637			bwn_led_event(mac, evt);
8638       }
8639
8640	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8641		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8642			bwn_start_locked(ifp);
8643	}
8644
8645	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8646	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8647
8648	BWN_UNLOCK(sc);
8649}
8650
8651static void
8652bwn_restart(struct bwn_mac *mac, const char *msg)
8653{
8654	struct bwn_softc *sc = mac->mac_sc;
8655	struct ifnet *ifp = sc->sc_ifp;
8656	struct ieee80211com *ic = ifp->if_l2com;
8657
8658	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8659		return;
8660
8661	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8662	ieee80211_runtask(ic, &mac->mac_hwreset);
8663}
8664
8665static void
8666bwn_intr_ucode_debug(struct bwn_mac *mac)
8667{
8668	struct bwn_softc *sc = mac->mac_sc;
8669	uint16_t reason;
8670
8671	if (mac->mac_fw.opensource == 0)
8672		return;
8673
8674	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8675	switch (reason) {
8676	case BWN_DEBUGINTR_PANIC:
8677		bwn_handle_fwpanic(mac);
8678		break;
8679	case BWN_DEBUGINTR_DUMP_SHM:
8680		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8681		break;
8682	case BWN_DEBUGINTR_DUMP_REGS:
8683		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8684		break;
8685	case BWN_DEBUGINTR_MARKER:
8686		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8687		break;
8688	default:
8689		device_printf(sc->sc_dev,
8690		    "ucode debug unknown reason: %#x\n", reason);
8691	}
8692
8693	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8694	    BWN_DEBUGINTR_ACK);
8695}
8696
8697static void
8698bwn_intr_tbtt_indication(struct bwn_mac *mac)
8699{
8700	struct bwn_softc *sc = mac->mac_sc;
8701	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8702
8703	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8704		bwn_psctl(mac, 0);
8705	if (ic->ic_opmode == IEEE80211_M_IBSS)
8706		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8707}
8708
8709static void
8710bwn_intr_atim_end(struct bwn_mac *mac)
8711{
8712
8713	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8714		BWN_WRITE_4(mac, BWN_MACCMD,
8715		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8716		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8717	}
8718}
8719
8720static void
8721bwn_intr_beacon(struct bwn_mac *mac)
8722{
8723	struct bwn_softc *sc = mac->mac_sc;
8724	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8725	uint32_t cmd, beacon0, beacon1;
8726
8727	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8728	    ic->ic_opmode == IEEE80211_M_MBSS)
8729		return;
8730
8731	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8732
8733	cmd = BWN_READ_4(mac, BWN_MACCMD);
8734	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8735	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8736
8737	if (beacon0 && beacon1) {
8738		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8739		mac->mac_intr_mask |= BWN_INTR_BEACON;
8740		return;
8741	}
8742
8743	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8744		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8745		bwn_load_beacon0(mac);
8746		bwn_load_beacon1(mac);
8747		cmd = BWN_READ_4(mac, BWN_MACCMD);
8748		cmd |= BWN_MACCMD_BEACON0_VALID;
8749		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8750	} else {
8751		if (!beacon0) {
8752			bwn_load_beacon0(mac);
8753			cmd = BWN_READ_4(mac, BWN_MACCMD);
8754			cmd |= BWN_MACCMD_BEACON0_VALID;
8755			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8756		} else if (!beacon1) {
8757			bwn_load_beacon1(mac);
8758			cmd = BWN_READ_4(mac, BWN_MACCMD);
8759			cmd |= BWN_MACCMD_BEACON1_VALID;
8760			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8761		}
8762	}
8763}
8764
8765static void
8766bwn_intr_pmq(struct bwn_mac *mac)
8767{
8768	uint32_t tmp;
8769
8770	while (1) {
8771		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8772		if (!(tmp & 0x00000008))
8773			break;
8774	}
8775	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8776}
8777
8778static void
8779bwn_intr_noise(struct bwn_mac *mac)
8780{
8781	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8782	uint16_t tmp;
8783	uint8_t noise[4];
8784	uint8_t i, j;
8785	int32_t average;
8786
8787	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8788		return;
8789
8790	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8791	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8792	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8793	    noise[3] == 0x7f)
8794		goto new;
8795
8796	KASSERT(mac->mac_noise.noi_nsamples < 8,
8797	    ("%s:%d: fail", __func__, __LINE__));
8798	i = mac->mac_noise.noi_nsamples;
8799	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8800	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8801	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8802	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8803	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8804	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8805	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8806	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8807	mac->mac_noise.noi_nsamples++;
8808	if (mac->mac_noise.noi_nsamples == 8) {
8809		average = 0;
8810		for (i = 0; i < 8; i++) {
8811			for (j = 0; j < 4; j++)
8812				average += mac->mac_noise.noi_samples[i][j];
8813		}
8814		average = (((average / 32) * 125) + 64) / 128;
8815		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8816		if (tmp >= 8)
8817			average += 2;
8818		else
8819			average -= 25;
8820		average -= (tmp == 8) ? 72 : 48;
8821
8822		mac->mac_stats.link_noise = average;
8823		mac->mac_noise.noi_running = 0;
8824		return;
8825	}
8826new:
8827	bwn_noise_gensample(mac);
8828}
8829
8830static int
8831bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8832{
8833	struct bwn_mac *mac = prq->prq_mac;
8834	struct bwn_softc *sc = mac->mac_sc;
8835	unsigned int i;
8836
8837	BWN_ASSERT_LOCKED(sc);
8838
8839	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8840		return (0);
8841
8842	for (i = 0; i < 5000; i++) {
8843		if (bwn_pio_rxeof(prq) == 0)
8844			break;
8845	}
8846	if (i >= 5000)
8847		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8848	return ((i > 0) ? 1 : 0);
8849}
8850
8851static void
8852bwn_dma_rx(struct bwn_dma_ring *dr)
8853{
8854	int slot, curslot;
8855
8856	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8857	curslot = dr->get_curslot(dr);
8858	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8859	    ("%s:%d: fail", __func__, __LINE__));
8860
8861	slot = dr->dr_curslot;
8862	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8863		bwn_dma_rxeof(dr, &slot);
8864
8865	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8866	    BUS_DMASYNC_PREWRITE);
8867
8868	dr->set_curslot(dr, slot);
8869	dr->dr_curslot = slot;
8870}
8871
8872static void
8873bwn_intr_txeof(struct bwn_mac *mac)
8874{
8875	struct bwn_txstatus stat;
8876	uint32_t stat0, stat1;
8877	uint16_t tmp;
8878
8879	BWN_ASSERT_LOCKED(mac->mac_sc);
8880
8881	while (1) {
8882		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8883		if (!(stat0 & 0x00000001))
8884			break;
8885		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8886
8887		stat.cookie = (stat0 >> 16);
8888		stat.seq = (stat1 & 0x0000ffff);
8889		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8890		tmp = (stat0 & 0x0000ffff);
8891		stat.framecnt = ((tmp & 0xf000) >> 12);
8892		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8893		stat.sreason = ((tmp & 0x001c) >> 2);
8894		stat.pm = (tmp & 0x0080) ? 1 : 0;
8895		stat.im = (tmp & 0x0040) ? 1 : 0;
8896		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8897		stat.ack = (tmp & 0x0002) ? 1 : 0;
8898
8899		bwn_handle_txeof(mac, &stat);
8900	}
8901}
8902
8903static void
8904bwn_hwreset(void *arg, int npending)
8905{
8906	struct bwn_mac *mac = arg;
8907	struct bwn_softc *sc = mac->mac_sc;
8908	int error = 0;
8909	int prev_status;
8910
8911	BWN_LOCK(sc);
8912
8913	prev_status = mac->mac_status;
8914	if (prev_status >= BWN_MAC_STATUS_STARTED)
8915		bwn_core_stop(mac);
8916	if (prev_status >= BWN_MAC_STATUS_INITED)
8917		bwn_core_exit(mac);
8918
8919	if (prev_status >= BWN_MAC_STATUS_INITED) {
8920		error = bwn_core_init(mac);
8921		if (error)
8922			goto out;
8923	}
8924	if (prev_status >= BWN_MAC_STATUS_STARTED)
8925		bwn_core_start(mac);
8926out:
8927	if (error) {
8928		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8929		sc->sc_curmac = NULL;
8930	}
8931	BWN_UNLOCK(sc);
8932}
8933
8934static void
8935bwn_handle_fwpanic(struct bwn_mac *mac)
8936{
8937	struct bwn_softc *sc = mac->mac_sc;
8938	uint16_t reason;
8939
8940	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8941	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8942
8943	if (reason == BWN_FWPANIC_RESTART)
8944		bwn_restart(mac, "ucode panic");
8945}
8946
8947static void
8948bwn_load_beacon0(struct bwn_mac *mac)
8949{
8950
8951	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8952}
8953
8954static void
8955bwn_load_beacon1(struct bwn_mac *mac)
8956{
8957
8958	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8959}
8960
8961static uint32_t
8962bwn_jssi_read(struct bwn_mac *mac)
8963{
8964	uint32_t val = 0;
8965
8966	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8967	val <<= 16;
8968	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8969
8970	return (val);
8971}
8972
8973static void
8974bwn_noise_gensample(struct bwn_mac *mac)
8975{
8976	uint32_t jssi = 0x7f7f7f7f;
8977
8978	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8979	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8980	BWN_WRITE_4(mac, BWN_MACCMD,
8981	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8982}
8983
8984static int
8985bwn_dma_freeslot(struct bwn_dma_ring *dr)
8986{
8987	struct bwn_mac *mac = dr->dr_mac;
8988
8989	BWN_ASSERT_LOCKED(mac->mac_sc);
8990
8991	return (dr->dr_numslots - dr->dr_usedslot);
8992}
8993
8994static int
8995bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8996{
8997	struct bwn_mac *mac = dr->dr_mac;
8998
8999	BWN_ASSERT_LOCKED(mac->mac_sc);
9000
9001	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
9002	    ("%s:%d: fail", __func__, __LINE__));
9003	if (slot == dr->dr_numslots - 1)
9004		return (0);
9005	return (slot + 1);
9006}
9007
9008static void
9009bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
9010{
9011	struct bwn_mac *mac = dr->dr_mac;
9012	struct bwn_softc *sc = mac->mac_sc;
9013	struct bwn_dma *dma = &mac->mac_method.dma;
9014	struct bwn_dmadesc_generic *desc;
9015	struct bwn_dmadesc_meta *meta;
9016	struct bwn_rxhdr4 *rxhdr;
9017	struct ifnet *ifp = sc->sc_ifp;
9018	struct mbuf *m;
9019	uint32_t macstat;
9020	int32_t tmp;
9021	int cnt = 0;
9022	uint16_t len;
9023
9024	dr->getdesc(dr, *slot, &desc, &meta);
9025
9026	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9027	m = meta->mt_m;
9028
9029	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9030		ifp->if_ierrors++;
9031		return;
9032	}
9033
9034	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9035	len = le16toh(rxhdr->frame_len);
9036	if (len <= 0) {
9037		ifp->if_ierrors++;
9038		return;
9039	}
9040	if (bwn_dma_check_redzone(dr, m)) {
9041		device_printf(sc->sc_dev, "redzone error.\n");
9042		bwn_dma_set_redzone(dr, m);
9043		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9044		    BUS_DMASYNC_PREWRITE);
9045		return;
9046	}
9047	if (len > dr->dr_rx_bufsize) {
9048		tmp = len;
9049		while (1) {
9050			dr->getdesc(dr, *slot, &desc, &meta);
9051			bwn_dma_set_redzone(dr, meta->mt_m);
9052			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9053			    BUS_DMASYNC_PREWRITE);
9054			*slot = bwn_dma_nextslot(dr, *slot);
9055			cnt++;
9056			tmp -= dr->dr_rx_bufsize;
9057			if (tmp <= 0)
9058				break;
9059		}
9060		device_printf(sc->sc_dev, "too small buffer "
9061		       "(len %u buffer %u dropped %d)\n",
9062		       len, dr->dr_rx_bufsize, cnt);
9063		return;
9064	}
9065	macstat = le32toh(rxhdr->mac_status);
9066	if (macstat & BWN_RX_MAC_FCSERR) {
9067		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9068			device_printf(sc->sc_dev, "RX drop\n");
9069			return;
9070		}
9071	}
9072
9073	m->m_pkthdr.rcvif = ifp;
9074	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9075	m_adj(m, dr->dr_frameoffset);
9076
9077	bwn_rxeof(dr->dr_mac, m, rxhdr);
9078}
9079
9080static void
9081bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9082{
9083	struct bwn_dma_ring *dr;
9084	struct bwn_dmadesc_generic *desc;
9085	struct bwn_dmadesc_meta *meta;
9086	struct bwn_node *bn;
9087	struct bwn_pio_txqueue *tq;
9088	struct bwn_pio_txpkt *tp = NULL;
9089	struct bwn_softc *sc = mac->mac_sc;
9090	struct ieee80211_node *ni;
9091	int slot;
9092
9093	BWN_ASSERT_LOCKED(mac->mac_sc);
9094
9095	if (status->im)
9096		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9097	if (status->ampdu)
9098		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9099	if (status->rtscnt) {
9100		if (status->rtscnt == 0xf)
9101			device_printf(sc->sc_dev, "TODO: RTS fail\n");
9102		else
9103			device_printf(sc->sc_dev, "TODO: RTS ok\n");
9104	}
9105
9106	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9107		if (status->ack) {
9108			dr = bwn_dma_parse_cookie(mac, status,
9109			    status->cookie, &slot);
9110			if (dr == NULL) {
9111				device_printf(sc->sc_dev,
9112				    "failed to parse cookie\n");
9113				return;
9114			}
9115			while (1) {
9116				dr->getdesc(dr, slot, &desc, &meta);
9117				if (meta->mt_islast) {
9118					ni = meta->mt_ni;
9119					bn = (struct bwn_node *)ni;
9120					ieee80211_amrr_tx_complete(&bn->bn_amn,
9121					    status->ack, 0);
9122					break;
9123				}
9124				slot = bwn_dma_nextslot(dr, slot);
9125			}
9126		}
9127		bwn_dma_handle_txeof(mac, status);
9128	} else {
9129		if (status->ack) {
9130			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9131			if (tq == NULL) {
9132				device_printf(sc->sc_dev,
9133				    "failed to parse cookie\n");
9134				return;
9135			}
9136			ni = tp->tp_ni;
9137			bn = (struct bwn_node *)ni;
9138			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9139		}
9140		bwn_pio_handle_txeof(mac, status);
9141	}
9142
9143	bwn_phy_txpower_check(mac, 0);
9144}
9145
9146static uint8_t
9147bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9148{
9149	struct bwn_mac *mac = prq->prq_mac;
9150	struct bwn_softc *sc = mac->mac_sc;
9151	struct bwn_rxhdr4 rxhdr;
9152	struct ifnet *ifp = sc->sc_ifp;
9153	struct mbuf *m;
9154	uint32_t ctl32, macstat, v32;
9155	unsigned int i, padding;
9156	uint16_t ctl16, len, v16;
9157	unsigned char *mp;
9158	char *data;
9159
9160	memset(&rxhdr, 0, sizeof(rxhdr));
9161
9162	if (prq->prq_rev >= 8) {
9163		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9164		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9165			return (0);
9166		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9167		    BWN_PIO8_RXCTL_FRAMEREADY);
9168		for (i = 0; i < 10; i++) {
9169			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9170			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9171				goto ready;
9172			DELAY(10);
9173		}
9174	} else {
9175		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9176		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9177			return (0);
9178		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9179		    BWN_PIO_RXCTL_FRAMEREADY);
9180		for (i = 0; i < 10; i++) {
9181			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9182			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9183				goto ready;
9184			DELAY(10);
9185		}
9186	}
9187	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9188	return (1);
9189ready:
9190	if (prq->prq_rev >= 8)
9191		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9192		    prq->prq_base + BWN_PIO8_RXDATA);
9193	else
9194		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9195		    prq->prq_base + BWN_PIO_RXDATA);
9196	len = le16toh(rxhdr.frame_len);
9197	if (len > 0x700) {
9198		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9199		goto error;
9200	}
9201	if (len == 0) {
9202		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9203		goto error;
9204	}
9205
9206	macstat = le32toh(rxhdr.mac_status);
9207	if (macstat & BWN_RX_MAC_FCSERR) {
9208		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9209			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9210			goto error;
9211		}
9212	}
9213
9214	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9215	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9216	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9217	if (m == NULL) {
9218		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9219		goto error;
9220	}
9221	mp = mtod(m, unsigned char *);
9222	if (prq->prq_rev >= 8) {
9223		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9224		    prq->prq_base + BWN_PIO8_RXDATA);
9225		if (len & 3) {
9226			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9227			data = &(mp[len + padding - 1]);
9228			switch (len & 3) {
9229			case 3:
9230				*data = (v32 >> 16);
9231				data--;
9232			case 2:
9233				*data = (v32 >> 8);
9234				data--;
9235			case 1:
9236				*data = v32;
9237			}
9238		}
9239	} else {
9240		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9241		    prq->prq_base + BWN_PIO_RXDATA);
9242		if (len & 1) {
9243			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9244			mp[len + padding - 1] = v16;
9245		}
9246	}
9247
9248	m->m_pkthdr.rcvif = ifp;
9249	m->m_len = m->m_pkthdr.len = len + padding;
9250
9251	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9252
9253	return (1);
9254error:
9255	if (prq->prq_rev >= 8)
9256		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9257		    BWN_PIO8_RXCTL_DATAREADY);
9258	else
9259		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9260	return (1);
9261}
9262
9263static int
9264bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9265    struct bwn_dmadesc_meta *meta, int init)
9266{
9267	struct bwn_mac *mac = dr->dr_mac;
9268	struct bwn_dma *dma = &mac->mac_method.dma;
9269	struct bwn_rxhdr4 *hdr;
9270	bus_dmamap_t map;
9271	bus_addr_t paddr;
9272	struct mbuf *m;
9273	int error;
9274
9275	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9276	if (m == NULL) {
9277		error = ENOBUFS;
9278
9279		/*
9280		 * If the NIC is up and running, we need to:
9281		 * - Clear RX buffer's header.
9282		 * - Restore RX descriptor settings.
9283		 */
9284		if (init)
9285			return (error);
9286		else
9287			goto back;
9288	}
9289	m->m_len = m->m_pkthdr.len = MCLBYTES;
9290
9291	bwn_dma_set_redzone(dr, m);
9292
9293	/*
9294	 * Try to load RX buf into temporary DMA map
9295	 */
9296	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9297	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9298	if (error) {
9299		m_freem(m);
9300
9301		/*
9302		 * See the comment above
9303		 */
9304		if (init)
9305			return (error);
9306		else
9307			goto back;
9308	}
9309
9310	if (!init)
9311		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9312	meta->mt_m = m;
9313	meta->mt_paddr = paddr;
9314
9315	/*
9316	 * Swap RX buf's DMA map with the loaded temporary one
9317	 */
9318	map = meta->mt_dmap;
9319	meta->mt_dmap = dr->dr_spare_dmap;
9320	dr->dr_spare_dmap = map;
9321
9322back:
9323	/*
9324	 * Clear RX buf header
9325	 */
9326	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9327	bzero(hdr, sizeof(*hdr));
9328	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9329	    BUS_DMASYNC_PREWRITE);
9330
9331	/*
9332	 * Setup RX buf descriptor
9333	 */
9334	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9335	    sizeof(*hdr), 0, 0, 0);
9336	return (error);
9337}
9338
9339static void
9340bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9341		 bus_size_t mapsz __unused, int error)
9342{
9343
9344	if (!error) {
9345		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9346		*((bus_addr_t *)arg) = seg->ds_addr;
9347	}
9348}
9349
9350static int
9351bwn_hwrate2ieeerate(int rate)
9352{
9353
9354	switch (rate) {
9355	case BWN_CCK_RATE_1MB:
9356		return (2);
9357	case BWN_CCK_RATE_2MB:
9358		return (4);
9359	case BWN_CCK_RATE_5MB:
9360		return (11);
9361	case BWN_CCK_RATE_11MB:
9362		return (22);
9363	case BWN_OFDM_RATE_6MB:
9364		return (12);
9365	case BWN_OFDM_RATE_9MB:
9366		return (18);
9367	case BWN_OFDM_RATE_12MB:
9368		return (24);
9369	case BWN_OFDM_RATE_18MB:
9370		return (36);
9371	case BWN_OFDM_RATE_24MB:
9372		return (48);
9373	case BWN_OFDM_RATE_36MB:
9374		return (72);
9375	case BWN_OFDM_RATE_48MB:
9376		return (96);
9377	case BWN_OFDM_RATE_54MB:
9378		return (108);
9379	default:
9380		printf("Ooops\n");
9381		return (0);
9382	}
9383}
9384
9385static void
9386bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9387{
9388	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9389	struct bwn_plcp6 *plcp;
9390	struct bwn_softc *sc = mac->mac_sc;
9391	struct ieee80211_frame_min *wh;
9392	struct ieee80211_node *ni;
9393	struct ifnet *ifp = sc->sc_ifp;
9394	struct ieee80211com *ic = ifp->if_l2com;
9395	uint32_t macstat;
9396	int padding, rate, rssi, noise, type;
9397	uint16_t phytype, phystat0, phystat3, chanstat;
9398	unsigned char *mp = mtod(m, unsigned char *);
9399
9400	BWN_ASSERT_LOCKED(sc);
9401
9402	phystat0 = le16toh(rxhdr->phy_status0);
9403	phystat3 = le16toh(rxhdr->phy_status3);
9404	macstat = le32toh(rxhdr->mac_status);
9405	chanstat = le16toh(rxhdr->channel);
9406	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9407
9408	if (macstat & BWN_RX_MAC_FCSERR)
9409		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9410	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9411		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9412	if (phystat0 & BWN_RX_PHYST0_SHORTPRMBL)
9413		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_SHORTPRE\n");
9414	if (macstat & BWN_RX_MAC_DECERR)
9415		goto drop;
9416
9417	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9418	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9419		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9420		    m->m_pkthdr.len);
9421		goto drop;
9422	}
9423	plcp = (struct bwn_plcp6 *)(mp + padding);
9424	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9425	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9426		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9427		    m->m_pkthdr.len);
9428		goto drop;
9429	}
9430	wh = mtod(m, struct ieee80211_frame_min *);
9431
9432	if (macstat & BWN_RX_MAC_DEC)
9433		device_printf(sc->sc_dev,
9434		    "RX decryption attempted (old %d keyidx %#x)\n",
9435		    BWN_ISOLDFMT(mac),
9436		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9437
9438	/* XXX calculating RSSI & noise & antenna */
9439
9440	if (phystat0 & BWN_RX_PHYST0_OFDM)
9441		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9442		    phytype == BWN_PHYTYPE_A);
9443	else
9444		rate = bwn_plcp_get_cckrate(mac, plcp);
9445	if (rate == -1) {
9446		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9447			goto drop;
9448	}
9449	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9450
9451	/* RX radio tap */
9452	if (ieee80211_radiotap_active(ic))
9453		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9454	m_adj(m, -IEEE80211_CRC_LEN);
9455
9456	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9457	noise = mac->mac_stats.link_noise;
9458
9459	BWN_UNLOCK(sc);
9460
9461	ni = ieee80211_find_rxnode(ic, wh);
9462	if (ni != NULL) {
9463		type = ieee80211_input(ni, m, rssi, noise);
9464		ieee80211_free_node(ni);
9465	} else
9466		type = ieee80211_input_all(ic, m, rssi, noise);
9467
9468	BWN_LOCK(sc);
9469	return;
9470drop:
9471	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9472}
9473
9474static void
9475bwn_dma_handle_txeof(struct bwn_mac *mac,
9476    const struct bwn_txstatus *status)
9477{
9478	struct bwn_dma *dma = &mac->mac_method.dma;
9479	struct bwn_dma_ring *dr;
9480	struct bwn_dmadesc_generic *desc;
9481	struct bwn_dmadesc_meta *meta;
9482	struct bwn_softc *sc = mac->mac_sc;
9483	struct ieee80211_node *ni;
9484	struct ifnet *ifp = sc->sc_ifp;
9485	struct mbuf *m;
9486	int slot;
9487
9488	BWN_ASSERT_LOCKED(sc);
9489
9490	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9491	if (dr == NULL) {
9492		device_printf(sc->sc_dev, "failed to parse cookie\n");
9493		return;
9494	}
9495	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9496
9497	while (1) {
9498		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9499		    ("%s:%d: fail", __func__, __LINE__));
9500		dr->getdesc(dr, slot, &desc, &meta);
9501
9502		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9503			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9504		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9505			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9506
9507		if (meta->mt_islast) {
9508			KASSERT(meta->mt_m != NULL,
9509			    ("%s:%d: fail", __func__, __LINE__));
9510
9511			ni = meta->mt_ni;
9512			m = meta->mt_m;
9513			if (ni != NULL) {
9514				/*
9515				 * Do any tx complete callback. Note this must
9516				 * be done before releasing the node reference.
9517				 */
9518				if (m->m_flags & M_TXCB)
9519					ieee80211_process_callback(ni, m, 0);
9520				ieee80211_free_node(ni);
9521				meta->mt_ni = NULL;
9522			}
9523			m_freem(m);
9524			meta->mt_m = NULL;
9525		} else {
9526			KASSERT(meta->mt_m == NULL,
9527			    ("%s:%d: fail", __func__, __LINE__));
9528		}
9529
9530		dr->dr_usedslot--;
9531		if (meta->mt_islast) {
9532			ifp->if_opackets++;
9533			break;
9534		}
9535		slot = bwn_dma_nextslot(dr, slot);
9536	}
9537	sc->sc_watchdog_timer = 0;
9538	if (dr->dr_stop) {
9539		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9540		    ("%s:%d: fail", __func__, __LINE__));
9541		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9542		dr->dr_stop = 0;
9543	}
9544}
9545
9546static void
9547bwn_pio_handle_txeof(struct bwn_mac *mac,
9548    const struct bwn_txstatus *status)
9549{
9550	struct bwn_pio_txqueue *tq;
9551	struct bwn_pio_txpkt *tp = NULL;
9552	struct bwn_softc *sc = mac->mac_sc;
9553	struct ifnet *ifp = sc->sc_ifp;
9554
9555	BWN_ASSERT_LOCKED(sc);
9556
9557	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9558	if (tq == NULL)
9559		return;
9560
9561	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9562	tq->tq_free++;
9563
9564	if (tp->tp_ni != NULL) {
9565		/*
9566		 * Do any tx complete callback.  Note this must
9567		 * be done before releasing the node reference.
9568		 */
9569		if (tp->tp_m->m_flags & M_TXCB)
9570			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9571		ieee80211_free_node(tp->tp_ni);
9572		tp->tp_ni = NULL;
9573	}
9574	m_freem(tp->tp_m);
9575	tp->tp_m = NULL;
9576	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9577
9578	ifp->if_opackets++;
9579
9580	sc->sc_watchdog_timer = 0;
9581	if (tq->tq_stop) {
9582		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9583		tq->tq_stop = 0;
9584	}
9585}
9586
9587static void
9588bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9589{
9590	struct bwn_softc *sc = mac->mac_sc;
9591	struct bwn_phy *phy = &mac->mac_phy;
9592	struct ifnet *ifp = sc->sc_ifp;
9593	struct ieee80211com *ic = ifp->if_l2com;
9594	struct siba_softc *siba = mac->mac_sd->sd_bus;
9595	unsigned long now;
9596	int result;
9597
9598	BWN_GETTIME(now);
9599
9600	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9601		return;
9602	phy->nexttime = now + 2 * 1000;
9603
9604	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9605	    siba->siba_board_type == SIBA_BOARD_BU4306)
9606		return;
9607
9608	if (phy->recalc_txpwr != NULL) {
9609		result = phy->recalc_txpwr(mac,
9610		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9611		if (result == BWN_TXPWR_RES_DONE)
9612			return;
9613		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9614		    ("%s: fail", __func__));
9615		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9616
9617		ieee80211_runtask(ic, &mac->mac_txpower);
9618	}
9619}
9620
9621static uint16_t
9622bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9623{
9624
9625	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9626}
9627
9628static uint32_t
9629bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9630{
9631
9632	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9633}
9634
9635static void
9636bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9637{
9638
9639	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9640}
9641
9642static void
9643bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9644{
9645
9646	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9647}
9648
9649static int
9650bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9651{
9652
9653	switch (rate) {
9654	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9655	case 12:
9656		return (BWN_OFDM_RATE_6MB);
9657	case 18:
9658		return (BWN_OFDM_RATE_9MB);
9659	case 24:
9660		return (BWN_OFDM_RATE_12MB);
9661	case 36:
9662		return (BWN_OFDM_RATE_18MB);
9663	case 48:
9664		return (BWN_OFDM_RATE_24MB);
9665	case 72:
9666		return (BWN_OFDM_RATE_36MB);
9667	case 96:
9668		return (BWN_OFDM_RATE_48MB);
9669	case 108:
9670		return (BWN_OFDM_RATE_54MB);
9671	/* CCK rates (NB: not IEEE std, device-specific) */
9672	case 2:
9673		return (BWN_CCK_RATE_1MB);
9674	case 4:
9675		return (BWN_CCK_RATE_2MB);
9676	case 11:
9677		return (BWN_CCK_RATE_5MB);
9678	case 22:
9679		return (BWN_CCK_RATE_11MB);
9680	}
9681
9682	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9683	return (BWN_CCK_RATE_1MB);
9684}
9685
9686static int
9687bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9688    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9689{
9690	const struct bwn_phy *phy = &mac->mac_phy;
9691	struct bwn_softc *sc = mac->mac_sc;
9692	struct ieee80211_frame *wh;
9693	struct ieee80211_frame *protwh;
9694	struct ieee80211_frame_cts *cts;
9695	struct ieee80211_frame_rts *rts;
9696	const struct ieee80211_txparam *tp;
9697	struct ieee80211vap *vap = ni->ni_vap;
9698	struct ifnet *ifp = sc->sc_ifp;
9699	struct ieee80211com *ic = ifp->if_l2com;
9700	struct mbuf *mprot;
9701	unsigned int len;
9702	uint32_t macctl = 0;
9703	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9704	uint16_t phyctl = 0;
9705	uint8_t rate, rate_fb;
9706
9707	wh = mtod(m, struct ieee80211_frame *);
9708	memset(txhdr, 0, sizeof(*txhdr));
9709
9710	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9711	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9712	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9713
9714	/*
9715	 * Find TX rate
9716	 */
9717	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9718	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9719		rate = rate_fb = tp->mgmtrate;
9720	else if (ismcast)
9721		rate = rate_fb = tp->mcastrate;
9722	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9723		rate = rate_fb = tp->ucastrate;
9724	else {
9725		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9726		rate = ni->ni_txrate;
9727
9728		if (rix > 0)
9729			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9730			    IEEE80211_RATE_VAL;
9731		else
9732			rate_fb = rate;
9733	}
9734
9735	sc->sc_tx_rate = rate;
9736
9737	rate = bwn_ieeerate2hwrate(sc, rate);
9738	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9739
9740	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9741	    bwn_plcp_getcck(rate);
9742	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9743	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9744
9745	if ((rate_fb == rate) ||
9746	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9747	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9748		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9749	else
9750		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9751		    m->m_pkthdr.len, rate, isshort);
9752
9753	/* XXX TX encryption */
9754	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9755	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9756	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9757	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9758	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9759	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9760
9761	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9762	    BWN_TX_EFT_FB_CCK;
9763	txhdr->chan = phy->chan;
9764	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9765	    BWN_TX_PHY_ENC_CCK;
9766	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9767	     rate == BWN_CCK_RATE_11MB))
9768		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9769
9770	/* XXX TX antenna selection */
9771
9772	switch (bwn_antenna_sanitize(mac, 0)) {
9773	case 0:
9774		phyctl |= BWN_TX_PHY_ANT01AUTO;
9775		break;
9776	case 1:
9777		phyctl |= BWN_TX_PHY_ANT0;
9778		break;
9779	case 2:
9780		phyctl |= BWN_TX_PHY_ANT1;
9781		break;
9782	case 3:
9783		phyctl |= BWN_TX_PHY_ANT2;
9784		break;
9785	case 4:
9786		phyctl |= BWN_TX_PHY_ANT3;
9787		break;
9788	default:
9789		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9790	}
9791
9792	if (!ismcast)
9793		macctl |= BWN_TX_MAC_ACK;
9794
9795	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9796	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9797	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9798		macctl |= BWN_TX_MAC_LONGFRAME;
9799
9800	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9801		/* XXX RTS rate is always 1MB??? */
9802		rts_rate = BWN_CCK_RATE_1MB;
9803		rts_rate_fb = bwn_get_fbrate(rts_rate);
9804
9805		protdur = ieee80211_compute_duration(ic->ic_rt,
9806		    m->m_pkthdr.len, rate, isshort) +
9807		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9808
9809		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9810			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9811			    (txhdr->body.old.rts_frame) :
9812			    (txhdr->body.new.rts_frame));
9813			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9814			    protdur);
9815			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9816			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9817			    mprot->m_pkthdr.len);
9818			m_freem(mprot);
9819			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9820			len = sizeof(struct ieee80211_frame_cts);
9821		} else {
9822			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9823			    (txhdr->body.old.rts_frame) :
9824			    (txhdr->body.new.rts_frame));
9825			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9826			    isshort);
9827			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9828			    wh->i_addr2, protdur);
9829			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9830			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9831			    mprot->m_pkthdr.len);
9832			m_freem(mprot);
9833			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9834			len = sizeof(struct ieee80211_frame_rts);
9835		}
9836		len += IEEE80211_CRC_LEN;
9837		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9838		    &txhdr->body.old.rts_plcp :
9839		    &txhdr->body.new.rts_plcp), len, rts_rate);
9840		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9841		    rts_rate_fb);
9842
9843		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9844		    (&txhdr->body.old.rts_frame) :
9845		    (&txhdr->body.new.rts_frame));
9846		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9847
9848		if (BWN_ISOFDMRATE(rts_rate)) {
9849			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9850			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9851		} else {
9852			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9853			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9854		}
9855		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9856		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9857	}
9858
9859	if (BWN_ISOLDFMT(mac))
9860		txhdr->body.old.cookie = htole16(cookie);
9861	else
9862		txhdr->body.new.cookie = htole16(cookie);
9863
9864	txhdr->macctl = htole32(macctl);
9865	txhdr->phyctl = htole16(phyctl);
9866
9867	/*
9868	 * TX radio tap
9869	 */
9870	if (ieee80211_radiotap_active_vap(vap)) {
9871		sc->sc_tx_th.wt_flags = 0;
9872		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9873			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9874		if (isshort &&
9875		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9876		     rate == BWN_CCK_RATE_11MB))
9877			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9878		sc->sc_tx_th.wt_rate = rate;
9879
9880		ieee80211_radiotap_tx(vap, m);
9881	}
9882
9883	return (0);
9884}
9885
9886static void
9887bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9888    const uint8_t rate)
9889{
9890	uint32_t d, plen;
9891	uint8_t *raw = plcp->o.raw;
9892
9893	if (BWN_ISOFDMRATE(rate)) {
9894		d = bwn_plcp_getofdm(rate);
9895		KASSERT(!(octets & 0xf000),
9896		    ("%s:%d: fail", __func__, __LINE__));
9897		d |= (octets << 5);
9898		plcp->o.data = htole32(d);
9899	} else {
9900		plen = octets * 16 / rate;
9901		if ((octets * 16 % rate) > 0) {
9902			plen++;
9903			if ((rate == BWN_CCK_RATE_11MB)
9904			    && ((octets * 8 % 11) < 4)) {
9905				raw[1] = 0x84;
9906			} else
9907				raw[1] = 0x04;
9908		} else
9909			raw[1] = 0x04;
9910		plcp->o.data |= htole32(plen << 16);
9911		raw[0] = bwn_plcp_getcck(rate);
9912	}
9913}
9914
9915static uint8_t
9916bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9917{
9918	uint8_t mask;
9919
9920	if (n == 0)
9921		return (0);
9922	if (mac->mac_phy.gmode)
9923		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9924	else
9925		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9926	if (!(mask & (1 << (n - 1))))
9927		return (0);
9928	return (n);
9929}
9930
9931static uint8_t
9932bwn_get_fbrate(uint8_t bitrate)
9933{
9934	switch (bitrate) {
9935	case BWN_CCK_RATE_1MB:
9936		return (BWN_CCK_RATE_1MB);
9937	case BWN_CCK_RATE_2MB:
9938		return (BWN_CCK_RATE_1MB);
9939	case BWN_CCK_RATE_5MB:
9940		return (BWN_CCK_RATE_2MB);
9941	case BWN_CCK_RATE_11MB:
9942		return (BWN_CCK_RATE_5MB);
9943	case BWN_OFDM_RATE_6MB:
9944		return (BWN_CCK_RATE_5MB);
9945	case BWN_OFDM_RATE_9MB:
9946		return (BWN_OFDM_RATE_6MB);
9947	case BWN_OFDM_RATE_12MB:
9948		return (BWN_OFDM_RATE_9MB);
9949	case BWN_OFDM_RATE_18MB:
9950		return (BWN_OFDM_RATE_12MB);
9951	case BWN_OFDM_RATE_24MB:
9952		return (BWN_OFDM_RATE_18MB);
9953	case BWN_OFDM_RATE_36MB:
9954		return (BWN_OFDM_RATE_24MB);
9955	case BWN_OFDM_RATE_48MB:
9956		return (BWN_OFDM_RATE_36MB);
9957	case BWN_OFDM_RATE_54MB:
9958		return (BWN_OFDM_RATE_48MB);
9959	}
9960	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9961	return (0);
9962}
9963
9964static uint32_t
9965bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9966    uint32_t ctl, const void *_data, int len)
9967{
9968	uint32_t value = 0;
9969	const uint8_t *data = _data;
9970
9971	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9972	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9973	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9974
9975	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9976	    tq->tq_base + BWN_PIO8_TXDATA);
9977	if (len & 3) {
9978		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9979		    BWN_PIO8_TXCTL_24_31);
9980		data = &(data[len - 1]);
9981		switch (len & 3) {
9982		case 3:
9983			ctl |= BWN_PIO8_TXCTL_16_23;
9984			value |= (uint32_t)(*data) << 16;
9985			data--;
9986		case 2:
9987			ctl |= BWN_PIO8_TXCTL_8_15;
9988			value |= (uint32_t)(*data) << 8;
9989			data--;
9990		case 1:
9991			value |= (uint32_t)(*data);
9992		}
9993		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9994		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9995	}
9996
9997	return (ctl);
9998}
9999
10000static void
10001bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10002    uint16_t offset, uint32_t value)
10003{
10004
10005	BWN_WRITE_4(mac, tq->tq_base + offset, value);
10006}
10007
10008static uint16_t
10009bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10010    uint16_t ctl, const void *_data, int len)
10011{
10012	const uint8_t *data = _data;
10013
10014	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10015	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10016
10017	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10018	    tq->tq_base + BWN_PIO_TXDATA);
10019	if (len & 1) {
10020		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10021		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10022		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10023	}
10024
10025	return (ctl);
10026}
10027
10028static uint16_t
10029bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10030    uint16_t ctl, struct mbuf *m0)
10031{
10032	int i, j = 0;
10033	uint16_t data = 0;
10034	const uint8_t *buf;
10035	struct mbuf *m = m0;
10036
10037	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10038	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10039
10040	for (; m != NULL; m = m->m_next) {
10041		buf = mtod(m, const uint8_t *);
10042		for (i = 0; i < m->m_len; i++) {
10043			if (!((j++) % 2))
10044				data |= buf[i];
10045			else {
10046				data |= (buf[i] << 8);
10047				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10048				data = 0;
10049			}
10050		}
10051	}
10052	if (m0->m_pkthdr.len % 2) {
10053		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10054		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10055		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10056	}
10057
10058	return (ctl);
10059}
10060
10061static void
10062bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10063{
10064
10065	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10066		return;
10067	BWN_WRITE_2(mac, 0x684, 510 + time);
10068	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10069}
10070
10071static struct bwn_dma_ring *
10072bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10073{
10074
10075	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10076		return (mac->mac_method.dma.wme[WME_AC_BE]);
10077
10078	switch (prio) {
10079	case 3:
10080		return (mac->mac_method.dma.wme[WME_AC_VO]);
10081	case 2:
10082		return (mac->mac_method.dma.wme[WME_AC_VI]);
10083	case 0:
10084		return (mac->mac_method.dma.wme[WME_AC_BE]);
10085	case 1:
10086		return (mac->mac_method.dma.wme[WME_AC_BK]);
10087	}
10088	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10089}
10090
10091static int
10092bwn_dma_getslot(struct bwn_dma_ring *dr)
10093{
10094	struct bwn_mac *mac = dr->dr_mac;
10095	int slot;
10096
10097	BWN_ASSERT_LOCKED(mac->mac_sc);
10098
10099	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10100	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10101	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10102
10103	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10104	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10105	dr->dr_curslot = slot;
10106	dr->dr_usedslot++;
10107
10108	return (slot);
10109}
10110
10111static int
10112bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10113{
10114	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10115	unsigned int a, b, c, d;
10116	unsigned int avg;
10117	uint32_t tmp;
10118
10119	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10120	a = tmp & 0xff;
10121	b = (tmp >> 8) & 0xff;
10122	c = (tmp >> 16) & 0xff;
10123	d = (tmp >> 24) & 0xff;
10124	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10125	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10126		return (ENOENT);
10127	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10128	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10129	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10130
10131	if (ofdm) {
10132		a = (a + 32) & 0x3f;
10133		b = (b + 32) & 0x3f;
10134		c = (c + 32) & 0x3f;
10135		d = (d + 32) & 0x3f;
10136	}
10137
10138	avg = (a + b + c + d + 2) / 4;
10139	if (ofdm) {
10140		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10141		    & BWN_HF_4DB_CCK_POWERBOOST)
10142			avg = (avg >= 13) ? (avg - 13) : 0;
10143	}
10144	return (avg);
10145}
10146
10147static void
10148bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10149{
10150	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10151	int rfatt = *rfattp;
10152	int bbatt = *bbattp;
10153
10154	while (1) {
10155		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10156			break;
10157		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10158			break;
10159		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10160			break;
10161		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10162			break;
10163		if (bbatt > lo->bbatt.max) {
10164			bbatt -= 4;
10165			rfatt += 1;
10166			continue;
10167		}
10168		if (bbatt < lo->bbatt.min) {
10169			bbatt += 4;
10170			rfatt -= 1;
10171			continue;
10172		}
10173		if (rfatt > lo->rfatt.max) {
10174			rfatt -= 1;
10175			bbatt += 4;
10176			continue;
10177		}
10178		if (rfatt < lo->rfatt.min) {
10179			rfatt += 1;
10180			bbatt -= 4;
10181			continue;
10182		}
10183		break;
10184	}
10185
10186	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10187	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10188}
10189
10190static void
10191bwn_phy_lock(struct bwn_mac *mac)
10192{
10193	struct bwn_softc *sc = mac->mac_sc;
10194	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10195
10196	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10197	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10198
10199	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10200		bwn_psctl(mac, BWN_PS_AWAKE);
10201}
10202
10203static void
10204bwn_phy_unlock(struct bwn_mac *mac)
10205{
10206	struct bwn_softc *sc = mac->mac_sc;
10207	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10208
10209	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10210	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10211
10212	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10213		bwn_psctl(mac, 0);
10214}
10215
10216static void
10217bwn_rf_lock(struct bwn_mac *mac)
10218{
10219
10220	BWN_WRITE_4(mac, BWN_MACCTL,
10221	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10222	BWN_READ_4(mac, BWN_MACCTL);
10223	DELAY(10);
10224}
10225
10226static void
10227bwn_rf_unlock(struct bwn_mac *mac)
10228{
10229
10230	BWN_READ_2(mac, BWN_PHYVER);
10231	BWN_WRITE_4(mac, BWN_MACCTL,
10232	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10233}
10234
10235static struct bwn_pio_txqueue *
10236bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10237    struct bwn_pio_txpkt **pack)
10238{
10239	struct bwn_pio *pio = &mac->mac_method.pio;
10240	struct bwn_pio_txqueue *tq = NULL;
10241	unsigned int index;
10242
10243	switch (cookie & 0xf000) {
10244	case 0x1000:
10245		tq = &pio->wme[WME_AC_BK];
10246		break;
10247	case 0x2000:
10248		tq = &pio->wme[WME_AC_BE];
10249		break;
10250	case 0x3000:
10251		tq = &pio->wme[WME_AC_VI];
10252		break;
10253	case 0x4000:
10254		tq = &pio->wme[WME_AC_VO];
10255		break;
10256	case 0x5000:
10257		tq = &pio->mcast;
10258		break;
10259	}
10260	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10261	if (tq == NULL)
10262		return (NULL);
10263	index = (cookie & 0x0fff);
10264	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10265	if (index >= N(tq->tq_pkts))
10266		return (NULL);
10267	*pack = &tq->tq_pkts[index];
10268	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10269	return (tq);
10270}
10271
10272static void
10273bwn_txpwr(void *arg, int npending)
10274{
10275	struct bwn_mac *mac = arg;
10276	struct bwn_softc *sc = mac->mac_sc;
10277
10278	BWN_LOCK(sc);
10279	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10280	    mac->mac_phy.set_txpwr != NULL)
10281		mac->mac_phy.set_txpwr(mac);
10282	BWN_UNLOCK(sc);
10283}
10284
10285static void
10286bwn_task_15s(struct bwn_mac *mac)
10287{
10288	uint16_t reg;
10289
10290	if (mac->mac_fw.opensource) {
10291		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10292		if (reg) {
10293			bwn_restart(mac, "fw watchdog");
10294			return;
10295		}
10296		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10297	}
10298	if (mac->mac_phy.task_15s)
10299		mac->mac_phy.task_15s(mac);
10300
10301	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10302}
10303
10304static void
10305bwn_task_30s(struct bwn_mac *mac)
10306{
10307
10308	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10309		return;
10310	mac->mac_noise.noi_running = 1;
10311	mac->mac_noise.noi_nsamples = 0;
10312
10313	bwn_noise_gensample(mac);
10314}
10315
10316static void
10317bwn_task_60s(struct bwn_mac *mac)
10318{
10319
10320	if (mac->mac_phy.task_60s)
10321		mac->mac_phy.task_60s(mac);
10322	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10323}
10324
10325static void
10326bwn_tasks(void *arg)
10327{
10328	struct bwn_mac *mac = arg;
10329	struct bwn_softc *sc = mac->mac_sc;
10330
10331	BWN_ASSERT_LOCKED(sc);
10332	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10333		return;
10334
10335	if (mac->mac_task_state % 4 == 0)
10336		bwn_task_60s(mac);
10337	if (mac->mac_task_state % 2 == 0)
10338		bwn_task_30s(mac);
10339	bwn_task_15s(mac);
10340
10341	mac->mac_task_state++;
10342	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10343}
10344
10345static int
10346bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10347{
10348	struct bwn_softc *sc = mac->mac_sc;
10349
10350	KASSERT(a == 0, ("not support APHY\n"));
10351
10352	switch (plcp->o.raw[0] & 0xf) {
10353	case 0xb:
10354		return (BWN_OFDM_RATE_6MB);
10355	case 0xf:
10356		return (BWN_OFDM_RATE_9MB);
10357	case 0xa:
10358		return (BWN_OFDM_RATE_12MB);
10359	case 0xe:
10360		return (BWN_OFDM_RATE_18MB);
10361	case 0x9:
10362		return (BWN_OFDM_RATE_24MB);
10363	case 0xd:
10364		return (BWN_OFDM_RATE_36MB);
10365	case 0x8:
10366		return (BWN_OFDM_RATE_48MB);
10367	case 0xc:
10368		return (BWN_OFDM_RATE_54MB);
10369	}
10370	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10371	    plcp->o.raw[0] & 0xf);
10372	return (-1);
10373}
10374
10375static int
10376bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10377{
10378	struct bwn_softc *sc = mac->mac_sc;
10379
10380	switch (plcp->o.raw[0]) {
10381	case 0x0a:
10382		return (BWN_CCK_RATE_1MB);
10383	case 0x14:
10384		return (BWN_CCK_RATE_2MB);
10385	case 0x37:
10386		return (BWN_CCK_RATE_5MB);
10387	case 0x6e:
10388		return (BWN_CCK_RATE_11MB);
10389	}
10390	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10391	return (-1);
10392}
10393
10394static void
10395bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10396    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10397    int rssi, int noise)
10398{
10399	struct bwn_softc *sc = mac->mac_sc;
10400	const struct ieee80211_frame_min *wh;
10401	uint64_t tsf;
10402	uint16_t low_mactime_now;
10403
10404	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10405		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10406
10407	wh = mtod(m, const struct ieee80211_frame_min *);
10408	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10409		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10410
10411	bwn_tsf_read(mac, &tsf);
10412	low_mactime_now = tsf;
10413	tsf = tsf & ~0xffffULL;
10414	tsf += le16toh(rxhdr->mac_time);
10415	if (low_mactime_now < le16toh(rxhdr->mac_time))
10416		tsf -= 0x10000;
10417
10418	sc->sc_rx_th.wr_tsf = tsf;
10419	sc->sc_rx_th.wr_rate = rate;
10420	sc->sc_rx_th.wr_antsignal = rssi;
10421	sc->sc_rx_th.wr_antnoise = noise;
10422}
10423
10424static void
10425bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10426{
10427	uint32_t low, high;
10428
10429	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10430	    ("%s:%d: fail", __func__, __LINE__));
10431
10432	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10433	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10434	*tsf = high;
10435	*tsf <<= 32;
10436	*tsf |= low;
10437}
10438
10439static int
10440bwn_dma_attach(struct bwn_mac *mac)
10441{
10442	struct bwn_dma *dma = &mac->mac_method.dma;
10443	struct bwn_softc *sc = mac->mac_sc;
10444	struct siba_dev_softc *sd = mac->mac_sd;
10445	struct siba_softc *siba = sd->sd_bus;
10446	bus_addr_t lowaddr = 0;
10447	int error;
10448
10449	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10450		return (0);
10451
10452	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10453
10454	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10455
10456	dma->dmatype = bwn_dma_gettype(mac);
10457	if (dma->dmatype == BWN_DMA_30BIT)
10458		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10459	else if (dma->dmatype == BWN_DMA_32BIT)
10460		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10461	else
10462		lowaddr = BUS_SPACE_MAXADDR;
10463
10464	/*
10465	 * Create top level DMA tag
10466	 */
10467	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10468			       BWN_ALIGN, 0,		/* alignment, bounds */
10469			       lowaddr,			/* lowaddr */
10470			       BUS_SPACE_MAXADDR,	/* highaddr */
10471			       NULL, NULL,		/* filter, filterarg */
10472			       MAXBSIZE,		/* maxsize */
10473			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10474			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10475			       0,			/* flags */
10476			       NULL, NULL,		/* lockfunc, lockarg */
10477			       &dma->parent_dtag);
10478	if (error) {
10479		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10480		return (error);
10481	}
10482
10483	/*
10484	 * Create TX/RX mbuf DMA tag
10485	 */
10486	error = bus_dma_tag_create(dma->parent_dtag,
10487				1,
10488				0,
10489				BUS_SPACE_MAXADDR,
10490				BUS_SPACE_MAXADDR,
10491				NULL, NULL,
10492				MCLBYTES,
10493				1,
10494				BUS_SPACE_MAXSIZE_32BIT,
10495				0,
10496				NULL, NULL,
10497				&dma->rxbuf_dtag);
10498	if (error) {
10499		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10500		goto fail0;
10501	}
10502	error = bus_dma_tag_create(dma->parent_dtag,
10503				1,
10504				0,
10505				BUS_SPACE_MAXADDR,
10506				BUS_SPACE_MAXADDR,
10507				NULL, NULL,
10508				MCLBYTES,
10509				1,
10510				BUS_SPACE_MAXSIZE_32BIT,
10511				0,
10512				NULL, NULL,
10513				&dma->txbuf_dtag);
10514	if (error) {
10515		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10516		goto fail1;
10517	}
10518
10519	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10520	if (!dma->wme[WME_AC_BK])
10521		goto fail2;
10522
10523	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10524	if (!dma->wme[WME_AC_BE])
10525		goto fail3;
10526
10527	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10528	if (!dma->wme[WME_AC_VI])
10529		goto fail4;
10530
10531	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10532	if (!dma->wme[WME_AC_VO])
10533		goto fail5;
10534
10535	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10536	if (!dma->mcast)
10537		goto fail6;
10538	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10539	if (!dma->rx)
10540		goto fail7;
10541
10542	return (error);
10543
10544fail7:	bwn_dma_ringfree(&dma->mcast);
10545fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10546fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10547fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10548fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10549fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10550fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10551fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10552	return (error);
10553}
10554
10555static struct bwn_dma_ring *
10556bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10557    uint16_t cookie, int *slot)
10558{
10559	struct bwn_dma *dma = &mac->mac_method.dma;
10560	struct bwn_dma_ring *dr;
10561	struct bwn_softc *sc = mac->mac_sc;
10562
10563	BWN_ASSERT_LOCKED(mac->mac_sc);
10564
10565	switch (cookie & 0xf000) {
10566	case 0x1000:
10567		dr = dma->wme[WME_AC_BK];
10568		break;
10569	case 0x2000:
10570		dr = dma->wme[WME_AC_BE];
10571		break;
10572	case 0x3000:
10573		dr = dma->wme[WME_AC_VI];
10574		break;
10575	case 0x4000:
10576		dr = dma->wme[WME_AC_VO];
10577		break;
10578	case 0x5000:
10579		dr = dma->mcast;
10580		break;
10581	default:
10582		KASSERT(0 == 1,
10583		    ("invalid cookie value %d", cookie & 0xf000));
10584	}
10585	*slot = (cookie & 0x0fff);
10586	if (*slot < 0 || *slot >= dr->dr_numslots) {
10587		/*
10588		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10589		 * that it occurs events which have same H/W sequence numbers.
10590		 * When it's occurred just prints a WARNING msgs and ignores.
10591		 */
10592		KASSERT(status->seq == dma->lastseq,
10593		    ("%s:%d: fail", __func__, __LINE__));
10594		device_printf(sc->sc_dev,
10595		    "out of slot ranges (0 < %d < %d)\n", *slot,
10596		    dr->dr_numslots);
10597		return (NULL);
10598	}
10599	dma->lastseq = status->seq;
10600	return (dr);
10601}
10602
10603static void
10604bwn_dma_stop(struct bwn_mac *mac)
10605{
10606	struct bwn_dma *dma;
10607
10608	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10609		return;
10610	dma = &mac->mac_method.dma;
10611
10612	bwn_dma_ringstop(&dma->rx);
10613	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10614	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10615	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10616	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10617	bwn_dma_ringstop(&dma->mcast);
10618}
10619
10620static void
10621bwn_dma_ringstop(struct bwn_dma_ring **dr)
10622{
10623
10624	if (dr == NULL)
10625		return;
10626
10627	bwn_dma_cleanup(*dr);
10628}
10629
10630static void
10631bwn_pio_stop(struct bwn_mac *mac)
10632{
10633	struct bwn_pio *pio;
10634
10635	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10636		return;
10637	pio = &mac->mac_method.pio;
10638
10639	bwn_destroy_queue_tx(&pio->mcast);
10640	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10641	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10642	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10643	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10644}
10645
10646static void
10647bwn_led_attach(struct bwn_mac *mac)
10648{
10649	struct bwn_softc *sc = mac->mac_sc;
10650	struct siba_softc *siba = mac->mac_sd->sd_bus;
10651	const uint8_t *led_act = NULL;
10652	uint16_t val[BWN_LED_MAX];
10653	int i;
10654
10655	sc->sc_led_idle = (2350 * hz) / 1000;
10656	sc->sc_led_blink = 1;
10657
10658	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10659		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10660			led_act = bwn_vendor_led_act[i].led_act;
10661			break;
10662		}
10663	}
10664	if (led_act == NULL)
10665		led_act = bwn_default_led_act;
10666
10667	val[0] = siba->siba_sprom.gpio0;
10668	val[1] = siba->siba_sprom.gpio1;
10669	val[2] = siba->siba_sprom.gpio2;
10670	val[3] = siba->siba_sprom.gpio3;
10671
10672	for (i = 0; i < BWN_LED_MAX; ++i) {
10673		struct bwn_led *led = &sc->sc_leds[i];
10674
10675		if (val[i] == 0xff) {
10676			led->led_act = led_act[i];
10677		} else {
10678			if (val[i] & BWN_LED_ACT_LOW)
10679				led->led_flags |= BWN_LED_F_ACTLOW;
10680			led->led_act = val[i] & BWN_LED_ACT_MASK;
10681		}
10682		led->led_mask = (1 << i);
10683
10684		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10685		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10686		    led->led_act == BWN_LED_ACT_BLINK) {
10687			led->led_flags |= BWN_LED_F_BLINK;
10688			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10689				led->led_flags |= BWN_LED_F_POLLABLE;
10690			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10691				led->led_flags |= BWN_LED_F_SLOW;
10692
10693			if (sc->sc_blink_led == NULL) {
10694				sc->sc_blink_led = led;
10695				if (led->led_flags & BWN_LED_F_SLOW)
10696					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10697			}
10698		}
10699
10700		DPRINTF(sc, BWN_DEBUG_LED,
10701		    "%dth led, act %d, lowact %d\n", i,
10702		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10703	}
10704	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10705}
10706
10707static __inline uint16_t
10708bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10709{
10710
10711	if (led->led_flags & BWN_LED_F_ACTLOW)
10712		on = !on;
10713	if (on)
10714		val |= led->led_mask;
10715	else
10716		val &= ~led->led_mask;
10717	return val;
10718}
10719
10720static void
10721bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10722{
10723	struct bwn_softc *sc = mac->mac_sc;
10724	struct ifnet *ifp = sc->sc_ifp;
10725	struct ieee80211com *ic = ifp->if_l2com;
10726	uint16_t val;
10727	int i;
10728
10729	if (nstate == IEEE80211_S_INIT) {
10730		callout_stop(&sc->sc_led_blink_ch);
10731		sc->sc_led_blinking = 0;
10732	}
10733
10734	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10735		return;
10736
10737	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10738	for (i = 0; i < BWN_LED_MAX; ++i) {
10739		struct bwn_led *led = &sc->sc_leds[i];
10740		int on;
10741
10742		if (led->led_act == BWN_LED_ACT_UNKN ||
10743		    led->led_act == BWN_LED_ACT_NULL)
10744			continue;
10745
10746		if ((led->led_flags & BWN_LED_F_BLINK) &&
10747		    nstate != IEEE80211_S_INIT)
10748			continue;
10749
10750		switch (led->led_act) {
10751		case BWN_LED_ACT_ON:    /* Always on */
10752			on = 1;
10753			break;
10754		case BWN_LED_ACT_OFF:   /* Always off */
10755		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10756			on = 0;
10757			break;
10758		default:
10759			on = 1;
10760			switch (nstate) {
10761			case IEEE80211_S_INIT:
10762				on = 0;
10763				break;
10764			case IEEE80211_S_RUN:
10765				if (led->led_act == BWN_LED_ACT_11G &&
10766				    ic->ic_curmode != IEEE80211_MODE_11G)
10767					on = 0;
10768				break;
10769			default:
10770				if (led->led_act == BWN_LED_ACT_ASSOC)
10771					on = 0;
10772				break;
10773			}
10774			break;
10775		}
10776
10777		val = bwn_led_onoff(led, val, on);
10778	}
10779	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10780}
10781
10782static void
10783bwn_led_event(struct bwn_mac *mac, int event)
10784{
10785	struct bwn_softc *sc = mac->mac_sc;
10786        struct bwn_led *led = sc->sc_blink_led;
10787        int rate;
10788
10789        if (event == BWN_LED_EVENT_POLL) {
10790                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10791                        return;
10792                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10793                        return;
10794        }
10795
10796        sc->sc_led_ticks = ticks;
10797        if (sc->sc_led_blinking)
10798                return;
10799
10800        switch (event) {
10801        case BWN_LED_EVENT_RX:
10802                rate = sc->sc_rx_rate;
10803                break;
10804        case BWN_LED_EVENT_TX:
10805                rate = sc->sc_tx_rate;
10806                break;
10807        case BWN_LED_EVENT_POLL:
10808                rate = 0;
10809                break;
10810        default:
10811                panic("unknown LED event %d\n", event);
10812                break;
10813        }
10814        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10815            bwn_led_duration[rate].off_dur);
10816}
10817
10818static void
10819bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10820{
10821	struct bwn_softc *sc = mac->mac_sc;
10822        struct bwn_led *led = sc->sc_blink_led;
10823        uint16_t val;
10824
10825        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10826        val = bwn_led_onoff(led, val, 1);
10827        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10828
10829        if (led->led_flags & BWN_LED_F_SLOW) {
10830                BWN_LED_SLOWDOWN(on_dur);
10831                BWN_LED_SLOWDOWN(off_dur);
10832        }
10833
10834        sc->sc_led_blinking = 1;
10835        sc->sc_led_blink_offdur = off_dur;
10836
10837        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10838}
10839
10840static void
10841bwn_led_blink_next(void *arg)
10842{
10843	struct bwn_mac *mac = arg;
10844        struct bwn_softc *sc = mac->mac_sc;
10845        uint16_t val;
10846
10847        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10848        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10849        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10850
10851        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10852            bwn_led_blink_end, mac);
10853}
10854
10855static void
10856bwn_led_blink_end(void *arg)
10857{
10858	struct bwn_mac *mac = arg;
10859        struct bwn_softc *sc = mac->mac_sc;
10860
10861        sc->sc_led_blinking = 0;
10862}
10863
10864static int
10865bwn_suspend(device_t dev)
10866{
10867	struct bwn_softc *sc = device_get_softc(dev);
10868
10869	bwn_stop(sc, 1);
10870	return (0);
10871}
10872
10873static int
10874bwn_resume(device_t dev)
10875{
10876	struct bwn_softc *sc = device_get_softc(dev);
10877	struct ifnet *ifp = sc->sc_ifp;
10878
10879	if (ifp->if_flags & IFF_UP)
10880		bwn_init(sc);
10881	return (0);
10882}
10883
10884static void
10885bwn_rfswitch(void *arg)
10886{
10887	struct bwn_softc *sc = arg;
10888	struct bwn_mac *mac = sc->sc_curmac;
10889	int cur = 0, prev = 0;
10890
10891	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10892	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10893
10894	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10895		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10896			& BWN_RF_HWENABLED_HI_MASK))
10897			cur = 1;
10898	} else {
10899		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10900		    & BWN_RF_HWENABLED_LO_MASK)
10901			cur = 1;
10902	}
10903
10904	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10905		prev = 1;
10906
10907	if (cur != prev) {
10908		if (cur)
10909			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10910		else
10911			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10912
10913		device_printf(sc->sc_dev,
10914		    "status of RF switch is changed to %s\n",
10915		    cur ? "ON" : "OFF");
10916		if (cur != mac->mac_phy.rf_on) {
10917			if (cur)
10918				bwn_rf_turnon(mac);
10919			else
10920				bwn_rf_turnoff(mac);
10921		}
10922	}
10923
10924	callout_schedule(&sc->sc_rfswitch_ch, hz);
10925}
10926
10927static void
10928bwn_phy_lp_init_pre(struct bwn_mac *mac)
10929{
10930	struct bwn_phy *phy = &mac->mac_phy;
10931	struct bwn_phy_lp *plp = &phy->phy_lp;
10932
10933	plp->plp_antenna = BWN_ANT_DEFAULT;
10934}
10935
10936static int
10937bwn_phy_lp_init(struct bwn_mac *mac)
10938{
10939	static const struct bwn_stxtable tables[] = {
10940		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10941		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10942		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10943		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10944		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10945		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10946		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10947		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10948		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10949		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10950		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10951		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10952		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10953		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10954		{ 2, 11, 0x40, 0, 0x0f }
10955	};
10956	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10957	struct bwn_softc *sc = mac->mac_sc;
10958	const struct bwn_stxtable *st;
10959	struct ifnet *ifp = sc->sc_ifp;
10960	struct ieee80211com *ic = ifp->if_l2com;
10961	int i, error;
10962	uint16_t tmp;
10963
10964	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10965	bwn_phy_lp_bbinit(mac);
10966
10967	/* initialize RF */
10968	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10969	DELAY(1);
10970	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10971	DELAY(1);
10972
10973	if (mac->mac_phy.rf_ver == 0x2062)
10974		bwn_phy_lp_b2062_init(mac);
10975	else {
10976		bwn_phy_lp_b2063_init(mac);
10977
10978		/* synchronize stx table. */
10979		for (i = 0; i < N(tables); i++) {
10980			st = &tables[i];
10981			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10982			tmp >>= st->st_rfshift;
10983			tmp <<= st->st_physhift;
10984			BWN_PHY_SETMASK(mac,
10985			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10986			    ~(st->st_mask << st->st_physhift), tmp);
10987		}
10988
10989		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10990		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10991	}
10992
10993	/* calibrate RC */
10994	if (mac->mac_phy.rev >= 2)
10995		bwn_phy_lp_rxcal_r2(mac);
10996	else if (!plp->plp_rccap) {
10997		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10998			bwn_phy_lp_rccal_r12(mac);
10999	} else
11000		bwn_phy_lp_set_rccap(mac);
11001
11002	error = bwn_phy_lp_switch_channel(mac, 7);
11003	if (error)
11004		device_printf(sc->sc_dev,
11005		    "failed to change channel 7 (%d)\n", error);
11006	bwn_phy_lp_txpctl_init(mac);
11007	bwn_phy_lp_calib(mac);
11008	return (0);
11009}
11010
11011static uint16_t
11012bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11013{
11014
11015	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11016	return (BWN_READ_2(mac, BWN_PHYDATA));
11017}
11018
11019static void
11020bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11021{
11022
11023	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11024	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11025}
11026
11027static void
11028bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11029    uint16_t set)
11030{
11031
11032	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11033	BWN_WRITE_2(mac, BWN_PHYDATA,
11034	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11035}
11036
11037static uint16_t
11038bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11039{
11040
11041	KASSERT(reg != 1, ("unaccessible register %d", reg));
11042	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11043		reg |= 0x100;
11044	if (mac->mac_phy.rev >= 2)
11045		reg |= 0x200;
11046	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11047	return BWN_READ_2(mac, BWN_RFDATALO);
11048}
11049
11050static void
11051bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11052{
11053
11054	KASSERT(reg != 1, ("unaccessible register %d", reg));
11055	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11056	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11057}
11058
11059static void
11060bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11061{
11062
11063	if (on) {
11064		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11065		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11066		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11067		return;
11068	}
11069
11070	if (mac->mac_phy.rev >= 2) {
11071		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11072		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11073		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11074		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11075		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11076		return;
11077	}
11078
11079	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11080	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11081	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11082	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11083}
11084
11085static int
11086bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11087{
11088	struct bwn_phy *phy = &mac->mac_phy;
11089	struct bwn_phy_lp *plp = &phy->phy_lp;
11090	int error;
11091
11092	if (phy->rf_ver == 0x2063) {
11093		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11094		if (error)
11095			return (error);
11096	} else {
11097		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11098		if (error)
11099			return (error);
11100		bwn_phy_lp_set_anafilter(mac, chan);
11101		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11102	}
11103
11104	plp->plp_chan = chan;
11105	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11106	return (0);
11107}
11108
11109static uint32_t
11110bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11111{
11112	struct bwn_softc *sc = mac->mac_sc;
11113	struct ifnet *ifp = sc->sc_ifp;
11114	struct ieee80211com *ic = ifp->if_l2com;
11115
11116	device_printf(sc->sc_dev, "correct?\n");
11117
11118	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11119}
11120
11121static void
11122bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11123{
11124	struct bwn_phy *phy = &mac->mac_phy;
11125	struct bwn_phy_lp *plp = &phy->phy_lp;
11126
11127	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11128		return;
11129
11130	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11131	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11132	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11133	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11134	plp->plp_antenna = antenna;
11135}
11136
11137static void
11138bwn_phy_lp_task_60s(struct bwn_mac *mac)
11139{
11140
11141	bwn_phy_lp_calib(mac);
11142}
11143
11144static void
11145bwn_phy_lp_readsprom(struct bwn_mac *mac)
11146{
11147	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11148	struct bwn_softc *sc = mac->mac_sc;
11149	struct ifnet *ifp = sc->sc_ifp;
11150	struct ieee80211com *ic = ifp->if_l2com;
11151	struct siba_dev_softc *sd = mac->mac_sd;
11152	struct siba_softc *siba = sd->sd_bus;
11153	struct siba_sprom *sprom = &siba->siba_sprom;
11154
11155	device_printf(sc->sc_dev, "XXX using %dghz\n",
11156	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11157
11158	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11159		plp->plp_txisoband_m = sprom->tri2g;
11160		plp->plp_bxarch = sprom->bxa2g;
11161		plp->plp_rxpwroffset = sprom->rxpo2g;
11162		plp->plp_rssivf = sprom->rssismf2g;
11163		plp->plp_rssivc = sprom->rssismc2g;
11164		plp->plp_rssigs = sprom->rssisav2g;
11165		return;
11166	}
11167
11168	plp->plp_txisoband_l = sprom->tri5gl;
11169	plp->plp_txisoband_m = sprom->tri5g;
11170	plp->plp_txisoband_h = sprom->tri5gh;
11171	plp->plp_bxarch = sprom->bxa5g;
11172	plp->plp_rxpwroffset = sprom->rxpo5g;
11173	plp->plp_rssivf = sprom->rssismf5g;
11174	plp->plp_rssivc = sprom->rssismc5g;
11175	plp->plp_rssigs = sprom->rssisav5g;
11176}
11177
11178static void
11179bwn_phy_lp_bbinit(struct bwn_mac *mac)
11180{
11181
11182	bwn_phy_lp_tblinit(mac);
11183	if (mac->mac_phy.rev >= 2)
11184		bwn_phy_lp_bbinit_r2(mac);
11185	else
11186		bwn_phy_lp_bbinit_r01(mac);
11187}
11188
11189static void
11190bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11191{
11192	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11193	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11194	struct bwn_softc *sc = mac->mac_sc;
11195	struct ifnet *ifp = sc->sc_ifp;
11196	struct ieee80211com *ic = ifp->if_l2com;
11197
11198	bwn_phy_lp_set_txgain(mac,
11199	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11200	bwn_phy_lp_set_bbmult(mac, 150);
11201}
11202
11203static void
11204bwn_phy_lp_calib(struct bwn_mac *mac)
11205{
11206	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11207	struct siba_dev_softc *sd = mac->mac_sd;
11208	struct siba_softc *siba = sd->sd_bus;
11209	struct bwn_softc *sc = mac->mac_sc;
11210	struct ifnet *ifp = sc->sc_ifp;
11211	struct ieee80211com *ic = ifp->if_l2com;
11212	const struct bwn_rxcompco *rc = NULL;
11213	struct bwn_txgain ogain;
11214	int i, omode, oafeovr, orf, obbmult;
11215	uint8_t mode, fc = 0;
11216
11217	if (plp->plp_chanfullcal != plp->plp_chan) {
11218		plp->plp_chanfullcal = plp->plp_chan;
11219		fc = 1;
11220	}
11221
11222	bwn_mac_suspend(mac);
11223
11224	/* BlueTooth Coexistance Override */
11225	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11226	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11227
11228	if (mac->mac_phy.rev >= 2)
11229		bwn_phy_lp_digflt_save(mac);
11230	bwn_phy_lp_get_txpctlmode(mac);
11231	mode = plp->plp_txpctlmode;
11232	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11233	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11234		bwn_phy_lp_bugfix(mac);
11235	if (mac->mac_phy.rev >= 2 && fc == 1) {
11236		bwn_phy_lp_get_txpctlmode(mac);
11237		omode = plp->plp_txpctlmode;
11238		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11239		if (oafeovr)
11240			ogain = bwn_phy_lp_get_txgain(mac);
11241		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11242		obbmult = bwn_phy_lp_get_bbmult(mac);
11243		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11244		if (oafeovr)
11245			bwn_phy_lp_set_txgain(mac, &ogain);
11246		bwn_phy_lp_set_bbmult(mac, obbmult);
11247		bwn_phy_lp_set_txpctlmode(mac, omode);
11248		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11249	}
11250	bwn_phy_lp_set_txpctlmode(mac, mode);
11251	if (mac->mac_phy.rev >= 2)
11252		bwn_phy_lp_digflt_restore(mac);
11253
11254	/* do RX IQ Calculation; assumes that noise is true. */
11255	if (siba->siba_chipid == 0x5354) {
11256		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11257			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11258				rc = &bwn_rxcompco_5354[i];
11259		}
11260	} else if (mac->mac_phy.rev >= 2)
11261		rc = &bwn_rxcompco_r2;
11262	else {
11263		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11264			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11265				rc = &bwn_rxcompco_r12[i];
11266		}
11267	}
11268	if (rc == NULL)
11269		goto fail;
11270
11271	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11272	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11273
11274	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11275
11276	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11277		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11278		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11279	} else {
11280		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11281		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11282	}
11283
11284	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11285	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11286	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11287	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11288	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11289	bwn_phy_lp_set_deaf(mac, 0);
11290	/* XXX no checking return value? */
11291	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11292	bwn_phy_lp_clear_deaf(mac, 0);
11293	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11294	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11295	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11296
11297	/* disable RX GAIN override. */
11298	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11299	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11300	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11301	if (mac->mac_phy.rev >= 2) {
11302		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11303		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11304			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11305			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11306		}
11307	} else {
11308		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11309	}
11310
11311	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11312	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11313fail:
11314	bwn_mac_enable(mac);
11315}
11316
11317static void
11318bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11319{
11320
11321       if (on) {
11322               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11323	       return;
11324       }
11325
11326       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11327       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11328}
11329
11330static int
11331bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11332{
11333	struct siba_dev_softc *sd = mac->mac_sd;
11334	struct siba_softc *siba = sd->sd_bus;
11335	static const struct bwn_b206x_chan *bc = NULL;
11336	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11337	    tmp[6];
11338	uint16_t old, scale, tmp16;
11339	int i, div;
11340
11341	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11342		if (bwn_b2063_chantable[i].bc_chan == chan) {
11343			bc = &bwn_b2063_chantable[i];
11344			break;
11345		}
11346	}
11347	if (bc == NULL)
11348		return (EINVAL);
11349
11350	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11351	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11352	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11353	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11354	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11355	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11356	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11357	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11358	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11359	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11360	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11361	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11362
11363	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11364	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11365
11366	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11367	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11368	freqref = freqxtal * 3;
11369	div = (freqxtal <= 26000000 ? 1 : 2);
11370	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11371	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11372		999999) / 1000000) + 1;
11373
11374	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11375	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11376	    0xfff8, timeout >> 2);
11377	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11378	    0xff9f,timeout << 5);
11379	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11380
11381	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11382	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11383	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11384
11385	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11386	    (timeoutref + 1)) - 1;
11387	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11388	    0xf0, count >> 8);
11389	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11390
11391	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11392	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11393	while (tmp[1] >= freqref) {
11394		tmp[0]++;
11395		tmp[1] -= freqref;
11396	}
11397	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11398	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11399	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11400	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11401	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11402
11403	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11404	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11405	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11406	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11407
11408	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11409	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11410
11411	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11412		scale = 1;
11413		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11414	} else {
11415		scale = 0;
11416		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11417	}
11418	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11419	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11420
11421	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11422	    (scale + 1);
11423	if (tmp[5] > 150)
11424		tmp[5] = 0;
11425
11426	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11427	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11428
11429	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11430	if (freqxtal > 26000000)
11431		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11432	else
11433		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11434
11435	if (val[0] == 45)
11436		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11437	else
11438		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11439
11440	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11441	DELAY(1);
11442	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11443
11444	/* VCO Calibration */
11445	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11446	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11447	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11448	DELAY(1);
11449	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11450	DELAY(1);
11451	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11452	DELAY(1);
11453	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11454	DELAY(300);
11455	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11456
11457	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11458	return (0);
11459}
11460
11461static int
11462bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11463{
11464	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11465	struct siba_dev_softc *sd = mac->mac_sd;
11466	struct siba_softc *siba = sd->sd_bus;
11467	const struct bwn_b206x_chan *bc = NULL;
11468	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11469	uint32_t tmp[9];
11470	int i;
11471
11472	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11473		if (bwn_b2062_chantable[i].bc_chan == chan) {
11474			bc = &bwn_b2062_chantable[i];
11475			break;
11476		}
11477	}
11478
11479	if (bc == NULL)
11480		return (EINVAL);
11481
11482	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11483	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11484	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11485	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11486	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11487	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11488	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11489	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11490	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11491	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11492
11493	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11494	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11495	bwn_phy_lp_b2062_reset_pllbias(mac);
11496	tmp[0] = freqxtal / 1000;
11497	tmp[1] = plp->plp_div * 1000;
11498	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11499	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11500		tmp[2] *= 2;
11501	tmp[3] = 48 * tmp[0];
11502	tmp[5] = tmp[2] / tmp[3];
11503	tmp[6] = tmp[2] % tmp[3];
11504	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11505	tmp[4] = tmp[6] * 0x100;
11506	tmp[5] = tmp[4] / tmp[3];
11507	tmp[6] = tmp[4] % tmp[3];
11508	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11509	tmp[4] = tmp[6] * 0x100;
11510	tmp[5] = tmp[4] / tmp[3];
11511	tmp[6] = tmp[4] % tmp[3];
11512	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11513	tmp[4] = tmp[6] * 0x100;
11514	tmp[5] = tmp[4] / tmp[3];
11515	tmp[6] = tmp[4] % tmp[3];
11516	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11517	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11518	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11519	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11520	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11521	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11522
11523	bwn_phy_lp_b2062_vco_calib(mac);
11524	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11525		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11526		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11527		bwn_phy_lp_b2062_reset_pllbias(mac);
11528		bwn_phy_lp_b2062_vco_calib(mac);
11529		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11530			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11531			return (EIO);
11532		}
11533	}
11534	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11535	return (0);
11536}
11537
11538static void
11539bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11540{
11541	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11542	uint16_t tmp = (channel == 14);
11543
11544	if (mac->mac_phy.rev < 2) {
11545		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11546		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11547			bwn_phy_lp_set_rccap(mac);
11548		return;
11549	}
11550
11551	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11552}
11553
11554static void
11555bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11556{
11557	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11558	struct bwn_softc *sc = mac->mac_sc;
11559	struct ifnet *ifp = sc->sc_ifp;
11560	struct ieee80211com *ic = ifp->if_l2com;
11561	uint16_t iso, tmp[3];
11562
11563	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11564
11565	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11566		iso = plp->plp_txisoband_m;
11567	else if (freq <= 5320)
11568		iso = plp->plp_txisoband_l;
11569	else if (freq <= 5700)
11570		iso = plp->plp_txisoband_m;
11571	else
11572		iso = plp->plp_txisoband_h;
11573
11574	tmp[0] = ((iso - 26) / 12) << 12;
11575	tmp[1] = tmp[0] + 0x1000;
11576	tmp[2] = tmp[0] + 0x2000;
11577
11578	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11579	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11580}
11581
11582static void
11583bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11584{
11585	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11586	int i;
11587	static const uint16_t addr[] = {
11588		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11589		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11590		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11591		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11592		BWN_PHY_OFDM(0xcf),
11593	};
11594	static const uint16_t val[] = {
11595		0xde5e, 0xe832, 0xe331, 0x4d26,
11596		0x0026, 0x1420, 0x0020, 0xfe08,
11597		0x0008,
11598	};
11599
11600	for (i = 0; i < N(addr); i++) {
11601		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11602		BWN_PHY_WRITE(mac, addr[i], val[i]);
11603	}
11604}
11605
11606static void
11607bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11608{
11609	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11610	struct bwn_softc *sc = mac->mac_sc;
11611	uint16_t ctl;
11612
11613	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11614	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11615	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11616		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11617		break;
11618	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11619		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11620		break;
11621	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11622		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11623		break;
11624	default:
11625		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11626		device_printf(sc->sc_dev, "unknown command mode\n");
11627		break;
11628	}
11629}
11630
11631static void
11632bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11633{
11634	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11635	uint16_t ctl;
11636	uint8_t old;
11637
11638	bwn_phy_lp_get_txpctlmode(mac);
11639	old = plp->plp_txpctlmode;
11640	if (old == mode)
11641		return;
11642	plp->plp_txpctlmode = mode;
11643
11644	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11645		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11646		    plp->plp_tssiidx);
11647		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11648		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11649
11650		/* disable TX GAIN override */
11651		if (mac->mac_phy.rev < 2)
11652			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11653		else {
11654			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11655			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11656		}
11657		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11658
11659		plp->plp_txpwridx = -1;
11660	}
11661	if (mac->mac_phy.rev >= 2) {
11662		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11663			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11664		else
11665			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11666	}
11667
11668	/* writes TX Power Control mode */
11669	switch (plp->plp_txpctlmode) {
11670	case BWN_PHYLP_TXPCTL_OFF:
11671		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11672		break;
11673	case BWN_PHYLP_TXPCTL_ON_HW:
11674		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11675		break;
11676	case BWN_PHYLP_TXPCTL_ON_SW:
11677		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11678		break;
11679	default:
11680		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11681	}
11682	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11683	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11684}
11685
11686static void
11687bwn_phy_lp_bugfix(struct bwn_mac *mac)
11688{
11689	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11690	struct bwn_softc *sc = mac->mac_sc;
11691	const unsigned int size = 256;
11692	struct bwn_txgain tg;
11693	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11694	uint16_t tssinpt, tssiidx, value[2];
11695	uint8_t mode;
11696	int8_t txpwridx;
11697
11698	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11699	    M_NOWAIT | M_ZERO);
11700	if (tabs == NULL) {
11701		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11702		return;
11703	}
11704
11705	bwn_phy_lp_get_txpctlmode(mac);
11706	mode = plp->plp_txpctlmode;
11707	txpwridx = plp->plp_txpwridx;
11708	tssinpt = plp->plp_tssinpt;
11709	tssiidx = plp->plp_tssiidx;
11710
11711	bwn_tab_read_multi(mac,
11712	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11713	    BWN_TAB_4(7, 0x140), size, tabs);
11714
11715	bwn_phy_lp_tblinit(mac);
11716	bwn_phy_lp_bbinit(mac);
11717	bwn_phy_lp_txpctl_init(mac);
11718	bwn_phy_lp_rf_onoff(mac, 1);
11719	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11720
11721	bwn_tab_write_multi(mac,
11722	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11723	    BWN_TAB_4(7, 0x140), size, tabs);
11724
11725	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11726	plp->plp_tssinpt = tssinpt;
11727	plp->plp_tssiidx = tssiidx;
11728	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11729	if (txpwridx != -1) {
11730		/* set TX power by index */
11731		plp->plp_txpwridx = txpwridx;
11732		bwn_phy_lp_get_txpctlmode(mac);
11733		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11734			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11735		if (mac->mac_phy.rev >= 2) {
11736			rxcomp = bwn_tab_read(mac,
11737			    BWN_TAB_4(7, txpwridx + 320));
11738			txgain = bwn_tab_read(mac,
11739			    BWN_TAB_4(7, txpwridx + 192));
11740			tg.tg_pad = (txgain >> 16) & 0xff;
11741			tg.tg_gm = txgain & 0xff;
11742			tg.tg_pga = (txgain >> 8) & 0xff;
11743			tg.tg_dac = (rxcomp >> 28) & 0xff;
11744			bwn_phy_lp_set_txgain(mac, &tg);
11745		} else {
11746			rxcomp = bwn_tab_read(mac,
11747			    BWN_TAB_4(10, txpwridx + 320));
11748			txgain = bwn_tab_read(mac,
11749			    BWN_TAB_4(10, txpwridx + 192));
11750			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11751			    0xf800, (txgain >> 4) & 0x7fff);
11752			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11753			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11754		}
11755		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11756
11757		/* set TX IQCC */
11758		value[0] = (rxcomp >> 10) & 0x3ff;
11759		value[1] = rxcomp & 0x3ff;
11760		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11761
11762		coeff = bwn_tab_read(mac,
11763		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11764		    BWN_TAB_4(10, txpwridx + 448));
11765		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11766		if (mac->mac_phy.rev >= 2) {
11767			rfpwr = bwn_tab_read(mac,
11768			    BWN_TAB_4(7, txpwridx + 576));
11769			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11770			    rfpwr & 0xffff);
11771		}
11772		bwn_phy_lp_set_txgain_override(mac);
11773	}
11774	if (plp->plp_rccap)
11775		bwn_phy_lp_set_rccap(mac);
11776	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11777	bwn_phy_lp_set_txpctlmode(mac, mode);
11778	free(tabs, M_DEVBUF);
11779}
11780
11781static void
11782bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11783{
11784	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11785	int i;
11786	static const uint16_t addr[] = {
11787		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11788		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11789		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11790		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11791		BWN_PHY_OFDM(0xcf),
11792	};
11793
11794	for (i = 0; i < N(addr); i++)
11795		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11796}
11797
11798static void
11799bwn_phy_lp_tblinit(struct bwn_mac *mac)
11800{
11801	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11802
11803	if (mac->mac_phy.rev < 2) {
11804		bwn_phy_lp_tblinit_r01(mac);
11805		bwn_phy_lp_tblinit_txgain(mac);
11806		bwn_phy_lp_set_gaintbl(mac, freq);
11807		return;
11808	}
11809
11810	bwn_phy_lp_tblinit_r2(mac);
11811	bwn_phy_lp_tblinit_txgain(mac);
11812}
11813
11814struct bwn_wpair {
11815	uint16_t		reg;
11816	uint16_t		value;
11817};
11818
11819struct bwn_smpair {
11820	uint16_t		offset;
11821	uint16_t		mask;
11822	uint16_t		set;
11823};
11824
11825static void
11826bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11827{
11828	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11829	struct siba_dev_softc *sd = mac->mac_sd;
11830	struct siba_softc *siba = sd->sd_bus;
11831	struct bwn_softc *sc = mac->mac_sc;
11832	struct ifnet *ifp = sc->sc_ifp;
11833	struct ieee80211com *ic = ifp->if_l2com;
11834	static const struct bwn_wpair v1[] = {
11835		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11836		{ BWN_PHY_AFE_CTL, 0x8800 },
11837		{ BWN_PHY_AFE_CTL_OVR, 0 },
11838		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11839		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11840		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11841		{ BWN_PHY_OFDM(0xf9), 0 },
11842		{ BWN_PHY_TR_LOOKUP_1, 0 }
11843	};
11844	static const struct bwn_smpair v2[] = {
11845		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11846		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11847		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11848		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11849		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11850	};
11851	static const struct bwn_smpair v3[] = {
11852		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11853		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11854		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11855		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11856		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11857		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11858		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11859		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11860		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11861		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11862
11863	};
11864	int i;
11865
11866	for (i = 0; i < N(v1); i++)
11867		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11868	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11869	for (i = 0; i < N(v2); i++)
11870		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11871
11872	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11873	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11874	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11875	if (siba->siba_board_rev >= 0x18) {
11876		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11877		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11878	} else {
11879		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11880	}
11881	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11882	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11883	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11884	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11885	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11886	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11887	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11888	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11889	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11890	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11891	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11892	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11893		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11894		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11895	} else {
11896		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11897		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11898	}
11899	for (i = 0; i < N(v3); i++)
11900		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11901	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11902		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11903		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11904	}
11905
11906	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11907		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11908		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11909		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11910		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11911		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11912		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11913	} else
11914		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11915
11916	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11917	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11918	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11919	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11920	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11921	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11922	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11923	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11924	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11925
11926	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11927		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11928		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11929		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11930	}
11931
11932	bwn_phy_lp_digflt_save(mac);
11933}
11934
11935static void
11936bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11937{
11938	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11939	struct siba_dev_softc *sd = mac->mac_sd;
11940	struct siba_softc *siba = sd->sd_bus;
11941	struct bwn_softc *sc = mac->mac_sc;
11942	struct ifnet *ifp = sc->sc_ifp;
11943	struct ieee80211com *ic = ifp->if_l2com;
11944	static const struct bwn_smpair v1[] = {
11945		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11946		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11947		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11948		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11949		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11950		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11951		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11952	};
11953	static const struct bwn_smpair v2[] = {
11954		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11955		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11956		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11957		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11958		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11959		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11960		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11961		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11962		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11963		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11964		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11965		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11966		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11967		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11968		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11969		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11970	};
11971	static const struct bwn_smpair v3[] = {
11972		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11973		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11974		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11975		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11976		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11977		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11978		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11979		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11980	};
11981	static const struct bwn_smpair v4[] = {
11982		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11983		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11984		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11985		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11986		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11987		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11988		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11989		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11990	};
11991	static const struct bwn_smpair v5[] = {
11992		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11993		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11994		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11995		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11996		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11997		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11998		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11999		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
12000	};
12001	int i;
12002	uint16_t tmp, tmp2;
12003
12004	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
12005	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
12006	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
12007	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
12008	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
12009	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
12010	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
12011	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12012	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12013	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12014	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12015	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12016	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12017	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12018	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12019	for (i = 0; i < N(v1); i++)
12020		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12021	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12022	    0xff00, plp->plp_rxpwroffset);
12023	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12024	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12025	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12026		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12027		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12028		if (mac->mac_phy.rev == 0)
12029			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12030			    0xffcf, 0x0010);
12031		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12032	} else {
12033		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12034		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12035		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12036	}
12037	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12038	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12039	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12040		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12041	else
12042		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12043	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12044	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12045	    0xfff9, (plp->plp_bxarch << 1));
12046	if (mac->mac_phy.rev == 1 &&
12047	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12048		for (i = 0; i < N(v2); i++)
12049			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12050			    v2[i].set);
12051	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12052	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12053	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12054		for (i = 0; i < N(v3); i++)
12055			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12056			    v3[i].set);
12057	} else if (mac->mac_phy.rev == 1 ||
12058		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12059		for (i = 0; i < N(v4); i++)
12060			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12061			    v4[i].set);
12062	} else {
12063		for (i = 0; i < N(v5); i++)
12064			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12065			    v5[i].set);
12066	}
12067	if (mac->mac_phy.rev == 1 &&
12068	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12069		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12070		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12071		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12072		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12073	}
12074	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12075	    (siba->siba_chipid == 0x5354) &&
12076	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12077		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12078		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12079		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12080		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12081	}
12082	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12083		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12084		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12085		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12086		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12087		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12088		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12089		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12090		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12091	} else {
12092		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12093		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12094	}
12095	if (mac->mac_phy.rev == 1) {
12096		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12097		tmp2 = (tmp & 0x03e0) >> 5;
12098		tmp2 |= tmp2 << 5;
12099		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12100		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12101		tmp2 = (tmp & 0x1f00) >> 8;
12102		tmp2 |= tmp2 << 5;
12103		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12104		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12105		tmp2 = tmp & 0x00ff;
12106		tmp2 |= tmp << 8;
12107		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12108	}
12109}
12110
12111struct bwn_b2062_freq {
12112	uint16_t		freq;
12113	uint8_t			value[6];
12114};
12115
12116static void
12117bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12118{
12119#define	CALC_CTL7(freq, div)						\
12120	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12121#define	CALC_CTL18(freq, div)						\
12122	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12123#define	CALC_CTL19(freq, div)						\
12124	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12125	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12126	struct siba_dev_softc *sd = mac->mac_sd;
12127	struct siba_softc *siba = sd->sd_bus;
12128	struct bwn_softc *sc = mac->mac_sc;
12129	struct ifnet *ifp = sc->sc_ifp;
12130	struct ieee80211com *ic = ifp->if_l2com;
12131	static const struct bwn_b2062_freq freqdata_tab[] = {
12132		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12133		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12134		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12135		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12136		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12137		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12138	};
12139	static const struct bwn_wpair v1[] = {
12140		{ BWN_B2062_N_TXCTL3, 0 },
12141		{ BWN_B2062_N_TXCTL4, 0 },
12142		{ BWN_B2062_N_TXCTL5, 0 },
12143		{ BWN_B2062_N_TXCTL6, 0 },
12144		{ BWN_B2062_N_PDNCTL0, 0x40 },
12145		{ BWN_B2062_N_PDNCTL0, 0 },
12146		{ BWN_B2062_N_CALIB_TS, 0x10 },
12147		{ BWN_B2062_N_CALIB_TS, 0 }
12148	};
12149	const struct bwn_b2062_freq *f = NULL;
12150	uint32_t xtalfreq, ref;
12151	unsigned int i;
12152
12153	bwn_phy_lp_b2062_tblinit(mac);
12154
12155	for (i = 0; i < N(v1); i++)
12156		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157	if (mac->mac_phy.rev > 0)
12158		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12159		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12160	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12161		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12162	else
12163		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12164
12165	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12166	    ("%s:%d: fail", __func__, __LINE__));
12167	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12168	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12169
12170	if (xtalfreq <= 30000000) {
12171		plp->plp_div = 1;
12172		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12173	} else {
12174		plp->plp_div = 2;
12175		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12176	}
12177
12178	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12179	    CALC_CTL7(xtalfreq, plp->plp_div));
12180	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12181	    CALC_CTL18(xtalfreq, plp->plp_div));
12182	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12183	    CALC_CTL19(xtalfreq, plp->plp_div));
12184
12185	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12186	ref &= 0xffff;
12187	for (i = 0; i < N(freqdata_tab); i++) {
12188		if (ref < freqdata_tab[i].freq) {
12189			f = &freqdata_tab[i];
12190			break;
12191		}
12192	}
12193	if (f == NULL)
12194		f = &freqdata_tab[N(freqdata_tab) - 1];
12195	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12196	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12197	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12198	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12199	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12200	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12201#undef CALC_CTL7
12202#undef CALC_CTL18
12203#undef CALC_CTL19
12204}
12205
12206static void
12207bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12208{
12209
12210	bwn_phy_lp_b2063_tblinit(mac);
12211	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12212	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12213	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12214	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12215	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12216	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12217	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12218	if (mac->mac_phy.rev == 2) {
12219		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12220		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12221		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12222	} else {
12223		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12224		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12225	}
12226}
12227
12228static void
12229bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12230{
12231	struct siba_dev_softc *sd = mac->mac_sd;
12232	struct siba_softc *siba = sd->sd_bus;
12233	static const struct bwn_wpair v1[] = {
12234		{ BWN_B2063_RX_BB_SP8, 0x0 },
12235		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12236		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12237		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12238		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12239		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12240		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12241		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12242	};
12243	static const struct bwn_wpair v2[] = {
12244		{ BWN_B2063_TX_BB_SP3, 0x0 },
12245		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12246		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12247		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12248		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12249	};
12250	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12251	int i;
12252	uint8_t tmp;
12253
12254	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12255
12256	for (i = 0; i < 2; i++)
12257		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12258	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12259	for (i = 2; i < N(v1); i++)
12260		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12261	for (i = 0; i < 10000; i++) {
12262		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12263			break;
12264		DELAY(1000);
12265	}
12266
12267	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12268		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12269
12270	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12271
12272	for (i = 0; i < N(v2); i++)
12273		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12274	if (freqxtal == 24000000) {
12275		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12276		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12277	} else {
12278		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12279		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12280	}
12281	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12282	for (i = 0; i < 10000; i++) {
12283		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12284			break;
12285		DELAY(1000);
12286	}
12287	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12288		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12289	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12290}
12291
12292static void
12293bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12294{
12295	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12296	struct bwn_softc *sc = mac->mac_sc;
12297	struct bwn_phy_lp_iq_est ie;
12298	struct bwn_txgain tx_gains;
12299	static const uint32_t pwrtbl[21] = {
12300		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12301		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12302		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12303		0x0004c, 0x0002c, 0x0001a,
12304	};
12305	uint32_t npwr, ipwr, sqpwr, tmp;
12306	int loopback, i, j, sum, error;
12307	uint16_t save[7];
12308	uint8_t txo, bbmult, txpctlmode;
12309
12310	error = bwn_phy_lp_switch_channel(mac, 7);
12311	if (error)
12312		device_printf(sc->sc_dev,
12313		    "failed to change channel to 7 (%d)\n", error);
12314	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12315	bbmult = bwn_phy_lp_get_bbmult(mac);
12316	if (txo)
12317		tx_gains = bwn_phy_lp_get_txgain(mac);
12318
12319	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12320	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12321	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12322	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12323	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12324	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12325	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12326
12327	bwn_phy_lp_get_txpctlmode(mac);
12328	txpctlmode = plp->plp_txpctlmode;
12329	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12330
12331	/* disable CRS */
12332	bwn_phy_lp_set_deaf(mac, 1);
12333	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12335	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12336	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12337	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12338	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12339	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12340	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12341	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12342	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12343	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12344	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12345	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12346	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12347	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12348	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12349	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12350	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12351	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12352	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12353	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12354	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12355	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12356	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12357
12358	loopback = bwn_phy_lp_loopback(mac);
12359	if (loopback == -1)
12360		goto done;
12361	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12362	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12363	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12364	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12365	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12366
12367	tmp = 0;
12368	memset(&ie, 0, sizeof(ie));
12369	for (i = 128; i <= 159; i++) {
12370		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12371		sum = 0;
12372		for (j = 5; j <= 25; j++) {
12373			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12374			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12375				goto done;
12376			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12377			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12378			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12379			    12);
12380			sum += ((ipwr - npwr) * (ipwr - npwr));
12381			if ((i == 128) || (sum < tmp)) {
12382				plp->plp_rccap = i;
12383				tmp = sum;
12384			}
12385		}
12386	}
12387	bwn_phy_lp_ddfs_turnoff(mac);
12388done:
12389	/* restore CRS */
12390	bwn_phy_lp_clear_deaf(mac, 1);
12391	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12392	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12393
12394	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12395	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12396	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12397	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12398	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12399	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12400	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12401
12402	bwn_phy_lp_set_bbmult(mac, bbmult);
12403	if (txo)
12404		bwn_phy_lp_set_txgain(mac, &tx_gains);
12405	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12406	if (plp->plp_rccap)
12407		bwn_phy_lp_set_rccap(mac);
12408}
12409
12410static void
12411bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12412{
12413	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12414	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12415
12416	if (mac->mac_phy.rev == 1)
12417		rc_cap = MIN(rc_cap + 5, 15);
12418
12419	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12420	    MAX(plp->plp_rccap - 4, 0x80));
12421	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12422	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12423	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12424}
12425
12426static uint32_t
12427bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12428{
12429	uint32_t i, q, r;
12430
12431	if (div == 0)
12432		return (0);
12433
12434	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12435		q <<= 1;
12436		if (r << 1 >= div) {
12437			q++;
12438			r = (r << 1) - div;
12439		}
12440	}
12441	if (r << 1 >= div)
12442		q++;
12443	return (q);
12444}
12445
12446static void
12447bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12448{
12449	struct siba_dev_softc *sd = mac->mac_sd;
12450	struct siba_softc *siba = sd->sd_bus;
12451
12452	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12453	DELAY(20);
12454	if (siba->siba_chipid == 0x5354) {
12455		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12456		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12457	} else {
12458		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12459	}
12460	DELAY(5);
12461}
12462
12463static void
12464bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12465{
12466
12467	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12468	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12469	DELAY(200);
12470}
12471
12472static void
12473bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12474{
12475#define	FLAG_A	0x01
12476#define	FLAG_G	0x02
12477	struct bwn_softc *sc = mac->mac_sc;
12478	struct ifnet *ifp = sc->sc_ifp;
12479	struct ieee80211com *ic = ifp->if_l2com;
12480	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12481		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12483		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12486		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12492		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12516		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12517		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12518		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12519		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12520		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12521		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12522		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12523		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12524		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12525		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12526		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12527		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12528	};
12529	const struct bwn_b206x_rfinit_entry *br;
12530	unsigned int i;
12531
12532	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12533		br = &bwn_b2062_init_tab[i];
12534		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12535			if (br->br_flags & FLAG_G)
12536				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12537		} else {
12538			if (br->br_flags & FLAG_A)
12539				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12540		}
12541	}
12542#undef FLAG_A
12543#undef FLAG_B
12544}
12545
12546static void
12547bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12548{
12549#define	FLAG_A	0x01
12550#define	FLAG_G	0x02
12551	struct bwn_softc *sc = mac->mac_sc;
12552	struct ifnet *ifp = sc->sc_ifp;
12553	struct ieee80211com *ic = ifp->if_l2com;
12554	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12555		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12556		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12557		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12558		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12559		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12560		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12561		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12562		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12563		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12564		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12565		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12566		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12570		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12571		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12572		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12575		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12576		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12583		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12584		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12585		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12586		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12587		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12588		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12589		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12590		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12591		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12592		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12593		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12594		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12595		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12596		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12597	};
12598	const struct bwn_b206x_rfinit_entry *br;
12599	unsigned int i;
12600
12601	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12602		br = &bwn_b2063_init_tab[i];
12603		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12604			if (br->br_flags & FLAG_G)
12605				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12606		} else {
12607			if (br->br_flags & FLAG_A)
12608				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12609		}
12610	}
12611#undef FLAG_A
12612#undef FLAG_B
12613}
12614
12615static void
12616bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12617    int count, void *_data)
12618{
12619	unsigned int i;
12620	uint32_t offset, type;
12621	uint8_t *data = _data;
12622
12623	type = BWN_TAB_GETTYPE(typenoffset);
12624	offset = BWN_TAB_GETOFFSET(typenoffset);
12625	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12626
12627	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12628
12629	for (i = 0; i < count; i++) {
12630		switch (type) {
12631		case BWN_TAB_8BIT:
12632			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12633			data++;
12634			break;
12635		case BWN_TAB_16BIT:
12636			*((uint16_t *)data) = BWN_PHY_READ(mac,
12637			    BWN_PHY_TABLEDATALO);
12638			data += 2;
12639			break;
12640		case BWN_TAB_32BIT:
12641			*((uint32_t *)data) = BWN_PHY_READ(mac,
12642			    BWN_PHY_TABLEDATAHI);
12643			*((uint32_t *)data) <<= 16;
12644			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12645			    BWN_PHY_TABLEDATALO);
12646			data += 4;
12647			break;
12648		default:
12649			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12650		}
12651	}
12652}
12653
12654static void
12655bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12656    int count, const void *_data)
12657{
12658	uint32_t offset, type, value;
12659	const uint8_t *data = _data;
12660	unsigned int i;
12661
12662	type = BWN_TAB_GETTYPE(typenoffset);
12663	offset = BWN_TAB_GETOFFSET(typenoffset);
12664	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12665
12666	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12667
12668	for (i = 0; i < count; i++) {
12669		switch (type) {
12670		case BWN_TAB_8BIT:
12671			value = *data;
12672			data++;
12673			KASSERT(!(value & ~0xff),
12674			    ("%s:%d: fail", __func__, __LINE__));
12675			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12676			break;
12677		case BWN_TAB_16BIT:
12678			value = *((const uint16_t *)data);
12679			data += 2;
12680			KASSERT(!(value & ~0xffff),
12681			    ("%s:%d: fail", __func__, __LINE__));
12682			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12683			break;
12684		case BWN_TAB_32BIT:
12685			value = *((const uint32_t *)data);
12686			data += 4;
12687			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12688			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12689			break;
12690		default:
12691			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12692		}
12693	}
12694}
12695
12696static struct bwn_txgain
12697bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12698{
12699	struct bwn_txgain tg;
12700	uint16_t tmp;
12701
12702	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12703	if (mac->mac_phy.rev < 2) {
12704		tmp = BWN_PHY_READ(mac,
12705		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12706		tg.tg_gm = tmp & 0x0007;
12707		tg.tg_pga = (tmp & 0x0078) >> 3;
12708		tg.tg_pad = (tmp & 0x780) >> 7;
12709		return (tg);
12710	}
12711
12712	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12713	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12714	tg.tg_gm = tmp & 0xff;
12715	tg.tg_pga = (tmp >> 8) & 0xff;
12716	return (tg);
12717}
12718
12719static uint8_t
12720bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12721{
12722
12723	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12724}
12725
12726static void
12727bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12728{
12729	uint16_t pa;
12730
12731	if (mac->mac_phy.rev < 2) {
12732		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12733		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12734		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12735		bwn_phy_lp_set_txgain_override(mac);
12736		return;
12737	}
12738
12739	pa = bwn_phy_lp_get_pa_gain(mac);
12740	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12741	    (tg->tg_pga << 8) | tg->tg_gm);
12742	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12743	    tg->tg_pad | (pa << 6));
12744	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12745	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12746	    tg->tg_pad | (pa << 8));
12747	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12748	bwn_phy_lp_set_txgain_override(mac);
12749}
12750
12751static void
12752bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12753{
12754
12755	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12756}
12757
12758static void
12759bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12760{
12761	uint16_t trsw = (tx << 1) | rx;
12762
12763	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12764	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12765}
12766
12767static void
12768bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12769{
12770	struct bwn_softc *sc = mac->mac_sc;
12771	struct ifnet *ifp = sc->sc_ifp;
12772	struct ieee80211com *ic = ifp->if_l2com;
12773	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12774
12775	if (mac->mac_phy.rev < 2) {
12776		trsw = gain & 0x1;
12777		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12778		ext_lna = (gain & 2) >> 1;
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		    0xfbff, ext_lna << 10);
12783		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12784		    0xf7ff, ext_lna << 11);
12785		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12786	} else {
12787		low_gain = gain & 0xffff;
12788		high_gain = (gain >> 16) & 0xf;
12789		ext_lna = (gain >> 21) & 0x1;
12790		trsw = ~(gain >> 20) & 0x1;
12791
12792		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12793		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12794		    0xfdff, ext_lna << 9);
12795		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12796		    0xfbff, ext_lna << 10);
12797		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12798		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12799		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12800			tmp = (gain >> 2) & 0x3;
12801			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12802			    0xe7ff, tmp<<11);
12803			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12804			    tmp << 3);
12805		}
12806	}
12807
12808	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12809	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12810	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12811	if (mac->mac_phy.rev >= 2) {
12812		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12813		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12814			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12815			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12816		}
12817		return;
12818	}
12819	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12820}
12821
12822static void
12823bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12824{
12825	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12826
12827	if (user)
12828		plp->plp_crsusr_off = 1;
12829	else
12830		plp->plp_crssys_off = 1;
12831
12832	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12833}
12834
12835static void
12836bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12837{
12838	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12839	struct bwn_softc *sc = mac->mac_sc;
12840	struct ifnet *ifp = sc->sc_ifp;
12841	struct ieee80211com *ic = ifp->if_l2com;
12842
12843	if (user)
12844		plp->plp_crsusr_off = 0;
12845	else
12846		plp->plp_crssys_off = 0;
12847
12848	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12849		return;
12850
12851	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12852		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12853	else
12854		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12855}
12856
12857static unsigned int
12858bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12859{
12860	struct bwn_softc *sc = mac->mac_sc;
12861	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12862	static uint8_t sqrt_table[256] = {
12863		10, 14, 17, 20, 22, 24, 26, 28,
12864		30, 31, 33, 34, 36, 37, 38, 40,
12865		41, 42, 43, 44, 45, 46, 47, 48,
12866		50, 50, 51, 52, 53, 54, 55, 56,
12867		57, 58, 59, 60, 60, 61, 62, 63,
12868		64, 64, 65, 66, 67, 67, 68, 69,
12869		70, 70, 71, 72, 72, 73, 74, 74,
12870		75, 76, 76, 77, 78, 78, 79, 80,
12871		80, 81, 81, 82, 83, 83, 84, 84,
12872		85, 86, 86, 87, 87, 88, 88, 89,
12873		90, 90, 91, 91, 92, 92, 93, 93,
12874		94, 94, 95, 95, 96, 96, 97, 97,
12875		98, 98, 99, 100, 100, 100, 101, 101,
12876		102, 102, 103, 103, 104, 104, 105, 105,
12877		106, 106, 107, 107, 108, 108, 109, 109,
12878		110, 110, 110, 111, 111, 112, 112, 113,
12879		113, 114, 114, 114, 115, 115, 116, 116,
12880		117, 117, 117, 118, 118, 119, 119, 120,
12881		120, 120, 121, 121, 122, 122, 122, 123,
12882		123, 124, 124, 124, 125, 125, 126, 126,
12883		126, 127, 127, 128, 128, 128, 129, 129,
12884		130, 130, 130, 131, 131, 131, 132, 132,
12885		133, 133, 133, 134, 134, 134, 135, 135,
12886		136, 136, 136, 137, 137, 137, 138, 138,
12887		138, 139, 139, 140, 140, 140, 141, 141,
12888		141, 142, 142, 142, 143, 143, 143, 144,
12889		144, 144, 145, 145, 145, 146, 146, 146,
12890		147, 147, 147, 148, 148, 148, 149, 149,
12891		150, 150, 150, 150, 151, 151, 151, 152,
12892		152, 152, 153, 153, 153, 154, 154, 154,
12893		155, 155, 155, 156, 156, 156, 157, 157,
12894		157, 158, 158, 158, 159, 159, 159, 160
12895	};
12896
12897	if (x == 0)
12898		return (0);
12899	if (x >= 256) {
12900		device_printf(sc->sc_dev,
12901		    "out of bounds of the square-root table (%d)\n", x);
12902		return (16);
12903	}
12904	return (sqrt_table[x - 1] / 10);
12905}
12906
12907static int
12908bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12909{
12910#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12911	int _t;								\
12912	_t = _x - 20;							\
12913	if (_t >= 0) {							\
12914		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12915	} else {							\
12916		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12917	}								\
12918} while (0)
12919#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12920	int _t;								\
12921	_t = _x - 11;							\
12922	if (_t >= 0)							\
12923		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12924	else								\
12925		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12926} while (0)
12927	struct bwn_phy_lp_iq_est ie;
12928	uint16_t v0, v1;
12929	int tmp[2], ret;
12930
12931	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12932	v0 = v1 >> 8;
12933	v1 |= 0xff;
12934
12935	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12936	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12937
12938	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12939	if (ret == 0)
12940		goto done;
12941
12942	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12943		ret = 0;
12944		goto done;
12945	}
12946
12947	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12948	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12949
12950	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12951	v0 = tmp[0] >> 3;
12952	v1 = tmp[1] >> 4;
12953done:
12954	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12955	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12956	return ret;
12957#undef CALC_COEFF
12958#undef CALC_COEFF2
12959}
12960
12961static void
12962bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12963{
12964	static const uint16_t noisescale[] = {
12965		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12966		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12967		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12968		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12969		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12970	};
12971	static const uint16_t crsgainnft[] = {
12972		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12973		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12974		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12975		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12976		0x013d,
12977	};
12978	static const uint16_t filterctl[] = {
12979		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12980		0xff53, 0x0127,
12981	};
12982	static const uint32_t psctl[] = {
12983		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12984		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12985		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12986		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12987		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12988		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12989		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12990		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12991	};
12992	static const uint16_t ofdmcckgain_r0[] = {
12993		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12994		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12995		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12996		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12997		0x755d,
12998	};
12999	static const uint16_t ofdmcckgain_r1[] = {
13000		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
13001		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
13002		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
13003		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
13004		0x755d,
13005	};
13006	static const uint16_t gaindelta[] = {
13007		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13008		0x0000,
13009	};
13010	static const uint32_t txpwrctl[] = {
13011		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13012		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13013		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13014		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13015		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13016		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13017		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13018		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13019		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13020		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13021		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13022		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13023		0x00000014, 0x00000013, 0x00000012, 0x00000011, 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, 0x00000000, 0x00000000, 0x00000000,
13038		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13039		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13040		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13041		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13042		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13043		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13044		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13045		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13046		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13047		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13048		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13049		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13050		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13051		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13052		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13053		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13054		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13055		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13056		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13057		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13058		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13059		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13060		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13061		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13062		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13063		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13064		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13065		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13066		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13067		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13068		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13069		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13070		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13071		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13072		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13073		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13074		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
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, 0x04200000, 0x04000000,
13089		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13090		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13091		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13092		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13093		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13094		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13095		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13096		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13097		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13098		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13099		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13100		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13101		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13102		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13103		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13104		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13105		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13106		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13107		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13108		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13109		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13110		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13111		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13112		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13113		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13114		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13115		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13116		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13117		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13118		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13119		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13120		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13121		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13122		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13123		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13124		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13125		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13126		0x00000702,
13127	};
13128
13129	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13130
13131	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13132	    bwn_tab_sigsq_tbl);
13133	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13134	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13135	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13136	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13137	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13138	    bwn_tab_pllfrac_tbl);
13139	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13140	    bwn_tabl_iqlocal_tbl);
13141	if (mac->mac_phy.rev == 0) {
13142		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13143		    ofdmcckgain_r0);
13144		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13145		    ofdmcckgain_r0);
13146	} else {
13147		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13148		    ofdmcckgain_r1);
13149		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13150		    ofdmcckgain_r1);
13151	}
13152	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13153	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13154}
13155
13156static void
13157bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13158{
13159	struct siba_dev_softc *sd = mac->mac_sd;
13160	struct siba_softc *siba = sd->sd_bus;
13161	int i;
13162	static const uint16_t noisescale[] = {
13163		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13164		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13165		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13166		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13167		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13168		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13169		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13170	};
13171	static const uint32_t filterctl[] = {
13172		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13173		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13174	};
13175	static const uint32_t psctl[] = {
13176		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13177		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13178		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13179		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13180	};
13181	static const uint32_t gainidx[] = {
13182		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13183		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13184		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13185		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13186		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13187		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13188		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13189		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13190		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13191		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13192		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13193		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13194		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13195		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13196		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13197		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13198		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13199		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13200		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13201		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13202		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13203		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13204		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13205		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13206		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13207		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13208		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13209		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13210		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13211		0x0000001a, 0x64ca55ad, 0x0000001a
13212	};
13213	static const uint16_t auxgainidx[] = {
13214		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13215		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13216		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13217		0x0004, 0x0016
13218	};
13219	static const uint16_t swctl[] = {
13220		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13221		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13222		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13223		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13224		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13225		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13226		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13227		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13228	};
13229	static const uint8_t hf[] = {
13230		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13231		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13232	};
13233	static const uint32_t gainval[] = {
13234		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13235		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13236		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13237		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13238		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13239		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13240		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13241		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13242		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13243		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13244		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13245		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13246		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13247		0x000000f1, 0x00000000, 0x00000000
13248	};
13249	static const uint16_t gain[] = {
13250		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13251		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13252		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13253		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13254		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13255		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13256		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13257		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13258		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13259		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13260		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13261		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13262	};
13263	static const uint32_t papdeps[] = {
13264		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13265		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13266		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13267		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13268		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13269		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13270		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13271		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13272		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13273		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13274		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13275		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13276		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13277	};
13278	static const uint32_t papdmult[] = {
13279		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13280		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13281		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13282		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13283		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13284		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13285		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13286		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13287		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13288		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13289		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13290		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13291		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13292	};
13293	static const uint32_t gainidx_a0[] = {
13294		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13295		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13296		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13297		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13298		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13299		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13300		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13301		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13302		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13303		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13304		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13305		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13306		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13307	};
13308	static const uint16_t auxgainidx_a0[] = {
13309		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13310		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13311		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13312		0x0002, 0x0014
13313	};
13314	static const uint32_t gainval_a0[] = {
13315		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13316		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13317		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13318		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13319		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13320		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13321		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13322		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13323		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13324		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13325		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13326		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13327		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13328		0x000000f7, 0x00000000, 0x00000000
13329	};
13330	static const uint16_t gain_a0[] = {
13331		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13332		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13333		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13334		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13335		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13336		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13337		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13338		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13339		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13340		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13341		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13342		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13343	};
13344
13345	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13346
13347	for (i = 0; i < 704; i++)
13348		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13349
13350	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13351	    bwn_tab_sigsq_tbl);
13352	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13353	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13354	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13355	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13356	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13357	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13358	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13359	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13360	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13361	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13362	    bwn_tab_pllfrac_tbl);
13363	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13364	    bwn_tabl_iqlocal_tbl);
13365	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13366	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13367
13368	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13369		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13370		    gainidx_a0);
13371		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13372		    auxgainidx_a0);
13373		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13374		    gainval_a0);
13375		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13376	}
13377}
13378
13379static void
13380bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13381{
13382	struct siba_dev_softc *sd = mac->mac_sd;
13383	struct siba_softc *siba = sd->sd_bus;
13384	struct bwn_softc *sc = mac->mac_sc;
13385	struct ifnet *ifp = sc->sc_ifp;
13386	struct ieee80211com *ic = ifp->if_l2com;
13387	static struct bwn_txgain_entry txgain_r2[] = {
13388		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13389		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13390		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13391		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13392		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13393		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13394		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13395		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13396		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13397		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13398		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13399		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13400		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13401		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13402		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13403		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13404		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13405		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13406		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13407		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13408		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13409		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13410		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13411		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13412		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13413		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13414		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13415		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13416		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13417		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13418		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13419		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13420		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13421		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13422		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13423		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13424		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13425		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13426		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13427		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13428		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13429		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13430		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13431		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13432		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13433		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13434		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13435		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13436		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13437		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13438		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13439		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13440		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13441		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13442		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13443		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13444		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13445		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13446		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13447		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13448		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13449		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13450		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13451		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13452	};
13453	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13454		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13455		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13456		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13457		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13458		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13459		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13460		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13461		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13462		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13463		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13464		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13465		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13466		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13467		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13468		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13469		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13470		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13471		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13472		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13473		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13474		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13475		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13476		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13477		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13478		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13479		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13480		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13481		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13482		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13483		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13484		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13485		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13486		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13487		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13488		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13489		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13490		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13491		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13492		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13493		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13494		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13495		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13496		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13497		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13498		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13499		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13500		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13501		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13502		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13503		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13504		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13505		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13506		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13507		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13508		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13509		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13510		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13511		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13512		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13513		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13514		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13515		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13516		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13517		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13518	};
13519	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13520		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13521		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13522		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13523		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13524		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13525		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13526		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13527		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13528		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13529		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13530		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13531		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13532		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13533		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13534		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13535		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13536		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13537		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13538		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13539		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13540		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13541		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13542		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13543		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13544		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13545		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13546		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13547		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13548		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13549		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13550		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13551		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13552		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13553		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13554		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13555		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13556		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13557		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13558		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13559		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13560		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13561		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13562		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13563		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13564		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13565		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13566		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13567		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13568		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13569		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13570		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13571		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13572		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13573		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13574		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13575		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13576		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13577		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13578		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13579		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13580		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13581		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13582		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13583		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13584	};
13585	static struct bwn_txgain_entry txgain_r0[] = {
13586		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13587		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13588		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13589		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13590		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13591		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13592		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13593		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13594		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13595		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13596		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13597		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13598		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13599		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13600		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13601		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13602		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13603		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13604		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13605		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13606		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13607		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13608		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13609		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13610		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13611		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13612		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13613		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13614		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13615		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13616		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13617		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13618		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13619		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13620		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13621		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13622		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13623		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13624		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13625		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13626		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13627		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13628		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13629		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13630		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13631		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13632		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13633		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13634		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13635		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13636		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13637		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13638		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13639		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13640		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13641		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13642		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13643		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13644		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13645		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13646		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13647		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13648		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13649		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13650	};
13651	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13652		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13653		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13654		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13655		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13656		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13657		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13658		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13659		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13660		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13661		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13662		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13663		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13664		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13665		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13666		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13667		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13668		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13669		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13670		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13671		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13672		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13673		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13674		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13675		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13676		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13677		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13678		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13679		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13680		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13681		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13682		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13683		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13684		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13685		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13686		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13687		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13688		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13689		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13690		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13691		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13692		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13693		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13694		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13695		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13696		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13697		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13698		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13699		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13700		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13701		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13702		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13703		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13704		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13705		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13706		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13707		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13708		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13709		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13710		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13711		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13712		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13713		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13714		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13715		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13716	};
13717	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13718		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13719		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13720		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13721		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13722		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13723		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13724		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13725		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13726		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13727		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13728		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13729		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13730		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13731		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13732		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13733		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13734		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13735		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13736		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13737		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13738		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13739		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13740		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13741		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13742		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13743		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13744		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13745		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13746		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13747		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13748		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13749		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13750		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13751		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13752		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13753		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13754		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13755		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13756		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13757		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13758		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13759		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13760		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13761		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13762		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13763		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13764		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13765		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13766		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13767		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13768		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13769		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13770		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13771		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13772		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13773		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13774		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13775		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13776		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13777		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13778		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13779		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13780		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13781		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13782	};
13783	static struct bwn_txgain_entry txgain_r1[] = {
13784		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13785		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13786		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13787		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13788		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13789		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13790		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13791		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13792		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13793		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13794		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13795		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13796		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13797		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13798		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13799		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13800		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13801		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13802		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13803		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13804		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13805		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13806		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13807		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13808		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13809		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13810		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13811		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13812		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13813		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13814		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13815		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13816		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13817		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13818		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13819		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13820		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13821		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13822		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13823		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13824		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13825		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13826		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13827		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13828		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13829		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13830		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13831		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13832		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13833		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13834		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13835		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13836		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13837		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13838		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13839		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13840		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13841		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13842		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13843		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13844		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13845		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13846		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13847		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13848		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13849		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13850		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13851		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13852		{ 7, 11, 6, 0, 71 }
13853	};
13854	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13855		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13856		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13857		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13858		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13859		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13860		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13861		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13862		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13863		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13864		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13865		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13866		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13867		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13868		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13869		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13870		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13871		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13872		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13873		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13874		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13875		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13876		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13877		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13878		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13879		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13880		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13881		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13882		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13883		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13884		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13885		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13886		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13887		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13888		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13889		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13890		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13891		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13892		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13893		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13894		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13895		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13896		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13897		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13898		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13899		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13900		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13901		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13902		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13903		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13904		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13905		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13906		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13907		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13908		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13909		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13910		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13911		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13912		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13913		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13914		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13915		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13916		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13917		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13918		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13919	};
13920	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13921		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13922		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13923		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13924		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13925		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13926		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13927		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13928		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13929		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13930		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13931		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13932		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13933		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13934		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13935		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13936		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13937		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13938		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13939		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13940		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13941		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13942		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13943		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13944		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13945		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13946		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13947		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13948		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13949		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13950		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13951		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13952		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13953		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13954		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13955		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13956		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13957		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13958		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13959		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13960		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13961		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13962		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13963		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13964		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13965		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13966		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13967		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13968		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13969		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13970		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13971		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13972		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13973		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13974		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13975		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13976		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13977		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13978		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13979		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13980		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13981		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13982		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13983		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13984		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13985	};
13986
13987	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13988		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13989			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13990		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13991			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13992			    txgain_2ghz_r2);
13993		else
13994			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13995			    txgain_5ghz_r2);
13996		return;
13997	}
13998
13999	if (mac->mac_phy.rev == 0) {
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_r0);
14003		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14004			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
14005			    txgain_2ghz_r0);
14006		else
14007			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
14008			    txgain_5ghz_r0);
14009		return;
14010	}
14011
14012	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14013	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14014		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14015	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14016		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14017	else
14018		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14019}
14020
14021static void
14022bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14023{
14024	uint32_t offset, type;
14025
14026	type = BWN_TAB_GETTYPE(typeoffset);
14027	offset = BWN_TAB_GETOFFSET(typeoffset);
14028	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14029
14030	switch (type) {
14031	case BWN_TAB_8BIT:
14032		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14033		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14034		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14035		break;
14036	case BWN_TAB_16BIT:
14037		KASSERT(!(value & ~0xffff),
14038		    ("%s:%d: fail", __func__, __LINE__));
14039		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14040		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14041		break;
14042	case BWN_TAB_32BIT:
14043		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14044		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14045		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14046		break;
14047	default:
14048		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14049	}
14050}
14051
14052static int
14053bwn_phy_lp_loopback(struct bwn_mac *mac)
14054{
14055	struct bwn_phy_lp_iq_est ie;
14056	int i, index = -1;
14057	uint32_t tmp;
14058
14059	memset(&ie, 0, sizeof(ie));
14060
14061	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14062	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14063	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14064	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14065	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14066	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14067	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14068	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14069	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14070	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14071	for (i = 0; i < 32; i++) {
14072		bwn_phy_lp_set_rxgain_idx(mac, i);
14073		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14074		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14075			continue;
14076		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14077		if ((tmp > 4000) && (tmp < 10000)) {
14078			index = i;
14079			break;
14080		}
14081	}
14082	bwn_phy_lp_ddfs_turnoff(mac);
14083	return (index);
14084}
14085
14086static void
14087bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14088{
14089
14090	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14091}
14092
14093static void
14094bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14095    int incr1, int incr2, int scale_idx)
14096{
14097
14098	bwn_phy_lp_ddfs_turnoff(mac);
14099	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14100	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14101	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14102	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14103	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14104	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14105	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14106	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14107	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14108	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14109}
14110
14111static uint8_t
14112bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14113    struct bwn_phy_lp_iq_est *ie)
14114{
14115	int i;
14116
14117	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14118	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14119	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14120	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14121	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14122
14123	for (i = 0; i < 500; i++) {
14124		if (!(BWN_PHY_READ(mac,
14125		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14126			break;
14127		DELAY(1000);
14128	}
14129	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14130		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14131		return 0;
14132	}
14133
14134	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14135	ie->ie_iqprod <<= 16;
14136	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14137	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14138	ie->ie_ipwr <<= 16;
14139	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14140	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14141	ie->ie_qpwr <<= 16;
14142	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14143
14144	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14145	return 1;
14146}
14147
14148static uint32_t
14149bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14150{
14151	uint32_t offset, type, value;
14152
14153	type = BWN_TAB_GETTYPE(typeoffset);
14154	offset = BWN_TAB_GETOFFSET(typeoffset);
14155	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14156
14157	switch (type) {
14158	case BWN_TAB_8BIT:
14159		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14160		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14161		break;
14162	case BWN_TAB_16BIT:
14163		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14164		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14165		break;
14166	case BWN_TAB_32BIT:
14167		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14168		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14169		value <<= 16;
14170		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14171		break;
14172	default:
14173		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14174		value = 0;
14175	}
14176
14177	return (value);
14178}
14179
14180static void
14181bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14182{
14183
14184	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14185	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14186}
14187
14188static void
14189bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14190{
14191	uint16_t ctl;
14192
14193	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14194	ctl |= dac << 7;
14195	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14196}
14197
14198static void
14199bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14200{
14201
14202	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14203	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14204}
14205
14206static void
14207bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14208{
14209
14210	if (mac->mac_phy.rev < 2)
14211		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14212	else {
14213		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14214		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14215	}
14216	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14217}
14218
14219static uint16_t
14220bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14221{
14222
14223	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14224}
14225
14226static uint8_t
14227bwn_nbits(int32_t val)
14228{
14229	uint32_t tmp;
14230	uint8_t nbits = 0;
14231
14232	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14233		nbits++;
14234	return (nbits);
14235}
14236
14237static void
14238bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14239    struct bwn_txgain_entry *table)
14240{
14241	int i;
14242
14243	for (i = offset; i < count; i++)
14244		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14245}
14246
14247static void
14248bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14249    struct bwn_txgain_entry data)
14250{
14251
14252	if (mac->mac_phy.rev >= 2)
14253		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14254	else
14255		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14256}
14257
14258static void
14259bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14260    struct bwn_txgain_entry te)
14261{
14262	struct bwn_softc *sc = mac->mac_sc;
14263	struct ifnet *ifp = sc->sc_ifp;
14264	struct ieee80211com *ic = ifp->if_l2com;
14265	uint32_t tmp;
14266
14267	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14268
14269	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14270	if (mac->mac_phy.rev >= 3) {
14271		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14272		    (0x10 << 24) : (0x70 << 24));
14273	} else {
14274		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14275		    (0x14 << 24) : (0x7f << 24));
14276	}
14277	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14278	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14279	    te.te_bbmult << 20 | te.te_dac << 28);
14280}
14281
14282static void
14283bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14284    struct bwn_txgain_entry te)
14285{
14286
14287	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14288
14289	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14290	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14291	    te.te_dac);
14292	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14293}
14294
14295static void
14296bwn_identify(driver_t *driver, device_t parent)
14297{
14298
14299	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14300}
14301
14302static device_method_t bwn_methods[] = {
14303	/* Device interface */
14304	DEVMETHOD(device_identify,	bwn_identify),
14305	DEVMETHOD(device_probe,		bwn_probe),
14306	DEVMETHOD(device_attach,	bwn_attach),
14307	DEVMETHOD(device_detach,	bwn_detach),
14308	DEVMETHOD(device_suspend,	bwn_suspend),
14309	DEVMETHOD(device_resume,	bwn_resume),
14310	{ 0,0 }
14311};
14312static driver_t bwn_driver = {
14313	"bwn",
14314	bwn_methods,
14315	sizeof(struct bwn_softc)
14316};
14317static devclass_t bwn_devclass;
14318DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14319MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14320MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14321MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14322MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14323