if_bwn.c revision 204257
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 204257 2010-02-23 19:55:54Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(struct siba_softc *);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_fix_imcfglobug(struct bwn_mac *);
209static void	bwn_bt_disable(struct bwn_mac *);
210static int	bwn_chip_init(struct bwn_mac *);
211static uint64_t	bwn_hf_read(struct bwn_mac *);
212static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213static void	bwn_set_txretry(struct bwn_mac *, int, int);
214static void	bwn_rate_init(struct bwn_mac *);
215static void	bwn_set_phytxctl(struct bwn_mac *);
216static void	bwn_spu_setdelay(struct bwn_mac *, int);
217static void	bwn_bt_enable(struct bwn_mac *);
218static void	bwn_set_macaddr(struct bwn_mac *);
219static void	bwn_crypt_init(struct bwn_mac *);
220static void	bwn_chip_exit(struct bwn_mac *);
221static int	bwn_fw_fillinfo(struct bwn_mac *);
222static int	bwn_fw_loaducode(struct bwn_mac *);
223static int	bwn_gpio_init(struct bwn_mac *);
224static int	bwn_fw_loadinitvals(struct bwn_mac *);
225static int	bwn_phy_init(struct bwn_mac *);
226static void	bwn_set_txantenna(struct bwn_mac *, int);
227static void	bwn_set_opmode(struct bwn_mac *);
228static void	bwn_gpio_cleanup(struct bwn_mac *);
229static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230static uint8_t	bwn_plcp_getcck(const uint8_t);
231static uint8_t	bwn_plcp_getofdm(const uint8_t);
232static void	bwn_pio_init(struct bwn_mac *);
233static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    int);
236static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237		    struct bwn_pio_rxqueue *, int);
238static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240		    uint16_t);
241static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244static void	bwn_pio_handle_txeof(struct bwn_mac *,
245		    const struct bwn_txstatus *);
246static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249		    uint16_t);
250static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251		    uint32_t);
252static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253		    struct mbuf *);
254static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258		    uint16_t, uint32_t);
259static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264		    uint16_t, struct bwn_pio_txpkt **);
265static void	bwn_dma_init(struct bwn_mac *);
266static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267static int	bwn_dma_mask2type(uint64_t);
268static uint64_t	bwn_dma_mask(struct bwn_mac *);
269static uint16_t	bwn_dma_base(int, int);
270static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272		    int, struct bwn_dmadesc_generic **,
273		    struct bwn_dmadesc_meta **);
274static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276		    int, int);
277static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283		    int, struct bwn_dmadesc_generic **,
284		    struct bwn_dmadesc_meta **);
285static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287		    int, int);
288static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_setup(struct bwn_dma_ring *);
295static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_rx(struct bwn_dma_ring *);
300static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302		    struct bwn_dmadesc_meta *);
303static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304static int	bwn_dma_gettype(struct bwn_mac *);
305static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311		    int);
312static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313		    bus_size_t, int);
314static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315static void	bwn_dma_handle_txeof(struct bwn_mac *,
316		    const struct bwn_txstatus *);
317static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318		    struct mbuf *);
319static int	bwn_dma_getslot(struct bwn_dma_ring *);
320static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321		    uint8_t);
322static int	bwn_dma_attach(struct bwn_mac *);
323static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324		    int, int, int);
325static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326		    const struct bwn_txstatus *, uint16_t, int *);
327static void	bwn_dma_free(struct bwn_mac *);
328static void	bwn_phy_g_init_sub(struct bwn_mac *);
329static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330static void	bwn_phy_init_b5(struct bwn_mac *);
331static void	bwn_phy_init_b6(struct bwn_mac *);
332static void	bwn_phy_init_a(struct bwn_mac *);
333static void	bwn_loopback_calcgain(struct bwn_mac *);
334static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335static void	bwn_lo_g_init(struct bwn_mac *);
336static void	bwn_lo_g_adjust(struct bwn_mac *);
337static void	bwn_lo_get_powervector(struct bwn_mac *);
338static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345		    uint8_t);
346static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349static void	bwn_wa_init(struct bwn_mac *);
350static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354		    uint32_t);
355static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356		    uint16_t);
357static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358static void	bwn_mac_suspend(struct bwn_mac *);
359static void	bwn_mac_enable(struct bwn_mac *);
360static void	bwn_psctl(struct bwn_mac *, uint32_t);
361static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362static void	bwn_nrssi_offset(struct bwn_mac *);
363static void	bwn_nrssi_threshold(struct bwn_mac *);
364static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366		    int16_t);
367static void	bwn_set_original_gains(struct bwn_mac *);
368static void	bwn_hwpctl_early_init(struct bwn_mac *);
369static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373		    const char *, struct bwn_fwfile *);
374static void	bwn_release_firmware(struct bwn_mac *);
375static void	bwn_do_release_fw(struct bwn_fwfile *);
376static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377static int	bwn_fwinitvals_write(struct bwn_mac *,
378		    const struct bwn_fwinitvals *, size_t, size_t);
379static int	bwn_switch_channel(struct bwn_mac *, int);
380static uint16_t	bwn_ant2phy(int);
381static void	bwn_mac_write_bssid(struct bwn_mac *);
382static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383		    const uint8_t *);
384static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385		    const uint8_t *, size_t, const uint8_t *);
386static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387		    const uint8_t *);
388static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389		    const uint8_t *);
390static void	bwn_phy_exit(struct bwn_mac *);
391static void	bwn_core_stop(struct bwn_mac *);
392static int	bwn_switch_band(struct bwn_softc *,
393		    struct ieee80211_channel *);
394static void	bwn_phy_reset(struct bwn_mac *);
395static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396static void	bwn_set_pretbtt(struct bwn_mac *);
397static int	bwn_intr(void *);
398static void	bwn_intrtask(void *, int);
399static void	bwn_restart(struct bwn_mac *, const char *);
400static void	bwn_intr_ucode_debug(struct bwn_mac *);
401static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402static void	bwn_intr_atim_end(struct bwn_mac *);
403static void	bwn_intr_beacon(struct bwn_mac *);
404static void	bwn_intr_pmq(struct bwn_mac *);
405static void	bwn_intr_noise(struct bwn_mac *);
406static void	bwn_intr_txeof(struct bwn_mac *);
407static void	bwn_hwreset(void *, int);
408static void	bwn_handle_fwpanic(struct bwn_mac *);
409static void	bwn_load_beacon0(struct bwn_mac *);
410static void	bwn_load_beacon1(struct bwn_mac *);
411static uint32_t	bwn_jssi_read(struct bwn_mac *);
412static void	bwn_noise_gensample(struct bwn_mac *);
413static void	bwn_handle_txeof(struct bwn_mac *,
414		    const struct bwn_txstatus *);
415static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417static void	bwn_start_locked(struct ifnet *);
418static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419		    struct mbuf *);
420static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421static int	bwn_set_txhdr(struct bwn_mac *,
422		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423		    uint16_t);
424static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425		    const uint8_t);
426static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427static uint8_t	bwn_get_fbrate(uint8_t);
428static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430static void	bwn_phy_lock(struct bwn_mac *);
431static void	bwn_phy_unlock(struct bwn_mac *);
432static void	bwn_rf_lock(struct bwn_mac *);
433static void	bwn_rf_unlock(struct bwn_mac *);
434static void	bwn_txpwr(void *, int);
435static void	bwn_tasks(void *);
436static void	bwn_task_15s(struct bwn_mac *);
437static void	bwn_task_30s(struct bwn_mac *);
438static void	bwn_task_60s(struct bwn_mac *);
439static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440		    uint8_t);
441static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444		    int, int);
445static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448static void	bwn_watchdog(void *);
449static void	bwn_dma_stop(struct bwn_mac *);
450static void	bwn_pio_stop(struct bwn_mac *);
451static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452static void	bwn_led_attach(struct bwn_mac *);
453static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454static void	bwn_led_event(struct bwn_mac *, int);
455static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456static void	bwn_led_blink_next(void *);
457static void	bwn_led_blink_end(void *);
458static void	bwn_rfswitch(void *);
459static void	bwn_rf_turnon(struct bwn_mac *);
460static void	bwn_rf_turnoff(struct bwn_mac *);
461static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462static int	bwn_phy_lp_init(struct bwn_mac *);
463static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466		    uint16_t);
467static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477static void	bwn_phy_lp_calib(struct bwn_mac *);
478static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500		    const void *);
501static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502static struct bwn_txgain
503		bwn_phy_lp_get_txgain(struct bwn_mac *);
504static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518static int	bwn_phy_lp_loopback(struct bwn_mac *);
519static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521		    int);
522static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523		    struct bwn_phy_lp_iq_est *);
524static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530static uint8_t	bwn_nbits(int32_t);
531static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532		    struct bwn_txgain_entry *);
533static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538		    struct bwn_txgain_entry);
539static void	bwn_sysctl_node(struct bwn_softc *);
540
541static struct resource_spec bwn_res_spec_legacy[] = {
542	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
543	{ -1,			0,		0 }
544};
545
546static struct resource_spec bwn_res_spec_msi[] = {
547	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
548	{ -1,			0,		0 }
549};
550
551static const struct bwn_channelinfo bwn_chantable_bg = {
552	.channels = {
553		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
554		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
555		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
556		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
557		{ 2472, 13, 30 }, { 2484, 14, 30 } },
558	.nchannels = 14
559};
560
561static const struct bwn_channelinfo bwn_chantable_a = {
562	.channels = {
563		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
564		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
565		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
566		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
567		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
568		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
569		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
570		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
571		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
572		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
573		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
574		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
575		{ 6080, 216, 30 } },
576	.nchannels = 37
577};
578
579static const struct bwn_channelinfo bwn_chantable_n = {
580	.channels = {
581		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
582		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
583		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
584		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
585		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
586		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
587		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
588		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
589		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
590		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
591		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
592		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
593		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
594		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
595		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
596		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
597		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
598		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
599		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
600		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
601		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
602		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
603		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
604		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
605		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
606		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
607		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
608		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
609		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
610		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
611		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
612		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
613		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
614		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
615		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
616		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
617		{ 6130, 226, 30 }, { 6140, 228, 30 } },
618	.nchannels = 110
619};
620
621static const uint8_t bwn_b2063_chantable_data[33][12] = {
622	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
627	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
634	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
636	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
641	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
643	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
654	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
655};
656
657static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
658	{ 1, 2412, bwn_b2063_chantable_data[0] },
659	{ 2, 2417, bwn_b2063_chantable_data[0] },
660	{ 3, 2422, bwn_b2063_chantable_data[0] },
661	{ 4, 2427, bwn_b2063_chantable_data[1] },
662	{ 5, 2432, bwn_b2063_chantable_data[1] },
663	{ 6, 2437, bwn_b2063_chantable_data[1] },
664	{ 7, 2442, bwn_b2063_chantable_data[1] },
665	{ 8, 2447, bwn_b2063_chantable_data[1] },
666	{ 9, 2452, bwn_b2063_chantable_data[2] },
667	{ 10, 2457, bwn_b2063_chantable_data[2] },
668	{ 11, 2462, bwn_b2063_chantable_data[3] },
669	{ 12, 2467, bwn_b2063_chantable_data[3] },
670	{ 13, 2472, bwn_b2063_chantable_data[3] },
671	{ 14, 2484, bwn_b2063_chantable_data[4] },
672	{ 34, 5170, bwn_b2063_chantable_data[5] },
673	{ 36, 5180, bwn_b2063_chantable_data[6] },
674	{ 38, 5190, bwn_b2063_chantable_data[7] },
675	{ 40, 5200, bwn_b2063_chantable_data[8] },
676	{ 42, 5210, bwn_b2063_chantable_data[9] },
677	{ 44, 5220, bwn_b2063_chantable_data[10] },
678	{ 46, 5230, bwn_b2063_chantable_data[11] },
679	{ 48, 5240, bwn_b2063_chantable_data[12] },
680	{ 52, 5260, bwn_b2063_chantable_data[13] },
681	{ 56, 5280, bwn_b2063_chantable_data[14] },
682	{ 60, 5300, bwn_b2063_chantable_data[14] },
683	{ 64, 5320, bwn_b2063_chantable_data[15] },
684	{ 100, 5500, bwn_b2063_chantable_data[16] },
685	{ 104, 5520, bwn_b2063_chantable_data[17] },
686	{ 108, 5540, bwn_b2063_chantable_data[18] },
687	{ 112, 5560, bwn_b2063_chantable_data[19] },
688	{ 116, 5580, bwn_b2063_chantable_data[20] },
689	{ 120, 5600, bwn_b2063_chantable_data[21] },
690	{ 124, 5620, bwn_b2063_chantable_data[21] },
691	{ 128, 5640, bwn_b2063_chantable_data[22] },
692	{ 132, 5660, bwn_b2063_chantable_data[22] },
693	{ 136, 5680, bwn_b2063_chantable_data[22] },
694	{ 140, 5700, bwn_b2063_chantable_data[23] },
695	{ 149, 5745, bwn_b2063_chantable_data[23] },
696	{ 153, 5765, bwn_b2063_chantable_data[23] },
697	{ 157, 5785, bwn_b2063_chantable_data[23] },
698	{ 161, 5805, bwn_b2063_chantable_data[23] },
699	{ 165, 5825, bwn_b2063_chantable_data[23] },
700	{ 184, 4920, bwn_b2063_chantable_data[24] },
701	{ 188, 4940, bwn_b2063_chantable_data[25] },
702	{ 192, 4960, bwn_b2063_chantable_data[26] },
703	{ 196, 4980, bwn_b2063_chantable_data[27] },
704	{ 200, 5000, bwn_b2063_chantable_data[28] },
705	{ 204, 5020, bwn_b2063_chantable_data[29] },
706	{ 208, 5040, bwn_b2063_chantable_data[30] },
707	{ 212, 5060, bwn_b2063_chantable_data[31] },
708	{ 216, 5080, bwn_b2063_chantable_data[32] }
709};
710
711static const uint8_t bwn_b2062_chantable_data[22][12] = {
712	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
713	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
725	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
732	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
733	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
734};
735
736static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
737	{ 1, 2412, bwn_b2062_chantable_data[0] },
738	{ 2, 2417, bwn_b2062_chantable_data[0] },
739	{ 3, 2422, bwn_b2062_chantable_data[0] },
740	{ 4, 2427, bwn_b2062_chantable_data[0] },
741	{ 5, 2432, bwn_b2062_chantable_data[0] },
742	{ 6, 2437, bwn_b2062_chantable_data[0] },
743	{ 7, 2442, bwn_b2062_chantable_data[0] },
744	{ 8, 2447, bwn_b2062_chantable_data[0] },
745	{ 9, 2452, bwn_b2062_chantable_data[0] },
746	{ 10, 2457, bwn_b2062_chantable_data[0] },
747	{ 11, 2462, bwn_b2062_chantable_data[0] },
748	{ 12, 2467, bwn_b2062_chantable_data[0] },
749	{ 13, 2472, bwn_b2062_chantable_data[0] },
750	{ 14, 2484, bwn_b2062_chantable_data[0] },
751	{ 34, 5170, bwn_b2062_chantable_data[1] },
752	{ 38, 5190, bwn_b2062_chantable_data[2] },
753	{ 42, 5210, bwn_b2062_chantable_data[2] },
754	{ 46, 5230, bwn_b2062_chantable_data[3] },
755	{ 36, 5180, bwn_b2062_chantable_data[4] },
756	{ 40, 5200, bwn_b2062_chantable_data[5] },
757	{ 44, 5220, bwn_b2062_chantable_data[6] },
758	{ 48, 5240, bwn_b2062_chantable_data[3] },
759	{ 52, 5260, bwn_b2062_chantable_data[3] },
760	{ 56, 5280, bwn_b2062_chantable_data[3] },
761	{ 60, 5300, bwn_b2062_chantable_data[7] },
762	{ 64, 5320, bwn_b2062_chantable_data[8] },
763	{ 100, 5500, bwn_b2062_chantable_data[9] },
764	{ 104, 5520, bwn_b2062_chantable_data[10] },
765	{ 108, 5540, bwn_b2062_chantable_data[10] },
766	{ 112, 5560, bwn_b2062_chantable_data[10] },
767	{ 116, 5580, bwn_b2062_chantable_data[11] },
768	{ 120, 5600, bwn_b2062_chantable_data[12] },
769	{ 124, 5620, bwn_b2062_chantable_data[12] },
770	{ 128, 5640, bwn_b2062_chantable_data[12] },
771	{ 132, 5660, bwn_b2062_chantable_data[12] },
772	{ 136, 5680, bwn_b2062_chantable_data[12] },
773	{ 140, 5700, bwn_b2062_chantable_data[12] },
774	{ 149, 5745, bwn_b2062_chantable_data[12] },
775	{ 153, 5765, bwn_b2062_chantable_data[12] },
776	{ 157, 5785, bwn_b2062_chantable_data[12] },
777	{ 161, 5805, bwn_b2062_chantable_data[12] },
778	{ 165, 5825, bwn_b2062_chantable_data[12] },
779	{ 184, 4920, bwn_b2062_chantable_data[13] },
780	{ 188, 4940, bwn_b2062_chantable_data[14] },
781	{ 192, 4960, bwn_b2062_chantable_data[15] },
782	{ 196, 4980, bwn_b2062_chantable_data[16] },
783	{ 200, 5000, bwn_b2062_chantable_data[17] },
784	{ 204, 5020, bwn_b2062_chantable_data[18] },
785	{ 208, 5040, bwn_b2062_chantable_data[19] },
786	{ 212, 5060, bwn_b2062_chantable_data[20] },
787	{ 216, 5080, bwn_b2062_chantable_data[21] }
788};
789
790/* for LP PHY */
791static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
792	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
793	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
794	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
795	{ 13, -66, 13 }, { 14, -66, 13 },
796};
797
798/* for LP PHY */
799static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
800	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
801	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
802	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
803	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
804	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
805	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
806	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
807	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
808	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
809	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
810	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
811	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
812	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
813};
814
815static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
816
817static const uint8_t bwn_tab_sigsq_tbl[] = {
818	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
819	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
822	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
823	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
824};
825
826static const uint8_t bwn_tab_pllfrac_tbl[] = {
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
828	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
829};
830
831static const uint16_t bwn_tabl_iqlocal_tbl[] = {
832	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
833	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
836	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
837	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
844};
845
846static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
847static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
848static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
849static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
850static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
851const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
852
853#define	VENDOR_LED_ACT(vendor)				\
854{							\
855	.vid = PCI_VENDOR_##vendor,			\
856	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
857}
858
859static const struct {
860	uint16_t	vid;
861	uint8_t		led_act[BWN_LED_MAX];
862} bwn_vendor_led_act[] = {
863	VENDOR_LED_ACT(COMPAQ),
864	VENDOR_LED_ACT(ASUSTEK)
865};
866
867static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
868	{ BWN_VENDOR_LED_ACT_DEFAULT };
869
870#undef VENDOR_LED_ACT
871
872static const struct {
873	int		on_dur;
874	int		off_dur;
875} bwn_led_duration[109] = {
876	[0]	= { 400, 100 },
877	[2]	= { 150, 75 },
878	[4]	= { 90, 45 },
879	[11]	= { 66, 34 },
880	[12]	= { 53, 26 },
881	[18]	= { 42, 21 },
882	[22]	= { 35, 17 },
883	[24]	= { 32, 16 },
884	[36]	= { 21, 10 },
885	[48]	= { 16, 8 },
886	[72]	= { 11, 5 },
887	[96]	= { 9, 4 },
888	[108]	= { 7, 3 }
889};
890
891static const uint16_t bwn_wme_shm_offsets[] = {
892	[0] = BWN_WME_BESTEFFORT,
893	[1] = BWN_WME_BACKGROUND,
894	[2] = BWN_WME_VOICE,
895	[3] = BWN_WME_VIDEO,
896};
897
898static const struct siba_devid bwn_devs[] = {
899	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
900	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
901	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
902	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
903	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
904	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
905	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
906	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
907	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
908};
909
910static int
911bwn_probe(device_t dev)
912{
913	struct siba_dev_softc *sd = device_get_ivars(dev);
914	int i;
915
916	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
917		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
918		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
919		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
920			return (BUS_PROBE_DEFAULT);
921	}
922
923	return (ENXIO);
924}
925
926static int
927bwn_attach(device_t dev)
928{
929	struct bwn_mac *mac;
930	struct bwn_softc *sc = device_get_softc(dev);
931	struct siba_dev_softc *sd = device_get_ivars(dev);
932	struct siba_softc *siba = sd->sd_bus;
933	int error, i, msic, reg;
934
935	sc->sc_dev = dev;
936	sc->sc_sd = sd;
937#ifdef BWN_DEBUG
938	sc->sc_debug = bwn_debug;
939#endif
940
941	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
942		error = bwn_attach_pre(sc);
943		if (error != 0)
944			return (error);
945		bwn_sprom_bugfixes(sd->sd_bus);
946		sc->sc_flags |= BWN_FLAG_ATTACHED;
947	}
948
949	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
950		if (siba->siba_pci_did != 0x4313 &&
951		    siba->siba_pci_did != 0x431a &&
952		    siba->siba_pci_did != 0x4321) {
953			device_printf(sc->sc_dev,
954			    "skip 802.11 cores\n");
955			return (ENODEV);
956		}
957	}
958
959	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
960	    M_NOWAIT | M_ZERO);
961	if (mac == NULL)
962		return (ENOMEM);
963	mac->mac_sc = sc;
964	mac->mac_sd = sd;
965	mac->mac_status = BWN_MAC_STATUS_UNINIT;
966	if (bwn_bfp != 0)
967		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
968
969	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
970	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
971	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
972
973	error = bwn_attach_core(mac);
974	if (error)
975		goto fail0;
976	bwn_led_attach(mac);
977
978	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
979	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
980	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
981	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
982	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
983	    mac->mac_phy.rf_rev);
984	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
985		device_printf(sc->sc_dev, "DMA (%d bits)\n",
986		    mac->mac_method.dma.dmatype);
987	else
988		device_printf(sc->sc_dev, "PIO\n");
989
990	/*
991	 * setup PCI resources and interrupt.
992	 */
993	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
994		msic = pci_msi_count(dev);
995		if (bootverbose)
996			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
997	} else
998		msic = 0;
999
1000	mac->mac_intr_spec = bwn_res_spec_legacy;
1001	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1002		if (pci_alloc_msi(dev, &msic) == 0) {
1003			device_printf(sc->sc_dev,
1004			    "Using %d MSI messages\n", msic);
1005			mac->mac_intr_spec = bwn_res_spec_msi;
1006			mac->mac_msi = 1;
1007		}
1008	}
1009
1010	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1011	    mac->mac_res_irq);
1012	if (error) {
1013		device_printf(sc->sc_dev,
1014		    "couldn't allocate IRQ resources (%d)\n", error);
1015		goto fail1;
1016	}
1017
1018	if (mac->mac_msi == 0)
1019		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1020		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1021		    &mac->mac_intrhand[0]);
1022	else {
1023		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1024			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1025			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1026			    &mac->mac_intrhand[i]);
1027			if (error != 0) {
1028				device_printf(sc->sc_dev,
1029				    "couldn't setup interrupt (%d)\n", error);
1030				break;
1031			}
1032		}
1033	}
1034
1035	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1036
1037	/*
1038	 * calls attach-post routine
1039	 */
1040	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1041		bwn_attach_post(sc);
1042
1043	return (0);
1044fail1:
1045	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1046		pci_release_msi(dev);
1047fail0:
1048	free(mac, M_DEVBUF);
1049	return (error);
1050}
1051
1052static int
1053bwn_is_valid_ether_addr(uint8_t *addr)
1054{
1055	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1056
1057	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1058		return (FALSE);
1059
1060	return (TRUE);
1061}
1062
1063static int
1064bwn_attach_post(struct bwn_softc *sc)
1065{
1066	struct ieee80211com *ic;
1067	struct ifnet *ifp = sc->sc_ifp;
1068	struct siba_dev_softc *sd = sc->sc_sd;
1069	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1070
1071	ic = ifp->if_l2com;
1072	ic->ic_ifp = ifp;
1073	/* XXX not right but it's not used anywhere important */
1074	ic->ic_phytype = IEEE80211_T_OFDM;
1075	ic->ic_opmode = IEEE80211_M_STA;
1076	ic->ic_caps =
1077		  IEEE80211_C_STA		/* station mode supported */
1078		| IEEE80211_C_MONITOR		/* monitor mode */
1079		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1080		| IEEE80211_C_SHSLOT		/* short slot time supported */
1081		| IEEE80211_C_WME		/* WME/WMM supported */
1082		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1083		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1084		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1085		;
1086
1087	/* call MI attach routine. */
1088	ieee80211_ifattach(ic,
1089	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1090	    sprom->mac_80211bg);
1091
1092	ic->ic_headroom = sizeof(struct bwn_txhdr);
1093
1094	/* override default methods */
1095	ic->ic_raw_xmit = bwn_raw_xmit;
1096	ic->ic_newassoc = bwn_newassoc;
1097	ic->ic_updateslot = bwn_updateslot;
1098	ic->ic_update_promisc = bwn_update_promisc;
1099	ic->ic_wme.wme_update = bwn_wme_update;
1100
1101	ic->ic_node_alloc = bwn_node_alloc;
1102	sc->sc_node_cleanup = ic->ic_node_cleanup;
1103	ic->ic_node_cleanup = bwn_node_cleanup;
1104
1105	ic->ic_scan_start = bwn_scan_start;
1106	ic->ic_scan_end = bwn_scan_end;
1107	ic->ic_set_channel = bwn_set_channel;
1108
1109	ic->ic_vap_create = bwn_vap_create;
1110	ic->ic_vap_delete = bwn_vap_delete;
1111
1112	ieee80211_radiotap_attach(ic,
1113	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1114	    BWN_TX_RADIOTAP_PRESENT,
1115	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1116	    BWN_RX_RADIOTAP_PRESENT);
1117
1118	bwn_sysctl_node(sc);
1119
1120	if (bootverbose)
1121		ieee80211_announce(ic);
1122	return (0);
1123}
1124
1125static void
1126bwn_phy_detach(struct bwn_mac *mac)
1127{
1128
1129	if (mac->mac_phy.detach != NULL)
1130		mac->mac_phy.detach(mac);
1131}
1132
1133static int
1134bwn_detach(device_t dev)
1135{
1136	struct bwn_softc *sc = device_get_softc(dev);
1137	struct bwn_mac *mac = sc->sc_curmac;
1138	struct ifnet *ifp = sc->sc_ifp;
1139	struct ieee80211com *ic = ifp->if_l2com;
1140	int i;
1141
1142	sc->sc_flags |= BWN_FLAG_INVALID;
1143
1144	if (device_is_attached(sc->sc_dev)) {
1145		bwn_stop(sc, 1);
1146		bwn_dma_free(mac);
1147		callout_drain(&sc->sc_led_blink_ch);
1148		callout_drain(&sc->sc_rfswitch_ch);
1149		callout_drain(&sc->sc_task_ch);
1150		callout_drain(&sc->sc_watchdog_ch);
1151		bwn_phy_detach(mac);
1152		if (ifp != NULL) {
1153			ieee80211_draintask(ic, &mac->mac_hwreset);
1154			ieee80211_draintask(ic, &mac->mac_txpower);
1155			ieee80211_ifdetach(ic);
1156			if_free(ifp);
1157		}
1158	}
1159	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1160	taskqueue_free(sc->sc_tq);
1161
1162	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1163		if (mac->mac_intrhand[i] != NULL) {
1164			bus_teardown_intr(dev, mac->mac_res_irq[i],
1165			    mac->mac_intrhand[i]);
1166			mac->mac_intrhand[i] = NULL;
1167		}
1168	}
1169	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1170	if (mac->mac_msi != 0)
1171		pci_release_msi(dev);
1172
1173	BWN_LOCK_DESTROY(sc);
1174	return (0);
1175}
1176
1177static int
1178bwn_attach_pre(struct bwn_softc *sc)
1179{
1180	struct ifnet *ifp;
1181	int error = 0;
1182
1183	BWN_LOCK_INIT(sc);
1184	TAILQ_INIT(&sc->sc_maclist);
1185	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1186	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1187	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1188
1189	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1190		taskqueue_thread_enqueue, &sc->sc_tq);
1191	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1192		"%s taskq", device_get_nameunit(sc->sc_dev));
1193
1194	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1195	if (ifp == NULL) {
1196		device_printf(sc->sc_dev, "can not if_alloc()\n");
1197		error = ENOSPC;
1198		goto fail;
1199	}
1200
1201	/* set these up early for if_printf use */
1202	if_initname(ifp, device_get_name(sc->sc_dev),
1203	    device_get_unit(sc->sc_dev));
1204
1205	ifp->if_softc = sc;
1206	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1207	ifp->if_init = bwn_init;
1208	ifp->if_ioctl = bwn_ioctl;
1209	ifp->if_start = bwn_start;
1210	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1211	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1212	IFQ_SET_READY(&ifp->if_snd);
1213
1214	return (0);
1215
1216fail:	BWN_LOCK_DESTROY(sc);
1217	return (error);
1218}
1219
1220static void
1221bwn_sprom_bugfixes(struct siba_softc *siba)
1222{
1223#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1224	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1225	 (siba->siba_pci_did == _device) &&				\
1226	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1227	 (siba->siba_pci_subdid == _subdevice))
1228
1229	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1230	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1231		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1232	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1233	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1234		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1235	if (siba->siba_type == SIBA_TYPE_PCI) {
1236		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1237		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1238		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1239		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1240		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1241		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1242		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1243			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1244	}
1245#undef	BWN_ISDEV
1246}
1247
1248static int
1249bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1250{
1251#define	IS_RUNNING(ifp) \
1252	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1253	struct bwn_softc *sc = ifp->if_softc;
1254	struct ieee80211com *ic = ifp->if_l2com;
1255	struct ifreq *ifr = (struct ifreq *)data;
1256	int error = 0, startall;
1257
1258	switch (cmd) {
1259	case SIOCSIFFLAGS:
1260		startall = 0;
1261		if (IS_RUNNING(ifp)) {
1262			bwn_update_promisc(ifp);
1263		} else if (ifp->if_flags & IFF_UP) {
1264			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1265				bwn_init(sc);
1266				startall = 1;
1267			}
1268		} else
1269			bwn_stop(sc, 1);
1270		if (startall)
1271			ieee80211_start_all(ic);
1272		break;
1273	case SIOCGIFMEDIA:
1274		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1275		break;
1276	case SIOCGIFADDR:
1277		error = ether_ioctl(ifp, cmd, data);
1278		break;
1279	default:
1280		error = EINVAL;
1281		break;
1282	}
1283	return (error);
1284}
1285
1286static void
1287bwn_start(struct ifnet *ifp)
1288{
1289	struct bwn_softc *sc = ifp->if_softc;
1290
1291	BWN_LOCK(sc);
1292	bwn_start_locked(ifp);
1293	BWN_UNLOCK(sc);
1294}
1295
1296static void
1297bwn_start_locked(struct ifnet *ifp)
1298{
1299	struct bwn_softc *sc = ifp->if_softc;
1300	struct bwn_mac *mac = sc->sc_curmac;
1301	struct ieee80211_frame *wh;
1302	struct ieee80211_node *ni;
1303	struct ieee80211_key *k;
1304	struct mbuf *m;
1305
1306	BWN_ASSERT_LOCKED(sc);
1307
1308	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1309	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1310		return;
1311
1312	for (;;) {
1313		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1314		if (m == NULL)
1315			break;
1316
1317		if (bwn_tx_isfull(sc, m))
1318			break;
1319		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1320		if (ni == NULL) {
1321			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1322			m_freem(m);
1323			ifp->if_oerrors++;
1324			continue;
1325		}
1326		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1327		wh = mtod(m, struct ieee80211_frame *);
1328		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1329			k = ieee80211_crypto_encap(ni, m);
1330			if (k == NULL) {
1331				ieee80211_free_node(ni);
1332				m_freem(m);
1333				ifp->if_oerrors++;
1334				continue;
1335			}
1336		}
1337		wh = NULL;	/* Catch any invalid use */
1338
1339		if (bwn_tx_start(sc, ni, m) != 0) {
1340			if (ni != NULL)
1341				ieee80211_free_node(ni);
1342			ifp->if_oerrors++;
1343			continue;
1344		}
1345
1346		sc->sc_watchdog_timer = 5;
1347	}
1348}
1349
1350static int
1351bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1352{
1353	struct bwn_dma_ring *dr;
1354	struct bwn_mac *mac = sc->sc_curmac;
1355	struct bwn_pio_txqueue *tq;
1356	struct ifnet *ifp = sc->sc_ifp;
1357	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1358
1359	BWN_ASSERT_LOCKED(sc);
1360
1361	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1362		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1363		if (dr->dr_stop == 1 ||
1364		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1365			dr->dr_stop = 1;
1366			goto full;
1367		}
1368	} else {
1369		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1370		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1371		    pktlen > (tq->tq_size - tq->tq_used)) {
1372			tq->tq_stop = 1;
1373			goto full;
1374		}
1375	}
1376	return (0);
1377full:
1378	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1379	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1380	return (1);
1381}
1382
1383static int
1384bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1385{
1386	struct bwn_mac *mac = sc->sc_curmac;
1387	int error;
1388
1389	BWN_ASSERT_LOCKED(sc);
1390
1391	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1392		m_freem(m);
1393		return (ENXIO);
1394	}
1395
1396	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1397	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1398	if (error) {
1399		m_freem(m);
1400		return (error);
1401	}
1402	return (0);
1403}
1404
1405static int
1406bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1407{
1408	struct bwn_pio_txpkt *tp;
1409	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1410	struct bwn_softc *sc = mac->mac_sc;
1411	struct bwn_txhdr txhdr;
1412	struct mbuf *m_new;
1413	uint32_t ctl32;
1414	int error;
1415	uint16_t ctl16;
1416
1417	BWN_ASSERT_LOCKED(sc);
1418
1419	/* XXX TODO send packets after DTIM */
1420
1421	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1422	tp = TAILQ_FIRST(&tq->tq_pktlist);
1423	tp->tp_ni = ni;
1424	tp->tp_m = m;
1425
1426	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1427	if (error) {
1428		device_printf(sc->sc_dev, "tx fail\n");
1429		return (error);
1430	}
1431
1432	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1433	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1434	tq->tq_free--;
1435
1436	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1437		/*
1438		 * XXX please removes m_defrag(9)
1439		 */
1440		m_new = m_defrag(m, M_DONTWAIT);
1441		if (m_new == NULL) {
1442			device_printf(sc->sc_dev,
1443			    "%s: can't defrag TX buffer\n",
1444			    __func__);
1445			return (ENOBUFS);
1446		}
1447		if (m_new->m_next != NULL)
1448			device_printf(sc->sc_dev,
1449			    "TODO: fragmented packets for PIO\n");
1450		tp->tp_m = m_new;
1451
1452		/* send HEADER */
1453		ctl32 = bwn_pio_write_multi_4(mac, tq,
1454		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1455			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1456		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1457		/* send BODY */
1458		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1459		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1460		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1461		    ctl32 | BWN_PIO8_TXCTL_EOF);
1462	} else {
1463		ctl16 = bwn_pio_write_multi_2(mac, tq,
1464		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1465			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1466		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1467		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1468		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1469		    ctl16 | BWN_PIO_TXCTL_EOF);
1470	}
1471
1472	return (0);
1473}
1474
1475static struct bwn_pio_txqueue *
1476bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1477{
1478
1479	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1480		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1481
1482	switch (prio) {
1483	case 0:
1484		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1485	case 1:
1486		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1487	case 2:
1488		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1489	case 3:
1490		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1491	}
1492	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1493	return (NULL);
1494}
1495
1496static int
1497bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1498{
1499#define	BWN_GET_TXHDRCACHE(slot)					\
1500	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1501	struct bwn_dma *dma = &mac->mac_method.dma;
1502	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1503	struct bwn_dmadesc_generic *desc;
1504	struct bwn_dmadesc_meta *mt;
1505	struct bwn_softc *sc = mac->mac_sc;
1506	struct ifnet *ifp = sc->sc_ifp;
1507	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1508	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1509
1510	BWN_ASSERT_LOCKED(sc);
1511	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1512
1513	/* XXX send after DTIM */
1514
1515	slot = bwn_dma_getslot(dr);
1516	dr->getdesc(dr, slot, &desc, &mt);
1517	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1518	    ("%s:%d: fail", __func__, __LINE__));
1519
1520	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1521	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1522	    BWN_DMA_COOKIE(dr, slot));
1523	if (error)
1524		goto fail;
1525	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1526	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1527	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1528	if (error) {
1529		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1530		    __func__, error);
1531		goto fail;
1532	}
1533	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1534	    BUS_DMASYNC_PREWRITE);
1535	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1536	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1537	    BUS_DMASYNC_PREWRITE);
1538
1539	slot = bwn_dma_getslot(dr);
1540	dr->getdesc(dr, slot, &desc, &mt);
1541	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1542	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1543	mt->mt_m = m;
1544	mt->mt_ni = ni;
1545
1546	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1547	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1548	if (error && error != EFBIG) {
1549		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1550		    __func__, error);
1551		goto fail;
1552	}
1553	if (error) {    /* error == EFBIG */
1554		struct mbuf *m_new;
1555
1556		m_new = m_defrag(m, M_DONTWAIT);
1557		if (m_new == NULL) {
1558			if_printf(ifp, "%s: can't defrag TX buffer\n",
1559			    __func__);
1560			error = ENOBUFS;
1561			goto fail;
1562		} else {
1563			m = m_new;
1564		}
1565
1566		mt->mt_m = m;
1567		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1568		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1569		if (error) {
1570			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1571			    __func__, error);
1572			goto fail;
1573		}
1574	}
1575	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1576	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1577	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1578	    BUS_DMASYNC_PREWRITE);
1579
1580	/* XXX send after DTIM */
1581
1582	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1583	return (0);
1584fail:
1585	dr->dr_curslot = backup[0];
1586	dr->dr_usedslot = backup[1];
1587	return (error);
1588#undef BWN_GET_TXHDRCACHE
1589}
1590
1591static void
1592bwn_watchdog(void *arg)
1593{
1594	struct bwn_softc *sc = arg;
1595	struct ifnet *ifp = sc->sc_ifp;
1596
1597	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1598		if_printf(ifp, "device timeout\n");
1599		ifp->if_oerrors++;
1600	}
1601	callout_schedule(&sc->sc_watchdog_ch, hz);
1602}
1603
1604static int
1605bwn_attach_core(struct bwn_mac *mac)
1606{
1607	struct bwn_softc *sc = mac->mac_sc;
1608	struct siba_dev_softc *sd = mac->mac_sd;
1609	struct siba_softc *siba = sd->sd_bus;
1610	int error, have_bg = 0, have_a = 0;
1611	uint32_t high;
1612
1613	KASSERT(sd->sd_id.sd_rev >= 5,
1614	    ("unsupported revision %d", sd->sd_id.sd_rev));
1615
1616	siba_powerup(siba, 0);
1617
1618	high = siba_read_4(sd, SIBA_TGSHIGH);
1619	bwn_reset_core(mac,
1620	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1621	error = bwn_phy_getinfo(mac, high);
1622	if (error)
1623		goto fail;
1624
1625	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1626	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1627	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1628	    siba->siba_pci_did != 0x4324) {
1629		have_a = have_bg = 0;
1630		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1631			have_a = 1;
1632		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1633		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1634		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1635			have_bg = 1;
1636		else
1637			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1638			    mac->mac_phy.type));
1639	}
1640	/* XXX turns off PHY A because it's not supported */
1641	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1642	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1643		have_a = 0;
1644		have_bg = 1;
1645	}
1646
1647	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1648		mac->mac_phy.attach = bwn_phy_g_attach;
1649		mac->mac_phy.detach = bwn_phy_g_detach;
1650		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1651		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1652		mac->mac_phy.init = bwn_phy_g_init;
1653		mac->mac_phy.exit = bwn_phy_g_exit;
1654		mac->mac_phy.phy_read = bwn_phy_g_read;
1655		mac->mac_phy.phy_write = bwn_phy_g_write;
1656		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1657		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1658		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1659		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1660		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1661		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1662		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1663		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1664		mac->mac_phy.set_im = bwn_phy_g_im;
1665		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1666		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1667		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1668		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1669	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1670		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1671		mac->mac_phy.init = bwn_phy_lp_init;
1672		mac->mac_phy.phy_read = bwn_phy_lp_read;
1673		mac->mac_phy.phy_write = bwn_phy_lp_write;
1674		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1675		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1676		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1677		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1678		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1679		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1680		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1681		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1682		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1683	} else {
1684		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1685		    mac->mac_phy.type);
1686		error = ENXIO;
1687		goto fail;
1688	}
1689
1690	mac->mac_phy.gmode = have_bg;
1691	if (mac->mac_phy.attach != NULL) {
1692		error = mac->mac_phy.attach(mac);
1693		if (error) {
1694			device_printf(sc->sc_dev, "failed\n");
1695			goto fail;
1696		}
1697	}
1698
1699	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1700
1701	error = bwn_chiptest(mac);
1702	if (error)
1703		goto fail;
1704	error = bwn_setup_channels(mac, have_bg, have_a);
1705	if (error) {
1706		device_printf(sc->sc_dev, "failed to setup channels\n");
1707		goto fail;
1708	}
1709
1710	if (sc->sc_curmac == NULL)
1711		sc->sc_curmac = mac;
1712
1713	error = bwn_dma_attach(mac);
1714	if (error != 0) {
1715		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1716		goto fail;
1717	}
1718
1719	mac->mac_phy.switch_analog(mac, 0);
1720
1721	siba_dev_down(sd, 0);
1722fail:
1723	siba_powerdown(siba);
1724	return (error);
1725}
1726
1727static void
1728bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1729{
1730	struct siba_dev_softc *sd = mac->mac_sd;
1731	uint32_t low, ctl;
1732
1733	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1734
1735	siba_dev_up(sd, flags);
1736	DELAY(2000);
1737
1738	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1739	    ~BWN_TGSLOW_PHYRESET;
1740	siba_write_4(sd, SIBA_TGSLOW, low);
1741	siba_read_4(sd, SIBA_TGSLOW);
1742	DELAY(1000);
1743	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1744	siba_read_4(sd, SIBA_TGSLOW);
1745	DELAY(1000);
1746
1747	if (mac->mac_phy.switch_analog != NULL)
1748		mac->mac_phy.switch_analog(mac, 1);
1749
1750	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1751	if (flags & BWN_TGSLOW_SUPPORT_G)
1752		ctl |= BWN_MACCTL_GMODE;
1753	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1754}
1755
1756static int
1757bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1758{
1759	struct bwn_phy *phy = &mac->mac_phy;
1760	struct bwn_softc *sc = mac->mac_sc;
1761	struct siba_dev_softc *sd = mac->mac_sd;
1762	struct siba_softc *siba = sd->sd_bus;
1763	uint32_t tmp;
1764
1765	/* PHY */
1766	tmp = BWN_READ_2(mac, BWN_PHYVER);
1767	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1768	phy->rf_on = 1;
1769	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1770	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1771	phy->rev = (tmp & BWN_PHYVER_VERSION);
1772	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1773	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1774		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1775	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1776	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1777	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1778		goto unsupphy;
1779
1780	/* RADIO */
1781	if (siba->siba_chipid == 0x4317) {
1782		if (siba->siba_chiprev == 0)
1783			tmp = 0x3205017f;
1784		else if (siba->siba_chiprev == 1)
1785			tmp = 0x4205017f;
1786		else
1787			tmp = 0x5205017f;
1788	} else {
1789		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1790		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1791		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1792		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1793	}
1794	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1795	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1796	phy->rf_manuf = (tmp & 0x00000fff);
1797	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1798		goto unsupradio;
1799	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1800	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1801	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1802	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1803	    (phy->type == BWN_PHYTYPE_N &&
1804	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1805	    (phy->type == BWN_PHYTYPE_LP &&
1806	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1807		goto unsupradio;
1808
1809	return (0);
1810unsupphy:
1811	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1812	    "analog %#x)\n",
1813	    phy->type, phy->rev, phy->analog);
1814	return (ENXIO);
1815unsupradio:
1816	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1817	    "rev %#x)\n",
1818	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1819	return (ENXIO);
1820}
1821
1822static int
1823bwn_chiptest(struct bwn_mac *mac)
1824{
1825#define	TESTVAL0	0x55aaaa55
1826#define	TESTVAL1	0xaa5555aa
1827	struct bwn_softc *sc = mac->mac_sc;
1828	struct siba_dev_softc *sd = mac->mac_sd;
1829	uint32_t v, backup;
1830
1831	BWN_LOCK(sc);
1832
1833	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1834
1835	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1836	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1837		goto error;
1838	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1839	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1840		goto error;
1841
1842	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1843
1844	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1845		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1846		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1847		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1848			goto error;
1849		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1850			goto error;
1851	}
1852	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1853
1854	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1855	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1856		goto error;
1857
1858	BWN_UNLOCK(sc);
1859	return (0);
1860error:
1861	BWN_UNLOCK(sc);
1862	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1863	return (ENODEV);
1864}
1865
1866#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1867#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1868
1869static int
1870bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1871{
1872	struct bwn_softc *sc = mac->mac_sc;
1873	struct ifnet *ifp = sc->sc_ifp;
1874	struct ieee80211com *ic = ifp->if_l2com;
1875
1876	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1877	ic->ic_nchans = 0;
1878
1879	if (have_bg)
1880		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1881		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1882	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1883		if (have_a)
1884			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1885			    &ic->ic_nchans, &bwn_chantable_n,
1886			    IEEE80211_CHAN_HTA);
1887	} else {
1888		if (have_a)
1889			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1890			    &ic->ic_nchans, &bwn_chantable_a,
1891			    IEEE80211_CHAN_A);
1892	}
1893
1894	mac->mac_phy.supports_2ghz = have_bg;
1895	mac->mac_phy.supports_5ghz = have_a;
1896
1897	return (ic->ic_nchans == 0 ? ENXIO : 0);
1898}
1899
1900static uint32_t
1901bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1902{
1903	uint32_t ret;
1904
1905	BWN_ASSERT_LOCKED(mac->mac_sc);
1906
1907	if (way == BWN_SHARED) {
1908		KASSERT((offset & 0x0001) == 0,
1909		    ("%s:%d warn", __func__, __LINE__));
1910		if (offset & 0x0003) {
1911			bwn_shm_ctlword(mac, way, offset >> 2);
1912			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1913			ret <<= 16;
1914			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1915			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1916			goto out;
1917		}
1918		offset >>= 2;
1919	}
1920	bwn_shm_ctlword(mac, way, offset);
1921	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1922out:
1923	return (ret);
1924}
1925
1926static uint16_t
1927bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1928{
1929	uint16_t ret;
1930
1931	BWN_ASSERT_LOCKED(mac->mac_sc);
1932
1933	if (way == BWN_SHARED) {
1934		KASSERT((offset & 0x0001) == 0,
1935		    ("%s:%d warn", __func__, __LINE__));
1936		if (offset & 0x0003) {
1937			bwn_shm_ctlword(mac, way, offset >> 2);
1938			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1939			goto out;
1940		}
1941		offset >>= 2;
1942	}
1943	bwn_shm_ctlword(mac, way, offset);
1944	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1945out:
1946
1947	return (ret);
1948}
1949
1950static void
1951bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1952    uint16_t offset)
1953{
1954	uint32_t control;
1955
1956	control = way;
1957	control <<= 16;
1958	control |= offset;
1959	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1960}
1961
1962static void
1963bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1964    uint32_t value)
1965{
1966	BWN_ASSERT_LOCKED(mac->mac_sc);
1967
1968	if (way == BWN_SHARED) {
1969		KASSERT((offset & 0x0001) == 0,
1970		    ("%s:%d warn", __func__, __LINE__));
1971		if (offset & 0x0003) {
1972			bwn_shm_ctlword(mac, way, offset >> 2);
1973			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1974				    (value >> 16) & 0xffff);
1975			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1976			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1977			return;
1978		}
1979		offset >>= 2;
1980	}
1981	bwn_shm_ctlword(mac, way, offset);
1982	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1983}
1984
1985static void
1986bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1987    uint16_t value)
1988{
1989	BWN_ASSERT_LOCKED(mac->mac_sc);
1990
1991	if (way == BWN_SHARED) {
1992		KASSERT((offset & 0x0001) == 0,
1993		    ("%s:%d warn", __func__, __LINE__));
1994		if (offset & 0x0003) {
1995			bwn_shm_ctlword(mac, way, offset >> 2);
1996			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1997			return;
1998		}
1999		offset >>= 2;
2000	}
2001	bwn_shm_ctlword(mac, way, offset);
2002	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2003}
2004
2005static void
2006bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2007    int txpow)
2008{
2009
2010	c->ic_freq = freq;
2011	c->ic_flags = flags;
2012	c->ic_ieee = ieee;
2013	c->ic_minpower = 0;
2014	c->ic_maxpower = 2 * txpow;
2015	c->ic_maxregpower = txpow;
2016}
2017
2018static void
2019bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2020    const struct bwn_channelinfo *ci, int flags)
2021{
2022	struct ieee80211_channel *c;
2023	int i;
2024
2025	c = &chans[*nchans];
2026
2027	for (i = 0; i < ci->nchannels; i++) {
2028		const struct bwn_channel *hc;
2029
2030		hc = &ci->channels[i];
2031		if (*nchans >= maxchans)
2032			break;
2033		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2034		c++, (*nchans)++;
2035		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2036			/* g channel have a separate b-only entry */
2037			if (*nchans >= maxchans)
2038				break;
2039			c[0] = c[-1];
2040			c[-1].ic_flags = IEEE80211_CHAN_B;
2041			c++, (*nchans)++;
2042		}
2043		if (flags == IEEE80211_CHAN_HTG) {
2044			/* HT g channel have a separate g-only entry */
2045			if (*nchans >= maxchans)
2046				break;
2047			c[-1].ic_flags = IEEE80211_CHAN_G;
2048			c[0] = c[-1];
2049			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2050			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2051			c++, (*nchans)++;
2052		}
2053		if (flags == IEEE80211_CHAN_HTA) {
2054			/* HT a channel have a separate a-only entry */
2055			if (*nchans >= maxchans)
2056				break;
2057			c[-1].ic_flags = IEEE80211_CHAN_A;
2058			c[0] = c[-1];
2059			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2060			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2061			c++, (*nchans)++;
2062		}
2063	}
2064}
2065
2066static int
2067bwn_phy_g_attach(struct bwn_mac *mac)
2068{
2069	struct bwn_softc *sc = mac->mac_sc;
2070	struct bwn_phy *phy = &mac->mac_phy;
2071	struct bwn_phy_g *pg = &phy->phy_g;
2072	struct siba_dev_softc *sd = mac->mac_sd;
2073	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2074	unsigned int i;
2075	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2076	    pab2 = (int16_t)(sprom->pa0b2);
2077	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2078	int8_t bg = (int8_t)sprom->tssi_bg;
2079
2080	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2081		device_printf(sc->sc_dev, "not supported anymore\n");
2082
2083	pg->pg_flags = 0;
2084	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2085	    pab2 == -1) {
2086		pg->pg_idletssi = 52;
2087		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2088		return (0);
2089	}
2090
2091	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2092	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2093	if (pg->pg_tssi2dbm == NULL) {
2094		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2095		return (ENOMEM);
2096	}
2097	for (i = 0; i < 64; i++) {
2098		int32_t m1, m2, f, q, delta;
2099		int8_t j = 0;
2100
2101		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2102		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2103		f = 256;
2104
2105		do {
2106			if (j > 15) {
2107				device_printf(sc->sc_dev,
2108				    "failed to generate tssi2dBm\n");
2109				free(pg->pg_tssi2dbm, M_DEVBUF);
2110				return (ENOMEM);
2111			}
2112			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2113			    f, 2048);
2114			delta = abs(q - f);
2115			f = q;
2116			j++;
2117		} while (delta >= 2);
2118
2119		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2120		    128);
2121	}
2122
2123	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2124	return (0);
2125}
2126
2127static void
2128bwn_phy_g_detach(struct bwn_mac *mac)
2129{
2130	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2131
2132	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2133		free(pg->pg_tssi2dbm, M_DEVBUF);
2134		pg->pg_tssi2dbm = NULL;
2135	}
2136	pg->pg_flags = 0;
2137}
2138
2139static void
2140bwn_phy_g_init_pre(struct bwn_mac *mac)
2141{
2142	struct bwn_phy *phy = &mac->mac_phy;
2143	struct bwn_phy_g *pg = &phy->phy_g;
2144	void *tssi2dbm;
2145	int idletssi;
2146	unsigned int i;
2147
2148	tssi2dbm = pg->pg_tssi2dbm;
2149	idletssi = pg->pg_idletssi;
2150
2151	memset(pg, 0, sizeof(*pg));
2152
2153	pg->pg_tssi2dbm = tssi2dbm;
2154	pg->pg_idletssi = idletssi;
2155
2156	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2157
2158	for (i = 0; i < N(pg->pg_nrssi); i++)
2159		pg->pg_nrssi[i] = -1000;
2160	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2161		pg->pg_nrssi_lt[i] = i;
2162	pg->pg_lofcal = 0xffff;
2163	pg->pg_initval = 0xffff;
2164	pg->pg_immode = BWN_IMMODE_NONE;
2165	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2166	pg->pg_avgtssi = 0xff;
2167
2168	pg->pg_loctl.tx_bias = 0xff;
2169	TAILQ_INIT(&pg->pg_loctl.calib_list);
2170}
2171
2172static int
2173bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2174{
2175	struct bwn_phy *phy = &mac->mac_phy;
2176	struct bwn_phy_g *pg = &phy->phy_g;
2177	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2178	struct siba_softc *bus = mac->mac_sd->sd_bus;
2179	static const struct bwn_rfatt rfatt0[] = {
2180		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2181		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2182		{ 3, 1 }, { 4, 1 }
2183	};
2184	static const struct bwn_rfatt rfatt1[] = {
2185		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2186		{ 14, 1 }
2187	};
2188	static const struct bwn_rfatt rfatt2[] = {
2189		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2190		{ 9, 1 }
2191	};
2192	static const struct bwn_bbatt bbatt_0[] = {
2193		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2194	};
2195
2196	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2197
2198	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2199		pg->pg_bbatt.att = 0;
2200	else
2201		pg->pg_bbatt.att = 2;
2202
2203	/* prepare Radio Attenuation */
2204	pg->pg_rfatt.padmix = 0;
2205
2206	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2207	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2208		if (bus->siba_board_rev < 0x43) {
2209			pg->pg_rfatt.att = 2;
2210			goto done;
2211		} else if (bus->siba_board_rev < 0x51) {
2212			pg->pg_rfatt.att = 3;
2213			goto done;
2214		}
2215	}
2216
2217	if (phy->type == BWN_PHYTYPE_A) {
2218		pg->pg_rfatt.att = 0x60;
2219		goto done;
2220	}
2221
2222	switch (phy->rf_ver) {
2223	case 0x2050:
2224		switch (phy->rf_rev) {
2225		case 0:
2226			pg->pg_rfatt.att = 5;
2227			goto done;
2228		case 1:
2229			if (phy->type == BWN_PHYTYPE_G) {
2230				if (bus->siba_board_vendor ==
2231				    SIBA_BOARDVENDOR_BCM &&
2232				    bus->siba_board_type ==
2233				    SIBA_BOARD_BCM4309G &&
2234				    bus->siba_board_rev >= 30)
2235					pg->pg_rfatt.att = 3;
2236				else if (bus->siba_board_vendor ==
2237				    SIBA_BOARDVENDOR_BCM &&
2238				    bus->siba_board_type == SIBA_BOARD_BU4306)
2239					pg->pg_rfatt.att = 3;
2240				else
2241					pg->pg_rfatt.att = 1;
2242			} else {
2243				if (bus->siba_board_vendor ==
2244				    SIBA_BOARDVENDOR_BCM &&
2245				    bus->siba_board_type ==
2246				    SIBA_BOARD_BCM4309G &&
2247				    bus->siba_board_rev >= 30)
2248					pg->pg_rfatt.att = 7;
2249				else
2250					pg->pg_rfatt.att = 6;
2251			}
2252			goto done;
2253		case 2:
2254			if (phy->type == BWN_PHYTYPE_G) {
2255				if (bus->siba_board_vendor ==
2256				    SIBA_BOARDVENDOR_BCM &&
2257				    bus->siba_board_type ==
2258				    SIBA_BOARD_BCM4309G &&
2259				    bus->siba_board_rev >= 30)
2260					pg->pg_rfatt.att = 3;
2261				else if (bus->siba_board_vendor ==
2262				    SIBA_BOARDVENDOR_BCM &&
2263				    bus->siba_board_type == SIBA_BOARD_BU4306)
2264					pg->pg_rfatt.att = 5;
2265				else if (bus->siba_chipid == 0x4320)
2266					pg->pg_rfatt.att = 4;
2267				else
2268					pg->pg_rfatt.att = 3;
2269			} else
2270				pg->pg_rfatt.att = 6;
2271			goto done;
2272		case 3:
2273			pg->pg_rfatt.att = 5;
2274			goto done;
2275		case 4:
2276		case 5:
2277			pg->pg_rfatt.att = 1;
2278			goto done;
2279		case 6:
2280		case 7:
2281			pg->pg_rfatt.att = 5;
2282			goto done;
2283		case 8:
2284			pg->pg_rfatt.att = 0xa;
2285			pg->pg_rfatt.padmix = 1;
2286			goto done;
2287		case 9:
2288		default:
2289			pg->pg_rfatt.att = 5;
2290			goto done;
2291		}
2292		break;
2293	case 0x2053:
2294		switch (phy->rf_rev) {
2295		case 1:
2296			pg->pg_rfatt.att = 6;
2297			goto done;
2298		}
2299		break;
2300	}
2301	pg->pg_rfatt.att = 5;
2302done:
2303	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2304
2305	if (!bwn_has_hwpctl(mac)) {
2306		lo->rfatt.array = rfatt0;
2307		lo->rfatt.len = N(rfatt0);
2308		lo->rfatt.min = 0;
2309		lo->rfatt.max = 9;
2310		goto genbbatt;
2311	}
2312	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2313		lo->rfatt.array = rfatt1;
2314		lo->rfatt.len = N(rfatt1);
2315		lo->rfatt.min = 0;
2316		lo->rfatt.max = 14;
2317		goto genbbatt;
2318	}
2319	lo->rfatt.array = rfatt2;
2320	lo->rfatt.len = N(rfatt2);
2321	lo->rfatt.min = 0;
2322	lo->rfatt.max = 9;
2323genbbatt:
2324	lo->bbatt.array = bbatt_0;
2325	lo->bbatt.len = N(bbatt_0);
2326	lo->bbatt.min = 0;
2327	lo->bbatt.max = 8;
2328
2329	BWN_READ_4(mac, BWN_MACCTL);
2330	if (phy->rev == 1) {
2331		phy->gmode = 0;
2332		bwn_reset_core(mac, 0);
2333		bwn_phy_g_init_sub(mac);
2334		phy->gmode = 1;
2335		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2336	}
2337	return (0);
2338}
2339
2340static uint16_t
2341bwn_phy_g_txctl(struct bwn_mac *mac)
2342{
2343	struct bwn_phy *phy = &mac->mac_phy;
2344
2345	if (phy->rf_ver != 0x2050)
2346		return (0);
2347	if (phy->rf_rev == 1)
2348		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2349	if (phy->rf_rev < 6)
2350		return (BWN_TXCTL_PA2DB);
2351	if (phy->rf_rev == 8)
2352		return (BWN_TXCTL_TXMIX);
2353	return (0);
2354}
2355
2356static int
2357bwn_phy_g_init(struct bwn_mac *mac)
2358{
2359
2360	bwn_phy_g_init_sub(mac);
2361	return (0);
2362}
2363
2364static void
2365bwn_phy_g_exit(struct bwn_mac *mac)
2366{
2367	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2368	struct bwn_lo_calib *cal, *tmp;
2369
2370	if (lo == NULL)
2371		return;
2372	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2373		TAILQ_REMOVE(&lo->calib_list, cal, list);
2374		free(cal, M_DEVBUF);
2375	}
2376}
2377
2378static uint16_t
2379bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2380{
2381
2382	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383	return (BWN_READ_2(mac, BWN_PHYDATA));
2384}
2385
2386static void
2387bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2388{
2389
2390	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2391	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2392}
2393
2394static uint16_t
2395bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2396{
2397
2398	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2400	return (BWN_READ_2(mac, BWN_RFDATALO));
2401}
2402
2403static void
2404bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2405{
2406
2407	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2408	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2409	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2410}
2411
2412static int
2413bwn_phy_g_hwpctl(struct bwn_mac *mac)
2414{
2415
2416	return (mac->mac_phy.rev >= 6);
2417}
2418
2419static void
2420bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2421{
2422	struct bwn_phy *phy = &mac->mac_phy;
2423	struct bwn_phy_g *pg = &phy->phy_g;
2424	unsigned int channel;
2425	uint16_t rfover, rfoverval;
2426
2427	if (on) {
2428		if (phy->rf_on)
2429			return;
2430
2431		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2432		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2433		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2434		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2435			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2436			    pg->pg_radioctx_over);
2437			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2438			    pg->pg_radioctx_overval);
2439			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2440		}
2441		channel = phy->chan;
2442		bwn_phy_g_switch_chan(mac, 6, 1);
2443		bwn_phy_g_switch_chan(mac, channel, 0);
2444		return;
2445	}
2446
2447	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2448	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2449	pg->pg_radioctx_over = rfover;
2450	pg->pg_radioctx_overval = rfoverval;
2451	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2452	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2453	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2454}
2455
2456static int
2457bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2458{
2459
2460	if ((newchan < 1) || (newchan > 14))
2461		return (EINVAL);
2462	bwn_phy_g_switch_chan(mac, newchan, 0);
2463
2464	return (0);
2465}
2466
2467static uint32_t
2468bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2469{
2470
2471	return (1);
2472}
2473
2474static void
2475bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2476{
2477	struct bwn_phy *phy = &mac->mac_phy;
2478	uint64_t hf;
2479	int autodiv = 0;
2480	uint16_t tmp;
2481
2482	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2483		autodiv = 1;
2484
2485	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2486	bwn_hf_write(mac, hf);
2487
2488	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2489	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2490	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2491		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2492
2493	if (autodiv) {
2494		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2495		if (antenna == BWN_ANTAUTO1)
2496			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2497		else
2498			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2499		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2500	}
2501	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2502	if (autodiv)
2503		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2504	else
2505		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2506	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2507	if (phy->rev >= 2) {
2508		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2509		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2510		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2511		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2512		    0x15);
2513		if (phy->rev == 2)
2514			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2515		else
2516			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2517			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2518			    8);
2519	}
2520	if (phy->rev >= 6)
2521		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2522
2523	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2524	bwn_hf_write(mac, hf);
2525}
2526
2527static int
2528bwn_phy_g_im(struct bwn_mac *mac, int mode)
2529{
2530	struct bwn_phy *phy = &mac->mac_phy;
2531	struct bwn_phy_g *pg = &phy->phy_g;
2532
2533	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2534	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2535
2536	if (phy->rev == 0 || !phy->gmode)
2537		return (ENODEV);
2538
2539	pg->pg_aci_wlan_automatic = 0;
2540	return (0);
2541}
2542
2543static int
2544bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2545{
2546	struct bwn_phy *phy = &mac->mac_phy;
2547	struct bwn_phy_g *pg = &phy->phy_g;
2548	struct bwn_softc *sc = mac->mac_sc;
2549	struct siba_softc *siba = mac->mac_sd->sd_bus;
2550	unsigned int tssi;
2551	int cck, ofdm;
2552	int power;
2553	int rfatt, bbatt;
2554	unsigned int max;
2555
2556	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2557
2558	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2559	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2560	if (cck < 0 && ofdm < 0) {
2561		if (ignore_tssi == 0)
2562			return (BWN_TXPWR_RES_DONE);
2563		cck = 0;
2564		ofdm = 0;
2565	}
2566	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2567	if (pg->pg_avgtssi != 0xff)
2568		tssi = (tssi + pg->pg_avgtssi) / 2;
2569	pg->pg_avgtssi = tssi;
2570	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2571
2572	max = siba->siba_sprom.maxpwr_bg;
2573	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2574		max -= 3;
2575	if (max >= 120) {
2576		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2577		siba->siba_sprom.maxpwr_bg = max = 80;
2578	}
2579
2580	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2581	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2582	     tssi, 0x00), 0x3f)]);
2583	if (power == 0)
2584		return (BWN_TXPWR_RES_DONE);
2585
2586	rfatt = -((power + 7) / 8);
2587	bbatt = (-(power / 2)) - (4 * rfatt);
2588	if ((rfatt == 0) && (bbatt == 0))
2589		return (BWN_TXPWR_RES_DONE);
2590	pg->pg_bbatt_delta = bbatt;
2591	pg->pg_rfatt_delta = rfatt;
2592	return (BWN_TXPWR_RES_NEED_ADJUST);
2593}
2594
2595static void
2596bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2597{
2598	struct bwn_phy *phy = &mac->mac_phy;
2599	struct bwn_phy_g *pg = &phy->phy_g;
2600	struct bwn_softc *sc = mac->mac_sc;
2601	int rfatt, bbatt;
2602	uint8_t txctl;
2603
2604	bwn_mac_suspend(mac);
2605
2606	BWN_ASSERT_LOCKED(sc);
2607
2608	bbatt = pg->pg_bbatt.att;
2609	bbatt += pg->pg_bbatt_delta;
2610	rfatt = pg->pg_rfatt.att;
2611	rfatt += pg->pg_rfatt_delta;
2612
2613	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2614	txctl = pg->pg_txctl;
2615	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2616		if (rfatt <= 1) {
2617			if (txctl == 0) {
2618				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2619				rfatt += 2;
2620				bbatt += 2;
2621			} else if (mac->mac_sd->sd_bus->siba_sprom.
2622				   bf_lo &
2623				   BWN_BFL_PACTRL) {
2624				bbatt += 4 * (rfatt - 2);
2625				rfatt = 2;
2626			}
2627		} else if (rfatt > 4 && txctl) {
2628			txctl = 0;
2629			if (bbatt < 3) {
2630				rfatt -= 3;
2631				bbatt += 2;
2632			} else {
2633				rfatt -= 2;
2634				bbatt -= 2;
2635			}
2636		}
2637	}
2638	pg->pg_txctl = txctl;
2639	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2640	pg->pg_rfatt.att = rfatt;
2641	pg->pg_bbatt.att = bbatt;
2642
2643	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2644
2645	bwn_phy_lock(mac);
2646	bwn_rf_lock(mac);
2647	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2648	    pg->pg_txctl);
2649	bwn_rf_unlock(mac);
2650	bwn_phy_unlock(mac);
2651
2652	bwn_mac_enable(mac);
2653}
2654
2655static void
2656bwn_phy_g_task_15s(struct bwn_mac *mac)
2657{
2658	struct bwn_phy *phy = &mac->mac_phy;
2659	struct bwn_phy_g *pg = &phy->phy_g;
2660	struct bwn_softc *sc = mac->mac_sc;
2661	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2662	unsigned long expire, now;
2663	struct bwn_lo_calib *cal, *tmp;
2664	uint8_t expired = 0;
2665
2666	bwn_mac_suspend(mac);
2667
2668	if (lo == NULL)
2669		goto fail;
2670
2671	BWN_GETTIME(now);
2672	if (bwn_has_hwpctl(mac)) {
2673		expire = now - BWN_LO_PWRVEC_EXPIRE;
2674		if (time_before(lo->pwr_vec_read_time, expire)) {
2675			bwn_lo_get_powervector(mac);
2676			bwn_phy_g_dc_lookup_init(mac, 0);
2677		}
2678		goto fail;
2679	}
2680
2681	expire = now - BWN_LO_CALIB_EXPIRE;
2682	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2683		if (!time_before(cal->calib_time, expire))
2684			continue;
2685		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2686		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2687			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2688			expired = 1;
2689		}
2690
2691		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2692		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2693		    cal->ctl.i, cal->ctl.q);
2694
2695		TAILQ_REMOVE(&lo->calib_list, cal, list);
2696		free(cal, M_DEVBUF);
2697	}
2698	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2699		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2700		    &pg->pg_rfatt);
2701		if (cal == NULL) {
2702			device_printf(sc->sc_dev,
2703			    "failed to recalibrate LO\n");
2704			goto fail;
2705		}
2706		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2707		bwn_lo_write(mac, &cal->ctl);
2708	}
2709
2710fail:
2711	bwn_mac_enable(mac);
2712}
2713
2714static void
2715bwn_phy_g_task_60s(struct bwn_mac *mac)
2716{
2717	struct bwn_phy *phy = &mac->mac_phy;
2718	uint8_t old = phy->chan;
2719
2720	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2721		return;
2722
2723	bwn_mac_suspend(mac);
2724	bwn_nrssi_slope_11g(mac);
2725	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2726		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2727		bwn_switch_channel(mac, old);
2728	}
2729	bwn_mac_enable(mac);
2730}
2731
2732static void
2733bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2734{
2735
2736	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2737}
2738
2739static int
2740bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2741	const struct ieee80211_bpf_params *params)
2742{
2743	struct ieee80211com *ic = ni->ni_ic;
2744	struct ifnet *ifp = ic->ic_ifp;
2745	struct bwn_softc *sc = ifp->if_softc;
2746	struct bwn_mac *mac = sc->sc_curmac;
2747
2748	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2749	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2750		ieee80211_free_node(ni);
2751		m_freem(m);
2752		return (ENETDOWN);
2753	}
2754
2755	BWN_LOCK(sc);
2756	if (bwn_tx_isfull(sc, m)) {
2757		ieee80211_free_node(ni);
2758		m_freem(m);
2759		ifp->if_oerrors++;
2760		BWN_UNLOCK(sc);
2761		return (ENOBUFS);
2762	}
2763
2764	if (bwn_tx_start(sc, ni, m) != 0) {
2765		if (ni != NULL)
2766			ieee80211_free_node(ni);
2767		ifp->if_oerrors++;
2768	}
2769	sc->sc_watchdog_timer = 5;
2770	BWN_UNLOCK(sc);
2771	return (0);
2772}
2773
2774/*
2775 * Setup driver-specific state for a newly associated node.
2776 * Note that we're called also on a re-associate, the isnew
2777 * param tells us if this is the first time or not.
2778 */
2779static void
2780bwn_newassoc(struct ieee80211_node *ni, int isnew)
2781{
2782	struct ieee80211vap *vap = ni->ni_vap;
2783
2784	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2785	    &BWN_NODE(ni)->bn_amn, ni);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer to update the slot time
2790 * based on the current setting.  We use it to notify the
2791 * firmware of ERP changes and the f/w takes care of things
2792 * like slot time and preamble.
2793 */
2794static void
2795bwn_updateslot(struct ifnet *ifp)
2796{
2797	struct bwn_softc *sc = ifp->if_softc;
2798	struct ieee80211com *ic = ifp->if_l2com;
2799	struct bwn_mac *mac;
2800
2801	BWN_LOCK(sc);
2802	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2803		mac = (struct bwn_mac *)sc->sc_curmac;
2804		bwn_set_slot_time(mac,
2805		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2806	}
2807	BWN_UNLOCK(sc);
2808}
2809
2810/*
2811 * Callback from the 802.11 layer after a promiscuous mode change.
2812 * Note this interface does not check the operating mode as this
2813 * is an internal callback and we are expected to honor the current
2814 * state (e.g. this is used for setting the interface in promiscuous
2815 * mode when operating in hostap mode to do ACS).
2816 */
2817static void
2818bwn_update_promisc(struct ifnet *ifp)
2819{
2820	struct bwn_softc *sc = ifp->if_softc;
2821	struct bwn_mac *mac = sc->sc_curmac;
2822
2823	BWN_LOCK(sc);
2824	mac = sc->sc_curmac;
2825	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826		if (ifp->if_flags & IFF_PROMISC)
2827			sc->sc_filters |= BWN_MACCTL_PROMISC;
2828		else
2829			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2830		bwn_set_opmode(mac);
2831	}
2832	BWN_UNLOCK(sc);
2833}
2834
2835/*
2836 * Callback from the 802.11 layer to update WME parameters.
2837 */
2838static int
2839bwn_wme_update(struct ieee80211com *ic)
2840{
2841	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2842	struct bwn_mac *mac = sc->sc_curmac;
2843	struct wmeParams *wmep;
2844	int i;
2845
2846	BWN_LOCK(sc);
2847	mac = sc->sc_curmac;
2848	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2849		bwn_mac_suspend(mac);
2850		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2851			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2852			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2853		}
2854		bwn_mac_enable(mac);
2855	}
2856	BWN_UNLOCK(sc);
2857	return (0);
2858}
2859
2860static struct ieee80211_node *
2861bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2862{
2863	struct ieee80211com *ic = vap->iv_ic;
2864	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2865	const size_t space = sizeof(struct bwn_node);
2866	struct bwn_node *bn;
2867
2868	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2869	if (bn == NULL) {
2870		/* XXX stat+msg */
2871		return (NULL);
2872	}
2873	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2874	return (&bn->bn_node);
2875}
2876
2877static void
2878bwn_node_cleanup(struct ieee80211_node *ni)
2879{
2880	struct ieee80211com *ic = ni->ni_ic;
2881	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2882
2883	sc->sc_node_cleanup(ni);
2884}
2885
2886static void
2887bwn_scan_start(struct ieee80211com *ic)
2888{
2889	struct ifnet *ifp = ic->ic_ifp;
2890	struct bwn_softc *sc = ifp->if_softc;
2891	struct bwn_mac *mac;
2892
2893	BWN_LOCK(sc);
2894	mac = sc->sc_curmac;
2895	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2896		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2897		bwn_set_opmode(mac);
2898		/* disable CFP update during scan */
2899		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2900	}
2901	BWN_UNLOCK(sc);
2902}
2903
2904static void
2905bwn_scan_end(struct ieee80211com *ic)
2906{
2907	struct ifnet *ifp = ic->ic_ifp;
2908	struct bwn_softc *sc = ifp->if_softc;
2909	struct bwn_mac *mac;
2910
2911	BWN_LOCK(sc);
2912	mac = sc->sc_curmac;
2913	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2914		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2915		bwn_set_opmode(mac);
2916		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2917	}
2918	BWN_UNLOCK(sc);
2919}
2920
2921static void
2922bwn_set_channel(struct ieee80211com *ic)
2923{
2924	struct ifnet *ifp = ic->ic_ifp;
2925	struct bwn_softc *sc = ifp->if_softc;
2926	struct bwn_mac *mac = sc->sc_curmac;
2927	struct bwn_phy *phy = &mac->mac_phy;
2928	int chan, error;
2929
2930	BWN_LOCK(sc);
2931
2932	error = bwn_switch_band(sc, ic->ic_curchan);
2933	if (error)
2934		goto fail;;
2935	bwn_mac_suspend(mac);
2936	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2937	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2938	if (chan != phy->chan)
2939		bwn_switch_channel(mac, chan);
2940
2941	/* TX power level */
2942	if (ic->ic_curchan->ic_maxpower != 0 &&
2943	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2944		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2945		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2946		    BWN_TXPWR_IGNORE_TSSI);
2947	}
2948
2949	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2950	if (phy->set_antenna)
2951		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2952
2953	if (sc->sc_rf_enabled != phy->rf_on) {
2954		if (sc->sc_rf_enabled) {
2955			bwn_rf_turnon(mac);
2956			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2957				device_printf(sc->sc_dev,
2958				    "please turns on the RF switch\n");
2959		} else
2960			bwn_rf_turnoff(mac);
2961	}
2962
2963	bwn_mac_enable(mac);
2964
2965fail:
2966	/*
2967	 * Setup radio tap channel freq and flags
2968	 */
2969	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2970		htole16(ic->ic_curchan->ic_freq);
2971	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2972		htole16(ic->ic_curchan->ic_flags & 0xffff);
2973
2974	BWN_UNLOCK(sc);
2975}
2976
2977static struct ieee80211vap *
2978bwn_vap_create(struct ieee80211com *ic,
2979	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2980	const uint8_t bssid[IEEE80211_ADDR_LEN],
2981	const uint8_t mac0[IEEE80211_ADDR_LEN])
2982{
2983	struct ifnet *ifp = ic->ic_ifp;
2984	struct bwn_softc *sc = ifp->if_softc;
2985	struct ieee80211vap *vap;
2986	struct bwn_vap *bvp;
2987	uint8_t mac[IEEE80211_ADDR_LEN];
2988
2989	IEEE80211_ADDR_COPY(mac, mac0);
2990	switch (opmode) {
2991	case IEEE80211_M_HOSTAP:
2992	case IEEE80211_M_MBSS:
2993	case IEEE80211_M_STA:
2994	case IEEE80211_M_WDS:
2995	case IEEE80211_M_MONITOR:
2996	case IEEE80211_M_IBSS:
2997	case IEEE80211_M_AHDEMO:
2998		break;
2999	default:
3000		return (NULL);
3001	}
3002
3003	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3004
3005	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3006	    M_80211_VAP, M_NOWAIT | M_ZERO);
3007	if (bvp == NULL) {
3008		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3009		return (NULL);
3010	}
3011	vap = &bvp->bv_vap;
3012	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3013	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3014	/* override with driver methods */
3015	bvp->bv_newstate = vap->iv_newstate;
3016	vap->iv_newstate = bwn_newstate;
3017
3018	/* override max aid so sta's cannot assoc when we're out of sta id's */
3019	vap->iv_max_aid = BWN_STAID_MAX;
3020
3021	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3022	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3023	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3024	    500 /*ms*/);
3025
3026	/* complete setup */
3027	ieee80211_vap_attach(vap, ieee80211_media_change,
3028	    ieee80211_media_status);
3029	return (vap);
3030}
3031
3032static void
3033bwn_vap_delete(struct ieee80211vap *vap)
3034{
3035	struct bwn_vap *bvp = BWN_VAP(vap);
3036
3037	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3038	ieee80211_vap_detach(vap);
3039	free(bvp, M_80211_VAP);
3040}
3041
3042static void
3043bwn_init(void *arg)
3044{
3045	struct bwn_softc *sc = arg;
3046	struct ifnet *ifp = sc->sc_ifp;
3047	struct ieee80211com *ic = ifp->if_l2com;
3048	int error = 0;
3049
3050	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3051		__func__, ifp->if_flags);
3052
3053	BWN_LOCK(sc);
3054	error = bwn_init_locked(sc);
3055	BWN_UNLOCK(sc);
3056
3057	if (error == 0)
3058		ieee80211_start_all(ic);	/* start all vap's */
3059}
3060
3061static int
3062bwn_init_locked(struct bwn_softc *sc)
3063{
3064	struct bwn_mac *mac;
3065	struct ifnet *ifp = sc->sc_ifp;
3066	int error;
3067
3068	BWN_ASSERT_LOCKED(sc);
3069
3070	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3071	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3072	sc->sc_filters = 0;
3073	bwn_wme_clear(sc);
3074	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3075	sc->sc_rf_enabled = 1;
3076
3077	mac = sc->sc_curmac;
3078	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3079		error = bwn_core_init(mac);
3080		if (error != 0)
3081			return (error);
3082	}
3083	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3084		bwn_core_start(mac);
3085
3086	bwn_set_opmode(mac);
3087	bwn_set_pretbtt(mac);
3088	bwn_spu_setdelay(mac, 0);
3089	bwn_set_macaddr(mac);
3090
3091	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3092	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3093	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3094
3095	return (0);
3096}
3097
3098static void
3099bwn_stop(struct bwn_softc *sc, int statechg)
3100{
3101
3102	BWN_LOCK(sc);
3103	bwn_stop_locked(sc, statechg);
3104	BWN_UNLOCK(sc);
3105}
3106
3107static void
3108bwn_stop_locked(struct bwn_softc *sc, int statechg)
3109{
3110	struct bwn_mac *mac = sc->sc_curmac;
3111	struct ifnet *ifp = sc->sc_ifp;
3112
3113	BWN_ASSERT_LOCKED(sc);
3114
3115	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3116		/* XXX FIXME opmode not based on VAP */
3117		bwn_set_opmode(mac);
3118		bwn_set_macaddr(mac);
3119	}
3120
3121	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3122		bwn_core_stop(mac);
3123
3124	callout_stop(&sc->sc_led_blink_ch);
3125	sc->sc_led_blinking = 0;
3126
3127	bwn_core_exit(mac);
3128	sc->sc_rf_enabled = 0;
3129
3130	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3131}
3132
3133static void
3134bwn_wme_clear(struct bwn_softc *sc)
3135{
3136#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3137	struct wmeParams *p;
3138	unsigned int i;
3139
3140	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3141	    ("%s:%d: fail", __func__, __LINE__));
3142
3143	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3144		p = &(sc->sc_wmeParams[i]);
3145
3146		switch (bwn_wme_shm_offsets[i]) {
3147		case BWN_WME_VOICE:
3148			p->wmep_txopLimit = 0;
3149			p->wmep_aifsn = 2;
3150			/* XXX FIXME: log2(cwmin) */
3151			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3152			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3153			break;
3154		case BWN_WME_VIDEO:
3155			p->wmep_txopLimit = 0;
3156			p->wmep_aifsn = 2;
3157			/* XXX FIXME: log2(cwmin) */
3158			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3159			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3160			break;
3161		case BWN_WME_BESTEFFORT:
3162			p->wmep_txopLimit = 0;
3163			p->wmep_aifsn = 3;
3164			/* XXX FIXME: log2(cwmin) */
3165			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3166			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3167			break;
3168		case BWN_WME_BACKGROUND:
3169			p->wmep_txopLimit = 0;
3170			p->wmep_aifsn = 7;
3171			/* XXX FIXME: log2(cwmin) */
3172			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3173			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3174			break;
3175		default:
3176			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3177		}
3178	}
3179}
3180
3181static int
3182bwn_core_init(struct bwn_mac *mac)
3183{
3184#ifdef BWN_DEBUG
3185	struct bwn_softc *sc = mac->mac_sc;
3186#endif
3187	struct siba_dev_softc *sd = mac->mac_sd;
3188	struct siba_softc *siba = sd->sd_bus;
3189	struct siba_sprom *sprom = &siba->siba_sprom;
3190	uint64_t hf;
3191	int error;
3192
3193	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3194	    ("%s:%d: fail", __func__, __LINE__));
3195
3196	siba_powerup(siba, 0);
3197	if (!siba_dev_isup(sd))
3198		bwn_reset_core(mac,
3199		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3200
3201	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3202	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3203	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3204	BWN_GETTIME(mac->mac_phy.nexttime);
3205	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3206	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3207	mac->mac_stats.link_noise = -95;
3208	mac->mac_reason_intr = 0;
3209	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3210	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3211#ifdef BWN_DEBUG
3212	if (sc->sc_debug & BWN_DEBUG_XMIT)
3213		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3214#endif
3215	mac->mac_suspended = 1;
3216	mac->mac_task_state = 0;
3217	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3218
3219	mac->mac_phy.init_pre(mac);
3220
3221	siba_pcicore_intr(&siba->siba_pci, sd);
3222
3223	bwn_fix_imcfglobug(mac);
3224	bwn_bt_disable(mac);
3225	if (mac->mac_phy.prepare_hw) {
3226		error = mac->mac_phy.prepare_hw(mac);
3227		if (error)
3228			goto fail0;
3229	}
3230	error = bwn_chip_init(mac);
3231	if (error)
3232		goto fail0;
3233	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3234	    mac->mac_sd->sd_id.sd_rev);
3235	hf = bwn_hf_read(mac);
3236	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3237		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3238		if (sprom->bf_lo & BWN_BFL_PACTRL)
3239			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3240		if (mac->mac_phy.rev == 1)
3241			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3242	}
3243	if (mac->mac_phy.rf_ver == 0x2050) {
3244		if (mac->mac_phy.rf_rev < 6)
3245			hf |= BWN_HF_FORCE_VCO_RECALC;
3246		if (mac->mac_phy.rf_rev == 6)
3247			hf |= BWN_HF_4318_TSSI;
3248	}
3249	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3250		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3251	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3252	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3253		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3254	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3255	bwn_hf_write(mac, hf);
3256
3257	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3258	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3259	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3260	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3261
3262	bwn_rate_init(mac);
3263	bwn_set_phytxctl(mac);
3264
3265	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3266	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3267	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3268
3269	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3270		bwn_pio_init(mac);
3271	else
3272		bwn_dma_init(mac);
3273	if (error)
3274		goto fail1;
3275	bwn_wme_init(mac);
3276	bwn_spu_setdelay(mac, 1);
3277	bwn_bt_enable(mac);
3278
3279	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3280	bwn_set_macaddr(mac);
3281	bwn_crypt_init(mac);
3282
3283	/* XXX LED initializatin */
3284
3285	mac->mac_status = BWN_MAC_STATUS_INITED;
3286
3287	return (error);
3288
3289fail1:
3290	bwn_chip_exit(mac);
3291fail0:
3292	siba_powerdown(siba);
3293	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3294	    ("%s:%d: fail", __func__, __LINE__));
3295	return (error);
3296}
3297
3298static void
3299bwn_core_start(struct bwn_mac *mac)
3300{
3301	struct bwn_softc *sc = mac->mac_sc;
3302	uint32_t tmp;
3303
3304	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3305	    ("%s:%d: fail", __func__, __LINE__));
3306
3307	if (mac->mac_sd->sd_id.sd_rev < 5)
3308		return;
3309
3310	while (1) {
3311		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3312		if (!(tmp & 0x00000001))
3313			break;
3314		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3315	}
3316
3317	bwn_mac_enable(mac);
3318	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3319	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3320
3321	mac->mac_status = BWN_MAC_STATUS_STARTED;
3322}
3323
3324static void
3325bwn_core_exit(struct bwn_mac *mac)
3326{
3327	uint32_t macctl;
3328
3329	BWN_ASSERT_LOCKED(mac->mac_sc);
3330
3331	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3332	    ("%s:%d: fail", __func__, __LINE__));
3333
3334	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3335		return;
3336	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3337
3338	macctl = BWN_READ_4(mac, BWN_MACCTL);
3339	macctl &= ~BWN_MACCTL_MCODE_RUN;
3340	macctl |= BWN_MACCTL_MCODE_JMP0;
3341	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3342
3343	bwn_dma_stop(mac);
3344	bwn_pio_stop(mac);
3345	bwn_chip_exit(mac);
3346	mac->mac_phy.switch_analog(mac, 0);
3347	siba_dev_down(mac->mac_sd, 0);
3348	siba_powerdown(mac->mac_sd->sd_bus);
3349}
3350
3351static void
3352bwn_fix_imcfglobug(struct bwn_mac *mac)
3353{
3354	struct siba_dev_softc *sd = mac->mac_sd;
3355	struct siba_softc *siba = sd->sd_bus;
3356	uint32_t tmp;
3357
3358	if (siba->siba_pci.spc_dev == NULL)
3359		return;
3360	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3361	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3362		return;
3363
3364	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3365	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3366	switch (siba->siba_type) {
3367	case SIBA_TYPE_PCI:
3368	case SIBA_TYPE_PCMCIA:
3369		tmp |= 0x32;
3370		break;
3371	case SIBA_TYPE_SSB:
3372		tmp |= 0x53;
3373		break;
3374	}
3375	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3376}
3377
3378static void
3379bwn_bt_disable(struct bwn_mac *mac)
3380{
3381	struct bwn_softc *sc = mac->mac_sc;
3382
3383	(void)sc;
3384	/* XXX do nothing yet */
3385}
3386
3387static int
3388bwn_chip_init(struct bwn_mac *mac)
3389{
3390	struct bwn_phy *phy = &mac->mac_phy;
3391	uint32_t macctl;
3392	int error;
3393
3394	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3395	if (phy->gmode)
3396		macctl |= BWN_MACCTL_GMODE;
3397	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3398
3399	error = bwn_fw_fillinfo(mac);
3400	if (error)
3401		return (error);
3402	error = bwn_fw_loaducode(mac);
3403	if (error)
3404		return (error);
3405
3406	error = bwn_gpio_init(mac);
3407	if (error)
3408		return (error);
3409
3410	error = bwn_fw_loadinitvals(mac);
3411	if (error) {
3412		bwn_gpio_cleanup(mac);
3413		return (error);
3414	}
3415	phy->switch_analog(mac, 1);
3416	error = bwn_phy_init(mac);
3417	if (error) {
3418		bwn_gpio_cleanup(mac);
3419		return (error);
3420	}
3421	if (phy->set_im)
3422		phy->set_im(mac, BWN_IMMODE_NONE);
3423	if (phy->set_antenna)
3424		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3425	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3426
3427	if (phy->type == BWN_PHYTYPE_B)
3428		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3429	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3430	if (mac->mac_sd->sd_id.sd_rev < 5)
3431		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3432
3433	BWN_WRITE_4(mac, BWN_MACCTL,
3434	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3435	BWN_WRITE_4(mac, BWN_MACCTL,
3436	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3437	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3438
3439	bwn_set_opmode(mac);
3440	if (mac->mac_sd->sd_id.sd_rev < 3) {
3441		BWN_WRITE_2(mac, 0x060e, 0x0000);
3442		BWN_WRITE_2(mac, 0x0610, 0x8000);
3443		BWN_WRITE_2(mac, 0x0604, 0x0000);
3444		BWN_WRITE_2(mac, 0x0606, 0x0200);
3445	} else {
3446		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3447		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3448	}
3449	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3450	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3451	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3452	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3453	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3454	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3455	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3456	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3457	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3458	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3459	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3460	return (error);
3461}
3462
3463/* read hostflags */
3464static uint64_t
3465bwn_hf_read(struct bwn_mac *mac)
3466{
3467	uint64_t ret;
3468
3469	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3470	ret <<= 16;
3471	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3472	ret <<= 16;
3473	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3474	return (ret);
3475}
3476
3477static void
3478bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3479{
3480
3481	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3482	    (value & 0x00000000ffffull));
3483	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3484	    (value & 0x0000ffff0000ull) >> 16);
3485	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3486	    (value & 0xffff00000000ULL) >> 32);
3487}
3488
3489static void
3490bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3491{
3492
3493	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3494	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3495}
3496
3497static void
3498bwn_rate_init(struct bwn_mac *mac)
3499{
3500
3501	switch (mac->mac_phy.type) {
3502	case BWN_PHYTYPE_A:
3503	case BWN_PHYTYPE_G:
3504	case BWN_PHYTYPE_LP:
3505	case BWN_PHYTYPE_N:
3506		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3507		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3508		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3509		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3510		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3511		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3512		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3513		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3514			break;
3515		/* FALLTHROUGH */
3516	case BWN_PHYTYPE_B:
3517		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3518		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3519		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3520		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3521		break;
3522	default:
3523		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3524	}
3525}
3526
3527static void
3528bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3529{
3530	uint16_t offset;
3531
3532	if (ofdm) {
3533		offset = 0x480;
3534		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3535	} else {
3536		offset = 0x4c0;
3537		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3538	}
3539	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3540	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3541}
3542
3543static uint8_t
3544bwn_plcp_getcck(const uint8_t bitrate)
3545{
3546
3547	switch (bitrate) {
3548	case BWN_CCK_RATE_1MB:
3549		return (0x0a);
3550	case BWN_CCK_RATE_2MB:
3551		return (0x14);
3552	case BWN_CCK_RATE_5MB:
3553		return (0x37);
3554	case BWN_CCK_RATE_11MB:
3555		return (0x6e);
3556	}
3557	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3558	return (0);
3559}
3560
3561static uint8_t
3562bwn_plcp_getofdm(const uint8_t bitrate)
3563{
3564
3565	switch (bitrate) {
3566	case BWN_OFDM_RATE_6MB:
3567		return (0xb);
3568	case BWN_OFDM_RATE_9MB:
3569		return (0xf);
3570	case BWN_OFDM_RATE_12MB:
3571		return (0xa);
3572	case BWN_OFDM_RATE_18MB:
3573		return (0xe);
3574	case BWN_OFDM_RATE_24MB:
3575		return (0x9);
3576	case BWN_OFDM_RATE_36MB:
3577		return (0xd);
3578	case BWN_OFDM_RATE_48MB:
3579		return (0x8);
3580	case BWN_OFDM_RATE_54MB:
3581		return (0xc);
3582	}
3583	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3584	return (0);
3585}
3586
3587static void
3588bwn_set_phytxctl(struct bwn_mac *mac)
3589{
3590	uint16_t ctl;
3591
3592	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3593	    BWN_TX_PHY_TXPWR);
3594	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3595	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3596	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3597}
3598
3599static void
3600bwn_pio_init(struct bwn_mac *mac)
3601{
3602	struct bwn_pio *pio = &mac->mac_method.pio;
3603
3604	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3605	    & ~BWN_MACCTL_BIGENDIAN);
3606	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3607
3608	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3609	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3610	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3611	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3612	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3613	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3614}
3615
3616static void
3617bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3618    int index)
3619{
3620	struct bwn_pio_txpkt *tp;
3621	unsigned int i;
3622
3623	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3624	tq->tq_index = index;
3625
3626	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3627	if (mac->mac_sd->sd_id.sd_rev >= 8)
3628		tq->tq_size = 1920;
3629	else {
3630		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3631		tq->tq_size -= 80;
3632	}
3633
3634	TAILQ_INIT(&tq->tq_pktlist);
3635	for (i = 0; i < N(tq->tq_pkts); i++) {
3636		tp = &(tq->tq_pkts[i]);
3637		tp->tp_index = i;
3638		tp->tp_queue = tq;
3639		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3640	}
3641}
3642
3643static uint16_t
3644bwn_pio_idx2base(struct bwn_mac *mac, int index)
3645{
3646	struct bwn_softc *sc = mac->mac_sc;
3647	static const uint16_t bases[] = {
3648		BWN_PIO_BASE0,
3649		BWN_PIO_BASE1,
3650		BWN_PIO_BASE2,
3651		BWN_PIO_BASE3,
3652		BWN_PIO_BASE4,
3653		BWN_PIO_BASE5,
3654		BWN_PIO_BASE6,
3655		BWN_PIO_BASE7,
3656	};
3657	static const uint16_t bases_rev11[] = {
3658		BWN_PIO11_BASE0,
3659		BWN_PIO11_BASE1,
3660		BWN_PIO11_BASE2,
3661		BWN_PIO11_BASE3,
3662		BWN_PIO11_BASE4,
3663		BWN_PIO11_BASE5,
3664	};
3665
3666	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3667		if (index >= N(bases_rev11))
3668			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3669		return (bases_rev11[index]);
3670	}
3671	if (index >= N(bases))
3672		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3673	return (bases[index]);
3674}
3675
3676static void
3677bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3678    int index)
3679{
3680
3681	prq->prq_mac = mac;
3682	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3683	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3684	bwn_dma_rxdirectfifo(mac, index, 1);
3685}
3686
3687static void
3688bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3689{
3690	if (tq == NULL)
3691		return;
3692	bwn_pio_cancel_tx_packets(tq);
3693}
3694
3695static void
3696bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3697{
3698
3699	bwn_destroy_pioqueue_tx(pio);
3700}
3701
3702static uint16_t
3703bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3704    uint16_t offset)
3705{
3706
3707	return (BWN_READ_2(mac, tq->tq_base + offset));
3708}
3709
3710static void
3711bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3712{
3713	uint32_t ctl;
3714	int type;
3715	uint16_t base;
3716
3717	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3718	base = bwn_dma_base(type, idx);
3719	if (type == BWN_DMA_64BIT) {
3720		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3721		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3722		if (enable)
3723			ctl |= BWN_DMA64_RXDIRECTFIFO;
3724		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3725	} else {
3726		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3727		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3728		if (enable)
3729			ctl |= BWN_DMA32_RXDIRECTFIFO;
3730		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3731	}
3732}
3733
3734static uint64_t
3735bwn_dma_mask(struct bwn_mac *mac)
3736{
3737	uint32_t tmp;
3738	uint16_t base;
3739
3740	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3741	if (tmp & SIBA_TGSHIGH_DMA64)
3742		return (BWN_DMA_BIT_MASK(64));
3743	base = bwn_dma_base(0, 0);
3744	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3745	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3746	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3747		return (BWN_DMA_BIT_MASK(32));
3748
3749	return (BWN_DMA_BIT_MASK(30));
3750}
3751
3752static int
3753bwn_dma_mask2type(uint64_t dmamask)
3754{
3755
3756	if (dmamask == BWN_DMA_BIT_MASK(30))
3757		return (BWN_DMA_30BIT);
3758	if (dmamask == BWN_DMA_BIT_MASK(32))
3759		return (BWN_DMA_32BIT);
3760	if (dmamask == BWN_DMA_BIT_MASK(64))
3761		return (BWN_DMA_64BIT);
3762	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3763	return (BWN_DMA_30BIT);
3764}
3765
3766static void
3767bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3768{
3769	struct bwn_pio_txpkt *tp;
3770	unsigned int i;
3771
3772	for (i = 0; i < N(tq->tq_pkts); i++) {
3773		tp = &(tq->tq_pkts[i]);
3774		if (tp->tp_m) {
3775			m_freem(tp->tp_m);
3776			tp->tp_m = NULL;
3777		}
3778	}
3779}
3780
3781static uint16_t
3782bwn_dma_base(int type, int controller_idx)
3783{
3784	static const uint16_t map64[] = {
3785		BWN_DMA64_BASE0,
3786		BWN_DMA64_BASE1,
3787		BWN_DMA64_BASE2,
3788		BWN_DMA64_BASE3,
3789		BWN_DMA64_BASE4,
3790		BWN_DMA64_BASE5,
3791	};
3792	static const uint16_t map32[] = {
3793		BWN_DMA32_BASE0,
3794		BWN_DMA32_BASE1,
3795		BWN_DMA32_BASE2,
3796		BWN_DMA32_BASE3,
3797		BWN_DMA32_BASE4,
3798		BWN_DMA32_BASE5,
3799	};
3800
3801	if (type == BWN_DMA_64BIT) {
3802		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3803		    ("%s:%d: fail", __func__, __LINE__));
3804		return (map64[controller_idx]);
3805	}
3806	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3807	    ("%s:%d: fail", __func__, __LINE__));
3808	return (map32[controller_idx]);
3809}
3810
3811static void
3812bwn_dma_init(struct bwn_mac *mac)
3813{
3814	struct bwn_dma *dma = &mac->mac_method.dma;
3815
3816	/* setup TX DMA channels. */
3817	bwn_dma_setup(dma->wme[WME_AC_BK]);
3818	bwn_dma_setup(dma->wme[WME_AC_BE]);
3819	bwn_dma_setup(dma->wme[WME_AC_VI]);
3820	bwn_dma_setup(dma->wme[WME_AC_VO]);
3821	bwn_dma_setup(dma->mcast);
3822	/* setup RX DMA channel. */
3823	bwn_dma_setup(dma->rx);
3824}
3825
3826static struct bwn_dma_ring *
3827bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3828    int for_tx, int type)
3829{
3830	struct bwn_dma *dma = &mac->mac_method.dma;
3831	struct bwn_dma_ring *dr;
3832	struct bwn_dmadesc_generic *desc;
3833	struct bwn_dmadesc_meta *mt;
3834	struct bwn_softc *sc = mac->mac_sc;
3835	int error, i;
3836
3837	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3838	if (dr == NULL)
3839		goto out;
3840	dr->dr_numslots = BWN_RXRING_SLOTS;
3841	if (for_tx)
3842		dr->dr_numslots = BWN_TXRING_SLOTS;
3843
3844	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3845	    M_DEVBUF, M_NOWAIT | M_ZERO);
3846	if (dr->dr_meta == NULL)
3847		goto fail0;
3848
3849	dr->dr_type = type;
3850	dr->dr_mac = mac;
3851	dr->dr_base = bwn_dma_base(type, controller_index);
3852	dr->dr_index = controller_index;
3853	if (type == BWN_DMA_64BIT) {
3854		dr->getdesc = bwn_dma_64_getdesc;
3855		dr->setdesc = bwn_dma_64_setdesc;
3856		dr->start_transfer = bwn_dma_64_start_transfer;
3857		dr->suspend = bwn_dma_64_suspend;
3858		dr->resume = bwn_dma_64_resume;
3859		dr->get_curslot = bwn_dma_64_get_curslot;
3860		dr->set_curslot = bwn_dma_64_set_curslot;
3861	} else {
3862		dr->getdesc = bwn_dma_32_getdesc;
3863		dr->setdesc = bwn_dma_32_setdesc;
3864		dr->start_transfer = bwn_dma_32_start_transfer;
3865		dr->suspend = bwn_dma_32_suspend;
3866		dr->resume = bwn_dma_32_resume;
3867		dr->get_curslot = bwn_dma_32_get_curslot;
3868		dr->set_curslot = bwn_dma_32_set_curslot;
3869	}
3870	if (for_tx) {
3871		dr->dr_tx = 1;
3872		dr->dr_curslot = -1;
3873	} else {
3874		if (dr->dr_index == 0) {
3875			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3876			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3877		} else
3878			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3879	}
3880
3881	error = bwn_dma_allocringmemory(dr);
3882	if (error)
3883		goto fail2;
3884
3885	if (for_tx) {
3886		/*
3887		 * Assumption: BWN_TXRING_SLOTS can be divided by
3888		 * BWN_TX_SLOTS_PER_FRAME
3889		 */
3890		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3891		    ("%s:%d: fail", __func__, __LINE__));
3892
3893		dr->dr_txhdr_cache =
3894		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3895			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3896		KASSERT(dr->dr_txhdr_cache != NULL,
3897		    ("%s:%d: fail", __func__, __LINE__));
3898
3899		/*
3900		 * Create TX ring DMA stuffs
3901		 */
3902		error = bus_dma_tag_create(dma->parent_dtag,
3903				    BWN_ALIGN, 0,
3904				    BUS_SPACE_MAXADDR,
3905				    BUS_SPACE_MAXADDR,
3906				    NULL, NULL,
3907				    BWN_HDRSIZE(mac),
3908				    1,
3909				    BUS_SPACE_MAXSIZE_32BIT,
3910				    0,
3911				    NULL, NULL,
3912				    &dr->dr_txring_dtag);
3913		if (error) {
3914			device_printf(sc->sc_dev,
3915			    "can't create TX ring DMA tag: TODO frees\n");
3916			goto fail1;
3917		}
3918
3919		for (i = 0; i < dr->dr_numslots; i += 2) {
3920			dr->getdesc(dr, i, &desc, &mt);
3921
3922			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3923			mt->mt_m = NULL;
3924			mt->mt_ni = NULL;
3925			mt->mt_islast = 0;
3926			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3927			    &mt->mt_dmap);
3928			if (error) {
3929				device_printf(sc->sc_dev,
3930				     "can't create RX buf DMA map\n");
3931				goto fail1;
3932			}
3933
3934			dr->getdesc(dr, i + 1, &desc, &mt);
3935
3936			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3937			mt->mt_m = NULL;
3938			mt->mt_ni = NULL;
3939			mt->mt_islast = 1;
3940			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3941			    &mt->mt_dmap);
3942			if (error) {
3943				device_printf(sc->sc_dev,
3944				     "can't create RX buf DMA map\n");
3945				goto fail1;
3946			}
3947		}
3948	} else {
3949		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3950		    &dr->dr_spare_dmap);
3951		if (error) {
3952			device_printf(sc->sc_dev,
3953			    "can't create RX buf DMA map\n");
3954			goto out;		/* XXX wrong! */
3955		}
3956
3957		for (i = 0; i < dr->dr_numslots; i++) {
3958			dr->getdesc(dr, i, &desc, &mt);
3959
3960			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3961			    &mt->mt_dmap);
3962			if (error) {
3963				device_printf(sc->sc_dev,
3964				    "can't create RX buf DMA map\n");
3965				goto out;	/* XXX wrong! */
3966			}
3967			error = bwn_dma_newbuf(dr, desc, mt, 1);
3968			if (error) {
3969				device_printf(sc->sc_dev,
3970				    "failed to allocate RX buf\n");
3971				goto out;	/* XXX wrong! */
3972			}
3973		}
3974
3975		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3976		    BUS_DMASYNC_PREWRITE);
3977
3978		dr->dr_usedslot = dr->dr_numslots;
3979	}
3980
3981      out:
3982	return (dr);
3983
3984fail2:
3985	free(dr->dr_txhdr_cache, M_DEVBUF);
3986fail1:
3987	free(dr->dr_meta, M_DEVBUF);
3988fail0:
3989	free(dr, M_DEVBUF);
3990	return (NULL);
3991}
3992
3993static void
3994bwn_dma_ringfree(struct bwn_dma_ring **dr)
3995{
3996
3997	if (dr == NULL)
3998		return;
3999
4000	bwn_dma_free_descbufs(*dr);
4001	bwn_dma_free_ringmemory(*dr);
4002
4003	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4004	free((*dr)->dr_meta, M_DEVBUF);
4005	free(*dr, M_DEVBUF);
4006
4007	*dr = NULL;
4008}
4009
4010static void
4011bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4012    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4013{
4014	struct bwn_dmadesc32 *desc;
4015
4016	*meta = &(dr->dr_meta[slot]);
4017	desc = dr->dr_ring_descbase;
4018	desc = &(desc[slot]);
4019
4020	*gdesc = (struct bwn_dmadesc_generic *)desc;
4021}
4022
4023static void
4024bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4025    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4026    int start, int end, int irq)
4027{
4028	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4029	uint32_t addr, addrext, ctl;
4030	int slot;
4031
4032	slot = (int)(&(desc->dma.dma32) - descbase);
4033	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4034	    ("%s:%d: fail", __func__, __LINE__));
4035
4036	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4037	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4038	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4039	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4040	if (slot == dr->dr_numslots - 1)
4041		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4042	if (start)
4043		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4044	if (end)
4045		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4046	if (irq)
4047		ctl |= BWN_DMA32_DCTL_IRQ;
4048	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4049	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4050
4051	desc->dma.dma32.control = htole32(ctl);
4052	desc->dma.dma32.address = htole32(addr);
4053}
4054
4055static void
4056bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4057{
4058
4059	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4060	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4061}
4062
4063static void
4064bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4065{
4066
4067	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4068	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4069}
4070
4071static void
4072bwn_dma_32_resume(struct bwn_dma_ring *dr)
4073{
4074
4075	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4076	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4077}
4078
4079static int
4080bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4081{
4082	uint32_t val;
4083
4084	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4085	val &= BWN_DMA32_RXDPTR;
4086
4087	return (val / sizeof(struct bwn_dmadesc32));
4088}
4089
4090static void
4091bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4092{
4093
4094	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4095	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4096}
4097
4098static void
4099bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4100    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4101{
4102	struct bwn_dmadesc64 *desc;
4103
4104	*meta = &(dr->dr_meta[slot]);
4105	desc = dr->dr_ring_descbase;
4106	desc = &(desc[slot]);
4107
4108	*gdesc = (struct bwn_dmadesc_generic *)desc;
4109}
4110
4111static void
4112bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4113    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4114    int start, int end, int irq)
4115{
4116	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4117	int slot;
4118	uint32_t ctl0 = 0, ctl1 = 0;
4119	uint32_t addrlo, addrhi;
4120	uint32_t addrext;
4121
4122	slot = (int)(&(desc->dma.dma64) - descbase);
4123	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4124	    ("%s:%d: fail", __func__, __LINE__));
4125
4126	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4127	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4128	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4129	    30;
4130	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4131	if (slot == dr->dr_numslots - 1)
4132		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4133	if (start)
4134		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4135	if (end)
4136		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4137	if (irq)
4138		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4139	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4140	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4141	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4142
4143	desc->dma.dma64.control0 = htole32(ctl0);
4144	desc->dma.dma64.control1 = htole32(ctl1);
4145	desc->dma.dma64.address_low = htole32(addrlo);
4146	desc->dma.dma64.address_high = htole32(addrhi);
4147}
4148
4149static void
4150bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4151{
4152
4153	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4154	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4155}
4156
4157static void
4158bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4159{
4160
4161	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4162	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4163}
4164
4165static void
4166bwn_dma_64_resume(struct bwn_dma_ring *dr)
4167{
4168
4169	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4170	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4171}
4172
4173static int
4174bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4175{
4176	uint32_t val;
4177
4178	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4179	val &= BWN_DMA64_RXSTATDPTR;
4180
4181	return (val / sizeof(struct bwn_dmadesc64));
4182}
4183
4184static void
4185bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4186{
4187
4188	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4189	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4190}
4191
4192static int
4193bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4194{
4195	struct bwn_mac *mac = dr->dr_mac;
4196	struct bwn_dma *dma = &mac->mac_method.dma;
4197	struct bwn_softc *sc = mac->mac_sc;
4198	int error;
4199
4200	error = bus_dma_tag_create(dma->parent_dtag,
4201			    BWN_ALIGN, 0,
4202			    BUS_SPACE_MAXADDR,
4203			    BUS_SPACE_MAXADDR,
4204			    NULL, NULL,
4205			    BWN_DMA_RINGMEMSIZE,
4206			    1,
4207			    BUS_SPACE_MAXSIZE_32BIT,
4208			    0,
4209			    NULL, NULL,
4210			    &dr->dr_ring_dtag);
4211	if (error) {
4212		device_printf(sc->sc_dev,
4213		    "can't create TX ring DMA tag: TODO frees\n");
4214		return (-1);
4215	}
4216
4217	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4218	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4219	    &dr->dr_ring_dmap);
4220	if (error) {
4221		device_printf(sc->sc_dev,
4222		    "can't allocate DMA mem: TODO frees\n");
4223		return (-1);
4224	}
4225	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4226	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4227	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4228	if (error) {
4229		device_printf(sc->sc_dev,
4230		    "can't load DMA mem: TODO free\n");
4231		return (-1);
4232	}
4233
4234	return (0);
4235}
4236
4237static void
4238bwn_dma_setup(struct bwn_dma_ring *dr)
4239{
4240	uint64_t ring64;
4241	uint32_t addrext, ring32, value;
4242	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4243
4244	if (dr->dr_tx) {
4245		dr->dr_curslot = -1;
4246
4247		if (dr->dr_type == BWN_DMA_64BIT) {
4248			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4249			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4250			    >> 30;
4251			value = BWN_DMA64_TXENABLE;
4252			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4253			    & BWN_DMA64_TXADDREXT_MASK;
4254			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4255			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4256			    (ring64 & 0xffffffff));
4257			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4258			    ((ring64 >> 32) &
4259			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4260		} else {
4261			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4262			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4263			value = BWN_DMA32_TXENABLE;
4264			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4265			    & BWN_DMA32_TXADDREXT_MASK;
4266			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4267			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4268			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4269		}
4270		return;
4271	}
4272
4273	/*
4274	 * set for RX
4275	 */
4276	dr->dr_usedslot = dr->dr_numslots;
4277
4278	if (dr->dr_type == BWN_DMA_64BIT) {
4279		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4280		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4281		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4282		value |= BWN_DMA64_RXENABLE;
4283		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4284		    & BWN_DMA64_RXADDREXT_MASK;
4285		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4286		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4287		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4288		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4289		    | (trans << 1));
4290		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4291		    sizeof(struct bwn_dmadesc64));
4292	} else {
4293		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4294		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4295		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4296		value |= BWN_DMA32_RXENABLE;
4297		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4298		    & BWN_DMA32_RXADDREXT_MASK;
4299		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4300		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4301		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4302		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4303		    sizeof(struct bwn_dmadesc32));
4304	}
4305}
4306
4307static void
4308bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4309{
4310
4311	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4312	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4313	    dr->dr_ring_dmap);
4314}
4315
4316static void
4317bwn_dma_cleanup(struct bwn_dma_ring *dr)
4318{
4319
4320	if (dr->dr_tx) {
4321		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4322		if (dr->dr_type == BWN_DMA_64BIT) {
4323			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4324			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4325		} else
4326			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4327	} else {
4328		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4329		if (dr->dr_type == BWN_DMA_64BIT) {
4330			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4331			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4332		} else
4333			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4334	}
4335}
4336
4337static void
4338bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4339{
4340	struct bwn_dmadesc_generic *desc;
4341	struct bwn_dmadesc_meta *meta;
4342	struct bwn_mac *mac = dr->dr_mac;
4343	struct bwn_dma *dma = &mac->mac_method.dma;
4344	struct bwn_softc *sc = mac->mac_sc;
4345	int i;
4346
4347	if (!dr->dr_usedslot)
4348		return;
4349	for (i = 0; i < dr->dr_numslots; i++) {
4350		dr->getdesc(dr, i, &desc, &meta);
4351
4352		if (meta->mt_m == NULL) {
4353			if (!dr->dr_tx)
4354				device_printf(sc->sc_dev, "%s: not TX?\n",
4355				    __func__);
4356			continue;
4357		}
4358		if (dr->dr_tx) {
4359			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4360				bus_dmamap_unload(dr->dr_txring_dtag,
4361				    meta->mt_dmap);
4362			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4363				bus_dmamap_unload(dma->txbuf_dtag,
4364				    meta->mt_dmap);
4365		} else
4366			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4367		bwn_dma_free_descbuf(dr, meta);
4368	}
4369}
4370
4371static int
4372bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4373    int type)
4374{
4375	struct bwn_softc *sc = mac->mac_sc;
4376	uint32_t value;
4377	int i;
4378	uint16_t offset;
4379
4380	for (i = 0; i < 10; i++) {
4381		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4382		    BWN_DMA32_TXSTATUS;
4383		value = BWN_READ_4(mac, base + offset);
4384		if (type == BWN_DMA_64BIT) {
4385			value &= BWN_DMA64_TXSTAT;
4386			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4387			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4388			    value == BWN_DMA64_TXSTAT_STOPPED)
4389				break;
4390		} else {
4391			value &= BWN_DMA32_TXSTATE;
4392			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4393			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4394			    value == BWN_DMA32_TXSTAT_STOPPED)
4395				break;
4396		}
4397		DELAY(1000);
4398	}
4399	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4400	BWN_WRITE_4(mac, base + offset, 0);
4401	for (i = 0; i < 10; i++) {
4402		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4403						   BWN_DMA32_TXSTATUS;
4404		value = BWN_READ_4(mac, base + offset);
4405		if (type == BWN_DMA_64BIT) {
4406			value &= BWN_DMA64_TXSTAT;
4407			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4408				i = -1;
4409				break;
4410			}
4411		} else {
4412			value &= BWN_DMA32_TXSTATE;
4413			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4414				i = -1;
4415				break;
4416			}
4417		}
4418		DELAY(1000);
4419	}
4420	if (i != -1) {
4421		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4422		return (ENODEV);
4423	}
4424	DELAY(1000);
4425
4426	return (0);
4427}
4428
4429static int
4430bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4431    int type)
4432{
4433	struct bwn_softc *sc = mac->mac_sc;
4434	uint32_t value;
4435	int i;
4436	uint16_t offset;
4437
4438	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4439	BWN_WRITE_4(mac, base + offset, 0);
4440	for (i = 0; i < 10; i++) {
4441		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4442		    BWN_DMA32_RXSTATUS;
4443		value = BWN_READ_4(mac, base + offset);
4444		if (type == BWN_DMA_64BIT) {
4445			value &= BWN_DMA64_RXSTAT;
4446			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4447				i = -1;
4448				break;
4449			}
4450		} else {
4451			value &= BWN_DMA32_RXSTATE;
4452			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4453				i = -1;
4454				break;
4455			}
4456		}
4457		DELAY(1000);
4458	}
4459	if (i != -1) {
4460		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4461		return (ENODEV);
4462	}
4463
4464	return (0);
4465}
4466
4467static void
4468bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4469    struct bwn_dmadesc_meta *meta)
4470{
4471
4472	if (meta->mt_m != NULL) {
4473		m_freem(meta->mt_m);
4474		meta->mt_m = NULL;
4475	}
4476	if (meta->mt_ni != NULL) {
4477		ieee80211_free_node(meta->mt_ni);
4478		meta->mt_ni = NULL;
4479	}
4480}
4481
4482static void
4483bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4484{
4485	struct bwn_rxhdr4 *rxhdr;
4486	unsigned char *frame;
4487
4488	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4489	rxhdr->frame_len = 0;
4490
4491	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4492	    sizeof(struct bwn_plcp6) + 2,
4493	    ("%s:%d: fail", __func__, __LINE__));
4494	frame = mtod(m, char *) + dr->dr_frameoffset;
4495	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4496}
4497
4498static uint8_t
4499bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4500{
4501	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4502
4503	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4504	    == 0xff);
4505}
4506
4507static void
4508bwn_wme_init(struct bwn_mac *mac)
4509{
4510
4511	bwn_wme_load(mac);
4512
4513	/* enable WME support. */
4514	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4515	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4516	    BWN_IFSCTL_USE_EDCF);
4517}
4518
4519static void
4520bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4521{
4522	struct bwn_softc *sc = mac->mac_sc;
4523	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4524	uint16_t delay;	/* microsec */
4525
4526	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4527	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4528		delay = 500;
4529	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4530		delay = max(delay, (uint16_t)2400);
4531
4532	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4533}
4534
4535static void
4536bwn_bt_enable(struct bwn_mac *mac)
4537{
4538	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4539	uint64_t hf;
4540
4541	if (bwn_bluetooth == 0)
4542		return;
4543	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4544		return;
4545	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4546		return;
4547
4548	hf = bwn_hf_read(mac);
4549	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4550		hf |= BWN_HF_BT_COEXISTALT;
4551	else
4552		hf |= BWN_HF_BT_COEXIST;
4553	bwn_hf_write(mac, hf);
4554}
4555
4556static void
4557bwn_set_macaddr(struct bwn_mac *mac)
4558{
4559
4560	bwn_mac_write_bssid(mac);
4561	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4562}
4563
4564static void
4565bwn_clear_keys(struct bwn_mac *mac)
4566{
4567	int i;
4568
4569	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4570		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4571		    ("%s:%d: fail", __func__, __LINE__));
4572
4573		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4574		    NULL, BWN_SEC_KEYSIZE, NULL);
4575		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4576			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4577			    NULL, BWN_SEC_KEYSIZE, NULL);
4578		}
4579		mac->mac_key[i].keyconf = NULL;
4580	}
4581}
4582
4583static void
4584bwn_crypt_init(struct bwn_mac *mac)
4585{
4586
4587	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4588	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4589	    ("%s:%d: fail", __func__, __LINE__));
4590	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4591	mac->mac_ktp *= 2;
4592	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4593		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4594		    mac->mac_max_nr_keys - 8);
4595	}
4596	bwn_clear_keys(mac);
4597}
4598
4599static void
4600bwn_chip_exit(struct bwn_mac *mac)
4601{
4602
4603	bwn_phy_exit(mac);
4604	bwn_gpio_cleanup(mac);
4605}
4606
4607static int
4608bwn_fw_fillinfo(struct bwn_mac *mac)
4609{
4610	int error;
4611
4612	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4613	if (error == 0)
4614		return (0);
4615	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4616	if (error == 0)
4617		return (0);
4618	return (error);
4619}
4620
4621static int
4622bwn_gpio_init(struct bwn_mac *mac)
4623{
4624	struct siba_softc *bus = mac->mac_sd->sd_bus;
4625	struct siba_dev_softc *sd;
4626	uint32_t mask = 0x0000001f, set = 0x0000000f;
4627
4628	BWN_WRITE_4(mac, BWN_MACCTL,
4629	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4630	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4631	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4632
4633	if (bus->siba_chipid == 0x4301) {
4634		mask |= 0x0060;
4635		set |= 0x0060;
4636	}
4637	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4638		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4639		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4640		mask |= 0x0200;
4641		set |= 0x0200;
4642	}
4643	if (mac->mac_sd->sd_id.sd_rev >= 2)
4644		mask |= 0x0010;
4645	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4646	    bus->siba_pci.spc_dev;
4647	if (sd == NULL)
4648		return (0);
4649	siba_write_4(sd, BWN_GPIOCTL,
4650	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4651
4652	return (0);
4653}
4654
4655static int
4656bwn_fw_loadinitvals(struct bwn_mac *mac)
4657{
4658#define	GETFWOFFSET(fwp, offset)				\
4659	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4660	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4661	const struct bwn_fwhdr *hdr;
4662	struct bwn_fw *fw = &mac->mac_fw;
4663	int error;
4664
4665	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4666	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4667	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4668	if (error)
4669		return (error);
4670	if (fw->initvals_band.fw) {
4671		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4672		error = bwn_fwinitvals_write(mac,
4673		    GETFWOFFSET(fw->initvals_band, hdr_len),
4674		    be32toh(hdr->size),
4675		    fw->initvals_band.fw->datasize - hdr_len);
4676	}
4677	return (error);
4678#undef GETFWOFFSET
4679}
4680
4681static int
4682bwn_phy_init(struct bwn_mac *mac)
4683{
4684	struct bwn_softc *sc = mac->mac_sc;
4685	int error;
4686
4687	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4688	mac->mac_phy.rf_onoff(mac, 1);
4689	error = mac->mac_phy.init(mac);
4690	if (error) {
4691		device_printf(sc->sc_dev, "PHY init failed\n");
4692		goto fail0;
4693	}
4694	error = bwn_switch_channel(mac,
4695	    mac->mac_phy.get_default_chan(mac));
4696	if (error) {
4697		device_printf(sc->sc_dev,
4698		    "failed to switch default channel\n");
4699		goto fail1;
4700	}
4701	return (0);
4702fail1:
4703	if (mac->mac_phy.exit)
4704		mac->mac_phy.exit(mac);
4705fail0:
4706	mac->mac_phy.rf_onoff(mac, 0);
4707
4708	return (error);
4709}
4710
4711static void
4712bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4713{
4714	uint16_t ant;
4715	uint16_t tmp;
4716
4717	ant = bwn_ant2phy(antenna);
4718
4719	/* For ACK/CTS */
4720	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4721	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4722	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4723	/* For Probe Resposes */
4724	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4725	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4726	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4727}
4728
4729static void
4730bwn_set_opmode(struct bwn_mac *mac)
4731{
4732	struct bwn_softc *sc = mac->mac_sc;
4733	struct ifnet *ifp = sc->sc_ifp;
4734	struct ieee80211com *ic = ifp->if_l2com;
4735	uint32_t ctl;
4736	uint16_t cfp_pretbtt;
4737
4738	ctl = BWN_READ_4(mac, BWN_MACCTL);
4739	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4740	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4741	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4742	ctl |= BWN_MACCTL_STA;
4743
4744	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4745	    ic->ic_opmode == IEEE80211_M_MBSS)
4746		ctl |= BWN_MACCTL_HOSTAP;
4747	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4748		ctl &= ~BWN_MACCTL_STA;
4749	ctl |= sc->sc_filters;
4750
4751	if (mac->mac_sd->sd_id.sd_rev <= 4)
4752		ctl |= BWN_MACCTL_PROMISC;
4753
4754	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4755
4756	cfp_pretbtt = 2;
4757	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4758		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4759		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4760			cfp_pretbtt = 100;
4761		else
4762			cfp_pretbtt = 50;
4763	}
4764	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4765}
4766
4767static void
4768bwn_gpio_cleanup(struct bwn_mac *mac)
4769{
4770	struct siba_softc *bus = mac->mac_sd->sd_bus;
4771	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4772
4773	pcidev = bus->siba_pci.spc_dev;
4774	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4775	if (!gpiodev)
4776		return;
4777	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4778}
4779
4780static int
4781bwn_dma_gettype(struct bwn_mac *mac)
4782{
4783	uint32_t tmp;
4784	uint16_t base;
4785
4786	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4787	if (tmp & SIBA_TGSHIGH_DMA64)
4788		return (BWN_DMA_64BIT);
4789	base = bwn_dma_base(0, 0);
4790	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4791	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4792	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4793		return (BWN_DMA_32BIT);
4794
4795	return (BWN_DMA_30BIT);
4796}
4797
4798static void
4799bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4800{
4801	if (!error) {
4802		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4803		*((bus_addr_t *)arg) = seg->ds_addr;
4804	}
4805}
4806
4807static void
4808bwn_phy_g_init_sub(struct bwn_mac *mac)
4809{
4810	struct bwn_phy *phy = &mac->mac_phy;
4811	struct bwn_phy_g *pg = &phy->phy_g;
4812	uint16_t i, tmp;
4813
4814	if (phy->rev == 1)
4815		bwn_phy_init_b5(mac);
4816	else
4817		bwn_phy_init_b6(mac);
4818
4819	if (phy->rev >= 2 || phy->gmode)
4820		bwn_phy_init_a(mac);
4821
4822	if (phy->rev >= 2) {
4823		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4824		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4825	}
4826	if (phy->rev == 2) {
4827		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4828		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4829	}
4830	if (phy->rev > 5) {
4831		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4832		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4833	}
4834	if (phy->gmode || phy->rev >= 2) {
4835		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4836		tmp &= BWN_PHYVER_VERSION;
4837		if (tmp == 3 || tmp == 5) {
4838			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4839			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4840		}
4841		if (tmp == 5) {
4842			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4843			    0x1f00);
4844		}
4845	}
4846	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4847		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4848	if (phy->rf_rev == 8) {
4849		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4850		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4851	}
4852	if (BWN_HAS_LOOPBACK(phy))
4853		bwn_loopback_calcgain(mac);
4854
4855	if (phy->rf_rev != 8) {
4856		if (pg->pg_initval == 0xffff)
4857			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4858		else
4859			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4860	}
4861	bwn_lo_g_init(mac);
4862	if (BWN_HAS_TXMAG(phy)) {
4863		BWN_RF_WRITE(mac, 0x52,
4864		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4865		    | pg->pg_loctl.tx_bias |
4866		    pg->pg_loctl.tx_magn);
4867	} else {
4868		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4869	}
4870	if (phy->rev >= 6) {
4871		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4872		    (pg->pg_loctl.tx_bias << 12));
4873	}
4874	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4875		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4876	else
4877		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4878	if (phy->rev < 2)
4879		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4880	else
4881		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4882	if (phy->gmode || phy->rev >= 2) {
4883		bwn_lo_g_adjust(mac);
4884		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4885	}
4886
4887	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4888		for (i = 0; i < 64; i++) {
4889			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4890			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4891			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4892			    -32), 31));
4893		}
4894		bwn_nrssi_threshold(mac);
4895	} else if (phy->gmode || phy->rev >= 2) {
4896		if (pg->pg_nrssi[0] == -1000) {
4897			KASSERT(pg->pg_nrssi[1] == -1000,
4898			    ("%s:%d: fail", __func__, __LINE__));
4899			bwn_nrssi_slope_11g(mac);
4900		} else
4901			bwn_nrssi_threshold(mac);
4902	}
4903	if (phy->rf_rev == 8)
4904		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4905	bwn_phy_hwpctl_init(mac);
4906	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4907	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4908		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4909		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4910	}
4911}
4912
4913static uint8_t
4914bwn_has_hwpctl(struct bwn_mac *mac)
4915{
4916
4917	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4918		return (0);
4919	return (mac->mac_phy.use_hwpctl(mac));
4920}
4921
4922static void
4923bwn_phy_init_b5(struct bwn_mac *mac)
4924{
4925	struct siba_softc *bus = mac->mac_sd->sd_bus;
4926	struct bwn_phy *phy = &mac->mac_phy;
4927	struct bwn_phy_g *pg = &phy->phy_g;
4928	uint16_t offset, value;
4929	uint8_t old_channel;
4930
4931	if (phy->analog == 1)
4932		BWN_RF_SET(mac, 0x007a, 0x0050);
4933	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4934	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4935		value = 0x2120;
4936		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4937			BWN_PHY_WRITE(mac, offset, value);
4938			value += 0x202;
4939		}
4940	}
4941	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4942	if (phy->rf_ver == 0x2050)
4943		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4944
4945	if (phy->gmode || phy->rev >= 2) {
4946		if (phy->rf_ver == 0x2050) {
4947			BWN_RF_SET(mac, 0x007a, 0x0020);
4948			BWN_RF_SET(mac, 0x0051, 0x0004);
4949		}
4950		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4951
4952		BWN_PHY_SET(mac, 0x0802, 0x0100);
4953		BWN_PHY_SET(mac, 0x042b, 0x2000);
4954
4955		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4956
4957		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4958		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4959		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4960	}
4961
4962	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4963		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4964
4965	if (phy->analog == 1) {
4966		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4967		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4968		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4969		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4970		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4971	} else
4972		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4973	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4974	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4975
4976	if (phy->analog == 1)
4977		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4978	else
4979		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4980
4981	if (phy->analog == 0)
4982		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4983
4984	old_channel = phy->chan;
4985	bwn_phy_g_switch_chan(mac, 7, 0);
4986
4987	if (phy->rf_ver != 0x2050) {
4988		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4989		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4990	}
4991
4992	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4993	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4994
4995	if (phy->rf_ver == 0x2050) {
4996		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4997		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4998	}
4999
5000	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5001	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5002	BWN_RF_SET(mac, 0x007a, 0x0007);
5003
5004	bwn_phy_g_switch_chan(mac, old_channel, 0);
5005	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5006	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5007	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5008
5009	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5010	    pg->pg_txctl);
5011
5012	if (phy->rf_ver == 0x2050)
5013		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5014
5015	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5016}
5017
5018static void
5019bwn_loopback_calcgain(struct bwn_mac *mac)
5020{
5021	struct bwn_phy *phy = &mac->mac_phy;
5022	struct bwn_phy_g *pg = &phy->phy_g;
5023	uint16_t backup_phy[16] = { 0 };
5024	uint16_t backup_radio[3];
5025	uint16_t backup_bband;
5026	uint16_t i, j, loop_i_max;
5027	uint16_t trsw_rx;
5028	uint16_t loop1_outer_done, loop1_inner_done;
5029
5030	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5031	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5032	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5033	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5034	if (phy->rev != 1) {
5035		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5036		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5037	}
5038	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5039	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5040	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5041	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5042	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5043	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5044	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5045	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5046	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5047	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5048	backup_bband = pg->pg_bbatt.att;
5049	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5050	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5051	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5052
5053	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5054	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5055	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5056	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5057	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5058	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5059	if (phy->rev != 1) {
5060		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5061		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5062		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5063		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5064	}
5065	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5066	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5067	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5068	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5069
5070	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5071	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5072	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5073
5074	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5075	if (phy->rev != 1) {
5076		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5077		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5078	}
5079	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5080
5081	if (phy->rf_rev == 8)
5082		BWN_RF_WRITE(mac, 0x43, 0x000f);
5083	else {
5084		BWN_RF_WRITE(mac, 0x52, 0);
5085		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5086	}
5087	bwn_phy_g_set_bbatt(mac, 11);
5088
5089	if (phy->rev >= 3)
5090		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5091	else
5092		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5093	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5094
5095	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5096	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5097
5098	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5099	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5100
5101	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5102		if (phy->rev >= 7) {
5103			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5104			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5105		}
5106	}
5107	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5108
5109	j = 0;
5110	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5111	for (i = 0; i < loop_i_max; i++) {
5112		for (j = 0; j < 16; j++) {
5113			BWN_RF_WRITE(mac, 0x43, i);
5114			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5115			    (j << 8));
5116			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5117			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5118			DELAY(20);
5119			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5120				goto done0;
5121		}
5122	}
5123done0:
5124	loop1_outer_done = i;
5125	loop1_inner_done = j;
5126	if (j >= 8) {
5127		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5128		trsw_rx = 0x1b;
5129		for (j = j - 8; j < 16; j++) {
5130			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5131			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5132			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5133			DELAY(20);
5134			trsw_rx -= 3;
5135			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5136				goto done1;
5137		}
5138	} else
5139		trsw_rx = 0x18;
5140done1:
5141
5142	if (phy->rev != 1) {
5143		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5144		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5145	}
5146	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5147	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5148	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5149	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5150	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5151	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5152	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5153	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5154	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5155
5156	bwn_phy_g_set_bbatt(mac, backup_bband);
5157
5158	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5159	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5160	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5161
5162	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5163	DELAY(10);
5164	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5165	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5166	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5167	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5168
5169	pg->pg_max_lb_gain =
5170	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5171	pg->pg_trsw_rx_gain = trsw_rx * 2;
5172}
5173
5174static uint16_t
5175bwn_rf_init_bcm2050(struct bwn_mac *mac)
5176{
5177	struct bwn_phy *phy = &mac->mac_phy;
5178	uint32_t tmp1 = 0, tmp2 = 0;
5179	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5180	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5181	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5182	static const uint8_t rcc_table[] = {
5183		0x02, 0x03, 0x01, 0x0f,
5184		0x06, 0x07, 0x05, 0x0f,
5185		0x0a, 0x0b, 0x09, 0x0f,
5186		0x0e, 0x0f, 0x0d, 0x0f,
5187	};
5188
5189	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5190	    rfoverval = rfover = cck3 = 0;
5191	radio0 = BWN_RF_READ(mac, 0x43);
5192	radio1 = BWN_RF_READ(mac, 0x51);
5193	radio2 = BWN_RF_READ(mac, 0x52);
5194	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5195	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5196	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5197	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5198
5199	if (phy->type == BWN_PHYTYPE_B) {
5200		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5201		reg0 = BWN_READ_2(mac, 0x3ec);
5202
5203		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5204		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5205	} else if (phy->gmode || phy->rev >= 2) {
5206		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5207		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5208		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5209		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5210		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5211		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5212
5213		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5214		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5215		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5216		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5217		if (BWN_HAS_LOOPBACK(phy)) {
5218			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5219			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5220			if (phy->rev >= 3)
5221				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5222			else
5223				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5224			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5225		}
5226
5227		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5228		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5229			BWN_LPD(0, 1, 1)));
5230		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5231		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5232	}
5233	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5234
5235	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5236	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5237	reg1 = BWN_READ_2(mac, 0x3e6);
5238	reg2 = BWN_READ_2(mac, 0x3f4);
5239
5240	if (phy->analog == 0)
5241		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5242	else {
5243		if (phy->analog >= 2)
5244			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5245		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5246		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5247	}
5248
5249	reg = BWN_RF_READ(mac, 0x60);
5250	index = (reg & 0x001e) >> 1;
5251	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5252
5253	if (phy->type == BWN_PHYTYPE_B)
5254		BWN_RF_WRITE(mac, 0x78, 0x26);
5255	if (phy->gmode || phy->rev >= 2) {
5256		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5258			BWN_LPD(0, 1, 1)));
5259	}
5260	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5261	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5262	if (phy->gmode || phy->rev >= 2) {
5263		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5264		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5265			BWN_LPD(0, 0, 1)));
5266	}
5267	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5268	BWN_RF_SET(mac, 0x51, 0x0004);
5269	if (phy->rf_rev == 8)
5270		BWN_RF_WRITE(mac, 0x43, 0x1f);
5271	else {
5272		BWN_RF_WRITE(mac, 0x52, 0);
5273		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5274	}
5275	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5276
5277	for (i = 0; i < 16; i++) {
5278		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5279		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5280		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5281		if (phy->gmode || phy->rev >= 2) {
5282			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5283			    bwn_rf_2050_rfoverval(mac,
5284				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5285		}
5286		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5287		DELAY(10);
5288		if (phy->gmode || phy->rev >= 2) {
5289			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5290			    bwn_rf_2050_rfoverval(mac,
5291				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5292		}
5293		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5294		DELAY(10);
5295		if (phy->gmode || phy->rev >= 2) {
5296			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5297			    bwn_rf_2050_rfoverval(mac,
5298				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5299		}
5300		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5301		DELAY(20);
5302		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5303		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5304		if (phy->gmode || phy->rev >= 2) {
5305			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5306			    bwn_rf_2050_rfoverval(mac,
5307				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5308		}
5309		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5310	}
5311	DELAY(10);
5312
5313	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5314	tmp1++;
5315	tmp1 >>= 9;
5316
5317	for (i = 0; i < 16; i++) {
5318		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5319		BWN_RF_WRITE(mac, 0x78, radio78);
5320		DELAY(10);
5321		for (j = 0; j < 16; j++) {
5322			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5323			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5324			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5325			if (phy->gmode || phy->rev >= 2) {
5326				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5327				    bwn_rf_2050_rfoverval(mac,
5328					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5329			}
5330			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5331			DELAY(10);
5332			if (phy->gmode || phy->rev >= 2) {
5333				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5334				    bwn_rf_2050_rfoverval(mac,
5335					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5336			}
5337			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5338			DELAY(10);
5339			if (phy->gmode || phy->rev >= 2) {
5340				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5341				    bwn_rf_2050_rfoverval(mac,
5342					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5343			}
5344			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5345			DELAY(10);
5346			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5347			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5348			if (phy->gmode || phy->rev >= 2) {
5349				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5350				    bwn_rf_2050_rfoverval(mac,
5351					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5352			}
5353			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5354		}
5355		tmp2++;
5356		tmp2 >>= 8;
5357		if (tmp1 < tmp2)
5358			break;
5359	}
5360
5361	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5362	BWN_RF_WRITE(mac, 0x51, radio1);
5363	BWN_RF_WRITE(mac, 0x52, radio2);
5364	BWN_RF_WRITE(mac, 0x43, radio0);
5365	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5366	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5367	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5368	BWN_WRITE_2(mac, 0x3e6, reg1);
5369	if (phy->analog != 0)
5370		BWN_WRITE_2(mac, 0x3f4, reg2);
5371	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5372	bwn_spu_workaround(mac, phy->chan);
5373	if (phy->type == BWN_PHYTYPE_B) {
5374		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5375		BWN_WRITE_2(mac, 0x3ec, reg0);
5376	} else if (phy->gmode) {
5377		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5378			    BWN_READ_2(mac, BWN_PHY_RADIO)
5379			    & 0x7fff);
5380		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5381		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5382		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5383		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5384			      analogoverval);
5385		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5386		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5387		if (BWN_HAS_LOOPBACK(phy)) {
5388			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5389			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5390		}
5391	}
5392
5393	return ((i > 15) ? radio78 : rcc);
5394}
5395
5396static void
5397bwn_phy_init_b6(struct bwn_mac *mac)
5398{
5399	struct bwn_phy *phy = &mac->mac_phy;
5400	struct bwn_phy_g *pg = &phy->phy_g;
5401	uint16_t offset, val;
5402	uint8_t old_channel;
5403
5404	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5405	    ("%s:%d: fail", __func__, __LINE__));
5406
5407	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5408	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5409	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5410		BWN_RF_WRITE(mac, 0x51, 0x37);
5411		BWN_RF_WRITE(mac, 0x52, 0x70);
5412		BWN_RF_WRITE(mac, 0x53, 0xb3);
5413		BWN_RF_WRITE(mac, 0x54, 0x9b);
5414		BWN_RF_WRITE(mac, 0x5a, 0x88);
5415		BWN_RF_WRITE(mac, 0x5b, 0x88);
5416		BWN_RF_WRITE(mac, 0x5d, 0x88);
5417		BWN_RF_WRITE(mac, 0x5e, 0x88);
5418		BWN_RF_WRITE(mac, 0x7d, 0x88);
5419		bwn_hf_write(mac,
5420		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5421	}
5422	if (phy->rf_rev == 8) {
5423		BWN_RF_WRITE(mac, 0x51, 0);
5424		BWN_RF_WRITE(mac, 0x52, 0x40);
5425		BWN_RF_WRITE(mac, 0x53, 0xb7);
5426		BWN_RF_WRITE(mac, 0x54, 0x98);
5427		BWN_RF_WRITE(mac, 0x5a, 0x88);
5428		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5429		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5430		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5431			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5432			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5433		} else {
5434			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5435			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5436		}
5437		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5438		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5439		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5440		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5441	}
5442	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5443		BWN_PHY_WRITE(mac, offset, val);
5444		val -= 0x0202;
5445	}
5446	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5447		BWN_PHY_WRITE(mac, offset, val);
5448		val -= 0x0202;
5449	}
5450	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5451		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5452		val += 0x0202;
5453	}
5454	if (phy->type == BWN_PHYTYPE_G) {
5455		BWN_RF_SET(mac, 0x007a, 0x0020);
5456		BWN_RF_SET(mac, 0x0051, 0x0004);
5457		BWN_PHY_SET(mac, 0x0802, 0x0100);
5458		BWN_PHY_SET(mac, 0x042b, 0x2000);
5459		BWN_PHY_WRITE(mac, 0x5b, 0);
5460		BWN_PHY_WRITE(mac, 0x5c, 0);
5461	}
5462
5463	old_channel = phy->chan;
5464	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5465
5466	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5467	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5468	DELAY(40);
5469	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5470		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5471		BWN_RF_WRITE(mac, 0x50, 0x20);
5472	}
5473	if (phy->rf_rev <= 2) {
5474		BWN_RF_WRITE(mac, 0x7c, 0x20);
5475		BWN_RF_WRITE(mac, 0x5a, 0x70);
5476		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5477		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5478	}
5479	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5480
5481	bwn_phy_g_switch_chan(mac, old_channel, 0);
5482
5483	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5484	if (phy->rf_rev >= 6)
5485		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5486	else
5487		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5488	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5489	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5490	    pg->pg_txctl);
5491	if (phy->rf_rev <= 5)
5492		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5493	if (phy->rf_rev <= 2)
5494		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5495
5496	if (phy->analog == 4) {
5497		BWN_WRITE_2(mac, 0x3e4, 9);
5498		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5499	} else
5500		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5501	if (phy->type == BWN_PHYTYPE_B)
5502		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5503	else if (phy->type == BWN_PHYTYPE_G)
5504		BWN_WRITE_2(mac, 0x03e6, 0x0);
5505}
5506
5507static void
5508bwn_phy_init_a(struct bwn_mac *mac)
5509{
5510	struct bwn_phy *phy = &mac->mac_phy;
5511
5512	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5513	    ("%s:%d: fail", __func__, __LINE__));
5514
5515	if (phy->rev >= 6) {
5516		if (phy->type == BWN_PHYTYPE_A)
5517			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5518		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5519			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5520		else
5521			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5522	}
5523
5524	bwn_wa_init(mac);
5525
5526	if (phy->type == BWN_PHYTYPE_G &&
5527	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5528		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5529}
5530
5531static void
5532bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5533{
5534	int i;
5535
5536	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5537		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5538}
5539
5540static void
5541bwn_wa_agc(struct bwn_mac *mac)
5542{
5543	struct bwn_phy *phy = &mac->mac_phy;
5544
5545	if (phy->rev == 1) {
5546		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5547		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5548		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5549		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5550		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5551		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5552		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5553		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5554		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5555	} else {
5556		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5560	}
5561
5562	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5563	    0x5700);
5564	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5565	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5566	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5567	BWN_RF_SET(mac, 0x7a, 0x0008);
5568	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5569	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5570	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5571	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5572	if (phy->rev == 1)
5573		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5574	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5577	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5578	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5579	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5582	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5583	if (phy->rev == 1) {
5584		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5585		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5586	} else {
5587		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5588		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5589		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5590		if (phy->rev >= 6) {
5591			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5592			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5593			    (uint16_t)~0xf000, 0x3000);
5594		}
5595	}
5596	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5597	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5598	if (phy->rev == 1) {
5599		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5600		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5601		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5602		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5603		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5604		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5605		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5606		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5607	} else {
5608		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5609		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5610		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5611		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5612	}
5613	if (phy->rev >= 6) {
5614		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5615		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5616	}
5617	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5618}
5619
5620static void
5621bwn_wa_grev1(struct bwn_mac *mac)
5622{
5623	struct bwn_phy *phy = &mac->mac_phy;
5624	int i;
5625	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5626	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5627	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5628
5629	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5630
5631	/* init CRSTHRES and ANTDWELL */
5632	if (phy->rev == 1) {
5633		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5634	} else if (phy->rev == 2) {
5635		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5636		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5637		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5638	} else {
5639		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5640		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5641		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5642		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5643	}
5644	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5645	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5646	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5647
5648	/* XXX support PHY-A??? */
5649	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5650		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5651		    bwn_tab_finefreqg[i]);
5652
5653	/* XXX support PHY-A??? */
5654	if (phy->rev == 1)
5655		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5656			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5657			    bwn_tab_noise_g1[i]);
5658	else
5659		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5660			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5661			    bwn_tab_noise_g2[i]);
5662
5663
5664	for (i = 0; i < N(bwn_tab_rotor); i++)
5665		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5666		    bwn_tab_rotor[i]);
5667
5668	/* XXX support PHY-A??? */
5669	if (phy->rev >= 6) {
5670		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5671		    BWN_PHY_ENCORE_EN)
5672			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5673		else
5674			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5675	} else
5676		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5677
5678	for (i = 0; i < N(bwn_tab_retard); i++)
5679		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5680		    bwn_tab_retard[i]);
5681
5682	if (phy->rev == 1) {
5683		for (i = 0; i < 16; i++)
5684			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5685			    i, 0x0020);
5686	} else {
5687		for (i = 0; i < 32; i++)
5688			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5689	}
5690
5691	bwn_wa_agc(mac);
5692}
5693
5694static void
5695bwn_wa_grev26789(struct bwn_mac *mac)
5696{
5697	struct bwn_phy *phy = &mac->mac_phy;
5698	int i;
5699	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5700	uint16_t ofdmrev;
5701
5702	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5703
5704	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5705
5706	/* init CRSTHRES and ANTDWELL */
5707	if (phy->rev == 1)
5708		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5709	else if (phy->rev == 2) {
5710		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5711		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5712		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5713	} else {
5714		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5715		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5716		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5717		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5718	}
5719
5720	for (i = 0; i < 64; i++)
5721		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5722
5723	/* XXX support PHY-A??? */
5724	if (phy->rev == 1)
5725		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5726			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5727			    bwn_tab_noise_g1[i]);
5728	else
5729		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5730			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5731			    bwn_tab_noise_g2[i]);
5732
5733	/* XXX support PHY-A??? */
5734	if (phy->rev >= 6) {
5735		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5736		    BWN_PHY_ENCORE_EN)
5737			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5738		else
5739			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5740	} else
5741		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5742
5743	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5744		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5745		    bwn_tab_sigmasqr2[i]);
5746
5747	if (phy->rev == 1) {
5748		for (i = 0; i < 16; i++)
5749			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5750			    0x0020);
5751	} else {
5752		for (i = 0; i < 32; i++)
5753			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5754	}
5755
5756	bwn_wa_agc(mac);
5757
5758	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5759	if (ofdmrev > 2) {
5760		if (phy->type == BWN_PHYTYPE_A)
5761			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5762		else
5763			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5764	} else {
5765		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5766		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5767		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5768	}
5769
5770	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5771	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5772}
5773
5774static void
5775bwn_wa_init(struct bwn_mac *mac)
5776{
5777	struct bwn_phy *phy = &mac->mac_phy;
5778	struct siba_softc *bus = mac->mac_sd->sd_bus;
5779
5780	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5781
5782	switch (phy->rev) {
5783	case 1:
5784		bwn_wa_grev1(mac);
5785		break;
5786	case 2:
5787	case 6:
5788	case 7:
5789	case 8:
5790	case 9:
5791		bwn_wa_grev26789(mac);
5792		break;
5793	default:
5794		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5795	}
5796
5797	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5798	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5799	    bus->siba_board_rev != 0x17) {
5800		if (phy->rev < 2) {
5801			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5802			    0x0002);
5803			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5804			    0x0001);
5805		} else {
5806			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5807			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5808			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5809			    (phy->rev >= 7)) {
5810				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5811				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5812				    0x0020, 0x0001);
5813				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5814				    0x0021, 0x0001);
5815				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5816				    0x0022, 0x0001);
5817				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5818				    0x0023, 0x0000);
5819				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5820				    0x0000, 0x0000);
5821				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5822				    0x0003, 0x0002);
5823			}
5824		}
5825	}
5826	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5827		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5828		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5829	}
5830
5831	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5832	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5833}
5834
5835static void
5836bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5837    uint16_t value)
5838{
5839	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5840	uint16_t addr;
5841
5842	addr = table + offset;
5843	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5844	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5845		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5846		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5847	}
5848	pg->pg_ofdmtab_addr = addr;
5849	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5850}
5851
5852static void
5853bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5854    uint32_t value)
5855{
5856	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5857	uint16_t addr;
5858
5859	addr = table + offset;
5860	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5861	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5862		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5863		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5864	}
5865	pg->pg_ofdmtab_addr = addr;
5866
5867	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5868	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5869}
5870
5871static void
5872bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5873    uint16_t value)
5874{
5875
5876	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5877	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5878}
5879
5880static void
5881bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5882{
5883	struct bwn_phy *phy = &mac->mac_phy;
5884	unsigned int i, max_loop;
5885	uint16_t value;
5886	uint32_t buffer[5] = {
5887		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5888	};
5889
5890	if (ofdm) {
5891		max_loop = 0x1e;
5892		buffer[0] = 0x000201cc;
5893	} else {
5894		max_loop = 0xfa;
5895		buffer[0] = 0x000b846e;
5896	}
5897
5898	BWN_ASSERT_LOCKED(mac->mac_sc);
5899
5900	for (i = 0; i < 5; i++)
5901		bwn_ram_write(mac, i * 4, buffer[i]);
5902
5903	BWN_WRITE_2(mac, 0x0568, 0x0000);
5904	BWN_WRITE_2(mac, 0x07c0,
5905	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5906	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5907	BWN_WRITE_2(mac, 0x050c, value);
5908	if (phy->type == BWN_PHYTYPE_LP)
5909		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5910	BWN_WRITE_2(mac, 0x0508, 0x0000);
5911	BWN_WRITE_2(mac, 0x050a, 0x0000);
5912	BWN_WRITE_2(mac, 0x054c, 0x0000);
5913	BWN_WRITE_2(mac, 0x056a, 0x0014);
5914	BWN_WRITE_2(mac, 0x0568, 0x0826);
5915	BWN_WRITE_2(mac, 0x0500, 0x0000);
5916	if (phy->type == BWN_PHYTYPE_LP)
5917		BWN_WRITE_2(mac, 0x0502, 0x0050);
5918	else
5919		BWN_WRITE_2(mac, 0x0502, 0x0030);
5920
5921	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5922		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5923	for (i = 0x00; i < max_loop; i++) {
5924		value = BWN_READ_2(mac, 0x050e);
5925		if (value & 0x0080)
5926			break;
5927		DELAY(10);
5928	}
5929	for (i = 0x00; i < 0x0a; i++) {
5930		value = BWN_READ_2(mac, 0x050e);
5931		if (value & 0x0400)
5932			break;
5933		DELAY(10);
5934	}
5935	for (i = 0x00; i < 0x19; i++) {
5936		value = BWN_READ_2(mac, 0x0690);
5937		if (!(value & 0x0100))
5938			break;
5939		DELAY(10);
5940	}
5941	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5942		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5943}
5944
5945static void
5946bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5947{
5948	uint32_t macctl;
5949
5950	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5951
5952	macctl = BWN_READ_4(mac, BWN_MACCTL);
5953	if (macctl & BWN_MACCTL_BIGENDIAN)
5954		printf("TODO: need swap\n");
5955
5956	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5957	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5958	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5959}
5960
5961static void
5962bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5963{
5964	uint16_t value;
5965
5966	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5967	    ("%s:%d: fail", __func__, __LINE__));
5968
5969	value = (uint8_t) (ctl->q);
5970	value |= ((uint8_t) (ctl->i)) << 8;
5971	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5972}
5973
5974static uint16_t
5975bwn_lo_calcfeed(struct bwn_mac *mac,
5976    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5977{
5978	struct bwn_phy *phy = &mac->mac_phy;
5979	uint16_t rfover;
5980	uint16_t feedthrough;
5981
5982	if (phy->gmode) {
5983		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5984		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5985
5986		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5987		    ("%s:%d: fail", __func__, __LINE__));
5988		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5989		    ("%s:%d: fail", __func__, __LINE__));
5990
5991		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5992
5993		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5994		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
5995		    && phy->rev > 6)
5996			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5997
5998		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5999		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6000		DELAY(10);
6001		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6002		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6003		DELAY(10);
6004		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6005		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6006		DELAY(10);
6007		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6008	} else {
6009		pga |= BWN_PHY_PGACTL_UNKNOWN;
6010		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6011		DELAY(10);
6012		pga |= BWN_PHY_PGACTL_LOWBANDW;
6013		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6014		DELAY(10);
6015		pga |= BWN_PHY_PGACTL_LPF;
6016		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6017	}
6018	DELAY(21);
6019	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6020
6021	return (feedthrough);
6022}
6023
6024static uint16_t
6025bwn_lo_txctl_regtable(struct bwn_mac *mac,
6026    uint16_t *value, uint16_t *pad_mix_gain)
6027{
6028	struct bwn_phy *phy = &mac->mac_phy;
6029	uint16_t reg, v, padmix;
6030
6031	if (phy->type == BWN_PHYTYPE_B) {
6032		v = 0x30;
6033		if (phy->rf_rev <= 5) {
6034			reg = 0x43;
6035			padmix = 0;
6036		} else {
6037			reg = 0x52;
6038			padmix = 5;
6039		}
6040	} else {
6041		if (phy->rev >= 2 && phy->rf_rev == 8) {
6042			reg = 0x43;
6043			v = 0x10;
6044			padmix = 2;
6045		} else {
6046			reg = 0x52;
6047			v = 0x30;
6048			padmix = 5;
6049		}
6050	}
6051	if (value)
6052		*value = v;
6053	if (pad_mix_gain)
6054		*pad_mix_gain = padmix;
6055
6056	return (reg);
6057}
6058
6059static void
6060bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6061{
6062	struct bwn_phy *phy = &mac->mac_phy;
6063	struct bwn_phy_g *pg = &phy->phy_g;
6064	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6065	uint16_t reg, mask;
6066	uint16_t trsw_rx, pga;
6067	uint16_t rf_pctl_reg;
6068
6069	static const uint8_t tx_bias_values[] = {
6070		0x09, 0x08, 0x0a, 0x01, 0x00,
6071		0x02, 0x05, 0x04, 0x06,
6072	};
6073	static const uint8_t tx_magn_values[] = {
6074		0x70, 0x40,
6075	};
6076
6077	if (!BWN_HAS_LOOPBACK(phy)) {
6078		rf_pctl_reg = 6;
6079		trsw_rx = 2;
6080		pga = 0;
6081	} else {
6082		int lb_gain;
6083
6084		trsw_rx = 0;
6085		lb_gain = pg->pg_max_lb_gain / 2;
6086		if (lb_gain > 10) {
6087			rf_pctl_reg = 0;
6088			pga = abs(10 - lb_gain) / 6;
6089			pga = MIN(MAX(pga, 0), 15);
6090		} else {
6091			int cmp_val;
6092			int tmp;
6093
6094			pga = 0;
6095			cmp_val = 0x24;
6096			if ((phy->rev >= 2) &&
6097			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6098				cmp_val = 0x3c;
6099			tmp = lb_gain;
6100			if ((10 - lb_gain) < cmp_val)
6101				tmp = (10 - lb_gain);
6102			if (tmp < 0)
6103				tmp += 6;
6104			else
6105				tmp += 3;
6106			cmp_val /= 4;
6107			tmp /= 4;
6108			if (tmp >= cmp_val)
6109				rf_pctl_reg = cmp_val;
6110			else
6111				rf_pctl_reg = tmp;
6112		}
6113	}
6114	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6115	bwn_phy_g_set_bbatt(mac, 2);
6116
6117	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6118	mask = ~mask;
6119	BWN_RF_MASK(mac, reg, mask);
6120
6121	if (BWN_HAS_TXMAG(phy)) {
6122		int i, j;
6123		int feedthrough;
6124		int min_feedth = 0xffff;
6125		uint8_t tx_magn, tx_bias;
6126
6127		for (i = 0; i < N(tx_magn_values); i++) {
6128			tx_magn = tx_magn_values[i];
6129			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6130			for (j = 0; j < N(tx_bias_values); j++) {
6131				tx_bias = tx_bias_values[j];
6132				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6133				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6134				    trsw_rx);
6135				if (feedthrough < min_feedth) {
6136					lo->tx_bias = tx_bias;
6137					lo->tx_magn = tx_magn;
6138					min_feedth = feedthrough;
6139				}
6140				if (lo->tx_bias == 0)
6141					break;
6142			}
6143			BWN_RF_WRITE(mac, 0x52,
6144					  (BWN_RF_READ(mac, 0x52)
6145					   & 0xff00) | lo->tx_bias | lo->
6146					  tx_magn);
6147		}
6148	} else {
6149		lo->tx_magn = 0;
6150		lo->tx_bias = 0;
6151		BWN_RF_MASK(mac, 0x52, 0xfff0);
6152	}
6153
6154	BWN_GETTIME(lo->txctl_measured_time);
6155}
6156
6157static void
6158bwn_lo_get_powervector(struct bwn_mac *mac)
6159{
6160	struct bwn_phy *phy = &mac->mac_phy;
6161	struct bwn_phy_g *pg = &phy->phy_g;
6162	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6163	int i;
6164	uint64_t tmp;
6165	uint64_t power_vector = 0;
6166
6167	for (i = 0; i < 8; i += 2) {
6168		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6169		power_vector |= (tmp << (i * 8));
6170		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6171	}
6172	if (power_vector)
6173		lo->power_vector = power_vector;
6174
6175	BWN_GETTIME(lo->pwr_vec_read_time);
6176}
6177
6178static void
6179bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6180    int use_trsw_rx)
6181{
6182	struct bwn_phy *phy = &mac->mac_phy;
6183	struct bwn_phy_g *pg = &phy->phy_g;
6184	uint16_t tmp;
6185
6186	if (max_rx_gain < 0)
6187		max_rx_gain = 0;
6188
6189	if (BWN_HAS_LOOPBACK(phy)) {
6190		int trsw_rx = 0;
6191		int trsw_rx_gain;
6192
6193		if (use_trsw_rx) {
6194			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6195			if (max_rx_gain >= trsw_rx_gain) {
6196				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6197				trsw_rx = 0x20;
6198			}
6199		} else
6200			trsw_rx_gain = max_rx_gain;
6201		if (trsw_rx_gain < 9) {
6202			pg->pg_lna_lod_gain = 0;
6203		} else {
6204			pg->pg_lna_lod_gain = 1;
6205			trsw_rx_gain -= 8;
6206		}
6207		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6208		pg->pg_pga_gain = trsw_rx_gain / 3;
6209		if (pg->pg_pga_gain >= 5) {
6210			pg->pg_pga_gain -= 5;
6211			pg->pg_lna_gain = 2;
6212		} else
6213			pg->pg_lna_gain = 0;
6214	} else {
6215		pg->pg_lna_gain = 0;
6216		pg->pg_trsw_rx_gain = 0x20;
6217		if (max_rx_gain >= 0x14) {
6218			pg->pg_lna_lod_gain = 1;
6219			pg->pg_pga_gain = 2;
6220		} else if (max_rx_gain >= 0x12) {
6221			pg->pg_lna_lod_gain = 1;
6222			pg->pg_pga_gain = 1;
6223		} else if (max_rx_gain >= 0xf) {
6224			pg->pg_lna_lod_gain = 1;
6225			pg->pg_pga_gain = 0;
6226		} else {
6227			pg->pg_lna_lod_gain = 0;
6228			pg->pg_pga_gain = 0;
6229		}
6230	}
6231
6232	tmp = BWN_RF_READ(mac, 0x7a);
6233	if (pg->pg_lna_lod_gain == 0)
6234		tmp &= ~0x0008;
6235	else
6236		tmp |= 0x0008;
6237	BWN_RF_WRITE(mac, 0x7a, tmp);
6238}
6239
6240static void
6241bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6242{
6243	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6244	struct bwn_phy *phy = &mac->mac_phy;
6245	struct bwn_phy_g *pg = &phy->phy_g;
6246	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6247	struct timespec ts;
6248	uint16_t tmp;
6249
6250	if (bwn_has_hwpctl(mac)) {
6251		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6252		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6253		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6254		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6255		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6256
6257		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6258		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6259		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6260		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6261	}
6262	if (phy->type == BWN_PHYTYPE_B &&
6263	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6264		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6265		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6266	}
6267	if (phy->rev >= 2) {
6268		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6269		sav->phy_analogoverval =
6270		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6271		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6272		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6273		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6274		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6275		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6276
6277		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6278		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6279		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6280		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6281		if (phy->type == BWN_PHYTYPE_G) {
6282			if ((phy->rev >= 7) &&
6283			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6284				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6285			} else {
6286				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6287			}
6288		} else {
6289			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6290		}
6291		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6292	}
6293	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6294	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6295	sav->rf0 = BWN_RF_READ(mac, 0x43);
6296	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6297	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6298	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6299	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6300	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6301
6302	if (!BWN_HAS_TXMAG(phy)) {
6303		sav->rf2 = BWN_RF_READ(mac, 0x52);
6304		sav->rf2 &= 0x00f0;
6305	}
6306	if (phy->type == BWN_PHYTYPE_B) {
6307		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6308		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6309		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6310		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6311	} else {
6312		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6313			    | 0x8000);
6314	}
6315	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6316		    & 0xf000);
6317
6318	tmp =
6319	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6320	BWN_PHY_WRITE(mac, tmp, 0x007f);
6321
6322	tmp = sav->phy_syncctl;
6323	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6324	tmp = sav->rf1;
6325	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6326
6327	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6328	if (phy->type == BWN_PHYTYPE_G ||
6329	    (phy->type == BWN_PHYTYPE_B &&
6330	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6331		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6332	} else
6333		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6334	if (phy->rev >= 2)
6335		bwn_dummy_transmission(mac, 0, 1);
6336	bwn_phy_g_switch_chan(mac, 6, 0);
6337	BWN_RF_READ(mac, 0x51);
6338	if (phy->type == BWN_PHYTYPE_G)
6339		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6340
6341	nanouptime(&ts);
6342	if (time_before(lo->txctl_measured_time,
6343	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6344		bwn_lo_measure_txctl_values(mac);
6345
6346	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6347		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6348	else {
6349		if (phy->type == BWN_PHYTYPE_B)
6350			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6351		else
6352			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6353	}
6354}
6355
6356static void
6357bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6358{
6359	struct bwn_phy *phy = &mac->mac_phy;
6360	struct bwn_phy_g *pg = &phy->phy_g;
6361	uint16_t tmp;
6362
6363	if (phy->rev >= 2) {
6364		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6365		tmp = (pg->pg_pga_gain << 8);
6366		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6367		DELAY(5);
6368		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6369		DELAY(2);
6370		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6371	} else {
6372		tmp = (pg->pg_pga_gain | 0xefa0);
6373		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6374	}
6375	if (phy->type == BWN_PHYTYPE_G) {
6376		if (phy->rev >= 3)
6377			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6378		else
6379			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6380		if (phy->rev >= 2)
6381			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6382		else
6383			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6384	}
6385	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6386	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6387	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6388	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6389	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6390	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6391	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6392	if (!BWN_HAS_TXMAG(phy)) {
6393		tmp = sav->rf2;
6394		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6395	}
6396	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6397	if (phy->type == BWN_PHYTYPE_B &&
6398	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6399		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6400		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6401	}
6402	if (phy->rev >= 2) {
6403		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6404		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6405			      sav->phy_analogoverval);
6406		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6407		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6408		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6409		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6410		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6411	}
6412	if (bwn_has_hwpctl(mac)) {
6413		tmp = (sav->phy_lomask & 0xbfff);
6414		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6415		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6416		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6417		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6418		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6419	}
6420	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6421}
6422
6423static int
6424bwn_lo_probe_loctl(struct bwn_mac *mac,
6425    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6426{
6427	struct bwn_phy *phy = &mac->mac_phy;
6428	struct bwn_phy_g *pg = &phy->phy_g;
6429	struct bwn_loctl orig, test;
6430	struct bwn_loctl prev = { -100, -100 };
6431	static const struct bwn_loctl modifiers[] = {
6432		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6433		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6434	};
6435	int begin, end, lower = 0, i;
6436	uint16_t feedth;
6437
6438	if (d->curstate == 0) {
6439		begin = 1;
6440		end = 8;
6441	} else if (d->curstate % 2 == 0) {
6442		begin = d->curstate - 1;
6443		end = d->curstate + 1;
6444	} else {
6445		begin = d->curstate - 2;
6446		end = d->curstate + 2;
6447	}
6448	if (begin < 1)
6449		begin += 8;
6450	if (end > 8)
6451		end -= 8;
6452
6453	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6454	i = begin;
6455	d->curstate = i;
6456	while (1) {
6457		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6458		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6459		test.i += modifiers[i - 1].i * d->multipler;
6460		test.q += modifiers[i - 1].q * d->multipler;
6461		if ((test.i != prev.i || test.q != prev.q) &&
6462		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6463			bwn_lo_write(mac, &test);
6464			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6465			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6466			if (feedth < d->feedth) {
6467				memcpy(probe, &test,
6468				    sizeof(struct bwn_loctl));
6469				lower = 1;
6470				d->feedth = feedth;
6471				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6472					break;
6473			}
6474		}
6475		memcpy(&prev, &test, sizeof(prev));
6476		if (i == end)
6477			break;
6478		if (i == 8)
6479			i = 1;
6480		else
6481			i++;
6482		d->curstate = i;
6483	}
6484
6485	return (lower);
6486}
6487
6488static void
6489bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6490{
6491	struct bwn_phy *phy = &mac->mac_phy;
6492	struct bwn_phy_g *pg = &phy->phy_g;
6493	struct bwn_lo_g_sm d;
6494	struct bwn_loctl probe;
6495	int lower, repeat, cnt = 0;
6496	uint16_t feedth;
6497
6498	d.nmeasure = 0;
6499	d.multipler = 1;
6500	if (BWN_HAS_LOOPBACK(phy))
6501		d.multipler = 3;
6502
6503	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6504	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6505
6506	do {
6507		bwn_lo_write(mac, &d.loctl);
6508		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6509		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6510		if (feedth < 0x258) {
6511			if (feedth >= 0x12c)
6512				*rxgain += 6;
6513			else
6514				*rxgain += 3;
6515			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6516			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6517		}
6518		d.feedth = feedth;
6519		d.curstate = 0;
6520		do {
6521			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6522			    ("%s:%d: fail", __func__, __LINE__));
6523			memcpy(&probe, &d.loctl,
6524			       sizeof(struct bwn_loctl));
6525			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6526			if (!lower)
6527				break;
6528			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6529				break;
6530			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6531			d.nmeasure++;
6532		} while (d.nmeasure < 24);
6533		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6534
6535		if (BWN_HAS_LOOPBACK(phy)) {
6536			if (d.feedth > 0x1194)
6537				*rxgain -= 6;
6538			else if (d.feedth < 0x5dc)
6539				*rxgain += 3;
6540			if (cnt == 0) {
6541				if (d.feedth <= 0x5dc) {
6542					d.multipler = 1;
6543					cnt++;
6544				} else
6545					d.multipler = 2;
6546			} else if (cnt == 2)
6547				d.multipler = 1;
6548		}
6549		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6550	} while (++cnt < repeat);
6551}
6552
6553static struct bwn_lo_calib *
6554bwn_lo_calibset(struct bwn_mac *mac,
6555    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6556{
6557	struct bwn_phy *phy = &mac->mac_phy;
6558	struct bwn_phy_g *pg = &phy->phy_g;
6559	struct bwn_loctl loctl = { 0, 0 };
6560	struct bwn_lo_calib *cal;
6561	struct bwn_lo_g_value sval = { 0 };
6562	int rxgain;
6563	uint16_t pad, reg, value;
6564
6565	sval.old_channel = phy->chan;
6566	bwn_mac_suspend(mac);
6567	bwn_lo_save(mac, &sval);
6568
6569	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6570	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6571	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6572
6573	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6574	if (rfatt->padmix)
6575		rxgain -= pad;
6576	if (BWN_HAS_LOOPBACK(phy))
6577		rxgain += pg->pg_max_lb_gain;
6578	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6579	bwn_phy_g_set_bbatt(mac, bbatt->att);
6580	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6581
6582	bwn_lo_restore(mac, &sval);
6583	bwn_mac_enable(mac);
6584
6585	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6586	if (!cal) {
6587		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6588		return (NULL);
6589	}
6590	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6591	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6592	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6593
6594	BWN_GETTIME(cal->calib_time);
6595
6596	return (cal);
6597}
6598
6599static struct bwn_lo_calib *
6600bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6601    const struct bwn_rfatt *rfatt)
6602{
6603	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6604	struct bwn_lo_calib *c;
6605
6606	TAILQ_FOREACH(c, &lo->calib_list, list) {
6607		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6608			continue;
6609		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6610			continue;
6611		return (c);
6612	}
6613
6614	c = bwn_lo_calibset(mac, bbatt, rfatt);
6615	if (!c)
6616		return (NULL);
6617	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6618
6619	return (c);
6620}
6621
6622static void
6623bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6624{
6625	struct bwn_phy *phy = &mac->mac_phy;
6626	struct bwn_phy_g *pg = &phy->phy_g;
6627	struct bwn_softc *sc = mac->mac_sc;
6628	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6629	const struct bwn_rfatt *rfatt;
6630	const struct bwn_bbatt *bbatt;
6631	uint64_t pvector;
6632	int i;
6633	int rf_offset, bb_offset;
6634	uint8_t changed = 0;
6635
6636	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6637	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6638	    ("%s:%d: fail", __func__, __LINE__));
6639
6640	pvector = lo->power_vector;
6641	if (!update && !pvector)
6642		return;
6643
6644	bwn_mac_suspend(mac);
6645
6646	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6647		struct bwn_lo_calib *cal;
6648		int idx;
6649		uint16_t val;
6650
6651		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6652			continue;
6653		bb_offset = i / lo->rfatt.len;
6654		rf_offset = i % lo->rfatt.len;
6655		bbatt = &(lo->bbatt.array[bb_offset]);
6656		rfatt = &(lo->rfatt.array[rf_offset]);
6657
6658		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6659		if (!cal) {
6660			device_printf(sc->sc_dev, "LO: Could not "
6661			    "calibrate DC table entry\n");
6662			continue;
6663		}
6664		val = (uint8_t)(cal->ctl.q);
6665		val |= ((uint8_t)(cal->ctl.i)) << 4;
6666		free(cal, M_DEVBUF);
6667
6668		idx = i / 2;
6669		if (i % 2)
6670			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6671			    | ((val & 0x00ff) << 8);
6672		else
6673			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6674			    | (val & 0x00ff);
6675		changed = 1;
6676	}
6677	if (changed) {
6678		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6679			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6680	}
6681	bwn_mac_enable(mac);
6682}
6683
6684static void
6685bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6686{
6687
6688	if (!rf->padmix)
6689		return;
6690	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6691		rf->att = 4;
6692}
6693
6694static void
6695bwn_lo_g_adjust(struct bwn_mac *mac)
6696{
6697	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6698	struct bwn_lo_calib *cal;
6699	struct bwn_rfatt rf;
6700
6701	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6702	bwn_lo_fixup_rfatt(&rf);
6703
6704	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6705	if (!cal)
6706		return;
6707	bwn_lo_write(mac, &cal->ctl);
6708}
6709
6710static void
6711bwn_lo_g_init(struct bwn_mac *mac)
6712{
6713
6714	if (!bwn_has_hwpctl(mac))
6715		return;
6716
6717	bwn_lo_get_powervector(mac);
6718	bwn_phy_g_dc_lookup_init(mac, 1);
6719}
6720
6721static void
6722bwn_mac_suspend(struct bwn_mac *mac)
6723{
6724	struct bwn_softc *sc = mac->mac_sc;
6725	int i;
6726	uint32_t tmp;
6727
6728	KASSERT(mac->mac_suspended >= 0,
6729	    ("%s:%d: fail", __func__, __LINE__));
6730
6731	if (mac->mac_suspended == 0) {
6732		bwn_psctl(mac, BWN_PS_AWAKE);
6733		BWN_WRITE_4(mac, BWN_MACCTL,
6734			    BWN_READ_4(mac, BWN_MACCTL)
6735			    & ~BWN_MACCTL_ON);
6736		BWN_READ_4(mac, BWN_MACCTL);
6737		for (i = 35; i; i--) {
6738			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6739			if (tmp & BWN_INTR_MAC_SUSPENDED)
6740				goto out;
6741			DELAY(10);
6742		}
6743		for (i = 40; i; i--) {
6744			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6745			if (tmp & BWN_INTR_MAC_SUSPENDED)
6746				goto out;
6747			DELAY(1000);
6748		}
6749		device_printf(sc->sc_dev, "MAC suspend failed\n");
6750	}
6751out:
6752	mac->mac_suspended++;
6753}
6754
6755static void
6756bwn_mac_enable(struct bwn_mac *mac)
6757{
6758	struct bwn_softc *sc = mac->mac_sc;
6759	uint16_t state;
6760
6761	state = bwn_shm_read_2(mac, BWN_SHARED,
6762	    BWN_SHARED_UCODESTAT);
6763	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6764	    state != BWN_SHARED_UCODESTAT_SLEEP)
6765		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6766
6767	mac->mac_suspended--;
6768	KASSERT(mac->mac_suspended >= 0,
6769	    ("%s:%d: fail", __func__, __LINE__));
6770	if (mac->mac_suspended == 0) {
6771		BWN_WRITE_4(mac, BWN_MACCTL,
6772		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6773		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6774		BWN_READ_4(mac, BWN_MACCTL);
6775		BWN_READ_4(mac, BWN_INTR_REASON);
6776		bwn_psctl(mac, 0);
6777	}
6778}
6779
6780static void
6781bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6782{
6783	int i;
6784	uint16_t ucstat;
6785
6786	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6787	    ("%s:%d: fail", __func__, __LINE__));
6788	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6789	    ("%s:%d: fail", __func__, __LINE__));
6790
6791	/* XXX forcibly awake and hwps-off */
6792
6793	BWN_WRITE_4(mac, BWN_MACCTL,
6794	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6795	    ~BWN_MACCTL_HWPS);
6796	BWN_READ_4(mac, BWN_MACCTL);
6797	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6798		for (i = 0; i < 100; i++) {
6799			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6800			    BWN_SHARED_UCODESTAT);
6801			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6802				break;
6803			DELAY(10);
6804		}
6805	}
6806}
6807
6808static int16_t
6809bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6810{
6811
6812	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6813	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6814}
6815
6816static void
6817bwn_nrssi_threshold(struct bwn_mac *mac)
6818{
6819	struct bwn_phy *phy = &mac->mac_phy;
6820	struct bwn_phy_g *pg = &phy->phy_g;
6821	struct siba_softc *siba = mac->mac_sd->sd_bus;
6822	int32_t a, b;
6823	int16_t tmp16;
6824	uint16_t tmpu16;
6825
6826	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6827
6828	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6829		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6830			a = 0x13;
6831			b = 0x12;
6832		} else {
6833			a = 0xe;
6834			b = 0x11;
6835		}
6836
6837		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6838		a += (pg->pg_nrssi[0] << 6);
6839		a += (a < 32) ? 31 : 32;
6840		a = a >> 6;
6841		a = MIN(MAX(a, -31), 31);
6842
6843		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6844		b += (pg->pg_nrssi[0] << 6);
6845		if (b < 32)
6846			b += 31;
6847		else
6848			b += 32;
6849		b = b >> 6;
6850		b = MIN(MAX(b, -31), 31);
6851
6852		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6853		tmpu16 |= ((uint32_t)b & 0x0000003f);
6854		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6855		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6856		return;
6857	}
6858
6859	tmp16 = bwn_nrssi_read(mac, 0x20);
6860	if (tmp16 >= 0x20)
6861		tmp16 -= 0x40;
6862	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6863}
6864
6865static void
6866bwn_nrssi_slope_11g(struct bwn_mac *mac)
6867{
6868#define	SAVE_RF_MAX		3
6869#define	SAVE_PHY_COMM_MAX	4
6870#define	SAVE_PHY3_MAX		8
6871	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6872		{ 0x7a, 0x52, 0x43 };
6873	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6874		{ 0x15, 0x5a, 0x59, 0x58 };
6875	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6876		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6877		0x0801, 0x0060, 0x0014, 0x0478
6878	};
6879	struct bwn_phy *phy = &mac->mac_phy;
6880	struct bwn_phy_g *pg = &phy->phy_g;
6881	int32_t i, tmp32, phy3_idx = 0;
6882	uint16_t delta, tmp;
6883	uint16_t save_rf[SAVE_RF_MAX];
6884	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6885	uint16_t save_phy3[SAVE_PHY3_MAX];
6886	uint16_t ant_div, phy0, chan_ex;
6887	int16_t nrssi0, nrssi1;
6888
6889	KASSERT(phy->type == BWN_PHYTYPE_G,
6890	    ("%s:%d: fail", __func__, __LINE__));
6891
6892	if (phy->rf_rev >= 9)
6893		return;
6894	if (phy->rf_rev == 8)
6895		bwn_nrssi_offset(mac);
6896
6897	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6898	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6899
6900	/*
6901	 * Save RF/PHY registers for later restoration
6902	 */
6903	ant_div = BWN_READ_2(mac, 0x03e2);
6904	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6905	for (i = 0; i < SAVE_RF_MAX; ++i)
6906		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6907	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6908		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6909
6910	phy0 = BWN_READ_2(mac, BWN_PHY0);
6911	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6912	if (phy->rev >= 3) {
6913		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6914			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6915		BWN_PHY_WRITE(mac, 0x002e, 0);
6916		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6917		switch (phy->rev) {
6918		case 4:
6919		case 6:
6920		case 7:
6921			BWN_PHY_SET(mac, 0x0478, 0x0100);
6922			BWN_PHY_SET(mac, 0x0801, 0x0040);
6923			break;
6924		case 3:
6925		case 5:
6926			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6927			break;
6928		}
6929		BWN_PHY_SET(mac, 0x0060, 0x0040);
6930		BWN_PHY_SET(mac, 0x0014, 0x0200);
6931	}
6932	/*
6933	 * Calculate nrssi0
6934	 */
6935	BWN_RF_SET(mac, 0x007a, 0x0070);
6936	bwn_set_all_gains(mac, 0, 8, 0);
6937	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6938	if (phy->rev >= 2) {
6939		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6940		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6941	}
6942	BWN_RF_SET(mac, 0x007a, 0x0080);
6943	DELAY(20);
6944
6945	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6946	if (nrssi0 >= 0x0020)
6947		nrssi0 -= 0x0040;
6948
6949	/*
6950	 * Calculate nrssi1
6951	 */
6952	BWN_RF_MASK(mac, 0x007a, 0x007f);
6953	if (phy->rev >= 2)
6954		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6955
6956	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6957	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6958	BWN_RF_SET(mac, 0x007a, 0x000f);
6959	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6960	if (phy->rev >= 2) {
6961		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6962		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6963	}
6964
6965	bwn_set_all_gains(mac, 3, 0, 1);
6966	if (phy->rf_rev == 8) {
6967		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6968	} else {
6969		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6970		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6971		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6972		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6973	}
6974	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6975	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6976	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6977	DELAY(20);
6978	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6979
6980	/*
6981	 * Install calculated narrow RSSI values
6982	 */
6983	if (nrssi1 >= 0x0020)
6984		nrssi1 -= 0x0040;
6985	if (nrssi0 == nrssi1)
6986		pg->pg_nrssi_slope = 0x00010000;
6987	else
6988		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6989	if (nrssi0 >= -4) {
6990		pg->pg_nrssi[0] = nrssi1;
6991		pg->pg_nrssi[1] = nrssi0;
6992	}
6993
6994	/*
6995	 * Restore saved RF/PHY registers
6996	 */
6997	if (phy->rev >= 3) {
6998		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6999			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7000			    save_phy3[phy3_idx]);
7001		}
7002	}
7003	if (phy->rev >= 2) {
7004		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7005		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7006	}
7007
7008	for (i = 0; i < SAVE_RF_MAX; ++i)
7009		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7010
7011	BWN_WRITE_2(mac, 0x03e2, ant_div);
7012	BWN_WRITE_2(mac, 0x03e6, phy0);
7013	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7014
7015	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7016		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7017
7018	bwn_spu_workaround(mac, phy->chan);
7019	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7020	bwn_set_original_gains(mac);
7021	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7022	if (phy->rev >= 3) {
7023		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7024			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7025			    save_phy3[phy3_idx]);
7026		}
7027	}
7028
7029	delta = 0x1f - pg->pg_nrssi[0];
7030	for (i = 0; i < 64; i++) {
7031		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7032		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7033		pg->pg_nrssi_lt[i] = tmp32;
7034	}
7035
7036	bwn_nrssi_threshold(mac);
7037#undef SAVE_RF_MAX
7038#undef SAVE_PHY_COMM_MAX
7039#undef SAVE_PHY3_MAX
7040}
7041
7042static void
7043bwn_nrssi_offset(struct bwn_mac *mac)
7044{
7045#define	SAVE_RF_MAX		2
7046#define	SAVE_PHY_COMM_MAX	10
7047#define	SAVE_PHY6_MAX		8
7048	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7049		{ 0x7a, 0x43 };
7050	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7051		0x0001, 0x0811, 0x0812, 0x0814,
7052		0x0815, 0x005a, 0x0059, 0x0058,
7053		0x000a, 0x0003
7054	};
7055	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7056		0x002e, 0x002f, 0x080f, 0x0810,
7057		0x0801, 0x0060, 0x0014, 0x0478
7058	};
7059	struct bwn_phy *phy = &mac->mac_phy;
7060	int i, phy6_idx = 0;
7061	uint16_t save_rf[SAVE_RF_MAX];
7062	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7063	uint16_t save_phy6[SAVE_PHY6_MAX];
7064	int16_t nrssi;
7065	uint16_t saved = 0xffff;
7066
7067	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7068		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7069	for (i = 0; i < SAVE_RF_MAX; ++i)
7070		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7071
7072	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7073	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7074	BWN_PHY_SET(mac, 0x0811, 0x000c);
7075	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7076	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7077	if (phy->rev >= 6) {
7078		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7079			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7080
7081		BWN_PHY_WRITE(mac, 0x002e, 0);
7082		BWN_PHY_WRITE(mac, 0x002f, 0);
7083		BWN_PHY_WRITE(mac, 0x080f, 0);
7084		BWN_PHY_WRITE(mac, 0x0810, 0);
7085		BWN_PHY_SET(mac, 0x0478, 0x0100);
7086		BWN_PHY_SET(mac, 0x0801, 0x0040);
7087		BWN_PHY_SET(mac, 0x0060, 0x0040);
7088		BWN_PHY_SET(mac, 0x0014, 0x0200);
7089	}
7090	BWN_RF_SET(mac, 0x007a, 0x0070);
7091	BWN_RF_SET(mac, 0x007a, 0x0080);
7092	DELAY(30);
7093
7094	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7095	if (nrssi >= 0x20)
7096		nrssi -= 0x40;
7097	if (nrssi == 31) {
7098		for (i = 7; i >= 4; i--) {
7099			BWN_RF_WRITE(mac, 0x007b, i);
7100			DELAY(20);
7101			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7102			    0x003f);
7103			if (nrssi >= 0x20)
7104				nrssi -= 0x40;
7105			if (nrssi < 31 && saved == 0xffff)
7106				saved = i;
7107		}
7108		if (saved == 0xffff)
7109			saved = 4;
7110	} else {
7111		BWN_RF_MASK(mac, 0x007a, 0x007f);
7112		if (phy->rev != 1) {
7113			BWN_PHY_SET(mac, 0x0814, 0x0001);
7114			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7115		}
7116		BWN_PHY_SET(mac, 0x0811, 0x000c);
7117		BWN_PHY_SET(mac, 0x0812, 0x000c);
7118		BWN_PHY_SET(mac, 0x0811, 0x0030);
7119		BWN_PHY_SET(mac, 0x0812, 0x0030);
7120		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7121		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7122		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7123		if (phy->rev == 0)
7124			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7125		else
7126			BWN_PHY_SET(mac, 0x000a, 0x2000);
7127		if (phy->rev != 1) {
7128			BWN_PHY_SET(mac, 0x0814, 0x0004);
7129			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7130		}
7131		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7132		BWN_RF_SET(mac, 0x007a, 0x000f);
7133		bwn_set_all_gains(mac, 3, 0, 1);
7134		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7135		DELAY(30);
7136		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7137		if (nrssi >= 0x20)
7138			nrssi -= 0x40;
7139		if (nrssi == -32) {
7140			for (i = 0; i < 4; i++) {
7141				BWN_RF_WRITE(mac, 0x007b, i);
7142				DELAY(20);
7143				nrssi = (int16_t)((BWN_PHY_READ(mac,
7144				    0x047f) >> 8) & 0x003f);
7145				if (nrssi >= 0x20)
7146					nrssi -= 0x40;
7147				if (nrssi > -31 && saved == 0xffff)
7148					saved = i;
7149			}
7150			if (saved == 0xffff)
7151				saved = 3;
7152		} else
7153			saved = 0;
7154	}
7155	BWN_RF_WRITE(mac, 0x007b, saved);
7156
7157	/*
7158	 * Restore saved RF/PHY registers
7159	 */
7160	if (phy->rev >= 6) {
7161		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7162			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7163			    save_phy6[phy6_idx]);
7164		}
7165	}
7166	if (phy->rev != 1) {
7167		for (i = 3; i < 5; i++)
7168			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7169			    save_phy_comm[i]);
7170	}
7171	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7172		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7173
7174	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7175		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7176
7177	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7178	BWN_PHY_SET(mac, 0x0429, 0x8000);
7179	bwn_set_original_gains(mac);
7180	if (phy->rev >= 6) {
7181		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7182			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7183			    save_phy6[phy6_idx]);
7184		}
7185	}
7186
7187	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7188	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7189	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7190}
7191
7192static void
7193bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7194    int16_t third)
7195{
7196	struct bwn_phy *phy = &mac->mac_phy;
7197	uint16_t i;
7198	uint16_t start = 0x08, end = 0x18;
7199	uint16_t tmp;
7200	uint16_t table;
7201
7202	if (phy->rev <= 1) {
7203		start = 0x10;
7204		end = 0x20;
7205	}
7206
7207	table = BWN_OFDMTAB_GAINX;
7208	if (phy->rev <= 1)
7209		table = BWN_OFDMTAB_GAINX_R1;
7210	for (i = 0; i < 4; i++)
7211		bwn_ofdmtab_write_2(mac, table, i, first);
7212
7213	for (i = start; i < end; i++)
7214		bwn_ofdmtab_write_2(mac, table, i, second);
7215
7216	if (third != -1) {
7217		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7218		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7219		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7220		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7221	}
7222	bwn_dummy_transmission(mac, 0, 1);
7223}
7224
7225static void
7226bwn_set_original_gains(struct bwn_mac *mac)
7227{
7228	struct bwn_phy *phy = &mac->mac_phy;
7229	uint16_t i, tmp;
7230	uint16_t table;
7231	uint16_t start = 0x0008, end = 0x0018;
7232
7233	if (phy->rev <= 1) {
7234		start = 0x0010;
7235		end = 0x0020;
7236	}
7237
7238	table = BWN_OFDMTAB_GAINX;
7239	if (phy->rev <= 1)
7240		table = BWN_OFDMTAB_GAINX_R1;
7241	for (i = 0; i < 4; i++) {
7242		tmp = (i & 0xfffc);
7243		tmp |= (i & 0x0001) << 1;
7244		tmp |= (i & 0x0002) >> 1;
7245
7246		bwn_ofdmtab_write_2(mac, table, i, tmp);
7247	}
7248
7249	for (i = start; i < end; i++)
7250		bwn_ofdmtab_write_2(mac, table, i, i - start);
7251
7252	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7253	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7254	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7255	bwn_dummy_transmission(mac, 0, 1);
7256}
7257
7258static void
7259bwn_phy_hwpctl_init(struct bwn_mac *mac)
7260{
7261	struct siba_softc *bus = mac->mac_sd->sd_bus;
7262	struct bwn_phy *phy = &mac->mac_phy;
7263	struct bwn_phy_g *pg = &phy->phy_g;
7264	struct bwn_rfatt old_rfatt, rfatt;
7265	struct bwn_bbatt old_bbatt, bbatt;
7266	uint8_t old_txctl = 0;
7267
7268	KASSERT(phy->type == BWN_PHYTYPE_G,
7269	    ("%s:%d: fail", __func__, __LINE__));
7270
7271	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7272	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7273		return;
7274
7275	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7276
7277	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7278
7279	if (!phy->gmode)
7280		return;
7281	bwn_hwpctl_early_init(mac);
7282	if (pg->pg_curtssi == 0) {
7283		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7284			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7285		} else {
7286			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7287			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7288			old_txctl = pg->pg_txctl;
7289
7290			bbatt.att = 11;
7291			if (phy->rf_rev == 8) {
7292				rfatt.att = 15;
7293				rfatt.padmix = 1;
7294			} else {
7295				rfatt.att = 9;
7296				rfatt.padmix = 0;
7297			}
7298			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7299		}
7300		bwn_dummy_transmission(mac, 0, 1);
7301		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7302		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7303			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7304		else
7305			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7306			    &old_rfatt, old_txctl);
7307	}
7308	bwn_hwpctl_init_gphy(mac);
7309
7310	/* clear TSSI */
7311	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7312	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7313	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7314	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7315}
7316
7317static void
7318bwn_hwpctl_early_init(struct bwn_mac *mac)
7319{
7320	struct bwn_phy *phy = &mac->mac_phy;
7321
7322	if (!bwn_has_hwpctl(mac)) {
7323		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7324		return;
7325	}
7326
7327	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7328	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7329	BWN_PHY_SET(mac, 0x047c, 0x0002);
7330	BWN_PHY_SET(mac, 0x047a, 0xf000);
7331	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7332		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7333		BWN_PHY_SET(mac, 0x005d, 0x8000);
7334		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7335		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7336		BWN_PHY_SET(mac, 0x0036, 0x0400);
7337	} else {
7338		BWN_PHY_SET(mac, 0x0036, 0x0200);
7339		BWN_PHY_SET(mac, 0x0036, 0x0400);
7340		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7341		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7342		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7343		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7344		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7345	}
7346}
7347
7348static void
7349bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7350{
7351	struct bwn_phy *phy = &mac->mac_phy;
7352	struct bwn_phy_g *pg = &phy->phy_g;
7353	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7354	int i;
7355	uint16_t nr_written = 0, tmp, value;
7356	uint8_t rf, bb;
7357
7358	if (!bwn_has_hwpctl(mac)) {
7359		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7360		return;
7361	}
7362
7363	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7364	    (pg->pg_idletssi - pg->pg_curtssi));
7365	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7366	    (pg->pg_idletssi - pg->pg_curtssi));
7367
7368	for (i = 0; i < 32; i++)
7369		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7370	for (i = 32; i < 64; i++)
7371		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7372	for (i = 0; i < 64; i += 2) {
7373		value = (uint16_t) pg->pg_tssi2dbm[i];
7374		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7375		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7376	}
7377
7378	for (rf = 0; rf < lo->rfatt.len; rf++) {
7379		for (bb = 0; bb < lo->bbatt.len; bb++) {
7380			if (nr_written >= 0x40)
7381				return;
7382			tmp = lo->bbatt.array[bb].att;
7383			tmp <<= 8;
7384			if (phy->rf_rev == 8)
7385				tmp |= 0x50;
7386			else
7387				tmp |= 0x40;
7388			tmp |= lo->rfatt.array[rf].att;
7389			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7390			nr_written++;
7391		}
7392	}
7393
7394	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7395	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7396
7397	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7398	BWN_PHY_SET(mac, 0x0478, 0x0800);
7399	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7400	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7401
7402	bwn_phy_g_dc_lookup_init(mac, 1);
7403	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7404}
7405
7406static void
7407bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7408{
7409	struct siba_softc *siba = mac->mac_sd->sd_bus;
7410
7411	if (spu != 0)
7412		bwn_spu_workaround(mac, channel);
7413
7414	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7415
7416	if (channel == 14) {
7417		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7418			bwn_hf_write(mac,
7419			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7420		else
7421			bwn_hf_write(mac,
7422			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7423		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7424		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7425		return;
7426	}
7427
7428	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7429	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7430}
7431
7432static uint16_t
7433bwn_phy_g_chan2freq(uint8_t channel)
7434{
7435	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7436
7437	KASSERT(channel >= 1 && channel <= 14,
7438	    ("%s:%d: fail", __func__, __LINE__));
7439
7440	return (bwn_phy_g_rf_channels[channel - 1]);
7441}
7442
7443static void
7444bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7445    const struct bwn_rfatt *rfatt, uint8_t txctl)
7446{
7447	struct bwn_phy *phy = &mac->mac_phy;
7448	struct bwn_phy_g *pg = &phy->phy_g;
7449	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7450	uint16_t bb, rf;
7451	uint16_t tx_bias, tx_magn;
7452
7453	bb = bbatt->att;
7454	rf = rfatt->att;
7455	tx_bias = lo->tx_bias;
7456	tx_magn = lo->tx_magn;
7457	if (tx_bias == 0xff)
7458		tx_bias = 0;
7459
7460	pg->pg_txctl = txctl;
7461	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7462	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7463	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7464	bwn_phy_g_set_bbatt(mac, bb);
7465	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7466	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7467		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7468	else {
7469		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7470		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7471	}
7472	if (BWN_HAS_TXMAG(phy))
7473		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7474	else
7475		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7476	bwn_lo_g_adjust(mac);
7477}
7478
7479static void
7480bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7481    uint16_t bbatt)
7482{
7483	struct bwn_phy *phy = &mac->mac_phy;
7484
7485	if (phy->analog == 0) {
7486		BWN_WRITE_2(mac, BWN_PHY0,
7487		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7488		return;
7489	}
7490	if (phy->analog > 1) {
7491		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7492		return;
7493	}
7494	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7495}
7496
7497static uint16_t
7498bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7499{
7500	struct bwn_phy *phy = &mac->mac_phy;
7501	struct bwn_phy_g *pg = &phy->phy_g;
7502	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7503	int max_lb_gain;
7504	uint16_t extlna;
7505	uint16_t i;
7506
7507	if (phy->gmode == 0)
7508		return (0);
7509
7510	if (BWN_HAS_LOOPBACK(phy)) {
7511		max_lb_gain = pg->pg_max_lb_gain;
7512		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7513		if (max_lb_gain >= 0x46) {
7514			extlna = 0x3000;
7515			max_lb_gain -= 0x46;
7516		} else if (max_lb_gain >= 0x3a) {
7517			extlna = 0x1000;
7518			max_lb_gain -= 0x3a;
7519		} else if (max_lb_gain >= 0x2e) {
7520			extlna = 0x2000;
7521			max_lb_gain -= 0x2e;
7522		} else {
7523			extlna = 0;
7524			max_lb_gain -= 0x10;
7525		}
7526
7527		for (i = 0; i < 16; i++) {
7528			max_lb_gain -= (i * 6);
7529			if (max_lb_gain < 6)
7530				break;
7531		}
7532
7533		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7534			if (reg == BWN_PHY_RFOVER) {
7535				return (0x1b3);
7536			} else if (reg == BWN_PHY_RFOVERVAL) {
7537				extlna |= (i << 8);
7538				switch (lpd) {
7539				case BWN_LPD(0, 1, 1):
7540					return (0x0f92);
7541				case BWN_LPD(0, 0, 1):
7542				case BWN_LPD(1, 0, 1):
7543					return (0x0092 | extlna);
7544				case BWN_LPD(1, 0, 0):
7545					return (0x0093 | extlna);
7546				}
7547				KASSERT(0 == 1,
7548				    ("%s:%d: fail", __func__, __LINE__));
7549			}
7550			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7551		} else {
7552			if (reg == BWN_PHY_RFOVER)
7553				return (0x9b3);
7554			if (reg == BWN_PHY_RFOVERVAL) {
7555				if (extlna)
7556					extlna |= 0x8000;
7557				extlna |= (i << 8);
7558				switch (lpd) {
7559				case BWN_LPD(0, 1, 1):
7560					return (0x8f92);
7561				case BWN_LPD(0, 0, 1):
7562					return (0x8092 | extlna);
7563				case BWN_LPD(1, 0, 1):
7564					return (0x2092 | extlna);
7565				case BWN_LPD(1, 0, 0):
7566					return (0x2093 | extlna);
7567				}
7568				KASSERT(0 == 1,
7569				    ("%s:%d: fail", __func__, __LINE__));
7570			}
7571			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7572		}
7573		return (0);
7574	}
7575
7576	if ((phy->rev < 7) ||
7577	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7578		if (reg == BWN_PHY_RFOVER) {
7579			return (0x1b3);
7580		} else if (reg == BWN_PHY_RFOVERVAL) {
7581			switch (lpd) {
7582			case BWN_LPD(0, 1, 1):
7583				return (0x0fb2);
7584			case BWN_LPD(0, 0, 1):
7585				return (0x00b2);
7586			case BWN_LPD(1, 0, 1):
7587				return (0x30b2);
7588			case BWN_LPD(1, 0, 0):
7589				return (0x30b3);
7590			}
7591			KASSERT(0 == 1,
7592			    ("%s:%d: fail", __func__, __LINE__));
7593		}
7594		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7595	} else {
7596		if (reg == BWN_PHY_RFOVER) {
7597			return (0x9b3);
7598		} else if (reg == BWN_PHY_RFOVERVAL) {
7599			switch (lpd) {
7600			case BWN_LPD(0, 1, 1):
7601				return (0x8fb2);
7602			case BWN_LPD(0, 0, 1):
7603				return (0x80b2);
7604			case BWN_LPD(1, 0, 1):
7605				return (0x20b2);
7606			case BWN_LPD(1, 0, 0):
7607				return (0x20b3);
7608			}
7609			KASSERT(0 == 1,
7610			    ("%s:%d: fail", __func__, __LINE__));
7611		}
7612		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7613	}
7614	return (0);
7615}
7616
7617static void
7618bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7619{
7620
7621	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7622		return;
7623	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7624	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7625	DELAY(1000);
7626	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7627}
7628
7629static int
7630bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7631{
7632	struct bwn_softc *sc = mac->mac_sc;
7633	struct bwn_fw *fw = &mac->mac_fw;
7634	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7635	const char *filename;
7636	uint32_t high;
7637	int error;
7638
7639	/* microcode */
7640	if (rev >= 5 && rev <= 10)
7641		filename = "ucode5";
7642	else if (rev >= 11 && rev <= 12)
7643		filename = "ucode11";
7644	else if (rev == 13)
7645		filename = "ucode13";
7646	else if (rev == 14)
7647		filename = "ucode14";
7648	else if (rev >= 15)
7649		filename = "ucode15";
7650	else {
7651		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7652		bwn_release_firmware(mac);
7653		return (EOPNOTSUPP);
7654	}
7655	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7656	if (error) {
7657		bwn_release_firmware(mac);
7658		return (error);
7659	}
7660
7661	/* PCM */
7662	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7663	if (rev >= 5 && rev <= 10) {
7664		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7665		if (error == ENOENT)
7666			fw->no_pcmfile = 1;
7667		else if (error) {
7668			bwn_release_firmware(mac);
7669			return (error);
7670		}
7671	} else if (rev < 11) {
7672		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7673		return (EOPNOTSUPP);
7674	}
7675
7676	/* initvals */
7677	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7678	switch (mac->mac_phy.type) {
7679	case BWN_PHYTYPE_A:
7680		if (rev < 5 || rev > 10)
7681			goto fail1;
7682		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7683			filename = "a0g1initvals5";
7684		else
7685			filename = "a0g0initvals5";
7686		break;
7687	case BWN_PHYTYPE_G:
7688		if (rev >= 5 && rev <= 10)
7689			filename = "b0g0initvals5";
7690		else if (rev >= 13)
7691			filename = "b0g0initvals13";
7692		else
7693			goto fail1;
7694		break;
7695	case BWN_PHYTYPE_LP:
7696		if (rev == 13)
7697			filename = "lp0initvals13";
7698		else if (rev == 14)
7699			filename = "lp0initvals14";
7700		else if (rev >= 15)
7701			filename = "lp0initvals15";
7702		else
7703			goto fail1;
7704		break;
7705	case BWN_PHYTYPE_N:
7706		if (rev >= 11 && rev <= 12)
7707			filename = "n0initvals11";
7708		else
7709			goto fail1;
7710		break;
7711	default:
7712		goto fail1;
7713	}
7714	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7715	if (error) {
7716		bwn_release_firmware(mac);
7717		return (error);
7718	}
7719
7720	/* bandswitch initvals */
7721	switch (mac->mac_phy.type) {
7722	case BWN_PHYTYPE_A:
7723		if (rev >= 5 && rev <= 10) {
7724			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7725				filename = "a0g1bsinitvals5";
7726			else
7727				filename = "a0g0bsinitvals5";
7728		} else if (rev >= 11)
7729			filename = NULL;
7730		else
7731			goto fail1;
7732		break;
7733	case BWN_PHYTYPE_G:
7734		if (rev >= 5 && rev <= 10)
7735			filename = "b0g0bsinitvals5";
7736		else if (rev >= 11)
7737			filename = NULL;
7738		else
7739			goto fail1;
7740		break;
7741	case BWN_PHYTYPE_LP:
7742		if (rev == 13)
7743			filename = "lp0bsinitvals13";
7744		else if (rev == 14)
7745			filename = "lp0bsinitvals14";
7746		else if (rev >= 15)
7747			filename = "lp0bsinitvals15";
7748		else
7749			goto fail1;
7750		break;
7751	case BWN_PHYTYPE_N:
7752		if (rev >= 11 && rev <= 12)
7753			filename = "n0bsinitvals11";
7754		else
7755			goto fail1;
7756		break;
7757	default:
7758		goto fail1;
7759	}
7760	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7761	if (error) {
7762		bwn_release_firmware(mac);
7763		return (error);
7764	}
7765	return (0);
7766fail1:
7767	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7768	bwn_release_firmware(mac);
7769	return (EOPNOTSUPP);
7770}
7771
7772static int
7773bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7774    const char *name, struct bwn_fwfile *bfw)
7775{
7776	const struct bwn_fwhdr *hdr;
7777	struct bwn_softc *sc = mac->mac_sc;
7778	const struct firmware *fw;
7779	char namebuf[64];
7780
7781	if (name == NULL) {
7782		bwn_do_release_fw(bfw);
7783		return (0);
7784	}
7785	if (bfw->filename != NULL) {
7786		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7787			return (0);
7788		bwn_do_release_fw(bfw);
7789	}
7790
7791	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s",
7792	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", name);
7793	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7794	fw = firmware_get(namebuf);
7795	if (fw == NULL) {
7796		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7797		    namebuf);
7798		return (ENOENT);
7799	}
7800	if (fw->datasize < sizeof(struct bwn_fwhdr))
7801		goto fail;
7802	hdr = (const struct bwn_fwhdr *)(fw->data);
7803	switch (hdr->type) {
7804	case BWN_FWTYPE_UCODE:
7805	case BWN_FWTYPE_PCM:
7806		if (be32toh(hdr->size) !=
7807		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7808			goto fail;
7809		/* FALLTHROUGH */
7810	case BWN_FWTYPE_IV:
7811		if (hdr->ver != 1)
7812			goto fail;
7813		break;
7814	default:
7815		goto fail;
7816	}
7817	bfw->filename = name;
7818	bfw->fw = fw;
7819	bfw->type = type;
7820	return (0);
7821fail:
7822	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7823	if (fw != NULL)
7824		firmware_put(fw, FIRMWARE_UNLOAD);
7825	return (EPROTO);
7826}
7827
7828static void
7829bwn_release_firmware(struct bwn_mac *mac)
7830{
7831
7832	bwn_do_release_fw(&mac->mac_fw.ucode);
7833	bwn_do_release_fw(&mac->mac_fw.pcm);
7834	bwn_do_release_fw(&mac->mac_fw.initvals);
7835	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7836}
7837
7838static void
7839bwn_do_release_fw(struct bwn_fwfile *bfw)
7840{
7841
7842	if (bfw->fw != NULL)
7843		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7844	bfw->fw = NULL;
7845	bfw->filename = NULL;
7846}
7847
7848static int
7849bwn_fw_loaducode(struct bwn_mac *mac)
7850{
7851#define	GETFWOFFSET(fwp, offset)	\
7852	((const uint32_t *)((const char *)fwp.fw->data + offset))
7853#define	GETFWSIZE(fwp, offset)	\
7854	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7855	struct bwn_softc *sc = mac->mac_sc;
7856	const uint32_t *data;
7857	unsigned int i;
7858	uint32_t ctl;
7859	uint16_t date, fwcaps, time;
7860	int error = 0;
7861
7862	ctl = BWN_READ_4(mac, BWN_MACCTL);
7863	ctl |= BWN_MACCTL_MCODE_JMP0;
7864	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7865	    __LINE__));
7866	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7867	for (i = 0; i < 64; i++)
7868		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7869	for (i = 0; i < 4096; i += 2)
7870		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7871
7872	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7873	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7874	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7875	     i++) {
7876		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7877		DELAY(10);
7878	}
7879
7880	if (mac->mac_fw.pcm.fw) {
7881		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7882		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7883		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7884		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7885		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7886		    sizeof(struct bwn_fwhdr)); i++) {
7887			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7888			DELAY(10);
7889		}
7890	}
7891
7892	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7893	BWN_WRITE_4(mac, BWN_MACCTL,
7894	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7895	    BWN_MACCTL_MCODE_RUN);
7896
7897	for (i = 0; i < 21; i++) {
7898		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7899			break;
7900		if (i >= 20) {
7901			device_printf(sc->sc_dev, "ucode timeout\n");
7902			error = ENXIO;
7903			goto error;
7904		}
7905		DELAY(50000);
7906	}
7907	BWN_READ_4(mac, BWN_INTR_REASON);
7908
7909	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7910	if (mac->mac_fw.rev <= 0x128) {
7911		device_printf(sc->sc_dev, "the firmware is too old\n");
7912		error = EOPNOTSUPP;
7913		goto error;
7914	}
7915	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7916	    BWN_SHARED_UCODE_PATCH);
7917	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7918	mac->mac_fw.opensource = (date == 0xffff);
7919	if (bwn_wme != 0)
7920		mac->mac_flags |= BWN_MAC_FLAG_WME;
7921	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7922
7923	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7924	if (mac->mac_fw.opensource == 0) {
7925		device_printf(sc->sc_dev,
7926		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7927		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7928		if (mac->mac_fw.no_pcmfile)
7929			device_printf(sc->sc_dev,
7930			    "no HW crypto acceleration due to pcm5\n");
7931	} else {
7932		mac->mac_fw.patch = time;
7933		fwcaps = bwn_fwcaps_read(mac);
7934		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7935			device_printf(sc->sc_dev,
7936			    "disabling HW crypto acceleration\n");
7937			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7938		}
7939		if (!(fwcaps & BWN_FWCAPS_WME)) {
7940			device_printf(sc->sc_dev, "disabling WME support\n");
7941			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7942		}
7943	}
7944
7945	if (BWN_ISOLDFMT(mac))
7946		device_printf(sc->sc_dev, "using old firmware image\n");
7947
7948	return (0);
7949
7950error:
7951	BWN_WRITE_4(mac, BWN_MACCTL,
7952	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7953	    BWN_MACCTL_MCODE_JMP0);
7954
7955	return (error);
7956#undef GETFWSIZE
7957#undef GETFWOFFSET
7958}
7959
7960/* OpenFirmware only */
7961static uint16_t
7962bwn_fwcaps_read(struct bwn_mac *mac)
7963{
7964
7965	KASSERT(mac->mac_fw.opensource == 1,
7966	    ("%s:%d: fail", __func__, __LINE__));
7967	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7968}
7969
7970static int
7971bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7972    size_t count, size_t array_size)
7973{
7974#define	GET_NEXTIV16(iv)						\
7975	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7976	    sizeof(uint16_t) + sizeof(uint16_t)))
7977#define	GET_NEXTIV32(iv)						\
7978	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7979	    sizeof(uint16_t) + sizeof(uint32_t)))
7980	struct bwn_softc *sc = mac->mac_sc;
7981	const struct bwn_fwinitvals *iv;
7982	uint16_t offset;
7983	size_t i;
7984	uint8_t bit32;
7985
7986	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7987	    ("%s:%d: fail", __func__, __LINE__));
7988	iv = ivals;
7989	for (i = 0; i < count; i++) {
7990		if (array_size < sizeof(iv->offset_size))
7991			goto fail;
7992		array_size -= sizeof(iv->offset_size);
7993		offset = be16toh(iv->offset_size);
7994		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7995		offset &= BWN_FWINITVALS_OFFSET_MASK;
7996		if (offset >= 0x1000)
7997			goto fail;
7998		if (bit32) {
7999			if (array_size < sizeof(iv->data.d32))
8000				goto fail;
8001			array_size -= sizeof(iv->data.d32);
8002			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8003			iv = GET_NEXTIV32(iv);
8004		} else {
8005
8006			if (array_size < sizeof(iv->data.d16))
8007				goto fail;
8008			array_size -= sizeof(iv->data.d16);
8009			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8010
8011			iv = GET_NEXTIV16(iv);
8012		}
8013	}
8014	if (array_size != 0)
8015		goto fail;
8016	return (0);
8017fail:
8018	device_printf(sc->sc_dev, "initvals: invalid format\n");
8019	return (EPROTO);
8020#undef GET_NEXTIV16
8021#undef GET_NEXTIV32
8022}
8023
8024static int
8025bwn_switch_channel(struct bwn_mac *mac, int chan)
8026{
8027	struct bwn_phy *phy = &(mac->mac_phy);
8028	struct bwn_softc *sc = mac->mac_sc;
8029	struct ifnet *ifp = sc->sc_ifp;
8030	struct ieee80211com *ic = ifp->if_l2com;
8031	uint16_t channelcookie, savedcookie;
8032	int error;
8033
8034	if (chan == 0xffff)
8035		chan = phy->get_default_chan(mac);
8036
8037	channelcookie = chan;
8038	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8039		channelcookie |= 0x100;
8040	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8041	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8042	error = phy->switch_channel(mac, chan);
8043	if (error)
8044		goto fail;
8045
8046	mac->mac_phy.chan = chan;
8047	DELAY(8000);
8048	return (0);
8049fail:
8050	device_printf(sc->sc_dev, "failed to switch channel\n");
8051	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8052	return (error);
8053}
8054
8055static uint16_t
8056bwn_ant2phy(int antenna)
8057{
8058
8059	switch (antenna) {
8060	case BWN_ANT0:
8061		return (BWN_TX_PHY_ANT0);
8062	case BWN_ANT1:
8063		return (BWN_TX_PHY_ANT1);
8064	case BWN_ANT2:
8065		return (BWN_TX_PHY_ANT2);
8066	case BWN_ANT3:
8067		return (BWN_TX_PHY_ANT3);
8068	case BWN_ANTAUTO:
8069		return (BWN_TX_PHY_ANT01AUTO);
8070	}
8071	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8072	return (0);
8073}
8074
8075static void
8076bwn_wme_load(struct bwn_mac *mac)
8077{
8078	struct bwn_softc *sc = mac->mac_sc;
8079	int i;
8080
8081	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8082	    ("%s:%d: fail", __func__, __LINE__));
8083
8084	bwn_mac_suspend(mac);
8085	for (i = 0; i < N(sc->sc_wmeParams); i++)
8086		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8087		    bwn_wme_shm_offsets[i]);
8088	bwn_mac_enable(mac);
8089}
8090
8091static void
8092bwn_wme_loadparams(struct bwn_mac *mac,
8093    const struct wmeParams *p, uint16_t shm_offset)
8094{
8095#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8096	struct bwn_softc *sc = mac->mac_sc;
8097	uint16_t params[BWN_NR_WMEPARAMS];
8098	int slot, tmp;
8099	unsigned int i;
8100
8101	slot = BWN_READ_2(mac, BWN_RNG) &
8102	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8103
8104	memset(&params, 0, sizeof(params));
8105
8106	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8107	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8108	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8109
8110	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8111	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8112	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8113	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8114	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8115	params[BWN_WMEPARAM_BSLOTS] = slot;
8116	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8117
8118	for (i = 0; i < N(params); i++) {
8119		if (i == BWN_WMEPARAM_STATUS) {
8120			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8121			    shm_offset + (i * 2));
8122			tmp |= 0x100;
8123			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8124			    tmp);
8125		} else {
8126			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8127			    params[i]);
8128		}
8129	}
8130}
8131
8132static void
8133bwn_mac_write_bssid(struct bwn_mac *mac)
8134{
8135	struct bwn_softc *sc = mac->mac_sc;
8136	uint32_t tmp;
8137	int i;
8138	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8139
8140	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8141	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8142	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8143	    IEEE80211_ADDR_LEN);
8144
8145	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8146		tmp = (uint32_t) (mac_bssid[i + 0]);
8147		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8148		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8149		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8150		bwn_ram_write(mac, 0x20 + i, tmp);
8151	}
8152}
8153
8154static void
8155bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8156    const uint8_t *macaddr)
8157{
8158	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8159	uint16_t data;
8160
8161	if (!mac)
8162		macaddr = zero;
8163
8164	offset |= 0x0020;
8165	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8166
8167	data = macaddr[0];
8168	data |= macaddr[1] << 8;
8169	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8170	data = macaddr[2];
8171	data |= macaddr[3] << 8;
8172	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8173	data = macaddr[4];
8174	data |= macaddr[5] << 8;
8175	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8176}
8177
8178static void
8179bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8180    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8181{
8182	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8183	uint8_t per_sta_keys_start = 8;
8184
8185	if (BWN_SEC_NEWAPI(mac))
8186		per_sta_keys_start = 4;
8187
8188	KASSERT(index < mac->mac_max_nr_keys,
8189	    ("%s:%d: fail", __func__, __LINE__));
8190	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8191	    ("%s:%d: fail", __func__, __LINE__));
8192
8193	if (index >= per_sta_keys_start)
8194		bwn_key_macwrite(mac, index, NULL);
8195	if (key)
8196		memcpy(buf, key, key_len);
8197	bwn_key_write(mac, index, algorithm, buf);
8198	if (index >= per_sta_keys_start)
8199		bwn_key_macwrite(mac, index, mac_addr);
8200
8201	mac->mac_key[index].algorithm = algorithm;
8202}
8203
8204static void
8205bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8206{
8207	uint32_t addrtmp[2] = { 0, 0 };
8208	uint8_t start = 8;
8209
8210	if (BWN_SEC_NEWAPI(mac))
8211		start = 4;
8212
8213	KASSERT(index >= start,
8214	    ("%s:%d: fail", __func__, __LINE__));
8215	index -= start;
8216
8217	if (addr) {
8218		addrtmp[0] = addr[0];
8219		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8220		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8221		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8222		addrtmp[1] = addr[4];
8223		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8224	}
8225
8226	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8227		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8228		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8229	} else {
8230		if (index >= 8) {
8231			bwn_shm_write_4(mac, BWN_SHARED,
8232			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8233			bwn_shm_write_2(mac, BWN_SHARED,
8234			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8235		}
8236	}
8237}
8238
8239static void
8240bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8241    const uint8_t *key)
8242{
8243	unsigned int i;
8244	uint32_t offset;
8245	uint16_t kidx, value;
8246
8247	kidx = BWN_SEC_KEY2FW(mac, index);
8248	bwn_shm_write_2(mac, BWN_SHARED,
8249	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8250
8251	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8252	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8253		value = key[i];
8254		value |= (uint16_t)(key[i + 1]) << 8;
8255		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8256	}
8257}
8258
8259static void
8260bwn_phy_exit(struct bwn_mac *mac)
8261{
8262
8263	mac->mac_phy.rf_onoff(mac, 0);
8264	if (mac->mac_phy.exit != NULL)
8265		mac->mac_phy.exit(mac);
8266}
8267
8268static void
8269bwn_dma_free(struct bwn_mac *mac)
8270{
8271	struct bwn_dma *dma;
8272
8273	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8274		return;
8275	dma = &mac->mac_method.dma;
8276
8277	bwn_dma_ringfree(&dma->rx);
8278	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8279	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8280	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8281	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8282	bwn_dma_ringfree(&dma->mcast);
8283}
8284
8285static void
8286bwn_core_stop(struct bwn_mac *mac)
8287{
8288	struct bwn_softc *sc = mac->mac_sc;
8289
8290	BWN_ASSERT_LOCKED(sc);
8291
8292	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8293		return;
8294
8295	callout_stop(&sc->sc_rfswitch_ch);
8296	callout_stop(&sc->sc_task_ch);
8297	callout_stop(&sc->sc_watchdog_ch);
8298	sc->sc_watchdog_timer = 0;
8299	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8300	BWN_READ_4(mac, BWN_INTR_MASK);
8301	bwn_mac_suspend(mac);
8302
8303	mac->mac_status = BWN_MAC_STATUS_INITED;
8304}
8305
8306static int
8307bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8308{
8309	struct bwn_mac *up_dev = NULL;
8310	struct bwn_mac *down_dev;
8311	struct bwn_mac *mac;
8312	int err, status;
8313	uint8_t gmode;
8314
8315	BWN_ASSERT_LOCKED(sc);
8316
8317	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8318		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8319		    mac->mac_phy.supports_2ghz) {
8320			up_dev = mac;
8321			gmode = 1;
8322		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8323		    mac->mac_phy.supports_5ghz) {
8324			up_dev = mac;
8325			gmode = 0;
8326		} else {
8327			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8328			return (EINVAL);
8329		}
8330		if (up_dev != NULL)
8331			break;
8332	}
8333	if (up_dev == NULL) {
8334		device_printf(sc->sc_dev, "Could not find a device\n");
8335		return (ENODEV);
8336	}
8337	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8338		return (0);
8339
8340	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8341	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8342
8343	down_dev = sc->sc_curmac;;
8344	status = down_dev->mac_status;
8345	if (status >= BWN_MAC_STATUS_STARTED)
8346		bwn_core_stop(down_dev);
8347	if (status >= BWN_MAC_STATUS_INITED)
8348		bwn_core_exit(down_dev);
8349
8350	if (down_dev != up_dev)
8351		bwn_phy_reset(down_dev);
8352
8353	up_dev->mac_phy.gmode = gmode;
8354	if (status >= BWN_MAC_STATUS_INITED) {
8355		err = bwn_core_init(up_dev);
8356		if (err) {
8357			device_printf(sc->sc_dev,
8358			    "fatal: failed to initialize for %s-GHz\n",
8359			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8360			goto fail;
8361		}
8362	}
8363	if (status >= BWN_MAC_STATUS_STARTED)
8364		bwn_core_start(up_dev);
8365	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8366	sc->sc_curmac = up_dev;
8367
8368	return (0);
8369fail:
8370	sc->sc_curmac = NULL;
8371	return (err);
8372}
8373
8374static void
8375bwn_rf_turnon(struct bwn_mac *mac)
8376{
8377
8378	bwn_mac_suspend(mac);
8379	mac->mac_phy.rf_onoff(mac, 1);
8380	mac->mac_phy.rf_on = 1;
8381	bwn_mac_enable(mac);
8382}
8383
8384static void
8385bwn_rf_turnoff(struct bwn_mac *mac)
8386{
8387
8388	bwn_mac_suspend(mac);
8389	mac->mac_phy.rf_onoff(mac, 0);
8390	mac->mac_phy.rf_on = 0;
8391	bwn_mac_enable(mac);
8392}
8393
8394static void
8395bwn_phy_reset(struct bwn_mac *mac)
8396{
8397	struct siba_dev_softc *sd = mac->mac_sd;
8398
8399	siba_write_4(sd, SIBA_TGSLOW,
8400	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8401	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8402	DELAY(1000);
8403	siba_write_4(sd, SIBA_TGSLOW,
8404	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8405	    BWN_TGSLOW_PHYRESET);
8406	DELAY(1000);
8407}
8408
8409static int
8410bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8411{
8412	struct bwn_vap *bvp = BWN_VAP(vap);
8413	struct ieee80211com *ic= vap->iv_ic;
8414	struct ifnet *ifp = ic->ic_ifp;
8415	enum ieee80211_state ostate = vap->iv_state;
8416	struct bwn_softc *sc = ifp->if_softc;
8417	struct bwn_mac *mac = sc->sc_curmac;
8418	int error;
8419
8420	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8421	    ieee80211_state_name[vap->iv_state],
8422	    ieee80211_state_name[nstate]);
8423
8424	error = bvp->bv_newstate(vap, nstate, arg);
8425	if (error != 0)
8426		return (error);
8427
8428	BWN_LOCK(sc);
8429
8430	bwn_led_newstate(mac, nstate);
8431
8432	/*
8433	 * Clear the BSSID when we stop a STA
8434	 */
8435	if (vap->iv_opmode == IEEE80211_M_STA) {
8436		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8437			/*
8438			 * Clear out the BSSID.  If we reassociate to
8439			 * the same AP, this will reinialize things
8440			 * correctly...
8441			 */
8442			if (ic->ic_opmode == IEEE80211_M_STA &&
8443			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8444				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8445				bwn_set_macaddr(mac);
8446			}
8447		}
8448	}
8449
8450	if (vap->iv_opmode == IEEE80211_M_MONITOR) {
8451		/* XXX nothing to do? */
8452	} else if (nstate == IEEE80211_S_RUN) {
8453		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8454		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8455		bwn_set_opmode(mac);
8456		bwn_set_pretbtt(mac);
8457		bwn_spu_setdelay(mac, 0);
8458		bwn_set_macaddr(mac);
8459	}
8460
8461	BWN_UNLOCK(sc);
8462
8463	return (error);
8464}
8465
8466static void
8467bwn_set_pretbtt(struct bwn_mac *mac)
8468{
8469	struct bwn_softc *sc = mac->mac_sc;
8470	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8471	uint16_t pretbtt;
8472
8473	if (ic->ic_opmode == IEEE80211_M_IBSS)
8474		pretbtt = 2;
8475	else
8476		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8477	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8478	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8479}
8480
8481static int
8482bwn_intr(void *arg)
8483{
8484	struct bwn_mac *mac = arg;
8485	struct bwn_softc *sc = mac->mac_sc;
8486	struct siba_softc *siba = mac->mac_sd->sd_bus;
8487	uint32_t reason;
8488
8489	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8490		return (FILTER_STRAY);
8491
8492	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8493	if (reason == 0xffffffff)	/* shared IRQ */
8494		return (FILTER_STRAY);
8495	reason &= mac->mac_intr_mask;
8496	if (reason == 0)
8497		return (FILTER_HANDLED);
8498
8499	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8500	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8501	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8502	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8503	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8504	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8505	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8506	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8507	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8508	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8509	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8510
8511	/* Disable interrupts. */
8512	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8513
8514	mac->mac_reason_intr = reason;
8515
8516	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8517	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8518
8519	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8520	return (FILTER_HANDLED);
8521}
8522
8523static void
8524bwn_intrtask(void *arg, int npending)
8525{
8526	struct bwn_mac *mac = arg;
8527	struct bwn_softc *sc = mac->mac_sc;
8528	struct ifnet *ifp = sc->sc_ifp;
8529	struct siba_softc *siba = mac->mac_sd->sd_bus;
8530	uint32_t merged = 0;
8531	int i, tx = 0, rx = 0;
8532
8533	BWN_LOCK(sc);
8534	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8535		BWN_UNLOCK(sc);
8536		return;
8537	}
8538
8539	for (i = 0; i < N(mac->mac_reason); i++)
8540		merged |= mac->mac_reason[i];
8541
8542	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8543		device_printf(sc->sc_dev, "MAC trans error\n");
8544
8545	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8546		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8547		mac->mac_phy.txerrors--;
8548		if (mac->mac_phy.txerrors == 0) {
8549			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8550			bwn_restart(mac, "PHY TX errors");
8551		}
8552	}
8553
8554	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8555		if (merged & BWN_DMAINTR_FATALMASK) {
8556			device_printf(sc->sc_dev,
8557			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8558			    mac->mac_reason[0], mac->mac_reason[1],
8559			    mac->mac_reason[2], mac->mac_reason[3],
8560			    mac->mac_reason[4], mac->mac_reason[5]);
8561			bwn_restart(mac, "DMA error");
8562			BWN_UNLOCK(sc);
8563			return;
8564		}
8565		if (merged & BWN_DMAINTR_NONFATALMASK) {
8566			device_printf(sc->sc_dev,
8567			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8568			    mac->mac_reason[0], mac->mac_reason[1],
8569			    mac->mac_reason[2], mac->mac_reason[3],
8570			    mac->mac_reason[4], mac->mac_reason[5]);
8571		}
8572	}
8573
8574	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8575		bwn_intr_ucode_debug(mac);
8576	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8577		bwn_intr_tbtt_indication(mac);
8578	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8579		bwn_intr_atim_end(mac);
8580	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8581		bwn_intr_beacon(mac);
8582	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8583		bwn_intr_pmq(mac);
8584	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8585		bwn_intr_noise(mac);
8586
8587	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8588		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8589			bwn_dma_rx(mac->mac_method.dma.rx);
8590			rx = 1;
8591		}
8592	} else
8593		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8594
8595	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8596	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8597	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8598	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8599	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8600
8601	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8602		bwn_intr_txeof(mac);
8603		tx = 1;
8604	}
8605
8606	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8607
8608	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8609		int evt = BWN_LED_EVENT_NONE;
8610
8611		if (tx && rx) {
8612			if (sc->sc_rx_rate > sc->sc_tx_rate)
8613				evt = BWN_LED_EVENT_RX;
8614			else
8615				evt = BWN_LED_EVENT_TX;
8616		} else if (tx) {
8617			evt = BWN_LED_EVENT_TX;
8618		} else if (rx) {
8619			evt = BWN_LED_EVENT_RX;
8620		} else if (rx == 0) {
8621			evt = BWN_LED_EVENT_POLL;
8622		}
8623
8624		if (evt != BWN_LED_EVENT_NONE)
8625			bwn_led_event(mac, evt);
8626       }
8627
8628	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8629		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8630			bwn_start_locked(ifp);
8631	}
8632
8633	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8634	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8635
8636	BWN_UNLOCK(sc);
8637}
8638
8639static void
8640bwn_restart(struct bwn_mac *mac, const char *msg)
8641{
8642	struct bwn_softc *sc = mac->mac_sc;
8643	struct ifnet *ifp = sc->sc_ifp;
8644	struct ieee80211com *ic = ifp->if_l2com;
8645
8646	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8647		return;
8648
8649	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8650	ieee80211_runtask(ic, &mac->mac_hwreset);
8651}
8652
8653static void
8654bwn_intr_ucode_debug(struct bwn_mac *mac)
8655{
8656	struct bwn_softc *sc = mac->mac_sc;
8657	uint16_t reason;
8658
8659	if (mac->mac_fw.opensource == 0)
8660		return;
8661
8662	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8663	switch (reason) {
8664	case BWN_DEBUGINTR_PANIC:
8665		bwn_handle_fwpanic(mac);
8666		break;
8667	case BWN_DEBUGINTR_DUMP_SHM:
8668		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8669		break;
8670	case BWN_DEBUGINTR_DUMP_REGS:
8671		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8672		break;
8673	case BWN_DEBUGINTR_MARKER:
8674		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8675		break;
8676	default:
8677		device_printf(sc->sc_dev,
8678		    "ucode debug unknown reason: %#x\n", reason);
8679	}
8680
8681	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8682	    BWN_DEBUGINTR_ACK);
8683}
8684
8685static void
8686bwn_intr_tbtt_indication(struct bwn_mac *mac)
8687{
8688	struct bwn_softc *sc = mac->mac_sc;
8689	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8690
8691	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8692		bwn_psctl(mac, 0);
8693	if (ic->ic_opmode == IEEE80211_M_IBSS)
8694		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8695}
8696
8697static void
8698bwn_intr_atim_end(struct bwn_mac *mac)
8699{
8700
8701	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8702		BWN_WRITE_4(mac, BWN_MACCMD,
8703		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8704		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8705	}
8706}
8707
8708static void
8709bwn_intr_beacon(struct bwn_mac *mac)
8710{
8711	struct bwn_softc *sc = mac->mac_sc;
8712	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8713	uint32_t cmd, beacon0, beacon1;
8714
8715	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8716	    ic->ic_opmode == IEEE80211_M_MBSS)
8717		return;
8718
8719	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8720
8721	cmd = BWN_READ_4(mac, BWN_MACCMD);
8722	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8723	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8724
8725	if (beacon0 && beacon1) {
8726		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8727		mac->mac_intr_mask |= BWN_INTR_BEACON;
8728		return;
8729	}
8730
8731	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8732		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8733		bwn_load_beacon0(mac);
8734		bwn_load_beacon1(mac);
8735		cmd = BWN_READ_4(mac, BWN_MACCMD);
8736		cmd |= BWN_MACCMD_BEACON0_VALID;
8737		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8738	} else {
8739		if (!beacon0) {
8740			bwn_load_beacon0(mac);
8741			cmd = BWN_READ_4(mac, BWN_MACCMD);
8742			cmd |= BWN_MACCMD_BEACON0_VALID;
8743			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8744		} else if (!beacon1) {
8745			bwn_load_beacon1(mac);
8746			cmd = BWN_READ_4(mac, BWN_MACCMD);
8747			cmd |= BWN_MACCMD_BEACON1_VALID;
8748			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8749		}
8750	}
8751}
8752
8753static void
8754bwn_intr_pmq(struct bwn_mac *mac)
8755{
8756	uint32_t tmp;
8757
8758	while (1) {
8759		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8760		if (!(tmp & 0x00000008))
8761			break;
8762	}
8763	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8764}
8765
8766static void
8767bwn_intr_noise(struct bwn_mac *mac)
8768{
8769	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8770	uint16_t tmp;
8771	uint8_t noise[4];
8772	uint8_t i, j;
8773	int32_t average;
8774
8775	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8776		return;
8777
8778	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8779	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8780	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8781	    noise[3] == 0x7f)
8782		goto new;
8783
8784	KASSERT(mac->mac_noise.noi_nsamples < 8,
8785	    ("%s:%d: fail", __func__, __LINE__));
8786	i = mac->mac_noise.noi_nsamples;
8787	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8788	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8789	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8790	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8791	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8792	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8793	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8794	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8795	mac->mac_noise.noi_nsamples++;
8796	if (mac->mac_noise.noi_nsamples == 8) {
8797		average = 0;
8798		for (i = 0; i < 8; i++) {
8799			for (j = 0; j < 4; j++)
8800				average += mac->mac_noise.noi_samples[i][j];
8801		}
8802		average = (((average / 32) * 125) + 64) / 128;
8803		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8804		if (tmp >= 8)
8805			average += 2;
8806		else
8807			average -= 25;
8808		average -= (tmp == 8) ? 72 : 48;
8809
8810		mac->mac_stats.link_noise = average;
8811		mac->mac_noise.noi_running = 0;
8812		return;
8813	}
8814new:
8815	bwn_noise_gensample(mac);
8816}
8817
8818static int
8819bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8820{
8821	struct bwn_mac *mac = prq->prq_mac;
8822	struct bwn_softc *sc = mac->mac_sc;
8823	unsigned int i;
8824
8825	BWN_ASSERT_LOCKED(sc);
8826
8827	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8828		return (0);
8829
8830	for (i = 0; i < 5000; i++) {
8831		if (bwn_pio_rxeof(prq) == 0)
8832			break;
8833	}
8834	if (i >= 5000)
8835		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8836	return ((i > 0) ? 1 : 0);
8837}
8838
8839static void
8840bwn_dma_rx(struct bwn_dma_ring *dr)
8841{
8842	int slot, curslot;
8843
8844	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8845	curslot = dr->get_curslot(dr);
8846	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8847	    ("%s:%d: fail", __func__, __LINE__));
8848
8849	slot = dr->dr_curslot;
8850	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8851		bwn_dma_rxeof(dr, &slot);
8852
8853	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8854	    BUS_DMASYNC_PREWRITE);
8855
8856	dr->set_curslot(dr, slot);
8857	dr->dr_curslot = slot;
8858}
8859
8860static void
8861bwn_intr_txeof(struct bwn_mac *mac)
8862{
8863	struct bwn_txstatus stat;
8864	uint32_t stat0, stat1;
8865	uint16_t tmp;
8866
8867	BWN_ASSERT_LOCKED(mac->mac_sc);
8868
8869	while (1) {
8870		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8871		if (!(stat0 & 0x00000001))
8872			break;
8873		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8874
8875		stat.cookie = (stat0 >> 16);
8876		stat.seq = (stat1 & 0x0000ffff);
8877		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8878		tmp = (stat0 & 0x0000ffff);
8879		stat.framecnt = ((tmp & 0xf000) >> 12);
8880		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8881		stat.sreason = ((tmp & 0x001c) >> 2);
8882		stat.pm = (tmp & 0x0080) ? 1 : 0;
8883		stat.im = (tmp & 0x0040) ? 1 : 0;
8884		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8885		stat.ack = (tmp & 0x0002) ? 1 : 0;
8886
8887		bwn_handle_txeof(mac, &stat);
8888	}
8889}
8890
8891static void
8892bwn_hwreset(void *arg, int npending)
8893{
8894	struct bwn_mac *mac = arg;
8895	struct bwn_softc *sc = mac->mac_sc;
8896	int error = 0;
8897	int prev_status;
8898
8899	BWN_LOCK(sc);
8900
8901	prev_status = mac->mac_status;
8902	if (prev_status >= BWN_MAC_STATUS_STARTED)
8903		bwn_core_stop(mac);
8904	if (prev_status >= BWN_MAC_STATUS_INITED)
8905		bwn_core_exit(mac);
8906
8907	if (prev_status >= BWN_MAC_STATUS_INITED) {
8908		error = bwn_core_init(mac);
8909		if (error)
8910			goto out;
8911	}
8912	if (prev_status >= BWN_MAC_STATUS_STARTED)
8913		bwn_core_start(mac);
8914out:
8915	if (error) {
8916		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8917		sc->sc_curmac = NULL;
8918	}
8919	BWN_UNLOCK(sc);
8920}
8921
8922static void
8923bwn_handle_fwpanic(struct bwn_mac *mac)
8924{
8925	struct bwn_softc *sc = mac->mac_sc;
8926	uint16_t reason;
8927
8928	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8929	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8930
8931	if (reason == BWN_FWPANIC_RESTART)
8932		bwn_restart(mac, "ucode panic");
8933}
8934
8935static void
8936bwn_load_beacon0(struct bwn_mac *mac)
8937{
8938
8939	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8940}
8941
8942static void
8943bwn_load_beacon1(struct bwn_mac *mac)
8944{
8945
8946	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8947}
8948
8949static uint32_t
8950bwn_jssi_read(struct bwn_mac *mac)
8951{
8952	uint32_t val = 0;
8953
8954	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8955	val <<= 16;
8956	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8957
8958	return (val);
8959}
8960
8961static void
8962bwn_noise_gensample(struct bwn_mac *mac)
8963{
8964	uint32_t jssi = 0x7f7f7f7f;
8965
8966	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8967	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8968	BWN_WRITE_4(mac, BWN_MACCMD,
8969	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8970}
8971
8972static int
8973bwn_dma_freeslot(struct bwn_dma_ring *dr)
8974{
8975	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8976
8977	return (dr->dr_numslots - dr->dr_usedslot);
8978}
8979
8980static int
8981bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8982{
8983	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8984
8985	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8986	    ("%s:%d: fail", __func__, __LINE__));
8987	if (slot == dr->dr_numslots - 1)
8988		return (0);
8989	return (slot + 1);
8990}
8991
8992static void
8993bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8994{
8995	struct bwn_mac *mac = dr->dr_mac;
8996	struct bwn_softc *sc = mac->mac_sc;
8997	struct bwn_dma *dma = &mac->mac_method.dma;
8998	struct bwn_dmadesc_generic *desc;
8999	struct bwn_dmadesc_meta *meta;
9000	struct bwn_rxhdr4 *rxhdr;
9001	struct ifnet *ifp = sc->sc_ifp;
9002	struct mbuf *m;
9003	uint32_t macstat;
9004	int32_t tmp;
9005	int cnt = 0;
9006	uint16_t len;
9007
9008	dr->getdesc(dr, *slot, &desc, &meta);
9009
9010	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9011	m = meta->mt_m;
9012
9013	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9014		ifp->if_ierrors++;
9015		return;
9016	}
9017
9018	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9019	len = le16toh(rxhdr->frame_len);
9020	if (len <= 0) {
9021		ifp->if_ierrors++;
9022		return;
9023	}
9024	if (bwn_dma_check_redzone(dr, m)) {
9025		device_printf(sc->sc_dev, "redzone error.\n");
9026		bwn_dma_set_redzone(dr, m);
9027		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9028		    BUS_DMASYNC_PREWRITE);
9029		return;
9030	}
9031	if (len > dr->dr_rx_bufsize) {
9032		tmp = len;
9033		while (1) {
9034			dr->getdesc(dr, *slot, &desc, &meta);
9035			bwn_dma_set_redzone(dr, meta->mt_m);
9036			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9037			    BUS_DMASYNC_PREWRITE);
9038			*slot = bwn_dma_nextslot(dr, *slot);
9039			cnt++;
9040			tmp -= dr->dr_rx_bufsize;
9041			if (tmp <= 0)
9042				break;
9043		}
9044		device_printf(sc->sc_dev, "too small buffer "
9045		       "(len %u buffer %u dropped %d)\n",
9046		       len, dr->dr_rx_bufsize, cnt);
9047		return;
9048	}
9049	macstat = le32toh(rxhdr->mac_status);
9050	if (macstat & BWN_RX_MAC_FCSERR) {
9051		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9052			device_printf(sc->sc_dev, "RX drop\n");
9053			return;
9054		}
9055	}
9056
9057	m->m_pkthdr.rcvif = ifp;
9058	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9059	m_adj(m, dr->dr_frameoffset);
9060
9061	bwn_rxeof(dr->dr_mac, m, rxhdr);
9062}
9063
9064static void
9065bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9066{
9067	struct bwn_dma_ring *dr;
9068	struct bwn_dmadesc_generic *desc;
9069	struct bwn_dmadesc_meta *meta;
9070	struct bwn_node *bn;
9071	struct bwn_pio_txqueue *tq;
9072	struct bwn_pio_txpkt *tp = NULL;
9073	struct bwn_softc *sc = mac->mac_sc;
9074	struct bwn_stats *stats = &mac->mac_stats;
9075	struct ieee80211_node *ni;
9076	int slot;
9077
9078	BWN_ASSERT_LOCKED(mac->mac_sc);
9079
9080	if (status->im)
9081		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9082	if (status->ampdu)
9083		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9084	if (status->rtscnt) {
9085		if (status->rtscnt == 0xf)
9086			stats->rtsfail++;
9087		else
9088			stats->rts++;
9089	}
9090
9091	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9092		if (status->ack) {
9093			dr = bwn_dma_parse_cookie(mac, status,
9094			    status->cookie, &slot);
9095			if (dr == NULL) {
9096				device_printf(sc->sc_dev,
9097				    "failed to parse cookie\n");
9098				return;
9099			}
9100			while (1) {
9101				dr->getdesc(dr, slot, &desc, &meta);
9102				if (meta->mt_islast) {
9103					ni = meta->mt_ni;
9104					bn = (struct bwn_node *)ni;
9105					ieee80211_amrr_tx_complete(&bn->bn_amn,
9106					    status->ack, 0);
9107					break;
9108				}
9109				slot = bwn_dma_nextslot(dr, slot);
9110			}
9111		}
9112		bwn_dma_handle_txeof(mac, status);
9113	} else {
9114		if (status->ack) {
9115			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9116			if (tq == NULL) {
9117				device_printf(sc->sc_dev,
9118				    "failed to parse cookie\n");
9119				return;
9120			}
9121			ni = tp->tp_ni;
9122			bn = (struct bwn_node *)ni;
9123			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9124		}
9125		bwn_pio_handle_txeof(mac, status);
9126	}
9127
9128	bwn_phy_txpower_check(mac, 0);
9129}
9130
9131static uint8_t
9132bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9133{
9134	struct bwn_mac *mac = prq->prq_mac;
9135	struct bwn_softc *sc = mac->mac_sc;
9136	struct bwn_rxhdr4 rxhdr;
9137	struct ifnet *ifp = sc->sc_ifp;
9138	struct mbuf *m;
9139	uint32_t ctl32, macstat, v32;
9140	unsigned int i, padding;
9141	uint16_t ctl16, len, v16;
9142	unsigned char *mp;
9143	char *data;
9144
9145	memset(&rxhdr, 0, sizeof(rxhdr));
9146
9147	if (prq->prq_rev >= 8) {
9148		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9149		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9150			return (0);
9151		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9152		    BWN_PIO8_RXCTL_FRAMEREADY);
9153		for (i = 0; i < 10; i++) {
9154			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9155			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9156				goto ready;
9157			DELAY(10);
9158		}
9159	} else {
9160		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9161		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9162			return (0);
9163		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9164		    BWN_PIO_RXCTL_FRAMEREADY);
9165		for (i = 0; i < 10; i++) {
9166			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9167			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9168				goto ready;
9169			DELAY(10);
9170		}
9171	}
9172	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9173	return (1);
9174ready:
9175	if (prq->prq_rev >= 8)
9176		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9177		    prq->prq_base + BWN_PIO8_RXDATA);
9178	else
9179		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9180		    prq->prq_base + BWN_PIO_RXDATA);
9181	len = le16toh(rxhdr.frame_len);
9182	if (len > 0x700) {
9183		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9184		goto error;
9185	}
9186	if (len == 0) {
9187		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9188		goto error;
9189	}
9190
9191	macstat = le32toh(rxhdr.mac_status);
9192	if (macstat & BWN_RX_MAC_FCSERR) {
9193		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9194			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9195			goto error;
9196		}
9197	}
9198
9199	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9200	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9201	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9202	if (m == NULL) {
9203		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9204		goto error;
9205	}
9206	mp = mtod(m, unsigned char *);
9207	if (prq->prq_rev >= 8) {
9208		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9209		    prq->prq_base + BWN_PIO8_RXDATA);
9210		if (len & 3) {
9211			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9212			data = &(mp[len + padding - 1]);
9213			switch (len & 3) {
9214			case 3:
9215				*data = (v32 >> 16);
9216				data--;
9217			case 2:
9218				*data = (v32 >> 8);
9219				data--;
9220			case 1:
9221				*data = v32;
9222			}
9223		}
9224	} else {
9225		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9226		    prq->prq_base + BWN_PIO_RXDATA);
9227		if (len & 1) {
9228			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9229			mp[len + padding - 1] = v16;
9230		}
9231	}
9232
9233	m->m_pkthdr.rcvif = ifp;
9234	m->m_len = m->m_pkthdr.len = len + padding;
9235
9236	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9237
9238	return (1);
9239error:
9240	if (prq->prq_rev >= 8)
9241		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9242		    BWN_PIO8_RXCTL_DATAREADY);
9243	else
9244		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9245	return (1);
9246}
9247
9248static int
9249bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9250    struct bwn_dmadesc_meta *meta, int init)
9251{
9252	struct bwn_mac *mac = dr->dr_mac;
9253	struct bwn_dma *dma = &mac->mac_method.dma;
9254	struct bwn_rxhdr4 *hdr;
9255	bus_dmamap_t map;
9256	bus_addr_t paddr;
9257	struct mbuf *m;
9258	int error;
9259
9260	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9261	if (m == NULL) {
9262		error = ENOBUFS;
9263
9264		/*
9265		 * If the NIC is up and running, we need to:
9266		 * - Clear RX buffer's header.
9267		 * - Restore RX descriptor settings.
9268		 */
9269		if (init)
9270			return (error);
9271		else
9272			goto back;
9273	}
9274	m->m_len = m->m_pkthdr.len = MCLBYTES;
9275
9276	bwn_dma_set_redzone(dr, m);
9277
9278	/*
9279	 * Try to load RX buf into temporary DMA map
9280	 */
9281	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9282	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9283	if (error) {
9284		m_freem(m);
9285
9286		/*
9287		 * See the comment above
9288		 */
9289		if (init)
9290			return (error);
9291		else
9292			goto back;
9293	}
9294
9295	if (!init)
9296		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9297	meta->mt_m = m;
9298	meta->mt_paddr = paddr;
9299
9300	/*
9301	 * Swap RX buf's DMA map with the loaded temporary one
9302	 */
9303	map = meta->mt_dmap;
9304	meta->mt_dmap = dr->dr_spare_dmap;
9305	dr->dr_spare_dmap = map;
9306
9307back:
9308	/*
9309	 * Clear RX buf header
9310	 */
9311	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9312	bzero(hdr, sizeof(*hdr));
9313	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9314	    BUS_DMASYNC_PREWRITE);
9315
9316	/*
9317	 * Setup RX buf descriptor
9318	 */
9319	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9320	    sizeof(*hdr), 0, 0, 0);
9321	return (error);
9322}
9323
9324static void
9325bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9326		 bus_size_t mapsz __unused, int error)
9327{
9328
9329	if (!error) {
9330		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9331		*((bus_addr_t *)arg) = seg->ds_addr;
9332	}
9333}
9334
9335static int
9336bwn_hwrate2ieeerate(int rate)
9337{
9338
9339	switch (rate) {
9340	case BWN_CCK_RATE_1MB:
9341		return (2);
9342	case BWN_CCK_RATE_2MB:
9343		return (4);
9344	case BWN_CCK_RATE_5MB:
9345		return (11);
9346	case BWN_CCK_RATE_11MB:
9347		return (22);
9348	case BWN_OFDM_RATE_6MB:
9349		return (12);
9350	case BWN_OFDM_RATE_9MB:
9351		return (18);
9352	case BWN_OFDM_RATE_12MB:
9353		return (24);
9354	case BWN_OFDM_RATE_18MB:
9355		return (36);
9356	case BWN_OFDM_RATE_24MB:
9357		return (48);
9358	case BWN_OFDM_RATE_36MB:
9359		return (72);
9360	case BWN_OFDM_RATE_48MB:
9361		return (96);
9362	case BWN_OFDM_RATE_54MB:
9363		return (108);
9364	default:
9365		printf("Ooops\n");
9366		return (0);
9367	}
9368}
9369
9370static void
9371bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9372{
9373	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9374	struct bwn_plcp6 *plcp;
9375	struct bwn_softc *sc = mac->mac_sc;
9376	struct ieee80211_frame_min *wh;
9377	struct ieee80211_node *ni;
9378	struct ifnet *ifp = sc->sc_ifp;
9379	struct ieee80211com *ic = ifp->if_l2com;
9380	uint32_t macstat;
9381	int padding, rate, rssi = 0, noise = 0, type;
9382	uint16_t phytype, phystat0, phystat3, chanstat;
9383	unsigned char *mp = mtod(m, unsigned char *);
9384	static int rx_mac_dec_rpt = 0;
9385
9386	BWN_ASSERT_LOCKED(sc);
9387
9388	phystat0 = le16toh(rxhdr->phy_status0);
9389	phystat3 = le16toh(rxhdr->phy_status3);
9390	macstat = le32toh(rxhdr->mac_status);
9391	chanstat = le16toh(rxhdr->channel);
9392	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9393
9394	if (macstat & BWN_RX_MAC_FCSERR)
9395		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9396	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9397		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9398	if (phystat0 & BWN_RX_PHYST0_SHORTPRMBL)
9399		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_SHORTPRE\n");
9400	if (macstat & BWN_RX_MAC_DECERR)
9401		goto drop;
9402
9403	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9404	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9405		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9406		    m->m_pkthdr.len);
9407		goto drop;
9408	}
9409	plcp = (struct bwn_plcp6 *)(mp + padding);
9410	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9411	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9412		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9413		    m->m_pkthdr.len);
9414		goto drop;
9415	}
9416	wh = mtod(m, struct ieee80211_frame_min *);
9417
9418	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9419		device_printf(sc->sc_dev,
9420		    "RX decryption attempted (old %d keyidx %#x)\n",
9421		    BWN_ISOLDFMT(mac),
9422		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9423
9424	/* XXX calculating RSSI & noise & antenna */
9425
9426	if (phystat0 & BWN_RX_PHYST0_OFDM)
9427		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9428		    phytype == BWN_PHYTYPE_A);
9429	else
9430		rate = bwn_plcp_get_cckrate(mac, plcp);
9431	if (rate == -1) {
9432		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9433			goto drop;
9434	}
9435	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9436
9437	/* RX radio tap */
9438	if (ieee80211_radiotap_active(ic))
9439		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9440	m_adj(m, -IEEE80211_CRC_LEN);
9441
9442	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9443	noise = mac->mac_stats.link_noise;
9444
9445	BWN_UNLOCK(sc);
9446
9447	ni = ieee80211_find_rxnode(ic, wh);
9448	if (ni != NULL) {
9449		type = ieee80211_input(ni, m, rssi, noise);
9450		ieee80211_free_node(ni);
9451	} else
9452		type = ieee80211_input_all(ic, m, rssi, noise);
9453
9454	BWN_LOCK(sc);
9455	return;
9456drop:
9457	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9458}
9459
9460static void
9461bwn_dma_handle_txeof(struct bwn_mac *mac,
9462    const struct bwn_txstatus *status)
9463{
9464	struct bwn_dma *dma = &mac->mac_method.dma;
9465	struct bwn_dma_ring *dr;
9466	struct bwn_dmadesc_generic *desc;
9467	struct bwn_dmadesc_meta *meta;
9468	struct bwn_softc *sc = mac->mac_sc;
9469	struct ieee80211_node *ni;
9470	struct ifnet *ifp = sc->sc_ifp;
9471	struct mbuf *m;
9472	int slot;
9473
9474	BWN_ASSERT_LOCKED(sc);
9475
9476	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9477	if (dr == NULL) {
9478		device_printf(sc->sc_dev, "failed to parse cookie\n");
9479		return;
9480	}
9481	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9482
9483	while (1) {
9484		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9485		    ("%s:%d: fail", __func__, __LINE__));
9486		dr->getdesc(dr, slot, &desc, &meta);
9487
9488		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9489			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9490		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9491			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9492
9493		if (meta->mt_islast) {
9494			KASSERT(meta->mt_m != NULL,
9495			    ("%s:%d: fail", __func__, __LINE__));
9496
9497			ni = meta->mt_ni;
9498			m = meta->mt_m;
9499			if (ni != NULL) {
9500				/*
9501				 * Do any tx complete callback. Note this must
9502				 * be done before releasing the node reference.
9503				 */
9504				if (m->m_flags & M_TXCB)
9505					ieee80211_process_callback(ni, m, 0);
9506				ieee80211_free_node(ni);
9507				meta->mt_ni = NULL;
9508			}
9509			m_freem(m);
9510			meta->mt_m = NULL;
9511		} else {
9512			KASSERT(meta->mt_m == NULL,
9513			    ("%s:%d: fail", __func__, __LINE__));
9514		}
9515
9516		dr->dr_usedslot--;
9517		if (meta->mt_islast) {
9518			ifp->if_opackets++;
9519			break;
9520		}
9521		slot = bwn_dma_nextslot(dr, slot);
9522	}
9523	sc->sc_watchdog_timer = 0;
9524	if (dr->dr_stop) {
9525		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9526		    ("%s:%d: fail", __func__, __LINE__));
9527		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9528		dr->dr_stop = 0;
9529	}
9530}
9531
9532static void
9533bwn_pio_handle_txeof(struct bwn_mac *mac,
9534    const struct bwn_txstatus *status)
9535{
9536	struct bwn_pio_txqueue *tq;
9537	struct bwn_pio_txpkt *tp = NULL;
9538	struct bwn_softc *sc = mac->mac_sc;
9539	struct ifnet *ifp = sc->sc_ifp;
9540
9541	BWN_ASSERT_LOCKED(sc);
9542
9543	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9544	if (tq == NULL)
9545		return;
9546
9547	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9548	tq->tq_free++;
9549
9550	if (tp->tp_ni != NULL) {
9551		/*
9552		 * Do any tx complete callback.  Note this must
9553		 * be done before releasing the node reference.
9554		 */
9555		if (tp->tp_m->m_flags & M_TXCB)
9556			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9557		ieee80211_free_node(tp->tp_ni);
9558		tp->tp_ni = NULL;
9559	}
9560	m_freem(tp->tp_m);
9561	tp->tp_m = NULL;
9562	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9563
9564	ifp->if_opackets++;
9565
9566	sc->sc_watchdog_timer = 0;
9567	if (tq->tq_stop) {
9568		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9569		tq->tq_stop = 0;
9570	}
9571}
9572
9573static void
9574bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9575{
9576	struct bwn_softc *sc = mac->mac_sc;
9577	struct bwn_phy *phy = &mac->mac_phy;
9578	struct ifnet *ifp = sc->sc_ifp;
9579	struct ieee80211com *ic = ifp->if_l2com;
9580	struct siba_softc *siba = mac->mac_sd->sd_bus;
9581	unsigned long now;
9582	int result;
9583
9584	BWN_GETTIME(now);
9585
9586	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9587		return;
9588	phy->nexttime = now + 2 * 1000;
9589
9590	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9591	    siba->siba_board_type == SIBA_BOARD_BU4306)
9592		return;
9593
9594	if (phy->recalc_txpwr != NULL) {
9595		result = phy->recalc_txpwr(mac,
9596		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9597		if (result == BWN_TXPWR_RES_DONE)
9598			return;
9599		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9600		    ("%s: fail", __func__));
9601		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9602
9603		ieee80211_runtask(ic, &mac->mac_txpower);
9604	}
9605}
9606
9607static uint16_t
9608bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9609{
9610
9611	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9612}
9613
9614static uint32_t
9615bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9616{
9617
9618	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9619}
9620
9621static void
9622bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9623{
9624
9625	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9626}
9627
9628static void
9629bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9630{
9631
9632	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9633}
9634
9635static int
9636bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9637{
9638
9639	switch (rate) {
9640	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9641	case 12:
9642		return (BWN_OFDM_RATE_6MB);
9643	case 18:
9644		return (BWN_OFDM_RATE_9MB);
9645	case 24:
9646		return (BWN_OFDM_RATE_12MB);
9647	case 36:
9648		return (BWN_OFDM_RATE_18MB);
9649	case 48:
9650		return (BWN_OFDM_RATE_24MB);
9651	case 72:
9652		return (BWN_OFDM_RATE_36MB);
9653	case 96:
9654		return (BWN_OFDM_RATE_48MB);
9655	case 108:
9656		return (BWN_OFDM_RATE_54MB);
9657	/* CCK rates (NB: not IEEE std, device-specific) */
9658	case 2:
9659		return (BWN_CCK_RATE_1MB);
9660	case 4:
9661		return (BWN_CCK_RATE_2MB);
9662	case 11:
9663		return (BWN_CCK_RATE_5MB);
9664	case 22:
9665		return (BWN_CCK_RATE_11MB);
9666	}
9667
9668	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9669	return (BWN_CCK_RATE_1MB);
9670}
9671
9672static int
9673bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9674    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9675{
9676	const struct bwn_phy *phy = &mac->mac_phy;
9677	struct bwn_softc *sc = mac->mac_sc;
9678	struct ieee80211_frame *wh;
9679	struct ieee80211_frame *protwh;
9680	struct ieee80211_frame_cts *cts;
9681	struct ieee80211_frame_rts *rts;
9682	const struct ieee80211_txparam *tp;
9683	struct ieee80211vap *vap = ni->ni_vap;
9684	struct ifnet *ifp = sc->sc_ifp;
9685	struct ieee80211com *ic = ifp->if_l2com;
9686	struct mbuf *mprot;
9687	unsigned int len;
9688	uint32_t macctl = 0;
9689	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9690	uint16_t phyctl = 0;
9691	uint8_t rate, rate_fb;
9692
9693	wh = mtod(m, struct ieee80211_frame *);
9694	memset(txhdr, 0, sizeof(*txhdr));
9695
9696	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9697	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9698	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9699
9700	/*
9701	 * Find TX rate
9702	 */
9703	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9704	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9705		rate = rate_fb = tp->mgmtrate;
9706	else if (ismcast)
9707		rate = rate_fb = tp->mcastrate;
9708	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9709		rate = rate_fb = tp->ucastrate;
9710	else {
9711		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9712		rate = ni->ni_txrate;
9713
9714		if (rix > 0)
9715			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9716			    IEEE80211_RATE_VAL;
9717		else
9718			rate_fb = rate;
9719	}
9720
9721	sc->sc_tx_rate = rate;
9722
9723	rate = bwn_ieeerate2hwrate(sc, rate);
9724	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9725
9726	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9727	    bwn_plcp_getcck(rate);
9728	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9729	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9730
9731	if ((rate_fb == rate) ||
9732	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9733	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9734		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9735	else
9736		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9737		    m->m_pkthdr.len, rate, isshort);
9738
9739	/* XXX TX encryption */
9740	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9741	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9742	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9743	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9744	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9745	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9746
9747	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9748	    BWN_TX_EFT_FB_CCK;
9749	txhdr->chan = phy->chan;
9750	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9751	    BWN_TX_PHY_ENC_CCK;
9752	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9753	     rate == BWN_CCK_RATE_11MB))
9754		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9755
9756	/* XXX TX antenna selection */
9757
9758	switch (bwn_antenna_sanitize(mac, 0)) {
9759	case 0:
9760		phyctl |= BWN_TX_PHY_ANT01AUTO;
9761		break;
9762	case 1:
9763		phyctl |= BWN_TX_PHY_ANT0;
9764		break;
9765	case 2:
9766		phyctl |= BWN_TX_PHY_ANT1;
9767		break;
9768	case 3:
9769		phyctl |= BWN_TX_PHY_ANT2;
9770		break;
9771	case 4:
9772		phyctl |= BWN_TX_PHY_ANT3;
9773		break;
9774	default:
9775		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9776	}
9777
9778	if (!ismcast)
9779		macctl |= BWN_TX_MAC_ACK;
9780
9781	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9782	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9783	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9784		macctl |= BWN_TX_MAC_LONGFRAME;
9785
9786	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9787		/* XXX RTS rate is always 1MB??? */
9788		rts_rate = BWN_CCK_RATE_1MB;
9789		rts_rate_fb = bwn_get_fbrate(rts_rate);
9790
9791		protdur = ieee80211_compute_duration(ic->ic_rt,
9792		    m->m_pkthdr.len, rate, isshort) +
9793		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9794
9795		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9796			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9797			    (txhdr->body.old.rts_frame) :
9798			    (txhdr->body.new.rts_frame));
9799			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9800			    protdur);
9801			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9802			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9803			    mprot->m_pkthdr.len);
9804			m_freem(mprot);
9805			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9806			len = sizeof(struct ieee80211_frame_cts);
9807		} else {
9808			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9809			    (txhdr->body.old.rts_frame) :
9810			    (txhdr->body.new.rts_frame));
9811			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9812			    isshort);
9813			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9814			    wh->i_addr2, protdur);
9815			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9816			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9817			    mprot->m_pkthdr.len);
9818			m_freem(mprot);
9819			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9820			len = sizeof(struct ieee80211_frame_rts);
9821		}
9822		len += IEEE80211_CRC_LEN;
9823		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9824		    &txhdr->body.old.rts_plcp :
9825		    &txhdr->body.new.rts_plcp), len, rts_rate);
9826		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9827		    rts_rate_fb);
9828
9829		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9830		    (&txhdr->body.old.rts_frame) :
9831		    (&txhdr->body.new.rts_frame));
9832		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9833
9834		if (BWN_ISOFDMRATE(rts_rate)) {
9835			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9836			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9837		} else {
9838			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9839			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9840		}
9841		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9842		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9843	}
9844
9845	if (BWN_ISOLDFMT(mac))
9846		txhdr->body.old.cookie = htole16(cookie);
9847	else
9848		txhdr->body.new.cookie = htole16(cookie);
9849
9850	txhdr->macctl = htole32(macctl);
9851	txhdr->phyctl = htole16(phyctl);
9852
9853	/*
9854	 * TX radio tap
9855	 */
9856	if (ieee80211_radiotap_active_vap(vap)) {
9857		sc->sc_tx_th.wt_flags = 0;
9858		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9859			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9860		if (isshort &&
9861		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9862		     rate == BWN_CCK_RATE_11MB))
9863			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9864		sc->sc_tx_th.wt_rate = rate;
9865
9866		ieee80211_radiotap_tx(vap, m);
9867	}
9868
9869	return (0);
9870}
9871
9872static void
9873bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9874    const uint8_t rate)
9875{
9876	uint32_t d, plen;
9877	uint8_t *raw = plcp->o.raw;
9878
9879	if (BWN_ISOFDMRATE(rate)) {
9880		d = bwn_plcp_getofdm(rate);
9881		KASSERT(!(octets & 0xf000),
9882		    ("%s:%d: fail", __func__, __LINE__));
9883		d |= (octets << 5);
9884		plcp->o.data = htole32(d);
9885	} else {
9886		plen = octets * 16 / rate;
9887		if ((octets * 16 % rate) > 0) {
9888			plen++;
9889			if ((rate == BWN_CCK_RATE_11MB)
9890			    && ((octets * 8 % 11) < 4)) {
9891				raw[1] = 0x84;
9892			} else
9893				raw[1] = 0x04;
9894		} else
9895			raw[1] = 0x04;
9896		plcp->o.data |= htole32(plen << 16);
9897		raw[0] = bwn_plcp_getcck(rate);
9898	}
9899}
9900
9901static uint8_t
9902bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9903{
9904	uint8_t mask;
9905
9906	if (n == 0)
9907		return (0);
9908	if (mac->mac_phy.gmode)
9909		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9910	else
9911		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9912	if (!(mask & (1 << (n - 1))))
9913		return (0);
9914	return (n);
9915}
9916
9917static uint8_t
9918bwn_get_fbrate(uint8_t bitrate)
9919{
9920	switch (bitrate) {
9921	case BWN_CCK_RATE_1MB:
9922		return (BWN_CCK_RATE_1MB);
9923	case BWN_CCK_RATE_2MB:
9924		return (BWN_CCK_RATE_1MB);
9925	case BWN_CCK_RATE_5MB:
9926		return (BWN_CCK_RATE_2MB);
9927	case BWN_CCK_RATE_11MB:
9928		return (BWN_CCK_RATE_5MB);
9929	case BWN_OFDM_RATE_6MB:
9930		return (BWN_CCK_RATE_5MB);
9931	case BWN_OFDM_RATE_9MB:
9932		return (BWN_OFDM_RATE_6MB);
9933	case BWN_OFDM_RATE_12MB:
9934		return (BWN_OFDM_RATE_9MB);
9935	case BWN_OFDM_RATE_18MB:
9936		return (BWN_OFDM_RATE_12MB);
9937	case BWN_OFDM_RATE_24MB:
9938		return (BWN_OFDM_RATE_18MB);
9939	case BWN_OFDM_RATE_36MB:
9940		return (BWN_OFDM_RATE_24MB);
9941	case BWN_OFDM_RATE_48MB:
9942		return (BWN_OFDM_RATE_36MB);
9943	case BWN_OFDM_RATE_54MB:
9944		return (BWN_OFDM_RATE_48MB);
9945	}
9946	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9947	return (0);
9948}
9949
9950static uint32_t
9951bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9952    uint32_t ctl, const void *_data, int len)
9953{
9954	uint32_t value = 0;
9955	const uint8_t *data = _data;
9956
9957	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9958	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9959	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9960
9961	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9962	    tq->tq_base + BWN_PIO8_TXDATA);
9963	if (len & 3) {
9964		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9965		    BWN_PIO8_TXCTL_24_31);
9966		data = &(data[len - 1]);
9967		switch (len & 3) {
9968		case 3:
9969			ctl |= BWN_PIO8_TXCTL_16_23;
9970			value |= (uint32_t)(*data) << 16;
9971			data--;
9972		case 2:
9973			ctl |= BWN_PIO8_TXCTL_8_15;
9974			value |= (uint32_t)(*data) << 8;
9975			data--;
9976		case 1:
9977			value |= (uint32_t)(*data);
9978		}
9979		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9980		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9981	}
9982
9983	return (ctl);
9984}
9985
9986static void
9987bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9988    uint16_t offset, uint32_t value)
9989{
9990
9991	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9992}
9993
9994static uint16_t
9995bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9996    uint16_t ctl, const void *_data, int len)
9997{
9998	const uint8_t *data = _data;
9999
10000	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10001	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10002
10003	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10004	    tq->tq_base + BWN_PIO_TXDATA);
10005	if (len & 1) {
10006		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10007		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10008		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10009	}
10010
10011	return (ctl);
10012}
10013
10014static uint16_t
10015bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10016    uint16_t ctl, struct mbuf *m0)
10017{
10018	int i, j = 0;
10019	uint16_t data = 0;
10020	const uint8_t *buf;
10021	struct mbuf *m = m0;
10022
10023	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10024	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10025
10026	for (; m != NULL; m = m->m_next) {
10027		buf = mtod(m, const uint8_t *);
10028		for (i = 0; i < m->m_len; i++) {
10029			if (!((j++) % 2))
10030				data |= buf[i];
10031			else {
10032				data |= (buf[i] << 8);
10033				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10034				data = 0;
10035			}
10036		}
10037	}
10038	if (m0->m_pkthdr.len % 2) {
10039		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10040		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10041		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10042	}
10043
10044	return (ctl);
10045}
10046
10047static void
10048bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10049{
10050
10051	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10052		return;
10053	BWN_WRITE_2(mac, 0x684, 510 + time);
10054	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10055}
10056
10057static struct bwn_dma_ring *
10058bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10059{
10060
10061	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10062		return (mac->mac_method.dma.wme[WME_AC_BE]);
10063
10064	switch (prio) {
10065	case 3:
10066		return (mac->mac_method.dma.wme[WME_AC_VO]);
10067	case 2:
10068		return (mac->mac_method.dma.wme[WME_AC_VI]);
10069	case 0:
10070		return (mac->mac_method.dma.wme[WME_AC_BE]);
10071	case 1:
10072		return (mac->mac_method.dma.wme[WME_AC_BK]);
10073	}
10074	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10075	return (NULL);
10076}
10077
10078static int
10079bwn_dma_getslot(struct bwn_dma_ring *dr)
10080{
10081	int slot;
10082
10083	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10084
10085	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10086	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10087	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10088
10089	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10090	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10091	dr->dr_curslot = slot;
10092	dr->dr_usedslot++;
10093
10094	return (slot);
10095}
10096
10097static int
10098bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10099{
10100	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10101	unsigned int a, b, c, d;
10102	unsigned int avg;
10103	uint32_t tmp;
10104
10105	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10106	a = tmp & 0xff;
10107	b = (tmp >> 8) & 0xff;
10108	c = (tmp >> 16) & 0xff;
10109	d = (tmp >> 24) & 0xff;
10110	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10111	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10112		return (ENOENT);
10113	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10114	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10115	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10116
10117	if (ofdm) {
10118		a = (a + 32) & 0x3f;
10119		b = (b + 32) & 0x3f;
10120		c = (c + 32) & 0x3f;
10121		d = (d + 32) & 0x3f;
10122	}
10123
10124	avg = (a + b + c + d + 2) / 4;
10125	if (ofdm) {
10126		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10127		    & BWN_HF_4DB_CCK_POWERBOOST)
10128			avg = (avg >= 13) ? (avg - 13) : 0;
10129	}
10130	return (avg);
10131}
10132
10133static void
10134bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10135{
10136	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10137	int rfatt = *rfattp;
10138	int bbatt = *bbattp;
10139
10140	while (1) {
10141		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10142			break;
10143		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10144			break;
10145		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10146			break;
10147		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10148			break;
10149		if (bbatt > lo->bbatt.max) {
10150			bbatt -= 4;
10151			rfatt += 1;
10152			continue;
10153		}
10154		if (bbatt < lo->bbatt.min) {
10155			bbatt += 4;
10156			rfatt -= 1;
10157			continue;
10158		}
10159		if (rfatt > lo->rfatt.max) {
10160			rfatt -= 1;
10161			bbatt += 4;
10162			continue;
10163		}
10164		if (rfatt < lo->rfatt.min) {
10165			rfatt += 1;
10166			bbatt -= 4;
10167			continue;
10168		}
10169		break;
10170	}
10171
10172	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10173	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10174}
10175
10176static void
10177bwn_phy_lock(struct bwn_mac *mac)
10178{
10179	struct bwn_softc *sc = mac->mac_sc;
10180	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10181
10182	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10183	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10184
10185	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10186		bwn_psctl(mac, BWN_PS_AWAKE);
10187}
10188
10189static void
10190bwn_phy_unlock(struct bwn_mac *mac)
10191{
10192	struct bwn_softc *sc = mac->mac_sc;
10193	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10194
10195	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10196	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10197
10198	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10199		bwn_psctl(mac, 0);
10200}
10201
10202static void
10203bwn_rf_lock(struct bwn_mac *mac)
10204{
10205
10206	BWN_WRITE_4(mac, BWN_MACCTL,
10207	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10208	BWN_READ_4(mac, BWN_MACCTL);
10209	DELAY(10);
10210}
10211
10212static void
10213bwn_rf_unlock(struct bwn_mac *mac)
10214{
10215
10216	BWN_READ_2(mac, BWN_PHYVER);
10217	BWN_WRITE_4(mac, BWN_MACCTL,
10218	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10219}
10220
10221static struct bwn_pio_txqueue *
10222bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10223    struct bwn_pio_txpkt **pack)
10224{
10225	struct bwn_pio *pio = &mac->mac_method.pio;
10226	struct bwn_pio_txqueue *tq = NULL;
10227	unsigned int index;
10228
10229	switch (cookie & 0xf000) {
10230	case 0x1000:
10231		tq = &pio->wme[WME_AC_BK];
10232		break;
10233	case 0x2000:
10234		tq = &pio->wme[WME_AC_BE];
10235		break;
10236	case 0x3000:
10237		tq = &pio->wme[WME_AC_VI];
10238		break;
10239	case 0x4000:
10240		tq = &pio->wme[WME_AC_VO];
10241		break;
10242	case 0x5000:
10243		tq = &pio->mcast;
10244		break;
10245	}
10246	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10247	if (tq == NULL)
10248		return (NULL);
10249	index = (cookie & 0x0fff);
10250	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10251	if (index >= N(tq->tq_pkts))
10252		return (NULL);
10253	*pack = &tq->tq_pkts[index];
10254	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10255	return (tq);
10256}
10257
10258static void
10259bwn_txpwr(void *arg, int npending)
10260{
10261	struct bwn_mac *mac = arg;
10262	struct bwn_softc *sc = mac->mac_sc;
10263
10264	BWN_LOCK(sc);
10265	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10266	    mac->mac_phy.set_txpwr != NULL)
10267		mac->mac_phy.set_txpwr(mac);
10268	BWN_UNLOCK(sc);
10269}
10270
10271static void
10272bwn_task_15s(struct bwn_mac *mac)
10273{
10274	uint16_t reg;
10275
10276	if (mac->mac_fw.opensource) {
10277		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10278		if (reg) {
10279			bwn_restart(mac, "fw watchdog");
10280			return;
10281		}
10282		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10283	}
10284	if (mac->mac_phy.task_15s)
10285		mac->mac_phy.task_15s(mac);
10286
10287	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10288}
10289
10290static void
10291bwn_task_30s(struct bwn_mac *mac)
10292{
10293
10294	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10295		return;
10296	mac->mac_noise.noi_running = 1;
10297	mac->mac_noise.noi_nsamples = 0;
10298
10299	bwn_noise_gensample(mac);
10300}
10301
10302static void
10303bwn_task_60s(struct bwn_mac *mac)
10304{
10305
10306	if (mac->mac_phy.task_60s)
10307		mac->mac_phy.task_60s(mac);
10308	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10309}
10310
10311static void
10312bwn_tasks(void *arg)
10313{
10314	struct bwn_mac *mac = arg;
10315	struct bwn_softc *sc = mac->mac_sc;
10316
10317	BWN_ASSERT_LOCKED(sc);
10318	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10319		return;
10320
10321	if (mac->mac_task_state % 4 == 0)
10322		bwn_task_60s(mac);
10323	if (mac->mac_task_state % 2 == 0)
10324		bwn_task_30s(mac);
10325	bwn_task_15s(mac);
10326
10327	mac->mac_task_state++;
10328	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10329}
10330
10331static int
10332bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10333{
10334	struct bwn_softc *sc = mac->mac_sc;
10335
10336	KASSERT(a == 0, ("not support APHY\n"));
10337
10338	switch (plcp->o.raw[0] & 0xf) {
10339	case 0xb:
10340		return (BWN_OFDM_RATE_6MB);
10341	case 0xf:
10342		return (BWN_OFDM_RATE_9MB);
10343	case 0xa:
10344		return (BWN_OFDM_RATE_12MB);
10345	case 0xe:
10346		return (BWN_OFDM_RATE_18MB);
10347	case 0x9:
10348		return (BWN_OFDM_RATE_24MB);
10349	case 0xd:
10350		return (BWN_OFDM_RATE_36MB);
10351	case 0x8:
10352		return (BWN_OFDM_RATE_48MB);
10353	case 0xc:
10354		return (BWN_OFDM_RATE_54MB);
10355	}
10356	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10357	    plcp->o.raw[0] & 0xf);
10358	return (-1);
10359}
10360
10361static int
10362bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10363{
10364	struct bwn_softc *sc = mac->mac_sc;
10365
10366	switch (plcp->o.raw[0]) {
10367	case 0x0a:
10368		return (BWN_CCK_RATE_1MB);
10369	case 0x14:
10370		return (BWN_CCK_RATE_2MB);
10371	case 0x37:
10372		return (BWN_CCK_RATE_5MB);
10373	case 0x6e:
10374		return (BWN_CCK_RATE_11MB);
10375	}
10376	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10377	return (-1);
10378}
10379
10380static void
10381bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10382    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10383    int rssi, int noise)
10384{
10385	struct bwn_softc *sc = mac->mac_sc;
10386	const struct ieee80211_frame_min *wh;
10387	uint64_t tsf;
10388	uint16_t low_mactime_now;
10389
10390	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10391		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10392
10393	wh = mtod(m, const struct ieee80211_frame_min *);
10394	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10395		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10396
10397	bwn_tsf_read(mac, &tsf);
10398	low_mactime_now = tsf;
10399	tsf = tsf & ~0xffffULL;
10400	tsf += le16toh(rxhdr->mac_time);
10401	if (low_mactime_now < le16toh(rxhdr->mac_time))
10402		tsf -= 0x10000;
10403
10404	sc->sc_rx_th.wr_tsf = tsf;
10405	sc->sc_rx_th.wr_rate = rate;
10406	sc->sc_rx_th.wr_antsignal = rssi;
10407	sc->sc_rx_th.wr_antnoise = noise;
10408}
10409
10410static void
10411bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10412{
10413	uint32_t low, high;
10414
10415	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10416	    ("%s:%d: fail", __func__, __LINE__));
10417
10418	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10419	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10420	*tsf = high;
10421	*tsf <<= 32;
10422	*tsf |= low;
10423}
10424
10425static int
10426bwn_dma_attach(struct bwn_mac *mac)
10427{
10428	struct bwn_dma *dma = &mac->mac_method.dma;
10429	struct bwn_softc *sc = mac->mac_sc;
10430	struct siba_dev_softc *sd = mac->mac_sd;
10431	struct siba_softc *siba = sd->sd_bus;
10432	bus_addr_t lowaddr = 0;
10433	int error;
10434
10435	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10436		return (0);
10437
10438	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10439
10440	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10441
10442	dma->dmatype = bwn_dma_gettype(mac);
10443	if (dma->dmatype == BWN_DMA_30BIT)
10444		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10445	else if (dma->dmatype == BWN_DMA_32BIT)
10446		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10447	else
10448		lowaddr = BUS_SPACE_MAXADDR;
10449
10450	/*
10451	 * Create top level DMA tag
10452	 */
10453	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10454			       BWN_ALIGN, 0,		/* alignment, bounds */
10455			       lowaddr,			/* lowaddr */
10456			       BUS_SPACE_MAXADDR,	/* highaddr */
10457			       NULL, NULL,		/* filter, filterarg */
10458			       MAXBSIZE,		/* maxsize */
10459			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10460			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10461			       0,			/* flags */
10462			       NULL, NULL,		/* lockfunc, lockarg */
10463			       &dma->parent_dtag);
10464	if (error) {
10465		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10466		return (error);
10467	}
10468
10469	/*
10470	 * Create TX/RX mbuf DMA tag
10471	 */
10472	error = bus_dma_tag_create(dma->parent_dtag,
10473				1,
10474				0,
10475				BUS_SPACE_MAXADDR,
10476				BUS_SPACE_MAXADDR,
10477				NULL, NULL,
10478				MCLBYTES,
10479				1,
10480				BUS_SPACE_MAXSIZE_32BIT,
10481				0,
10482				NULL, NULL,
10483				&dma->rxbuf_dtag);
10484	if (error) {
10485		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10486		goto fail0;
10487	}
10488	error = bus_dma_tag_create(dma->parent_dtag,
10489				1,
10490				0,
10491				BUS_SPACE_MAXADDR,
10492				BUS_SPACE_MAXADDR,
10493				NULL, NULL,
10494				MCLBYTES,
10495				1,
10496				BUS_SPACE_MAXSIZE_32BIT,
10497				0,
10498				NULL, NULL,
10499				&dma->txbuf_dtag);
10500	if (error) {
10501		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10502		goto fail1;
10503	}
10504
10505	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10506	if (!dma->wme[WME_AC_BK])
10507		goto fail2;
10508
10509	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10510	if (!dma->wme[WME_AC_BE])
10511		goto fail3;
10512
10513	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10514	if (!dma->wme[WME_AC_VI])
10515		goto fail4;
10516
10517	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10518	if (!dma->wme[WME_AC_VO])
10519		goto fail5;
10520
10521	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10522	if (!dma->mcast)
10523		goto fail6;
10524	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10525	if (!dma->rx)
10526		goto fail7;
10527
10528	return (error);
10529
10530fail7:	bwn_dma_ringfree(&dma->mcast);
10531fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10532fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10533fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10534fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10535fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10536fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10537fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10538	return (error);
10539}
10540
10541static struct bwn_dma_ring *
10542bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10543    uint16_t cookie, int *slot)
10544{
10545	struct bwn_dma *dma = &mac->mac_method.dma;
10546	struct bwn_dma_ring *dr;
10547	struct bwn_softc *sc = mac->mac_sc;
10548
10549	BWN_ASSERT_LOCKED(mac->mac_sc);
10550
10551	switch (cookie & 0xf000) {
10552	case 0x1000:
10553		dr = dma->wme[WME_AC_BK];
10554		break;
10555	case 0x2000:
10556		dr = dma->wme[WME_AC_BE];
10557		break;
10558	case 0x3000:
10559		dr = dma->wme[WME_AC_VI];
10560		break;
10561	case 0x4000:
10562		dr = dma->wme[WME_AC_VO];
10563		break;
10564	case 0x5000:
10565		dr = dma->mcast;
10566		break;
10567	default:
10568		dr = NULL;
10569		KASSERT(0 == 1,
10570		    ("invalid cookie value %d", cookie & 0xf000));
10571	}
10572	*slot = (cookie & 0x0fff);
10573	if (*slot < 0 || *slot >= dr->dr_numslots) {
10574		/*
10575		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10576		 * that it occurs events which have same H/W sequence numbers.
10577		 * When it's occurred just prints a WARNING msgs and ignores.
10578		 */
10579		KASSERT(status->seq == dma->lastseq,
10580		    ("%s:%d: fail", __func__, __LINE__));
10581		device_printf(sc->sc_dev,
10582		    "out of slot ranges (0 < %d < %d)\n", *slot,
10583		    dr->dr_numslots);
10584		return (NULL);
10585	}
10586	dma->lastseq = status->seq;
10587	return (dr);
10588}
10589
10590static void
10591bwn_dma_stop(struct bwn_mac *mac)
10592{
10593	struct bwn_dma *dma;
10594
10595	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10596		return;
10597	dma = &mac->mac_method.dma;
10598
10599	bwn_dma_ringstop(&dma->rx);
10600	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10601	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10602	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10603	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10604	bwn_dma_ringstop(&dma->mcast);
10605}
10606
10607static void
10608bwn_dma_ringstop(struct bwn_dma_ring **dr)
10609{
10610
10611	if (dr == NULL)
10612		return;
10613
10614	bwn_dma_cleanup(*dr);
10615}
10616
10617static void
10618bwn_pio_stop(struct bwn_mac *mac)
10619{
10620	struct bwn_pio *pio;
10621
10622	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10623		return;
10624	pio = &mac->mac_method.pio;
10625
10626	bwn_destroy_queue_tx(&pio->mcast);
10627	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10628	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10629	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10630	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10631}
10632
10633static void
10634bwn_led_attach(struct bwn_mac *mac)
10635{
10636	struct bwn_softc *sc = mac->mac_sc;
10637	struct siba_softc *siba = mac->mac_sd->sd_bus;
10638	const uint8_t *led_act = NULL;
10639	uint16_t val[BWN_LED_MAX];
10640	int i;
10641
10642	sc->sc_led_idle = (2350 * hz) / 1000;
10643	sc->sc_led_blink = 1;
10644
10645	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10646		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10647			led_act = bwn_vendor_led_act[i].led_act;
10648			break;
10649		}
10650	}
10651	if (led_act == NULL)
10652		led_act = bwn_default_led_act;
10653
10654	val[0] = siba->siba_sprom.gpio0;
10655	val[1] = siba->siba_sprom.gpio1;
10656	val[2] = siba->siba_sprom.gpio2;
10657	val[3] = siba->siba_sprom.gpio3;
10658
10659	for (i = 0; i < BWN_LED_MAX; ++i) {
10660		struct bwn_led *led = &sc->sc_leds[i];
10661
10662		if (val[i] == 0xff) {
10663			led->led_act = led_act[i];
10664		} else {
10665			if (val[i] & BWN_LED_ACT_LOW)
10666				led->led_flags |= BWN_LED_F_ACTLOW;
10667			led->led_act = val[i] & BWN_LED_ACT_MASK;
10668		}
10669		led->led_mask = (1 << i);
10670
10671		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10672		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10673		    led->led_act == BWN_LED_ACT_BLINK) {
10674			led->led_flags |= BWN_LED_F_BLINK;
10675			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10676				led->led_flags |= BWN_LED_F_POLLABLE;
10677			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10678				led->led_flags |= BWN_LED_F_SLOW;
10679
10680			if (sc->sc_blink_led == NULL) {
10681				sc->sc_blink_led = led;
10682				if (led->led_flags & BWN_LED_F_SLOW)
10683					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10684			}
10685		}
10686
10687		DPRINTF(sc, BWN_DEBUG_LED,
10688		    "%dth led, act %d, lowact %d\n", i,
10689		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10690	}
10691	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10692}
10693
10694static __inline uint16_t
10695bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10696{
10697
10698	if (led->led_flags & BWN_LED_F_ACTLOW)
10699		on = !on;
10700	if (on)
10701		val |= led->led_mask;
10702	else
10703		val &= ~led->led_mask;
10704	return val;
10705}
10706
10707static void
10708bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10709{
10710	struct bwn_softc *sc = mac->mac_sc;
10711	struct ifnet *ifp = sc->sc_ifp;
10712	struct ieee80211com *ic = ifp->if_l2com;
10713	uint16_t val;
10714	int i;
10715
10716	if (nstate == IEEE80211_S_INIT) {
10717		callout_stop(&sc->sc_led_blink_ch);
10718		sc->sc_led_blinking = 0;
10719	}
10720
10721	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10722		return;
10723
10724	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10725	for (i = 0; i < BWN_LED_MAX; ++i) {
10726		struct bwn_led *led = &sc->sc_leds[i];
10727		int on;
10728
10729		if (led->led_act == BWN_LED_ACT_UNKN ||
10730		    led->led_act == BWN_LED_ACT_NULL)
10731			continue;
10732
10733		if ((led->led_flags & BWN_LED_F_BLINK) &&
10734		    nstate != IEEE80211_S_INIT)
10735			continue;
10736
10737		switch (led->led_act) {
10738		case BWN_LED_ACT_ON:    /* Always on */
10739			on = 1;
10740			break;
10741		case BWN_LED_ACT_OFF:   /* Always off */
10742		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10743			on = 0;
10744			break;
10745		default:
10746			on = 1;
10747			switch (nstate) {
10748			case IEEE80211_S_INIT:
10749				on = 0;
10750				break;
10751			case IEEE80211_S_RUN:
10752				if (led->led_act == BWN_LED_ACT_11G &&
10753				    ic->ic_curmode != IEEE80211_MODE_11G)
10754					on = 0;
10755				break;
10756			default:
10757				if (led->led_act == BWN_LED_ACT_ASSOC)
10758					on = 0;
10759				break;
10760			}
10761			break;
10762		}
10763
10764		val = bwn_led_onoff(led, val, on);
10765	}
10766	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10767}
10768
10769static void
10770bwn_led_event(struct bwn_mac *mac, int event)
10771{
10772	struct bwn_softc *sc = mac->mac_sc;
10773        struct bwn_led *led = sc->sc_blink_led;
10774        int rate;
10775
10776        if (event == BWN_LED_EVENT_POLL) {
10777                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10778                        return;
10779                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10780                        return;
10781        }
10782
10783        sc->sc_led_ticks = ticks;
10784        if (sc->sc_led_blinking)
10785                return;
10786
10787        switch (event) {
10788        case BWN_LED_EVENT_RX:
10789                rate = sc->sc_rx_rate;
10790                break;
10791        case BWN_LED_EVENT_TX:
10792                rate = sc->sc_tx_rate;
10793                break;
10794        case BWN_LED_EVENT_POLL:
10795                rate = 0;
10796                break;
10797        default:
10798                panic("unknown LED event %d\n", event);
10799                break;
10800        }
10801        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10802            bwn_led_duration[rate].off_dur);
10803}
10804
10805static void
10806bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10807{
10808	struct bwn_softc *sc = mac->mac_sc;
10809        struct bwn_led *led = sc->sc_blink_led;
10810        uint16_t val;
10811
10812        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10813        val = bwn_led_onoff(led, val, 1);
10814        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10815
10816        if (led->led_flags & BWN_LED_F_SLOW) {
10817                BWN_LED_SLOWDOWN(on_dur);
10818                BWN_LED_SLOWDOWN(off_dur);
10819        }
10820
10821        sc->sc_led_blinking = 1;
10822        sc->sc_led_blink_offdur = off_dur;
10823
10824        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10825}
10826
10827static void
10828bwn_led_blink_next(void *arg)
10829{
10830	struct bwn_mac *mac = arg;
10831        struct bwn_softc *sc = mac->mac_sc;
10832        uint16_t val;
10833
10834        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10835        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10836        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10837
10838        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10839            bwn_led_blink_end, mac);
10840}
10841
10842static void
10843bwn_led_blink_end(void *arg)
10844{
10845	struct bwn_mac *mac = arg;
10846        struct bwn_softc *sc = mac->mac_sc;
10847
10848        sc->sc_led_blinking = 0;
10849}
10850
10851static int
10852bwn_suspend(device_t dev)
10853{
10854	struct bwn_softc *sc = device_get_softc(dev);
10855
10856	bwn_stop(sc, 1);
10857	return (0);
10858}
10859
10860static int
10861bwn_resume(device_t dev)
10862{
10863	struct bwn_softc *sc = device_get_softc(dev);
10864	struct ifnet *ifp = sc->sc_ifp;
10865
10866	if (ifp->if_flags & IFF_UP)
10867		bwn_init(sc);
10868	return (0);
10869}
10870
10871static void
10872bwn_rfswitch(void *arg)
10873{
10874	struct bwn_softc *sc = arg;
10875	struct bwn_mac *mac = sc->sc_curmac;
10876	int cur = 0, prev = 0;
10877
10878	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10879	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10880
10881	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10882		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10883			& BWN_RF_HWENABLED_HI_MASK))
10884			cur = 1;
10885	} else {
10886		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10887		    & BWN_RF_HWENABLED_LO_MASK)
10888			cur = 1;
10889	}
10890
10891	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10892		prev = 1;
10893
10894	if (cur != prev) {
10895		if (cur)
10896			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10897		else
10898			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10899
10900		device_printf(sc->sc_dev,
10901		    "status of RF switch is changed to %s\n",
10902		    cur ? "ON" : "OFF");
10903		if (cur != mac->mac_phy.rf_on) {
10904			if (cur)
10905				bwn_rf_turnon(mac);
10906			else
10907				bwn_rf_turnoff(mac);
10908		}
10909	}
10910
10911	callout_schedule(&sc->sc_rfswitch_ch, hz);
10912}
10913
10914static void
10915bwn_phy_lp_init_pre(struct bwn_mac *mac)
10916{
10917	struct bwn_phy *phy = &mac->mac_phy;
10918	struct bwn_phy_lp *plp = &phy->phy_lp;
10919
10920	plp->plp_antenna = BWN_ANT_DEFAULT;
10921}
10922
10923static int
10924bwn_phy_lp_init(struct bwn_mac *mac)
10925{
10926	static const struct bwn_stxtable tables[] = {
10927		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10928		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10929		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10930		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10931		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10932		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10933		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10934		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10935		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10936		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10937		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10938		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10939		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10940		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10941		{ 2, 11, 0x40, 0, 0x0f }
10942	};
10943	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10944	struct bwn_softc *sc = mac->mac_sc;
10945	const struct bwn_stxtable *st;
10946	struct ifnet *ifp = sc->sc_ifp;
10947	struct ieee80211com *ic = ifp->if_l2com;
10948	int i, error;
10949	uint16_t tmp;
10950
10951	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10952	bwn_phy_lp_bbinit(mac);
10953
10954	/* initialize RF */
10955	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10956	DELAY(1);
10957	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10958	DELAY(1);
10959
10960	if (mac->mac_phy.rf_ver == 0x2062)
10961		bwn_phy_lp_b2062_init(mac);
10962	else {
10963		bwn_phy_lp_b2063_init(mac);
10964
10965		/* synchronize stx table. */
10966		for (i = 0; i < N(tables); i++) {
10967			st = &tables[i];
10968			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10969			tmp >>= st->st_rfshift;
10970			tmp <<= st->st_physhift;
10971			BWN_PHY_SETMASK(mac,
10972			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10973			    ~(st->st_mask << st->st_physhift), tmp);
10974		}
10975
10976		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10977		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10978	}
10979
10980	/* calibrate RC */
10981	if (mac->mac_phy.rev >= 2)
10982		bwn_phy_lp_rxcal_r2(mac);
10983	else if (!plp->plp_rccap) {
10984		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10985			bwn_phy_lp_rccal_r12(mac);
10986	} else
10987		bwn_phy_lp_set_rccap(mac);
10988
10989	error = bwn_phy_lp_switch_channel(mac, 7);
10990	if (error)
10991		device_printf(sc->sc_dev,
10992		    "failed to change channel 7 (%d)\n", error);
10993	bwn_phy_lp_txpctl_init(mac);
10994	bwn_phy_lp_calib(mac);
10995	return (0);
10996}
10997
10998static uint16_t
10999bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11000{
11001
11002	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11003	return (BWN_READ_2(mac, BWN_PHYDATA));
11004}
11005
11006static void
11007bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11008{
11009
11010	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11011	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11012}
11013
11014static void
11015bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11016    uint16_t set)
11017{
11018
11019	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11020	BWN_WRITE_2(mac, BWN_PHYDATA,
11021	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11022}
11023
11024static uint16_t
11025bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11026{
11027
11028	KASSERT(reg != 1, ("unaccessible register %d", reg));
11029	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11030		reg |= 0x100;
11031	if (mac->mac_phy.rev >= 2)
11032		reg |= 0x200;
11033	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11034	return BWN_READ_2(mac, BWN_RFDATALO);
11035}
11036
11037static void
11038bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11039{
11040
11041	KASSERT(reg != 1, ("unaccessible register %d", reg));
11042	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11043	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11044}
11045
11046static void
11047bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11048{
11049
11050	if (on) {
11051		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11052		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11053		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11054		return;
11055	}
11056
11057	if (mac->mac_phy.rev >= 2) {
11058		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11059		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11060		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11061		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11062		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11063		return;
11064	}
11065
11066	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11067	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11068	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11069	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11070}
11071
11072static int
11073bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11074{
11075	struct bwn_phy *phy = &mac->mac_phy;
11076	struct bwn_phy_lp *plp = &phy->phy_lp;
11077	int error;
11078
11079	if (phy->rf_ver == 0x2063) {
11080		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11081		if (error)
11082			return (error);
11083	} else {
11084		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11085		if (error)
11086			return (error);
11087		bwn_phy_lp_set_anafilter(mac, chan);
11088		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11089	}
11090
11091	plp->plp_chan = chan;
11092	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11093	return (0);
11094}
11095
11096static uint32_t
11097bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11098{
11099	struct bwn_softc *sc = mac->mac_sc;
11100	struct ifnet *ifp = sc->sc_ifp;
11101	struct ieee80211com *ic = ifp->if_l2com;
11102
11103	device_printf(sc->sc_dev, "correct?\n");
11104
11105	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11106}
11107
11108static void
11109bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11110{
11111	struct bwn_phy *phy = &mac->mac_phy;
11112	struct bwn_phy_lp *plp = &phy->phy_lp;
11113
11114	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11115		return;
11116
11117	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11118	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11119	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11120	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11121	plp->plp_antenna = antenna;
11122}
11123
11124static void
11125bwn_phy_lp_task_60s(struct bwn_mac *mac)
11126{
11127
11128	bwn_phy_lp_calib(mac);
11129}
11130
11131static void
11132bwn_phy_lp_readsprom(struct bwn_mac *mac)
11133{
11134	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11135	struct bwn_softc *sc = mac->mac_sc;
11136	struct ifnet *ifp = sc->sc_ifp;
11137	struct ieee80211com *ic = ifp->if_l2com;
11138	struct siba_dev_softc *sd = mac->mac_sd;
11139	struct siba_softc *siba = sd->sd_bus;
11140	struct siba_sprom *sprom = &siba->siba_sprom;
11141
11142	device_printf(sc->sc_dev, "XXX using %dghz\n",
11143	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11144
11145	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11146		plp->plp_txisoband_m = sprom->tri2g;
11147		plp->plp_bxarch = sprom->bxa2g;
11148		plp->plp_rxpwroffset = sprom->rxpo2g;
11149		plp->plp_rssivf = sprom->rssismf2g;
11150		plp->plp_rssivc = sprom->rssismc2g;
11151		plp->plp_rssigs = sprom->rssisav2g;
11152		return;
11153	}
11154
11155	plp->plp_txisoband_l = sprom->tri5gl;
11156	plp->plp_txisoband_m = sprom->tri5g;
11157	plp->plp_txisoband_h = sprom->tri5gh;
11158	plp->plp_bxarch = sprom->bxa5g;
11159	plp->plp_rxpwroffset = sprom->rxpo5g;
11160	plp->plp_rssivf = sprom->rssismf5g;
11161	plp->plp_rssivc = sprom->rssismc5g;
11162	plp->plp_rssigs = sprom->rssisav5g;
11163}
11164
11165static void
11166bwn_phy_lp_bbinit(struct bwn_mac *mac)
11167{
11168
11169	bwn_phy_lp_tblinit(mac);
11170	if (mac->mac_phy.rev >= 2)
11171		bwn_phy_lp_bbinit_r2(mac);
11172	else
11173		bwn_phy_lp_bbinit_r01(mac);
11174}
11175
11176static void
11177bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11178{
11179	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11180	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11181	struct bwn_softc *sc = mac->mac_sc;
11182	struct ifnet *ifp = sc->sc_ifp;
11183	struct ieee80211com *ic = ifp->if_l2com;
11184
11185	bwn_phy_lp_set_txgain(mac,
11186	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11187	bwn_phy_lp_set_bbmult(mac, 150);
11188}
11189
11190static void
11191bwn_phy_lp_calib(struct bwn_mac *mac)
11192{
11193	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11194	struct siba_dev_softc *sd = mac->mac_sd;
11195	struct siba_softc *siba = sd->sd_bus;
11196	struct bwn_softc *sc = mac->mac_sc;
11197	struct ifnet *ifp = sc->sc_ifp;
11198	struct ieee80211com *ic = ifp->if_l2com;
11199	const struct bwn_rxcompco *rc = NULL;
11200	struct bwn_txgain ogain;
11201	int i, omode, oafeovr, orf, obbmult;
11202	uint8_t mode, fc = 0;
11203
11204	if (plp->plp_chanfullcal != plp->plp_chan) {
11205		plp->plp_chanfullcal = plp->plp_chan;
11206		fc = 1;
11207	}
11208
11209	bwn_mac_suspend(mac);
11210
11211	/* BlueTooth Coexistance Override */
11212	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11213	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11214
11215	if (mac->mac_phy.rev >= 2)
11216		bwn_phy_lp_digflt_save(mac);
11217	bwn_phy_lp_get_txpctlmode(mac);
11218	mode = plp->plp_txpctlmode;
11219	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11220	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11221		bwn_phy_lp_bugfix(mac);
11222	if (mac->mac_phy.rev >= 2 && fc == 1) {
11223		bwn_phy_lp_get_txpctlmode(mac);
11224		omode = plp->plp_txpctlmode;
11225		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11226		if (oafeovr)
11227			ogain = bwn_phy_lp_get_txgain(mac);
11228		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11229		obbmult = bwn_phy_lp_get_bbmult(mac);
11230		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11231		if (oafeovr)
11232			bwn_phy_lp_set_txgain(mac, &ogain);
11233		bwn_phy_lp_set_bbmult(mac, obbmult);
11234		bwn_phy_lp_set_txpctlmode(mac, omode);
11235		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11236	}
11237	bwn_phy_lp_set_txpctlmode(mac, mode);
11238	if (mac->mac_phy.rev >= 2)
11239		bwn_phy_lp_digflt_restore(mac);
11240
11241	/* do RX IQ Calculation; assumes that noise is true. */
11242	if (siba->siba_chipid == 0x5354) {
11243		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11244			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11245				rc = &bwn_rxcompco_5354[i];
11246		}
11247	} else if (mac->mac_phy.rev >= 2)
11248		rc = &bwn_rxcompco_r2;
11249	else {
11250		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11251			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11252				rc = &bwn_rxcompco_r12[i];
11253		}
11254	}
11255	if (rc == NULL)
11256		goto fail;
11257
11258	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11259	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11260
11261	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11262
11263	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11264		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11265		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11266	} else {
11267		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11268		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11269	}
11270
11271	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11272	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11273	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11274	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11275	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11276	bwn_phy_lp_set_deaf(mac, 0);
11277	/* XXX no checking return value? */
11278	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11279	bwn_phy_lp_clear_deaf(mac, 0);
11280	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11281	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11282	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11283
11284	/* disable RX GAIN override. */
11285	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11286	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11287	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11288	if (mac->mac_phy.rev >= 2) {
11289		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11290		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11291			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11292			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11293		}
11294	} else {
11295		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11296	}
11297
11298	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11299	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11300fail:
11301	bwn_mac_enable(mac);
11302}
11303
11304static void
11305bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11306{
11307
11308       if (on) {
11309               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11310	       return;
11311       }
11312
11313       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11314       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11315}
11316
11317static int
11318bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11319{
11320	struct siba_dev_softc *sd = mac->mac_sd;
11321	struct siba_softc *siba = sd->sd_bus;
11322	static const struct bwn_b206x_chan *bc = NULL;
11323	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11324	    tmp[6];
11325	uint16_t old, scale, tmp16;
11326	int i, div;
11327
11328	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11329		if (bwn_b2063_chantable[i].bc_chan == chan) {
11330			bc = &bwn_b2063_chantable[i];
11331			break;
11332		}
11333	}
11334	if (bc == NULL)
11335		return (EINVAL);
11336
11337	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11338	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11339	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11340	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11341	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11342	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11343	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11344	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11345	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11346	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11347	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11348	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11349
11350	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11351	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11352
11353	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11354	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11355	freqref = freqxtal * 3;
11356	div = (freqxtal <= 26000000 ? 1 : 2);
11357	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11358	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11359		999999) / 1000000) + 1;
11360
11361	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11362	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11363	    0xfff8, timeout >> 2);
11364	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11365	    0xff9f,timeout << 5);
11366	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11367
11368	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11369	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11370	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11371
11372	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11373	    (timeoutref + 1)) - 1;
11374	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11375	    0xf0, count >> 8);
11376	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11377
11378	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11379	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11380	while (tmp[1] >= freqref) {
11381		tmp[0]++;
11382		tmp[1] -= freqref;
11383	}
11384	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11385	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11386	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11387	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11388	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11389
11390	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11391	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11392	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11393	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11394
11395	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11396	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11397
11398	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11399		scale = 1;
11400		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11401	} else {
11402		scale = 0;
11403		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11404	}
11405	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11406	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11407
11408	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11409	    (scale + 1);
11410	if (tmp[5] > 150)
11411		tmp[5] = 0;
11412
11413	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11414	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11415
11416	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11417	if (freqxtal > 26000000)
11418		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11419	else
11420		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11421
11422	if (val[0] == 45)
11423		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11424	else
11425		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11426
11427	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11428	DELAY(1);
11429	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11430
11431	/* VCO Calibration */
11432	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11433	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11434	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11435	DELAY(1);
11436	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11437	DELAY(1);
11438	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11439	DELAY(1);
11440	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11441	DELAY(300);
11442	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11443
11444	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11445	return (0);
11446}
11447
11448static int
11449bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11450{
11451	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11452	struct siba_dev_softc *sd = mac->mac_sd;
11453	struct siba_softc *siba = sd->sd_bus;
11454	const struct bwn_b206x_chan *bc = NULL;
11455	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11456	uint32_t tmp[9];
11457	int i;
11458
11459	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11460		if (bwn_b2062_chantable[i].bc_chan == chan) {
11461			bc = &bwn_b2062_chantable[i];
11462			break;
11463		}
11464	}
11465
11466	if (bc == NULL)
11467		return (EINVAL);
11468
11469	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11470	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11471	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11472	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11473	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11474	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11475	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11476	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11477	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11478	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11479
11480	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11481	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11482	bwn_phy_lp_b2062_reset_pllbias(mac);
11483	tmp[0] = freqxtal / 1000;
11484	tmp[1] = plp->plp_div * 1000;
11485	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11486	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11487		tmp[2] *= 2;
11488	tmp[3] = 48 * tmp[0];
11489	tmp[5] = tmp[2] / tmp[3];
11490	tmp[6] = tmp[2] % tmp[3];
11491	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11492	tmp[4] = tmp[6] * 0x100;
11493	tmp[5] = tmp[4] / tmp[3];
11494	tmp[6] = tmp[4] % tmp[3];
11495	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11496	tmp[4] = tmp[6] * 0x100;
11497	tmp[5] = tmp[4] / tmp[3];
11498	tmp[6] = tmp[4] % tmp[3];
11499	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11500	tmp[4] = tmp[6] * 0x100;
11501	tmp[5] = tmp[4] / tmp[3];
11502	tmp[6] = tmp[4] % tmp[3];
11503	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11504	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11505	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11506	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11507	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11508	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11509
11510	bwn_phy_lp_b2062_vco_calib(mac);
11511	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11512		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11513		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11514		bwn_phy_lp_b2062_reset_pllbias(mac);
11515		bwn_phy_lp_b2062_vco_calib(mac);
11516		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11517			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11518			return (EIO);
11519		}
11520	}
11521	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11522	return (0);
11523}
11524
11525static void
11526bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11527{
11528	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11529	uint16_t tmp = (channel == 14);
11530
11531	if (mac->mac_phy.rev < 2) {
11532		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11533		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11534			bwn_phy_lp_set_rccap(mac);
11535		return;
11536	}
11537
11538	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11539}
11540
11541static void
11542bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11543{
11544	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11545	struct bwn_softc *sc = mac->mac_sc;
11546	struct ifnet *ifp = sc->sc_ifp;
11547	struct ieee80211com *ic = ifp->if_l2com;
11548	uint16_t iso, tmp[3];
11549
11550	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11551
11552	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11553		iso = plp->plp_txisoband_m;
11554	else if (freq <= 5320)
11555		iso = plp->plp_txisoband_l;
11556	else if (freq <= 5700)
11557		iso = plp->plp_txisoband_m;
11558	else
11559		iso = plp->plp_txisoband_h;
11560
11561	tmp[0] = ((iso - 26) / 12) << 12;
11562	tmp[1] = tmp[0] + 0x1000;
11563	tmp[2] = tmp[0] + 0x2000;
11564
11565	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11566	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11567}
11568
11569static void
11570bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11571{
11572	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11573	int i;
11574	static const uint16_t addr[] = {
11575		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11576		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11577		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11578		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11579		BWN_PHY_OFDM(0xcf),
11580	};
11581	static const uint16_t val[] = {
11582		0xde5e, 0xe832, 0xe331, 0x4d26,
11583		0x0026, 0x1420, 0x0020, 0xfe08,
11584		0x0008,
11585	};
11586
11587	for (i = 0; i < N(addr); i++) {
11588		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11589		BWN_PHY_WRITE(mac, addr[i], val[i]);
11590	}
11591}
11592
11593static void
11594bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11595{
11596	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11597	struct bwn_softc *sc = mac->mac_sc;
11598	uint16_t ctl;
11599
11600	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11601	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11602	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11603		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11604		break;
11605	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11606		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11607		break;
11608	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11609		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11610		break;
11611	default:
11612		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11613		device_printf(sc->sc_dev, "unknown command mode\n");
11614		break;
11615	}
11616}
11617
11618static void
11619bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11620{
11621	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11622	uint16_t ctl;
11623	uint8_t old;
11624
11625	bwn_phy_lp_get_txpctlmode(mac);
11626	old = plp->plp_txpctlmode;
11627	if (old == mode)
11628		return;
11629	plp->plp_txpctlmode = mode;
11630
11631	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11632		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11633		    plp->plp_tssiidx);
11634		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11635		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11636
11637		/* disable TX GAIN override */
11638		if (mac->mac_phy.rev < 2)
11639			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11640		else {
11641			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11642			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11643		}
11644		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11645
11646		plp->plp_txpwridx = -1;
11647	}
11648	if (mac->mac_phy.rev >= 2) {
11649		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11650			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11651		else
11652			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11653	}
11654
11655	/* writes TX Power Control mode */
11656	switch (plp->plp_txpctlmode) {
11657	case BWN_PHYLP_TXPCTL_OFF:
11658		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11659		break;
11660	case BWN_PHYLP_TXPCTL_ON_HW:
11661		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11662		break;
11663	case BWN_PHYLP_TXPCTL_ON_SW:
11664		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11665		break;
11666	default:
11667		ctl = 0;
11668		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11669	}
11670	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11671	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11672}
11673
11674static void
11675bwn_phy_lp_bugfix(struct bwn_mac *mac)
11676{
11677	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11678	struct bwn_softc *sc = mac->mac_sc;
11679	const unsigned int size = 256;
11680	struct bwn_txgain tg;
11681	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11682	uint16_t tssinpt, tssiidx, value[2];
11683	uint8_t mode;
11684	int8_t txpwridx;
11685
11686	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11687	    M_NOWAIT | M_ZERO);
11688	if (tabs == NULL) {
11689		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11690		return;
11691	}
11692
11693	bwn_phy_lp_get_txpctlmode(mac);
11694	mode = plp->plp_txpctlmode;
11695	txpwridx = plp->plp_txpwridx;
11696	tssinpt = plp->plp_tssinpt;
11697	tssiidx = plp->plp_tssiidx;
11698
11699	bwn_tab_read_multi(mac,
11700	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11701	    BWN_TAB_4(7, 0x140), size, tabs);
11702
11703	bwn_phy_lp_tblinit(mac);
11704	bwn_phy_lp_bbinit(mac);
11705	bwn_phy_lp_txpctl_init(mac);
11706	bwn_phy_lp_rf_onoff(mac, 1);
11707	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11708
11709	bwn_tab_write_multi(mac,
11710	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11711	    BWN_TAB_4(7, 0x140), size, tabs);
11712
11713	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11714	plp->plp_tssinpt = tssinpt;
11715	plp->plp_tssiidx = tssiidx;
11716	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11717	if (txpwridx != -1) {
11718		/* set TX power by index */
11719		plp->plp_txpwridx = txpwridx;
11720		bwn_phy_lp_get_txpctlmode(mac);
11721		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11722			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11723		if (mac->mac_phy.rev >= 2) {
11724			rxcomp = bwn_tab_read(mac,
11725			    BWN_TAB_4(7, txpwridx + 320));
11726			txgain = bwn_tab_read(mac,
11727			    BWN_TAB_4(7, txpwridx + 192));
11728			tg.tg_pad = (txgain >> 16) & 0xff;
11729			tg.tg_gm = txgain & 0xff;
11730			tg.tg_pga = (txgain >> 8) & 0xff;
11731			tg.tg_dac = (rxcomp >> 28) & 0xff;
11732			bwn_phy_lp_set_txgain(mac, &tg);
11733		} else {
11734			rxcomp = bwn_tab_read(mac,
11735			    BWN_TAB_4(10, txpwridx + 320));
11736			txgain = bwn_tab_read(mac,
11737			    BWN_TAB_4(10, txpwridx + 192));
11738			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11739			    0xf800, (txgain >> 4) & 0x7fff);
11740			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11741			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11742		}
11743		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11744
11745		/* set TX IQCC */
11746		value[0] = (rxcomp >> 10) & 0x3ff;
11747		value[1] = rxcomp & 0x3ff;
11748		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11749
11750		coeff = bwn_tab_read(mac,
11751		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11752		    BWN_TAB_4(10, txpwridx + 448));
11753		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11754		if (mac->mac_phy.rev >= 2) {
11755			rfpwr = bwn_tab_read(mac,
11756			    BWN_TAB_4(7, txpwridx + 576));
11757			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11758			    rfpwr & 0xffff);
11759		}
11760		bwn_phy_lp_set_txgain_override(mac);
11761	}
11762	if (plp->plp_rccap)
11763		bwn_phy_lp_set_rccap(mac);
11764	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11765	bwn_phy_lp_set_txpctlmode(mac, mode);
11766	free(tabs, M_DEVBUF);
11767}
11768
11769static void
11770bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11771{
11772	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11773	int i;
11774	static const uint16_t addr[] = {
11775		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11776		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11777		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11778		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11779		BWN_PHY_OFDM(0xcf),
11780	};
11781
11782	for (i = 0; i < N(addr); i++)
11783		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11784}
11785
11786static void
11787bwn_phy_lp_tblinit(struct bwn_mac *mac)
11788{
11789	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11790
11791	if (mac->mac_phy.rev < 2) {
11792		bwn_phy_lp_tblinit_r01(mac);
11793		bwn_phy_lp_tblinit_txgain(mac);
11794		bwn_phy_lp_set_gaintbl(mac, freq);
11795		return;
11796	}
11797
11798	bwn_phy_lp_tblinit_r2(mac);
11799	bwn_phy_lp_tblinit_txgain(mac);
11800}
11801
11802struct bwn_wpair {
11803	uint16_t		reg;
11804	uint16_t		value;
11805};
11806
11807struct bwn_smpair {
11808	uint16_t		offset;
11809	uint16_t		mask;
11810	uint16_t		set;
11811};
11812
11813static void
11814bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11815{
11816	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11817	struct siba_dev_softc *sd = mac->mac_sd;
11818	struct siba_softc *siba = sd->sd_bus;
11819	struct bwn_softc *sc = mac->mac_sc;
11820	struct ifnet *ifp = sc->sc_ifp;
11821	struct ieee80211com *ic = ifp->if_l2com;
11822	static const struct bwn_wpair v1[] = {
11823		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11824		{ BWN_PHY_AFE_CTL, 0x8800 },
11825		{ BWN_PHY_AFE_CTL_OVR, 0 },
11826		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11827		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11828		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11829		{ BWN_PHY_OFDM(0xf9), 0 },
11830		{ BWN_PHY_TR_LOOKUP_1, 0 }
11831	};
11832	static const struct bwn_smpair v2[] = {
11833		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11834		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11835		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11836		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11837		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11838	};
11839	static const struct bwn_smpair v3[] = {
11840		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11841		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11842		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11843		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11844		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11845		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11846		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11847		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11848		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11849		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11850
11851	};
11852	int i;
11853
11854	for (i = 0; i < N(v1); i++)
11855		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11856	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11857	for (i = 0; i < N(v2); i++)
11858		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11859
11860	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11861	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11862	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11863	if (siba->siba_board_rev >= 0x18) {
11864		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11865		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11866	} else {
11867		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11868	}
11869	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11870	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11871	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11872	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11873	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11874	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11875	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11876	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11878	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11879	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11880	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11881		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11882		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11883	} else {
11884		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11885		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11886	}
11887	for (i = 0; i < N(v3); i++)
11888		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11889	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11890		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11891		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11892	}
11893
11894	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11895		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11896		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11897		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11898		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11899		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11900		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11901	} else
11902		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11903
11904	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11905	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11906	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11907	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11908	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11909	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11910	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11911	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11912	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11913
11914	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11915		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11916		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11917		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11918	}
11919
11920	bwn_phy_lp_digflt_save(mac);
11921}
11922
11923static void
11924bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11925{
11926	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11927	struct siba_dev_softc *sd = mac->mac_sd;
11928	struct siba_softc *siba = sd->sd_bus;
11929	struct bwn_softc *sc = mac->mac_sc;
11930	struct ifnet *ifp = sc->sc_ifp;
11931	struct ieee80211com *ic = ifp->if_l2com;
11932	static const struct bwn_smpair v1[] = {
11933		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11934		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11935		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11936		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11937		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11938		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11939		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11940	};
11941	static const struct bwn_smpair v2[] = {
11942		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11943		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11944		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11945		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11946		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11947		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11948		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11949		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11950		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11951		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11952		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11953		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11954		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11955		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11956		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11957		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11958	};
11959	static const struct bwn_smpair v3[] = {
11960		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11961		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11962		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11963		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11964		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11965		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11966		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11967		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11968	};
11969	static const struct bwn_smpair v4[] = {
11970		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11971		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11972		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11973		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11974		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11975		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11976		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11977		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11978	};
11979	static const struct bwn_smpair v5[] = {
11980		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11981		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11982		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11983		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11984		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11985		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11986		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11987		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11988	};
11989	int i;
11990	uint16_t tmp, tmp2;
11991
11992	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11993	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11994	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11995	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11996	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11997	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11998	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11999	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12000	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12001	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12002	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12003	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12004	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12005	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12006	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12007	for (i = 0; i < N(v1); i++)
12008		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12009	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12010	    0xff00, plp->plp_rxpwroffset);
12011	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12012	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12013	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12014		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12015		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12016		if (mac->mac_phy.rev == 0)
12017			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12018			    0xffcf, 0x0010);
12019		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12020	} else {
12021		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12022		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12023		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12024	}
12025	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12026	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12027	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12028		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12029	else
12030		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12031	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12032	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12033	    0xfff9, (plp->plp_bxarch << 1));
12034	if (mac->mac_phy.rev == 1 &&
12035	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12036		for (i = 0; i < N(v2); i++)
12037			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12038			    v2[i].set);
12039	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12040	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12041	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12042		for (i = 0; i < N(v3); i++)
12043			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12044			    v3[i].set);
12045	} else if (mac->mac_phy.rev == 1 ||
12046		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12047		for (i = 0; i < N(v4); i++)
12048			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12049			    v4[i].set);
12050	} else {
12051		for (i = 0; i < N(v5); i++)
12052			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12053			    v5[i].set);
12054	}
12055	if (mac->mac_phy.rev == 1 &&
12056	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12057		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12058		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12059		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12060		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12061	}
12062	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12063	    (siba->siba_chipid == 0x5354) &&
12064	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12065		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12066		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12067		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12068		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12069	}
12070	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12071		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12072		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12073		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12074		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12075		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12076		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12077		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12078		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12079	} else {
12080		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12081		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12082	}
12083	if (mac->mac_phy.rev == 1) {
12084		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12085		tmp2 = (tmp & 0x03e0) >> 5;
12086		tmp2 |= tmp2 << 5;
12087		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12088		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12089		tmp2 = (tmp & 0x1f00) >> 8;
12090		tmp2 |= tmp2 << 5;
12091		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12092		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12093		tmp2 = tmp & 0x00ff;
12094		tmp2 |= tmp << 8;
12095		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12096	}
12097}
12098
12099struct bwn_b2062_freq {
12100	uint16_t		freq;
12101	uint8_t			value[6];
12102};
12103
12104static void
12105bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12106{
12107#define	CALC_CTL7(freq, div)						\
12108	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12109#define	CALC_CTL18(freq, div)						\
12110	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12111#define	CALC_CTL19(freq, div)						\
12112	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12113	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12114	struct siba_dev_softc *sd = mac->mac_sd;
12115	struct siba_softc *siba = sd->sd_bus;
12116	struct bwn_softc *sc = mac->mac_sc;
12117	struct ifnet *ifp = sc->sc_ifp;
12118	struct ieee80211com *ic = ifp->if_l2com;
12119	static const struct bwn_b2062_freq freqdata_tab[] = {
12120		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12121		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12122		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12123		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12124		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12125		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12126	};
12127	static const struct bwn_wpair v1[] = {
12128		{ BWN_B2062_N_TXCTL3, 0 },
12129		{ BWN_B2062_N_TXCTL4, 0 },
12130		{ BWN_B2062_N_TXCTL5, 0 },
12131		{ BWN_B2062_N_TXCTL6, 0 },
12132		{ BWN_B2062_N_PDNCTL0, 0x40 },
12133		{ BWN_B2062_N_PDNCTL0, 0 },
12134		{ BWN_B2062_N_CALIB_TS, 0x10 },
12135		{ BWN_B2062_N_CALIB_TS, 0 }
12136	};
12137	const struct bwn_b2062_freq *f = NULL;
12138	uint32_t xtalfreq, ref;
12139	unsigned int i;
12140
12141	bwn_phy_lp_b2062_tblinit(mac);
12142
12143	for (i = 0; i < N(v1); i++)
12144		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12145	if (mac->mac_phy.rev > 0)
12146		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12147		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12148	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12149		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12150	else
12151		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12152
12153	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12154	    ("%s:%d: fail", __func__, __LINE__));
12155	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12156	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12157
12158	if (xtalfreq <= 30000000) {
12159		plp->plp_div = 1;
12160		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12161	} else {
12162		plp->plp_div = 2;
12163		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12164	}
12165
12166	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12167	    CALC_CTL7(xtalfreq, plp->plp_div));
12168	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12169	    CALC_CTL18(xtalfreq, plp->plp_div));
12170	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12171	    CALC_CTL19(xtalfreq, plp->plp_div));
12172
12173	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12174	ref &= 0xffff;
12175	for (i = 0; i < N(freqdata_tab); i++) {
12176		if (ref < freqdata_tab[i].freq) {
12177			f = &freqdata_tab[i];
12178			break;
12179		}
12180	}
12181	if (f == NULL)
12182		f = &freqdata_tab[N(freqdata_tab) - 1];
12183	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12184	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12185	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12186	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12187	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12188	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12189#undef CALC_CTL7
12190#undef CALC_CTL18
12191#undef CALC_CTL19
12192}
12193
12194static void
12195bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12196{
12197
12198	bwn_phy_lp_b2063_tblinit(mac);
12199	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12200	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12201	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12202	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12203	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12204	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12205	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12206	if (mac->mac_phy.rev == 2) {
12207		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12208		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12209		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12210	} else {
12211		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12212		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12213	}
12214}
12215
12216static void
12217bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12218{
12219	struct siba_dev_softc *sd = mac->mac_sd;
12220	struct siba_softc *siba = sd->sd_bus;
12221	static const struct bwn_wpair v1[] = {
12222		{ BWN_B2063_RX_BB_SP8, 0x0 },
12223		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12224		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12225		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12226		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12227		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12228		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12229		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12230	};
12231	static const struct bwn_wpair v2[] = {
12232		{ BWN_B2063_TX_BB_SP3, 0x0 },
12233		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12234		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12235		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12236		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12237	};
12238	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12239	int i;
12240	uint8_t tmp;
12241
12242	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12243
12244	for (i = 0; i < 2; i++)
12245		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12246	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12247	for (i = 2; i < N(v1); i++)
12248		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12249	for (i = 0; i < 10000; i++) {
12250		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12251			break;
12252		DELAY(1000);
12253	}
12254
12255	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12256		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12257
12258	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12259
12260	for (i = 0; i < N(v2); i++)
12261		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12262	if (freqxtal == 24000000) {
12263		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12264		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12265	} else {
12266		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12267		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12268	}
12269	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12270	for (i = 0; i < 10000; i++) {
12271		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12272			break;
12273		DELAY(1000);
12274	}
12275	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12276		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12277	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12278}
12279
12280static void
12281bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12282{
12283	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12284	struct bwn_softc *sc = mac->mac_sc;
12285	struct bwn_phy_lp_iq_est ie;
12286	struct bwn_txgain tx_gains;
12287	static const uint32_t pwrtbl[21] = {
12288		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12289		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12290		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12291		0x0004c, 0x0002c, 0x0001a,
12292	};
12293	uint32_t npwr, ipwr, sqpwr, tmp;
12294	int loopback, i, j, sum, error;
12295	uint16_t save[7];
12296	uint8_t txo, bbmult, txpctlmode;
12297
12298	error = bwn_phy_lp_switch_channel(mac, 7);
12299	if (error)
12300		device_printf(sc->sc_dev,
12301		    "failed to change channel to 7 (%d)\n", error);
12302	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12303	bbmult = bwn_phy_lp_get_bbmult(mac);
12304	if (txo)
12305		tx_gains = bwn_phy_lp_get_txgain(mac);
12306
12307	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12308	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12309	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12310	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12311	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12312	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12313	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12314
12315	bwn_phy_lp_get_txpctlmode(mac);
12316	txpctlmode = plp->plp_txpctlmode;
12317	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12318
12319	/* disable CRS */
12320	bwn_phy_lp_set_deaf(mac, 1);
12321	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12322	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12323	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12324	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12325	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12326	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12327	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12328	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12329	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12330	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12331	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12332	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12333	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12335	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12336	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12337	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12338	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12339	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12340	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12341	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12342	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12343	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12344	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12345
12346	loopback = bwn_phy_lp_loopback(mac);
12347	if (loopback == -1)
12348		goto done;
12349	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12350	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12351	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12352	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12353	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12354
12355	tmp = 0;
12356	memset(&ie, 0, sizeof(ie));
12357	for (i = 128; i <= 159; i++) {
12358		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12359		sum = 0;
12360		for (j = 5; j <= 25; j++) {
12361			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12362			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12363				goto done;
12364			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12365			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12366			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12367			    12);
12368			sum += ((ipwr - npwr) * (ipwr - npwr));
12369			if ((i == 128) || (sum < tmp)) {
12370				plp->plp_rccap = i;
12371				tmp = sum;
12372			}
12373		}
12374	}
12375	bwn_phy_lp_ddfs_turnoff(mac);
12376done:
12377	/* restore CRS */
12378	bwn_phy_lp_clear_deaf(mac, 1);
12379	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12380	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12381
12382	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12383	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12384	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12385	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12386	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12387	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12388	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12389
12390	bwn_phy_lp_set_bbmult(mac, bbmult);
12391	if (txo)
12392		bwn_phy_lp_set_txgain(mac, &tx_gains);
12393	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12394	if (plp->plp_rccap)
12395		bwn_phy_lp_set_rccap(mac);
12396}
12397
12398static void
12399bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12400{
12401	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12402	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12403
12404	if (mac->mac_phy.rev == 1)
12405		rc_cap = MIN(rc_cap + 5, 15);
12406
12407	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12408	    MAX(plp->plp_rccap - 4, 0x80));
12409	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12410	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12411	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12412}
12413
12414static uint32_t
12415bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12416{
12417	uint32_t i, q, r;
12418
12419	if (div == 0)
12420		return (0);
12421
12422	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12423		q <<= 1;
12424		if (r << 1 >= div) {
12425			q++;
12426			r = (r << 1) - div;
12427		}
12428	}
12429	if (r << 1 >= div)
12430		q++;
12431	return (q);
12432}
12433
12434static void
12435bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12436{
12437	struct siba_dev_softc *sd = mac->mac_sd;
12438	struct siba_softc *siba = sd->sd_bus;
12439
12440	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12441	DELAY(20);
12442	if (siba->siba_chipid == 0x5354) {
12443		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12444		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12445	} else {
12446		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12447	}
12448	DELAY(5);
12449}
12450
12451static void
12452bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12453{
12454
12455	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12456	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12457	DELAY(200);
12458}
12459
12460static void
12461bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12462{
12463#define	FLAG_A	0x01
12464#define	FLAG_G	0x02
12465	struct bwn_softc *sc = mac->mac_sc;
12466	struct ifnet *ifp = sc->sc_ifp;
12467	struct ieee80211com *ic = ifp->if_l2com;
12468	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12469		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12470		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12471		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12472		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12473		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12474		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12475		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12476		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12478		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12479		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12480		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12481		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12516	};
12517	const struct bwn_b206x_rfinit_entry *br;
12518	unsigned int i;
12519
12520	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12521		br = &bwn_b2062_init_tab[i];
12522		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12523			if (br->br_flags & FLAG_G)
12524				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12525		} else {
12526			if (br->br_flags & FLAG_A)
12527				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12528		}
12529	}
12530#undef FLAG_A
12531#undef FLAG_B
12532}
12533
12534static void
12535bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12536{
12537#define	FLAG_A	0x01
12538#define	FLAG_G	0x02
12539	struct bwn_softc *sc = mac->mac_sc;
12540	struct ifnet *ifp = sc->sc_ifp;
12541	struct ieee80211com *ic = ifp->if_l2com;
12542	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12543		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12544		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12545		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12546		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12547		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12548		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12549		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12550		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12552		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12553		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12554		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12555		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12556		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12557		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12558		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12559		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12560		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12561		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12562		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12563		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12564		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12565		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12566		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12570		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12571		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12576		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12583		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12584		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12585	};
12586	const struct bwn_b206x_rfinit_entry *br;
12587	unsigned int i;
12588
12589	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12590		br = &bwn_b2063_init_tab[i];
12591		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12592			if (br->br_flags & FLAG_G)
12593				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12594		} else {
12595			if (br->br_flags & FLAG_A)
12596				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12597		}
12598	}
12599#undef FLAG_A
12600#undef FLAG_B
12601}
12602
12603static void
12604bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12605    int count, void *_data)
12606{
12607	unsigned int i;
12608	uint32_t offset, type;
12609	uint8_t *data = _data;
12610
12611	type = BWN_TAB_GETTYPE(typenoffset);
12612	offset = BWN_TAB_GETOFFSET(typenoffset);
12613	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12614
12615	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12616
12617	for (i = 0; i < count; i++) {
12618		switch (type) {
12619		case BWN_TAB_8BIT:
12620			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12621			data++;
12622			break;
12623		case BWN_TAB_16BIT:
12624			*((uint16_t *)data) = BWN_PHY_READ(mac,
12625			    BWN_PHY_TABLEDATALO);
12626			data += 2;
12627			break;
12628		case BWN_TAB_32BIT:
12629			*((uint32_t *)data) = BWN_PHY_READ(mac,
12630			    BWN_PHY_TABLEDATAHI);
12631			*((uint32_t *)data) <<= 16;
12632			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12633			    BWN_PHY_TABLEDATALO);
12634			data += 4;
12635			break;
12636		default:
12637			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12638		}
12639	}
12640}
12641
12642static void
12643bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12644    int count, const void *_data)
12645{
12646	uint32_t offset, type, value;
12647	const uint8_t *data = _data;
12648	unsigned int i;
12649
12650	type = BWN_TAB_GETTYPE(typenoffset);
12651	offset = BWN_TAB_GETOFFSET(typenoffset);
12652	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12653
12654	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12655
12656	for (i = 0; i < count; i++) {
12657		switch (type) {
12658		case BWN_TAB_8BIT:
12659			value = *data;
12660			data++;
12661			KASSERT(!(value & ~0xff),
12662			    ("%s:%d: fail", __func__, __LINE__));
12663			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12664			break;
12665		case BWN_TAB_16BIT:
12666			value = *((const uint16_t *)data);
12667			data += 2;
12668			KASSERT(!(value & ~0xffff),
12669			    ("%s:%d: fail", __func__, __LINE__));
12670			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12671			break;
12672		case BWN_TAB_32BIT:
12673			value = *((const uint32_t *)data);
12674			data += 4;
12675			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12676			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12677			break;
12678		default:
12679			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12680		}
12681	}
12682}
12683
12684static struct bwn_txgain
12685bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12686{
12687	struct bwn_txgain tg;
12688	uint16_t tmp;
12689
12690	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12691	if (mac->mac_phy.rev < 2) {
12692		tmp = BWN_PHY_READ(mac,
12693		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12694		tg.tg_gm = tmp & 0x0007;
12695		tg.tg_pga = (tmp & 0x0078) >> 3;
12696		tg.tg_pad = (tmp & 0x780) >> 7;
12697		return (tg);
12698	}
12699
12700	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12701	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12702	tg.tg_gm = tmp & 0xff;
12703	tg.tg_pga = (tmp >> 8) & 0xff;
12704	return (tg);
12705}
12706
12707static uint8_t
12708bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12709{
12710
12711	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12712}
12713
12714static void
12715bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12716{
12717	uint16_t pa;
12718
12719	if (mac->mac_phy.rev < 2) {
12720		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12721		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12722		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12723		bwn_phy_lp_set_txgain_override(mac);
12724		return;
12725	}
12726
12727	pa = bwn_phy_lp_get_pa_gain(mac);
12728	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12729	    (tg->tg_pga << 8) | tg->tg_gm);
12730	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12731	    tg->tg_pad | (pa << 6));
12732	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12733	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12734	    tg->tg_pad | (pa << 8));
12735	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12736	bwn_phy_lp_set_txgain_override(mac);
12737}
12738
12739static void
12740bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12741{
12742
12743	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12744}
12745
12746static void
12747bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12748{
12749	uint16_t trsw = (tx << 1) | rx;
12750
12751	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12752	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12753}
12754
12755static void
12756bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12757{
12758	struct bwn_softc *sc = mac->mac_sc;
12759	struct ifnet *ifp = sc->sc_ifp;
12760	struct ieee80211com *ic = ifp->if_l2com;
12761	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12762
12763	if (mac->mac_phy.rev < 2) {
12764		trsw = gain & 0x1;
12765		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12766		ext_lna = (gain & 2) >> 1;
12767
12768		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12769		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12770		    0xfbff, ext_lna << 10);
12771		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12772		    0xf7ff, ext_lna << 11);
12773		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12774	} else {
12775		low_gain = gain & 0xffff;
12776		high_gain = (gain >> 16) & 0xf;
12777		ext_lna = (gain >> 21) & 0x1;
12778		trsw = ~(gain >> 20) & 0x1;
12779
12780		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12781		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12782		    0xfdff, ext_lna << 9);
12783		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12784		    0xfbff, ext_lna << 10);
12785		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12786		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12787		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12788			tmp = (gain >> 2) & 0x3;
12789			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12790			    0xe7ff, tmp<<11);
12791			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12792			    tmp << 3);
12793		}
12794	}
12795
12796	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12797	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12798	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12799	if (mac->mac_phy.rev >= 2) {
12800		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12801		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12802			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12803			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12804		}
12805		return;
12806	}
12807	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12808}
12809
12810static void
12811bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12812{
12813	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12814
12815	if (user)
12816		plp->plp_crsusr_off = 1;
12817	else
12818		plp->plp_crssys_off = 1;
12819
12820	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12821}
12822
12823static void
12824bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12825{
12826	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12827	struct bwn_softc *sc = mac->mac_sc;
12828	struct ifnet *ifp = sc->sc_ifp;
12829	struct ieee80211com *ic = ifp->if_l2com;
12830
12831	if (user)
12832		plp->plp_crsusr_off = 0;
12833	else
12834		plp->plp_crssys_off = 0;
12835
12836	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12837		return;
12838
12839	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12840		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12841	else
12842		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12843}
12844
12845static unsigned int
12846bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12847{
12848	struct bwn_softc *sc = mac->mac_sc;
12849	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12850	static uint8_t sqrt_table[256] = {
12851		10, 14, 17, 20, 22, 24, 26, 28,
12852		30, 31, 33, 34, 36, 37, 38, 40,
12853		41, 42, 43, 44, 45, 46, 47, 48,
12854		50, 50, 51, 52, 53, 54, 55, 56,
12855		57, 58, 59, 60, 60, 61, 62, 63,
12856		64, 64, 65, 66, 67, 67, 68, 69,
12857		70, 70, 71, 72, 72, 73, 74, 74,
12858		75, 76, 76, 77, 78, 78, 79, 80,
12859		80, 81, 81, 82, 83, 83, 84, 84,
12860		85, 86, 86, 87, 87, 88, 88, 89,
12861		90, 90, 91, 91, 92, 92, 93, 93,
12862		94, 94, 95, 95, 96, 96, 97, 97,
12863		98, 98, 99, 100, 100, 100, 101, 101,
12864		102, 102, 103, 103, 104, 104, 105, 105,
12865		106, 106, 107, 107, 108, 108, 109, 109,
12866		110, 110, 110, 111, 111, 112, 112, 113,
12867		113, 114, 114, 114, 115, 115, 116, 116,
12868		117, 117, 117, 118, 118, 119, 119, 120,
12869		120, 120, 121, 121, 122, 122, 122, 123,
12870		123, 124, 124, 124, 125, 125, 126, 126,
12871		126, 127, 127, 128, 128, 128, 129, 129,
12872		130, 130, 130, 131, 131, 131, 132, 132,
12873		133, 133, 133, 134, 134, 134, 135, 135,
12874		136, 136, 136, 137, 137, 137, 138, 138,
12875		138, 139, 139, 140, 140, 140, 141, 141,
12876		141, 142, 142, 142, 143, 143, 143, 144,
12877		144, 144, 145, 145, 145, 146, 146, 146,
12878		147, 147, 147, 148, 148, 148, 149, 149,
12879		150, 150, 150, 150, 151, 151, 151, 152,
12880		152, 152, 153, 153, 153, 154, 154, 154,
12881		155, 155, 155, 156, 156, 156, 157, 157,
12882		157, 158, 158, 158, 159, 159, 159, 160
12883	};
12884
12885	if (x == 0)
12886		return (0);
12887	if (x >= 256) {
12888		device_printf(sc->sc_dev,
12889		    "out of bounds of the square-root table (%d)\n", x);
12890		return (16);
12891	}
12892	return (sqrt_table[x - 1] / 10);
12893}
12894
12895static int
12896bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12897{
12898#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12899	int _t;								\
12900	_t = _x - 20;							\
12901	if (_t >= 0) {							\
12902		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12903	} else {							\
12904		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12905	}								\
12906} while (0)
12907#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12908	int _t;								\
12909	_t = _x - 11;							\
12910	if (_t >= 0)							\
12911		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12912	else								\
12913		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12914} while (0)
12915	struct bwn_phy_lp_iq_est ie;
12916	uint16_t v0, v1;
12917	int tmp[2], ret;
12918
12919	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12920	v0 = v1 >> 8;
12921	v1 |= 0xff;
12922
12923	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12924	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12925
12926	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12927	if (ret == 0)
12928		goto done;
12929
12930	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12931		ret = 0;
12932		goto done;
12933	}
12934
12935	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12936	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12937
12938	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12939	v0 = tmp[0] >> 3;
12940	v1 = tmp[1] >> 4;
12941done:
12942	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12943	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12944	return ret;
12945#undef CALC_COEFF
12946#undef CALC_COEFF2
12947}
12948
12949static void
12950bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12951{
12952	static const uint16_t noisescale[] = {
12953		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12954		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12955		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12956		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12957		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12958	};
12959	static const uint16_t crsgainnft[] = {
12960		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12961		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12962		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12963		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12964		0x013d,
12965	};
12966	static const uint16_t filterctl[] = {
12967		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12968		0xff53, 0x0127,
12969	};
12970	static const uint32_t psctl[] = {
12971		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12972		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12973		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12974		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12975		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12976		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12977		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12978		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12979	};
12980	static const uint16_t ofdmcckgain_r0[] = {
12981		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12982		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12983		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12984		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12985		0x755d,
12986	};
12987	static const uint16_t ofdmcckgain_r1[] = {
12988		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12989		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12990		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12991		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12992		0x755d,
12993	};
12994	static const uint16_t gaindelta[] = {
12995		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12996		0x0000,
12997	};
12998	static const uint32_t txpwrctl[] = {
12999		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13000		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13001		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13002		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13003		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13004		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13005		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13006		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13007		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13008		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13009		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13010		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13011		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13012		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13013		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13014		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13015		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13016		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13017		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13018		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13019		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13038		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13039		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13040		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13041		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13042		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13043		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13044		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13045		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13046		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13047		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13048		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13049		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13050		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13051		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13052		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13053		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13054		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13055		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13056		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13057		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13058		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13059		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13060		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13061		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13062		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13063		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13064		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13065		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13066		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13067		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13068		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13069		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13070		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13071		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13072		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13073		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13074		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13075		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13076		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13077		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13078		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13079		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13080		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13081		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13082		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13083		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13084		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13085		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13086		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13087		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13088		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13089		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13090		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13091		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13092		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13093		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13094		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13095		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13096		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13097		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13098		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13099		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13100		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13101		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13102		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13103		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13104		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13105		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13106		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13107		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13108		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13109		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13110		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13111		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13112		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13113		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13114		0x00000702,
13115	};
13116
13117	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13118
13119	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13120	    bwn_tab_sigsq_tbl);
13121	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13122	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13123	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13124	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13125	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13126	    bwn_tab_pllfrac_tbl);
13127	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13128	    bwn_tabl_iqlocal_tbl);
13129	if (mac->mac_phy.rev == 0) {
13130		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13131		    ofdmcckgain_r0);
13132		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13133		    ofdmcckgain_r0);
13134	} else {
13135		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13136		    ofdmcckgain_r1);
13137		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13138		    ofdmcckgain_r1);
13139	}
13140	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13141	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13142}
13143
13144static void
13145bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13146{
13147	struct siba_dev_softc *sd = mac->mac_sd;
13148	struct siba_softc *siba = sd->sd_bus;
13149	int i;
13150	static const uint16_t noisescale[] = {
13151		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13152		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13153		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13154		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13155		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13156		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13157		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13158	};
13159	static const uint32_t filterctl[] = {
13160		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13161		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13162	};
13163	static const uint32_t psctl[] = {
13164		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13165		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13166		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13167		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13168	};
13169	static const uint32_t gainidx[] = {
13170		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13171		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13172		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13173		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13174		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13175		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13176		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13177		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13178		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13179		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13180		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13181		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13182		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13183		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13184		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13185		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13186		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13187		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13188		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13189		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13190		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13191		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13192		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13193		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13194		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13195		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13196		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13197		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13198		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13199		0x0000001a, 0x64ca55ad, 0x0000001a
13200	};
13201	static const uint16_t auxgainidx[] = {
13202		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13203		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13204		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13205		0x0004, 0x0016
13206	};
13207	static const uint16_t swctl[] = {
13208		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13209		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13210		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13211		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13212		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13213		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13214		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13215		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13216	};
13217	static const uint8_t hf[] = {
13218		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13219		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13220	};
13221	static const uint32_t gainval[] = {
13222		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13223		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13224		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13225		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13226		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13227		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13228		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13231		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13232		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13233		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13234		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13235		0x000000f1, 0x00000000, 0x00000000
13236	};
13237	static const uint16_t gain[] = {
13238		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13239		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13240		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13241		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13242		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13243		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13244		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13245		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13246		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13250	};
13251	static const uint32_t papdeps[] = {
13252		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13253		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13254		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13255		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13256		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13257		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13258		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13259		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13260		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13261		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13262		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13263		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13264		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13265	};
13266	static const uint32_t papdmult[] = {
13267		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13268		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13269		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13270		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13271		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13272		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13273		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13274		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13275		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13276		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13277		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13278		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13279		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13280	};
13281	static const uint32_t gainidx_a0[] = {
13282		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13283		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13284		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13285		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13286		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13287		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13288		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13289		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13290		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13291		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13292		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13293		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13294		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13295	};
13296	static const uint16_t auxgainidx_a0[] = {
13297		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13298		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13299		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13300		0x0002, 0x0014
13301	};
13302	static const uint32_t gainval_a0[] = {
13303		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13304		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13305		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13306		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13307		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13308		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13309		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13310		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13311		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13312		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13313		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13314		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13315		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13316		0x000000f7, 0x00000000, 0x00000000
13317	};
13318	static const uint16_t gain_a0[] = {
13319		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13320		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13321		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13322		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13323		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13324		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13325		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13326		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13327		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13328		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13329		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13330		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13331	};
13332
13333	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13334
13335	for (i = 0; i < 704; i++)
13336		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13337
13338	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13339	    bwn_tab_sigsq_tbl);
13340	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13341	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13342	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13343	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13344	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13345	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13346	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13347	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13348	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13349	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13350	    bwn_tab_pllfrac_tbl);
13351	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13352	    bwn_tabl_iqlocal_tbl);
13353	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13354	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13355
13356	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13357		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13358		    gainidx_a0);
13359		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13360		    auxgainidx_a0);
13361		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13362		    gainval_a0);
13363		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13364	}
13365}
13366
13367static void
13368bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13369{
13370	struct siba_dev_softc *sd = mac->mac_sd;
13371	struct siba_softc *siba = sd->sd_bus;
13372	struct bwn_softc *sc = mac->mac_sc;
13373	struct ifnet *ifp = sc->sc_ifp;
13374	struct ieee80211com *ic = ifp->if_l2com;
13375	static struct bwn_txgain_entry txgain_r2[] = {
13376		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13377		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13378		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13379		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13380		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13381		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13382		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13383		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13384		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13385		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13386		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13387		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13388		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13389		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13390		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13391		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13392		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13393		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13394		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13395		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13396		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13397		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13398		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13399		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13400		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13401		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13402		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13403		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13404		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13405		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13406		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13407		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13408		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13409		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13410		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13411		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13412		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13413		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13414		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13415		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13416		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13417		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13418		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13419		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13420		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13421		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13422		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13423		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13424		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13425		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13426		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13427		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13428		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13429		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13430		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13431		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13432		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13433		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13434		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13435		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13436		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13437		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13438		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13439		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13440	};
13441	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13442		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13443		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13444		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13445		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13446		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13447		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13448		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13449		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13450		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13451		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13452		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13453		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13454		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13455		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13456		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13457		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13458		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13459		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13460		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13461		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13462		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13463		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13464		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13465		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13466		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13467		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13468		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13469		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13470		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13471		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13472		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13473		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13474		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13475		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13476		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13477		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13478		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13479		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13480		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13481		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13482		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13483		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13484		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13485		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13486		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13487		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13488		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13489		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13490		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13491		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13492		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13493		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13494		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13495		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13496		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13497		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13498		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13499		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13500		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13501		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13502		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13503		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13504		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13505		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13506	};
13507	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13508		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13509		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13510		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13511		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13512		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13513		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13514		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13515		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13516		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13517		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13518		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13519		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13520		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13521		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13522		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13523		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13524		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13525		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13526		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13527		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13528		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13529		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13530		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13531		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13532		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13533		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13534		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13535		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13536		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13537		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13538		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13539		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13540		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13541		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13542		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13543		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13544		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13545		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13546		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13547		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13548		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13549		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13550		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13551		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13552		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13553		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13554		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13555		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13556		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13557		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13558		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13559		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13560		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13561		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13562		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13563		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13564		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13565		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13566		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13567		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13568		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13569		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13570		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13571		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13572	};
13573	static struct bwn_txgain_entry txgain_r0[] = {
13574		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13575		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13576		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13577		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13578		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13579		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13580		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13581		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13582		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13583		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13584		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13585		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13586		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13587		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13588		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13589		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13590		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13591		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13592		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13593		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13594		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13595		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13596		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13597		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13598		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13599		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13600		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13601		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13602		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13603		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13604		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13605		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13606		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13607		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13608		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13609		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13610		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13611		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13612		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13613		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13614		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13615		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13616		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13617		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13618		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13619		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13620		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13621		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13622		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13623		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13624		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13625		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13626		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13627		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13628		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13629		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13630		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13631		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13632		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13633		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13634		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13635		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13636		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13637		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13638	};
13639	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13640		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13641		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13642		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13643		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13644		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13645		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13646		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13647		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13648		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13649		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13650		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13651		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13652		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13653		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13654		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13655		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13656		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13657		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13658		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13659		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13660		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13661		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13662		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13663		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13664		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13665		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13666		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13667		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13668		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13669		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13670		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13671		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13672		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13673		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13674		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13675		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13676		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13677		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13678		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13679		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13680		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13681		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13682		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13683		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13684		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13685		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13686		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13687		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13688		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13689		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13690		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13691		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13692		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13693		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13694		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13695		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13696		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13697		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13698		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13699		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13700		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13701		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13702		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13703		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13704	};
13705	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13706		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13707		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13708		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13709		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13710		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13711		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13712		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13713		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13714		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13715		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13716		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13717		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13718		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13719		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13720		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13721		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13722		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13723		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13724		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13725		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13726		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13727		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13728		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13729		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13730		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13731		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13732		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13733		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13734		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13735		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13736		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13737		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13738		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13739		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13740		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13741		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13742		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13743		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13744		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13745		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13746		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13747		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13748		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13749		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13750		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13751		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13752		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13753		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13754		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13755		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13756		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13757		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13758		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13759		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13760		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13761		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13762		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13763		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13764		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13765		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13766		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13767		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13768		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13769		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13770	};
13771	static struct bwn_txgain_entry txgain_r1[] = {
13772		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13773		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13774		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13775		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13776		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13777		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13778		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13779		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13780		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13781		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13782		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13783		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13784		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13785		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13786		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13787		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13788		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13789		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13790		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13791		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13792		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13793		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13794		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13795		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13796		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13797		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13798		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13799		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13800		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13801		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13802		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13803		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13804		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13805		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13806		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13807		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13808		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13809		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13810		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13811		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13812		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13813		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13814		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13815		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13816		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13817		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13818		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13819		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13820		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13821		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13822		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13823		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13824		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13825		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13826		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13827		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13828		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13829		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13830		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13831		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13832		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13833		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13834		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13835		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13836		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13837		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13838		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13839		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13840		{ 7, 11, 6, 0, 71 }
13841	};
13842	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13843		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13844		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13845		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13846		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13847		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13848		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13849		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13850		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13851		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13852		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13853		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13854		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13855		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13856		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13857		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13858		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13859		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13860		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13861		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13862		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13863		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13864		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13865		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13866		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13867		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13868		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13869		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13870		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13871		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13872		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13873		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13874		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13875		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13876		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13877		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13878		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13879		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13880		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13881		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13882		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13883		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13884		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13885		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13886		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13887		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13888		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13889		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13890		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13891		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13892		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13893		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13894		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13895		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13896		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13897		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13898		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13899		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13900		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13901		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13902		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13903		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13904		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13905		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13906		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13907	};
13908	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13909		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13910		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13911		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13912		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13913		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13914		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13915		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13916		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13917		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13918		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13919		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13920		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13921		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13922		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13923		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13924		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13925		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13926		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13927		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13928		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13929		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13930		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13931		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13932		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13933		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13934		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13935		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13936		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13937		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13938		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13939		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13940		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13941		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13942		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13943		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13944		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13945		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13946		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13947		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13948		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13949		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13950		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13951		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13952		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13953		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13954		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13955		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13956		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13957		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13958		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13959		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13960		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13961		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13962		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13963		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13964		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13965		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13966		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13967		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13968		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13969		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13970		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13971		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13972		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13973	};
13974
13975	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13976		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13977			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13978		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13979			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13980			    txgain_2ghz_r2);
13981		else
13982			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13983			    txgain_5ghz_r2);
13984		return;
13985	}
13986
13987	if (mac->mac_phy.rev == 0) {
13988		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13989		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13990			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13991		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13992			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13993			    txgain_2ghz_r0);
13994		else
13995			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13996			    txgain_5ghz_r0);
13997		return;
13998	}
13999
14000	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14001	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14002		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14003	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14004		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14005	else
14006		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14007}
14008
14009static void
14010bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14011{
14012	uint32_t offset, type;
14013
14014	type = BWN_TAB_GETTYPE(typeoffset);
14015	offset = BWN_TAB_GETOFFSET(typeoffset);
14016	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14017
14018	switch (type) {
14019	case BWN_TAB_8BIT:
14020		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14021		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14022		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14023		break;
14024	case BWN_TAB_16BIT:
14025		KASSERT(!(value & ~0xffff),
14026		    ("%s:%d: fail", __func__, __LINE__));
14027		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14028		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14029		break;
14030	case BWN_TAB_32BIT:
14031		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14032		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14033		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14034		break;
14035	default:
14036		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14037	}
14038}
14039
14040static int
14041bwn_phy_lp_loopback(struct bwn_mac *mac)
14042{
14043	struct bwn_phy_lp_iq_est ie;
14044	int i, index = -1;
14045	uint32_t tmp;
14046
14047	memset(&ie, 0, sizeof(ie));
14048
14049	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14050	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14051	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14052	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14053	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14054	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14055	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14056	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14057	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14058	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14059	for (i = 0; i < 32; i++) {
14060		bwn_phy_lp_set_rxgain_idx(mac, i);
14061		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14062		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14063			continue;
14064		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14065		if ((tmp > 4000) && (tmp < 10000)) {
14066			index = i;
14067			break;
14068		}
14069	}
14070	bwn_phy_lp_ddfs_turnoff(mac);
14071	return (index);
14072}
14073
14074static void
14075bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14076{
14077
14078	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14079}
14080
14081static void
14082bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14083    int incr1, int incr2, int scale_idx)
14084{
14085
14086	bwn_phy_lp_ddfs_turnoff(mac);
14087	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14088	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14089	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14090	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14091	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14092	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14093	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14094	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14095	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14096	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14097}
14098
14099static uint8_t
14100bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14101    struct bwn_phy_lp_iq_est *ie)
14102{
14103	int i;
14104
14105	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14106	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14107	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14108	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14109	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14110
14111	for (i = 0; i < 500; i++) {
14112		if (!(BWN_PHY_READ(mac,
14113		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14114			break;
14115		DELAY(1000);
14116	}
14117	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14118		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14119		return 0;
14120	}
14121
14122	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14123	ie->ie_iqprod <<= 16;
14124	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14125	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14126	ie->ie_ipwr <<= 16;
14127	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14128	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14129	ie->ie_qpwr <<= 16;
14130	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14131
14132	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14133	return 1;
14134}
14135
14136static uint32_t
14137bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14138{
14139	uint32_t offset, type, value;
14140
14141	type = BWN_TAB_GETTYPE(typeoffset);
14142	offset = BWN_TAB_GETOFFSET(typeoffset);
14143	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14144
14145	switch (type) {
14146	case BWN_TAB_8BIT:
14147		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14148		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14149		break;
14150	case BWN_TAB_16BIT:
14151		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14152		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14153		break;
14154	case BWN_TAB_32BIT:
14155		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14156		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14157		value <<= 16;
14158		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14159		break;
14160	default:
14161		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14162		value = 0;
14163	}
14164
14165	return (value);
14166}
14167
14168static void
14169bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14170{
14171
14172	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14173	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14174}
14175
14176static void
14177bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14178{
14179	uint16_t ctl;
14180
14181	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14182	ctl |= dac << 7;
14183	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14184}
14185
14186static void
14187bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14188{
14189
14190	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14191	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14192}
14193
14194static void
14195bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14196{
14197
14198	if (mac->mac_phy.rev < 2)
14199		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14200	else {
14201		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14202		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14203	}
14204	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14205}
14206
14207static uint16_t
14208bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14209{
14210
14211	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14212}
14213
14214static uint8_t
14215bwn_nbits(int32_t val)
14216{
14217	uint32_t tmp;
14218	uint8_t nbits = 0;
14219
14220	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14221		nbits++;
14222	return (nbits);
14223}
14224
14225static void
14226bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14227    struct bwn_txgain_entry *table)
14228{
14229	int i;
14230
14231	for (i = offset; i < count; i++)
14232		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14233}
14234
14235static void
14236bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14237    struct bwn_txgain_entry data)
14238{
14239
14240	if (mac->mac_phy.rev >= 2)
14241		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14242	else
14243		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14244}
14245
14246static void
14247bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14248    struct bwn_txgain_entry te)
14249{
14250	struct bwn_softc *sc = mac->mac_sc;
14251	struct ifnet *ifp = sc->sc_ifp;
14252	struct ieee80211com *ic = ifp->if_l2com;
14253	uint32_t tmp;
14254
14255	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14256
14257	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14258	if (mac->mac_phy.rev >= 3) {
14259		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14260		    (0x10 << 24) : (0x70 << 24));
14261	} else {
14262		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14263		    (0x14 << 24) : (0x7f << 24));
14264	}
14265	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14266	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14267	    te.te_bbmult << 20 | te.te_dac << 28);
14268}
14269
14270static void
14271bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14272    struct bwn_txgain_entry te)
14273{
14274
14275	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14276
14277	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14278	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14279	    te.te_dac);
14280	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14281}
14282
14283static void
14284bwn_sysctl_node(struct bwn_softc *sc)
14285{
14286	device_t dev = sc->sc_dev;
14287	struct bwn_mac *mac;
14288	struct bwn_stats *stats;
14289
14290	/* XXX assume that count of MAC is only 1. */
14291
14292	if ((mac = sc->sc_curmac) == NULL)
14293		return;
14294	stats = &mac->mac_stats;
14295
14296	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14297	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14298	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14299	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14300	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14301	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14302	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14303	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14304	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14305
14306#ifdef BWN_DEBUG
14307	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14308	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14309	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14310#endif
14311}
14312
14313static void
14314bwn_identify(driver_t *driver, device_t parent)
14315{
14316
14317	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14318}
14319
14320static device_method_t bwn_methods[] = {
14321	/* Device interface */
14322	DEVMETHOD(device_identify,	bwn_identify),
14323	DEVMETHOD(device_probe,		bwn_probe),
14324	DEVMETHOD(device_attach,	bwn_attach),
14325	DEVMETHOD(device_detach,	bwn_detach),
14326	DEVMETHOD(device_suspend,	bwn_suspend),
14327	DEVMETHOD(device_resume,	bwn_resume),
14328	{ 0,0 }
14329};
14330static driver_t bwn_driver = {
14331	"bwn",
14332	bwn_methods,
14333	sizeof(struct bwn_softc)
14334};
14335static devclass_t bwn_devclass;
14336DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14337MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14338MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14339MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14340MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14341