if_bwn.c revision 204385
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 204385 2010-02-27 02:20:38Z 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 (macstat & BWN_RX_MAC_DECERR)
9399		goto drop;
9400
9401	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9402	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9403		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9404		    m->m_pkthdr.len);
9405		goto drop;
9406	}
9407	plcp = (struct bwn_plcp6 *)(mp + padding);
9408	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9409	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9410		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9411		    m->m_pkthdr.len);
9412		goto drop;
9413	}
9414	wh = mtod(m, struct ieee80211_frame_min *);
9415
9416	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9417		device_printf(sc->sc_dev,
9418		    "RX decryption attempted (old %d keyidx %#x)\n",
9419		    BWN_ISOLDFMT(mac),
9420		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9421
9422	/* XXX calculating RSSI & noise & antenna */
9423
9424	if (phystat0 & BWN_RX_PHYST0_OFDM)
9425		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9426		    phytype == BWN_PHYTYPE_A);
9427	else
9428		rate = bwn_plcp_get_cckrate(mac, plcp);
9429	if (rate == -1) {
9430		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9431			goto drop;
9432	}
9433	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9434
9435	/* RX radio tap */
9436	if (ieee80211_radiotap_active(ic))
9437		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9438	m_adj(m, -IEEE80211_CRC_LEN);
9439
9440	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9441	noise = mac->mac_stats.link_noise;
9442
9443	BWN_UNLOCK(sc);
9444
9445	ni = ieee80211_find_rxnode(ic, wh);
9446	if (ni != NULL) {
9447		type = ieee80211_input(ni, m, rssi, noise);
9448		ieee80211_free_node(ni);
9449	} else
9450		type = ieee80211_input_all(ic, m, rssi, noise);
9451
9452	BWN_LOCK(sc);
9453	return;
9454drop:
9455	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9456}
9457
9458static void
9459bwn_dma_handle_txeof(struct bwn_mac *mac,
9460    const struct bwn_txstatus *status)
9461{
9462	struct bwn_dma *dma = &mac->mac_method.dma;
9463	struct bwn_dma_ring *dr;
9464	struct bwn_dmadesc_generic *desc;
9465	struct bwn_dmadesc_meta *meta;
9466	struct bwn_softc *sc = mac->mac_sc;
9467	struct ieee80211_node *ni;
9468	struct ifnet *ifp = sc->sc_ifp;
9469	struct mbuf *m;
9470	int slot;
9471
9472	BWN_ASSERT_LOCKED(sc);
9473
9474	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9475	if (dr == NULL) {
9476		device_printf(sc->sc_dev, "failed to parse cookie\n");
9477		return;
9478	}
9479	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9480
9481	while (1) {
9482		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9483		    ("%s:%d: fail", __func__, __LINE__));
9484		dr->getdesc(dr, slot, &desc, &meta);
9485
9486		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9487			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9488		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9489			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9490
9491		if (meta->mt_islast) {
9492			KASSERT(meta->mt_m != NULL,
9493			    ("%s:%d: fail", __func__, __LINE__));
9494
9495			ni = meta->mt_ni;
9496			m = meta->mt_m;
9497			if (ni != NULL) {
9498				/*
9499				 * Do any tx complete callback. Note this must
9500				 * be done before releasing the node reference.
9501				 */
9502				if (m->m_flags & M_TXCB)
9503					ieee80211_process_callback(ni, m, 0);
9504				ieee80211_free_node(ni);
9505				meta->mt_ni = NULL;
9506			}
9507			m_freem(m);
9508			meta->mt_m = NULL;
9509		} else {
9510			KASSERT(meta->mt_m == NULL,
9511			    ("%s:%d: fail", __func__, __LINE__));
9512		}
9513
9514		dr->dr_usedslot--;
9515		if (meta->mt_islast) {
9516			ifp->if_opackets++;
9517			break;
9518		}
9519		slot = bwn_dma_nextslot(dr, slot);
9520	}
9521	sc->sc_watchdog_timer = 0;
9522	if (dr->dr_stop) {
9523		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9524		    ("%s:%d: fail", __func__, __LINE__));
9525		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9526		dr->dr_stop = 0;
9527	}
9528}
9529
9530static void
9531bwn_pio_handle_txeof(struct bwn_mac *mac,
9532    const struct bwn_txstatus *status)
9533{
9534	struct bwn_pio_txqueue *tq;
9535	struct bwn_pio_txpkt *tp = NULL;
9536	struct bwn_softc *sc = mac->mac_sc;
9537	struct ifnet *ifp = sc->sc_ifp;
9538
9539	BWN_ASSERT_LOCKED(sc);
9540
9541	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9542	if (tq == NULL)
9543		return;
9544
9545	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9546	tq->tq_free++;
9547
9548	if (tp->tp_ni != NULL) {
9549		/*
9550		 * Do any tx complete callback.  Note this must
9551		 * be done before releasing the node reference.
9552		 */
9553		if (tp->tp_m->m_flags & M_TXCB)
9554			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9555		ieee80211_free_node(tp->tp_ni);
9556		tp->tp_ni = NULL;
9557	}
9558	m_freem(tp->tp_m);
9559	tp->tp_m = NULL;
9560	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9561
9562	ifp->if_opackets++;
9563
9564	sc->sc_watchdog_timer = 0;
9565	if (tq->tq_stop) {
9566		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9567		tq->tq_stop = 0;
9568	}
9569}
9570
9571static void
9572bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9573{
9574	struct bwn_softc *sc = mac->mac_sc;
9575	struct bwn_phy *phy = &mac->mac_phy;
9576	struct ifnet *ifp = sc->sc_ifp;
9577	struct ieee80211com *ic = ifp->if_l2com;
9578	struct siba_softc *siba = mac->mac_sd->sd_bus;
9579	unsigned long now;
9580	int result;
9581
9582	BWN_GETTIME(now);
9583
9584	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9585		return;
9586	phy->nexttime = now + 2 * 1000;
9587
9588	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9589	    siba->siba_board_type == SIBA_BOARD_BU4306)
9590		return;
9591
9592	if (phy->recalc_txpwr != NULL) {
9593		result = phy->recalc_txpwr(mac,
9594		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9595		if (result == BWN_TXPWR_RES_DONE)
9596			return;
9597		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9598		    ("%s: fail", __func__));
9599		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9600
9601		ieee80211_runtask(ic, &mac->mac_txpower);
9602	}
9603}
9604
9605static uint16_t
9606bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9607{
9608
9609	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9610}
9611
9612static uint32_t
9613bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9614{
9615
9616	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9617}
9618
9619static void
9620bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9621{
9622
9623	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9624}
9625
9626static void
9627bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9628{
9629
9630	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9631}
9632
9633static int
9634bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9635{
9636
9637	switch (rate) {
9638	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9639	case 12:
9640		return (BWN_OFDM_RATE_6MB);
9641	case 18:
9642		return (BWN_OFDM_RATE_9MB);
9643	case 24:
9644		return (BWN_OFDM_RATE_12MB);
9645	case 36:
9646		return (BWN_OFDM_RATE_18MB);
9647	case 48:
9648		return (BWN_OFDM_RATE_24MB);
9649	case 72:
9650		return (BWN_OFDM_RATE_36MB);
9651	case 96:
9652		return (BWN_OFDM_RATE_48MB);
9653	case 108:
9654		return (BWN_OFDM_RATE_54MB);
9655	/* CCK rates (NB: not IEEE std, device-specific) */
9656	case 2:
9657		return (BWN_CCK_RATE_1MB);
9658	case 4:
9659		return (BWN_CCK_RATE_2MB);
9660	case 11:
9661		return (BWN_CCK_RATE_5MB);
9662	case 22:
9663		return (BWN_CCK_RATE_11MB);
9664	}
9665
9666	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9667	return (BWN_CCK_RATE_1MB);
9668}
9669
9670static int
9671bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9672    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9673{
9674	const struct bwn_phy *phy = &mac->mac_phy;
9675	struct bwn_softc *sc = mac->mac_sc;
9676	struct ieee80211_frame *wh;
9677	struct ieee80211_frame *protwh;
9678	struct ieee80211_frame_cts *cts;
9679	struct ieee80211_frame_rts *rts;
9680	const struct ieee80211_txparam *tp;
9681	struct ieee80211vap *vap = ni->ni_vap;
9682	struct ifnet *ifp = sc->sc_ifp;
9683	struct ieee80211com *ic = ifp->if_l2com;
9684	struct mbuf *mprot;
9685	unsigned int len;
9686	uint32_t macctl = 0;
9687	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9688	uint16_t phyctl = 0;
9689	uint8_t rate, rate_fb;
9690
9691	wh = mtod(m, struct ieee80211_frame *);
9692	memset(txhdr, 0, sizeof(*txhdr));
9693
9694	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9695	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9696	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9697
9698	/*
9699	 * Find TX rate
9700	 */
9701	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9702	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9703		rate = rate_fb = tp->mgmtrate;
9704	else if (ismcast)
9705		rate = rate_fb = tp->mcastrate;
9706	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9707		rate = rate_fb = tp->ucastrate;
9708	else {
9709		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9710		rate = ni->ni_txrate;
9711
9712		if (rix > 0)
9713			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9714			    IEEE80211_RATE_VAL;
9715		else
9716			rate_fb = rate;
9717	}
9718
9719	sc->sc_tx_rate = rate;
9720
9721	rate = bwn_ieeerate2hwrate(sc, rate);
9722	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9723
9724	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9725	    bwn_plcp_getcck(rate);
9726	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9727	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9728
9729	if ((rate_fb == rate) ||
9730	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9731	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9732		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9733	else
9734		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9735		    m->m_pkthdr.len, rate, isshort);
9736
9737	/* XXX TX encryption */
9738	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9739	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9740	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9741	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9742	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9743	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9744
9745	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9746	    BWN_TX_EFT_FB_CCK;
9747	txhdr->chan = phy->chan;
9748	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9749	    BWN_TX_PHY_ENC_CCK;
9750	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9751	     rate == BWN_CCK_RATE_11MB))
9752		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9753
9754	/* XXX TX antenna selection */
9755
9756	switch (bwn_antenna_sanitize(mac, 0)) {
9757	case 0:
9758		phyctl |= BWN_TX_PHY_ANT01AUTO;
9759		break;
9760	case 1:
9761		phyctl |= BWN_TX_PHY_ANT0;
9762		break;
9763	case 2:
9764		phyctl |= BWN_TX_PHY_ANT1;
9765		break;
9766	case 3:
9767		phyctl |= BWN_TX_PHY_ANT2;
9768		break;
9769	case 4:
9770		phyctl |= BWN_TX_PHY_ANT3;
9771		break;
9772	default:
9773		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9774	}
9775
9776	if (!ismcast)
9777		macctl |= BWN_TX_MAC_ACK;
9778
9779	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9780	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9781	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9782		macctl |= BWN_TX_MAC_LONGFRAME;
9783
9784	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9785		/* XXX RTS rate is always 1MB??? */
9786		rts_rate = BWN_CCK_RATE_1MB;
9787		rts_rate_fb = bwn_get_fbrate(rts_rate);
9788
9789		protdur = ieee80211_compute_duration(ic->ic_rt,
9790		    m->m_pkthdr.len, rate, isshort) +
9791		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9792
9793		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9794			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9795			    (txhdr->body.old.rts_frame) :
9796			    (txhdr->body.new.rts_frame));
9797			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9798			    protdur);
9799			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9800			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9801			    mprot->m_pkthdr.len);
9802			m_freem(mprot);
9803			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9804			len = sizeof(struct ieee80211_frame_cts);
9805		} else {
9806			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9807			    (txhdr->body.old.rts_frame) :
9808			    (txhdr->body.new.rts_frame));
9809			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9810			    isshort);
9811			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9812			    wh->i_addr2, protdur);
9813			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9814			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9815			    mprot->m_pkthdr.len);
9816			m_freem(mprot);
9817			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9818			len = sizeof(struct ieee80211_frame_rts);
9819		}
9820		len += IEEE80211_CRC_LEN;
9821		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9822		    &txhdr->body.old.rts_plcp :
9823		    &txhdr->body.new.rts_plcp), len, rts_rate);
9824		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9825		    rts_rate_fb);
9826
9827		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9828		    (&txhdr->body.old.rts_frame) :
9829		    (&txhdr->body.new.rts_frame));
9830		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9831
9832		if (BWN_ISOFDMRATE(rts_rate)) {
9833			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9834			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9835		} else {
9836			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9837			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9838		}
9839		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9840		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9841	}
9842
9843	if (BWN_ISOLDFMT(mac))
9844		txhdr->body.old.cookie = htole16(cookie);
9845	else
9846		txhdr->body.new.cookie = htole16(cookie);
9847
9848	txhdr->macctl = htole32(macctl);
9849	txhdr->phyctl = htole16(phyctl);
9850
9851	/*
9852	 * TX radio tap
9853	 */
9854	if (ieee80211_radiotap_active_vap(vap)) {
9855		sc->sc_tx_th.wt_flags = 0;
9856		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9857			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9858		if (isshort &&
9859		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9860		     rate == BWN_CCK_RATE_11MB))
9861			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9862		sc->sc_tx_th.wt_rate = rate;
9863
9864		ieee80211_radiotap_tx(vap, m);
9865	}
9866
9867	return (0);
9868}
9869
9870static void
9871bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9872    const uint8_t rate)
9873{
9874	uint32_t d, plen;
9875	uint8_t *raw = plcp->o.raw;
9876
9877	if (BWN_ISOFDMRATE(rate)) {
9878		d = bwn_plcp_getofdm(rate);
9879		KASSERT(!(octets & 0xf000),
9880		    ("%s:%d: fail", __func__, __LINE__));
9881		d |= (octets << 5);
9882		plcp->o.data = htole32(d);
9883	} else {
9884		plen = octets * 16 / rate;
9885		if ((octets * 16 % rate) > 0) {
9886			plen++;
9887			if ((rate == BWN_CCK_RATE_11MB)
9888			    && ((octets * 8 % 11) < 4)) {
9889				raw[1] = 0x84;
9890			} else
9891				raw[1] = 0x04;
9892		} else
9893			raw[1] = 0x04;
9894		plcp->o.data |= htole32(plen << 16);
9895		raw[0] = bwn_plcp_getcck(rate);
9896	}
9897}
9898
9899static uint8_t
9900bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9901{
9902	uint8_t mask;
9903
9904	if (n == 0)
9905		return (0);
9906	if (mac->mac_phy.gmode)
9907		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9908	else
9909		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9910	if (!(mask & (1 << (n - 1))))
9911		return (0);
9912	return (n);
9913}
9914
9915static uint8_t
9916bwn_get_fbrate(uint8_t bitrate)
9917{
9918	switch (bitrate) {
9919	case BWN_CCK_RATE_1MB:
9920		return (BWN_CCK_RATE_1MB);
9921	case BWN_CCK_RATE_2MB:
9922		return (BWN_CCK_RATE_1MB);
9923	case BWN_CCK_RATE_5MB:
9924		return (BWN_CCK_RATE_2MB);
9925	case BWN_CCK_RATE_11MB:
9926		return (BWN_CCK_RATE_5MB);
9927	case BWN_OFDM_RATE_6MB:
9928		return (BWN_CCK_RATE_5MB);
9929	case BWN_OFDM_RATE_9MB:
9930		return (BWN_OFDM_RATE_6MB);
9931	case BWN_OFDM_RATE_12MB:
9932		return (BWN_OFDM_RATE_9MB);
9933	case BWN_OFDM_RATE_18MB:
9934		return (BWN_OFDM_RATE_12MB);
9935	case BWN_OFDM_RATE_24MB:
9936		return (BWN_OFDM_RATE_18MB);
9937	case BWN_OFDM_RATE_36MB:
9938		return (BWN_OFDM_RATE_24MB);
9939	case BWN_OFDM_RATE_48MB:
9940		return (BWN_OFDM_RATE_36MB);
9941	case BWN_OFDM_RATE_54MB:
9942		return (BWN_OFDM_RATE_48MB);
9943	}
9944	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9945	return (0);
9946}
9947
9948static uint32_t
9949bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9950    uint32_t ctl, const void *_data, int len)
9951{
9952	uint32_t value = 0;
9953	const uint8_t *data = _data;
9954
9955	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9956	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9957	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9958
9959	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9960	    tq->tq_base + BWN_PIO8_TXDATA);
9961	if (len & 3) {
9962		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9963		    BWN_PIO8_TXCTL_24_31);
9964		data = &(data[len - 1]);
9965		switch (len & 3) {
9966		case 3:
9967			ctl |= BWN_PIO8_TXCTL_16_23;
9968			value |= (uint32_t)(*data) << 16;
9969			data--;
9970		case 2:
9971			ctl |= BWN_PIO8_TXCTL_8_15;
9972			value |= (uint32_t)(*data) << 8;
9973			data--;
9974		case 1:
9975			value |= (uint32_t)(*data);
9976		}
9977		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9978		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9979	}
9980
9981	return (ctl);
9982}
9983
9984static void
9985bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9986    uint16_t offset, uint32_t value)
9987{
9988
9989	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9990}
9991
9992static uint16_t
9993bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9994    uint16_t ctl, const void *_data, int len)
9995{
9996	const uint8_t *data = _data;
9997
9998	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9999	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10000
10001	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10002	    tq->tq_base + BWN_PIO_TXDATA);
10003	if (len & 1) {
10004		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10005		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10006		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10007	}
10008
10009	return (ctl);
10010}
10011
10012static uint16_t
10013bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10014    uint16_t ctl, struct mbuf *m0)
10015{
10016	int i, j = 0;
10017	uint16_t data = 0;
10018	const uint8_t *buf;
10019	struct mbuf *m = m0;
10020
10021	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10022	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10023
10024	for (; m != NULL; m = m->m_next) {
10025		buf = mtod(m, const uint8_t *);
10026		for (i = 0; i < m->m_len; i++) {
10027			if (!((j++) % 2))
10028				data |= buf[i];
10029			else {
10030				data |= (buf[i] << 8);
10031				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10032				data = 0;
10033			}
10034		}
10035	}
10036	if (m0->m_pkthdr.len % 2) {
10037		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10038		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10039		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10040	}
10041
10042	return (ctl);
10043}
10044
10045static void
10046bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10047{
10048
10049	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10050		return;
10051	BWN_WRITE_2(mac, 0x684, 510 + time);
10052	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10053}
10054
10055static struct bwn_dma_ring *
10056bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10057{
10058
10059	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10060		return (mac->mac_method.dma.wme[WME_AC_BE]);
10061
10062	switch (prio) {
10063	case 3:
10064		return (mac->mac_method.dma.wme[WME_AC_VO]);
10065	case 2:
10066		return (mac->mac_method.dma.wme[WME_AC_VI]);
10067	case 0:
10068		return (mac->mac_method.dma.wme[WME_AC_BE]);
10069	case 1:
10070		return (mac->mac_method.dma.wme[WME_AC_BK]);
10071	}
10072	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10073	return (NULL);
10074}
10075
10076static int
10077bwn_dma_getslot(struct bwn_dma_ring *dr)
10078{
10079	int slot;
10080
10081	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10082
10083	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10084	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10085	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10086
10087	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10088	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10089	dr->dr_curslot = slot;
10090	dr->dr_usedslot++;
10091
10092	return (slot);
10093}
10094
10095static int
10096bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10097{
10098	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10099	unsigned int a, b, c, d;
10100	unsigned int avg;
10101	uint32_t tmp;
10102
10103	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10104	a = tmp & 0xff;
10105	b = (tmp >> 8) & 0xff;
10106	c = (tmp >> 16) & 0xff;
10107	d = (tmp >> 24) & 0xff;
10108	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10109	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10110		return (ENOENT);
10111	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10112	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10113	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10114
10115	if (ofdm) {
10116		a = (a + 32) & 0x3f;
10117		b = (b + 32) & 0x3f;
10118		c = (c + 32) & 0x3f;
10119		d = (d + 32) & 0x3f;
10120	}
10121
10122	avg = (a + b + c + d + 2) / 4;
10123	if (ofdm) {
10124		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10125		    & BWN_HF_4DB_CCK_POWERBOOST)
10126			avg = (avg >= 13) ? (avg - 13) : 0;
10127	}
10128	return (avg);
10129}
10130
10131static void
10132bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10133{
10134	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10135	int rfatt = *rfattp;
10136	int bbatt = *bbattp;
10137
10138	while (1) {
10139		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10140			break;
10141		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10142			break;
10143		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10144			break;
10145		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10146			break;
10147		if (bbatt > lo->bbatt.max) {
10148			bbatt -= 4;
10149			rfatt += 1;
10150			continue;
10151		}
10152		if (bbatt < lo->bbatt.min) {
10153			bbatt += 4;
10154			rfatt -= 1;
10155			continue;
10156		}
10157		if (rfatt > lo->rfatt.max) {
10158			rfatt -= 1;
10159			bbatt += 4;
10160			continue;
10161		}
10162		if (rfatt < lo->rfatt.min) {
10163			rfatt += 1;
10164			bbatt -= 4;
10165			continue;
10166		}
10167		break;
10168	}
10169
10170	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10171	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10172}
10173
10174static void
10175bwn_phy_lock(struct bwn_mac *mac)
10176{
10177	struct bwn_softc *sc = mac->mac_sc;
10178	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10179
10180	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10181	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10182
10183	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10184		bwn_psctl(mac, BWN_PS_AWAKE);
10185}
10186
10187static void
10188bwn_phy_unlock(struct bwn_mac *mac)
10189{
10190	struct bwn_softc *sc = mac->mac_sc;
10191	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10192
10193	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10194	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10195
10196	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10197		bwn_psctl(mac, 0);
10198}
10199
10200static void
10201bwn_rf_lock(struct bwn_mac *mac)
10202{
10203
10204	BWN_WRITE_4(mac, BWN_MACCTL,
10205	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10206	BWN_READ_4(mac, BWN_MACCTL);
10207	DELAY(10);
10208}
10209
10210static void
10211bwn_rf_unlock(struct bwn_mac *mac)
10212{
10213
10214	BWN_READ_2(mac, BWN_PHYVER);
10215	BWN_WRITE_4(mac, BWN_MACCTL,
10216	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10217}
10218
10219static struct bwn_pio_txqueue *
10220bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10221    struct bwn_pio_txpkt **pack)
10222{
10223	struct bwn_pio *pio = &mac->mac_method.pio;
10224	struct bwn_pio_txqueue *tq = NULL;
10225	unsigned int index;
10226
10227	switch (cookie & 0xf000) {
10228	case 0x1000:
10229		tq = &pio->wme[WME_AC_BK];
10230		break;
10231	case 0x2000:
10232		tq = &pio->wme[WME_AC_BE];
10233		break;
10234	case 0x3000:
10235		tq = &pio->wme[WME_AC_VI];
10236		break;
10237	case 0x4000:
10238		tq = &pio->wme[WME_AC_VO];
10239		break;
10240	case 0x5000:
10241		tq = &pio->mcast;
10242		break;
10243	}
10244	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10245	if (tq == NULL)
10246		return (NULL);
10247	index = (cookie & 0x0fff);
10248	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10249	if (index >= N(tq->tq_pkts))
10250		return (NULL);
10251	*pack = &tq->tq_pkts[index];
10252	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10253	return (tq);
10254}
10255
10256static void
10257bwn_txpwr(void *arg, int npending)
10258{
10259	struct bwn_mac *mac = arg;
10260	struct bwn_softc *sc = mac->mac_sc;
10261
10262	BWN_LOCK(sc);
10263	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10264	    mac->mac_phy.set_txpwr != NULL)
10265		mac->mac_phy.set_txpwr(mac);
10266	BWN_UNLOCK(sc);
10267}
10268
10269static void
10270bwn_task_15s(struct bwn_mac *mac)
10271{
10272	uint16_t reg;
10273
10274	if (mac->mac_fw.opensource) {
10275		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10276		if (reg) {
10277			bwn_restart(mac, "fw watchdog");
10278			return;
10279		}
10280		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10281	}
10282	if (mac->mac_phy.task_15s)
10283		mac->mac_phy.task_15s(mac);
10284
10285	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10286}
10287
10288static void
10289bwn_task_30s(struct bwn_mac *mac)
10290{
10291
10292	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10293		return;
10294	mac->mac_noise.noi_running = 1;
10295	mac->mac_noise.noi_nsamples = 0;
10296
10297	bwn_noise_gensample(mac);
10298}
10299
10300static void
10301bwn_task_60s(struct bwn_mac *mac)
10302{
10303
10304	if (mac->mac_phy.task_60s)
10305		mac->mac_phy.task_60s(mac);
10306	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10307}
10308
10309static void
10310bwn_tasks(void *arg)
10311{
10312	struct bwn_mac *mac = arg;
10313	struct bwn_softc *sc = mac->mac_sc;
10314
10315	BWN_ASSERT_LOCKED(sc);
10316	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10317		return;
10318
10319	if (mac->mac_task_state % 4 == 0)
10320		bwn_task_60s(mac);
10321	if (mac->mac_task_state % 2 == 0)
10322		bwn_task_30s(mac);
10323	bwn_task_15s(mac);
10324
10325	mac->mac_task_state++;
10326	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10327}
10328
10329static int
10330bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10331{
10332	struct bwn_softc *sc = mac->mac_sc;
10333
10334	KASSERT(a == 0, ("not support APHY\n"));
10335
10336	switch (plcp->o.raw[0] & 0xf) {
10337	case 0xb:
10338		return (BWN_OFDM_RATE_6MB);
10339	case 0xf:
10340		return (BWN_OFDM_RATE_9MB);
10341	case 0xa:
10342		return (BWN_OFDM_RATE_12MB);
10343	case 0xe:
10344		return (BWN_OFDM_RATE_18MB);
10345	case 0x9:
10346		return (BWN_OFDM_RATE_24MB);
10347	case 0xd:
10348		return (BWN_OFDM_RATE_36MB);
10349	case 0x8:
10350		return (BWN_OFDM_RATE_48MB);
10351	case 0xc:
10352		return (BWN_OFDM_RATE_54MB);
10353	}
10354	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10355	    plcp->o.raw[0] & 0xf);
10356	return (-1);
10357}
10358
10359static int
10360bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10361{
10362	struct bwn_softc *sc = mac->mac_sc;
10363
10364	switch (plcp->o.raw[0]) {
10365	case 0x0a:
10366		return (BWN_CCK_RATE_1MB);
10367	case 0x14:
10368		return (BWN_CCK_RATE_2MB);
10369	case 0x37:
10370		return (BWN_CCK_RATE_5MB);
10371	case 0x6e:
10372		return (BWN_CCK_RATE_11MB);
10373	}
10374	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10375	return (-1);
10376}
10377
10378static void
10379bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10380    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10381    int rssi, int noise)
10382{
10383	struct bwn_softc *sc = mac->mac_sc;
10384	const struct ieee80211_frame_min *wh;
10385	uint64_t tsf;
10386	uint16_t low_mactime_now;
10387
10388	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10389		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10390
10391	wh = mtod(m, const struct ieee80211_frame_min *);
10392	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10393		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10394
10395	bwn_tsf_read(mac, &tsf);
10396	low_mactime_now = tsf;
10397	tsf = tsf & ~0xffffULL;
10398	tsf += le16toh(rxhdr->mac_time);
10399	if (low_mactime_now < le16toh(rxhdr->mac_time))
10400		tsf -= 0x10000;
10401
10402	sc->sc_rx_th.wr_tsf = tsf;
10403	sc->sc_rx_th.wr_rate = rate;
10404	sc->sc_rx_th.wr_antsignal = rssi;
10405	sc->sc_rx_th.wr_antnoise = noise;
10406}
10407
10408static void
10409bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10410{
10411	uint32_t low, high;
10412
10413	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10414	    ("%s:%d: fail", __func__, __LINE__));
10415
10416	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10417	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10418	*tsf = high;
10419	*tsf <<= 32;
10420	*tsf |= low;
10421}
10422
10423static int
10424bwn_dma_attach(struct bwn_mac *mac)
10425{
10426	struct bwn_dma *dma = &mac->mac_method.dma;
10427	struct bwn_softc *sc = mac->mac_sc;
10428	struct siba_dev_softc *sd = mac->mac_sd;
10429	struct siba_softc *siba = sd->sd_bus;
10430	bus_addr_t lowaddr = 0;
10431	int error;
10432
10433	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10434		return (0);
10435
10436	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10437
10438	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10439
10440	dma->dmatype = bwn_dma_gettype(mac);
10441	if (dma->dmatype == BWN_DMA_30BIT)
10442		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10443	else if (dma->dmatype == BWN_DMA_32BIT)
10444		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10445	else
10446		lowaddr = BUS_SPACE_MAXADDR;
10447
10448	/*
10449	 * Create top level DMA tag
10450	 */
10451	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10452			       BWN_ALIGN, 0,		/* alignment, bounds */
10453			       lowaddr,			/* lowaddr */
10454			       BUS_SPACE_MAXADDR,	/* highaddr */
10455			       NULL, NULL,		/* filter, filterarg */
10456			       MAXBSIZE,		/* maxsize */
10457			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10458			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10459			       0,			/* flags */
10460			       NULL, NULL,		/* lockfunc, lockarg */
10461			       &dma->parent_dtag);
10462	if (error) {
10463		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10464		return (error);
10465	}
10466
10467	/*
10468	 * Create TX/RX mbuf DMA tag
10469	 */
10470	error = bus_dma_tag_create(dma->parent_dtag,
10471				1,
10472				0,
10473				BUS_SPACE_MAXADDR,
10474				BUS_SPACE_MAXADDR,
10475				NULL, NULL,
10476				MCLBYTES,
10477				1,
10478				BUS_SPACE_MAXSIZE_32BIT,
10479				0,
10480				NULL, NULL,
10481				&dma->rxbuf_dtag);
10482	if (error) {
10483		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10484		goto fail0;
10485	}
10486	error = bus_dma_tag_create(dma->parent_dtag,
10487				1,
10488				0,
10489				BUS_SPACE_MAXADDR,
10490				BUS_SPACE_MAXADDR,
10491				NULL, NULL,
10492				MCLBYTES,
10493				1,
10494				BUS_SPACE_MAXSIZE_32BIT,
10495				0,
10496				NULL, NULL,
10497				&dma->txbuf_dtag);
10498	if (error) {
10499		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10500		goto fail1;
10501	}
10502
10503	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10504	if (!dma->wme[WME_AC_BK])
10505		goto fail2;
10506
10507	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10508	if (!dma->wme[WME_AC_BE])
10509		goto fail3;
10510
10511	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10512	if (!dma->wme[WME_AC_VI])
10513		goto fail4;
10514
10515	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10516	if (!dma->wme[WME_AC_VO])
10517		goto fail5;
10518
10519	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10520	if (!dma->mcast)
10521		goto fail6;
10522	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10523	if (!dma->rx)
10524		goto fail7;
10525
10526	return (error);
10527
10528fail7:	bwn_dma_ringfree(&dma->mcast);
10529fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10530fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10531fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10532fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10533fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10534fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10535fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10536	return (error);
10537}
10538
10539static struct bwn_dma_ring *
10540bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10541    uint16_t cookie, int *slot)
10542{
10543	struct bwn_dma *dma = &mac->mac_method.dma;
10544	struct bwn_dma_ring *dr;
10545	struct bwn_softc *sc = mac->mac_sc;
10546
10547	BWN_ASSERT_LOCKED(mac->mac_sc);
10548
10549	switch (cookie & 0xf000) {
10550	case 0x1000:
10551		dr = dma->wme[WME_AC_BK];
10552		break;
10553	case 0x2000:
10554		dr = dma->wme[WME_AC_BE];
10555		break;
10556	case 0x3000:
10557		dr = dma->wme[WME_AC_VI];
10558		break;
10559	case 0x4000:
10560		dr = dma->wme[WME_AC_VO];
10561		break;
10562	case 0x5000:
10563		dr = dma->mcast;
10564		break;
10565	default:
10566		dr = NULL;
10567		KASSERT(0 == 1,
10568		    ("invalid cookie value %d", cookie & 0xf000));
10569	}
10570	*slot = (cookie & 0x0fff);
10571	if (*slot < 0 || *slot >= dr->dr_numslots) {
10572		/*
10573		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10574		 * that it occurs events which have same H/W sequence numbers.
10575		 * When it's occurred just prints a WARNING msgs and ignores.
10576		 */
10577		KASSERT(status->seq == dma->lastseq,
10578		    ("%s:%d: fail", __func__, __LINE__));
10579		device_printf(sc->sc_dev,
10580		    "out of slot ranges (0 < %d < %d)\n", *slot,
10581		    dr->dr_numslots);
10582		return (NULL);
10583	}
10584	dma->lastseq = status->seq;
10585	return (dr);
10586}
10587
10588static void
10589bwn_dma_stop(struct bwn_mac *mac)
10590{
10591	struct bwn_dma *dma;
10592
10593	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10594		return;
10595	dma = &mac->mac_method.dma;
10596
10597	bwn_dma_ringstop(&dma->rx);
10598	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10599	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10600	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10601	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10602	bwn_dma_ringstop(&dma->mcast);
10603}
10604
10605static void
10606bwn_dma_ringstop(struct bwn_dma_ring **dr)
10607{
10608
10609	if (dr == NULL)
10610		return;
10611
10612	bwn_dma_cleanup(*dr);
10613}
10614
10615static void
10616bwn_pio_stop(struct bwn_mac *mac)
10617{
10618	struct bwn_pio *pio;
10619
10620	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10621		return;
10622	pio = &mac->mac_method.pio;
10623
10624	bwn_destroy_queue_tx(&pio->mcast);
10625	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10626	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10627	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10628	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10629}
10630
10631static void
10632bwn_led_attach(struct bwn_mac *mac)
10633{
10634	struct bwn_softc *sc = mac->mac_sc;
10635	struct siba_softc *siba = mac->mac_sd->sd_bus;
10636	const uint8_t *led_act = NULL;
10637	uint16_t val[BWN_LED_MAX];
10638	int i;
10639
10640	sc->sc_led_idle = (2350 * hz) / 1000;
10641	sc->sc_led_blink = 1;
10642
10643	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10644		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10645			led_act = bwn_vendor_led_act[i].led_act;
10646			break;
10647		}
10648	}
10649	if (led_act == NULL)
10650		led_act = bwn_default_led_act;
10651
10652	val[0] = siba->siba_sprom.gpio0;
10653	val[1] = siba->siba_sprom.gpio1;
10654	val[2] = siba->siba_sprom.gpio2;
10655	val[3] = siba->siba_sprom.gpio3;
10656
10657	for (i = 0; i < BWN_LED_MAX; ++i) {
10658		struct bwn_led *led = &sc->sc_leds[i];
10659
10660		if (val[i] == 0xff) {
10661			led->led_act = led_act[i];
10662		} else {
10663			if (val[i] & BWN_LED_ACT_LOW)
10664				led->led_flags |= BWN_LED_F_ACTLOW;
10665			led->led_act = val[i] & BWN_LED_ACT_MASK;
10666		}
10667		led->led_mask = (1 << i);
10668
10669		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10670		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10671		    led->led_act == BWN_LED_ACT_BLINK) {
10672			led->led_flags |= BWN_LED_F_BLINK;
10673			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10674				led->led_flags |= BWN_LED_F_POLLABLE;
10675			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10676				led->led_flags |= BWN_LED_F_SLOW;
10677
10678			if (sc->sc_blink_led == NULL) {
10679				sc->sc_blink_led = led;
10680				if (led->led_flags & BWN_LED_F_SLOW)
10681					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10682			}
10683		}
10684
10685		DPRINTF(sc, BWN_DEBUG_LED,
10686		    "%dth led, act %d, lowact %d\n", i,
10687		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10688	}
10689	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10690}
10691
10692static __inline uint16_t
10693bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10694{
10695
10696	if (led->led_flags & BWN_LED_F_ACTLOW)
10697		on = !on;
10698	if (on)
10699		val |= led->led_mask;
10700	else
10701		val &= ~led->led_mask;
10702	return val;
10703}
10704
10705static void
10706bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10707{
10708	struct bwn_softc *sc = mac->mac_sc;
10709	struct ifnet *ifp = sc->sc_ifp;
10710	struct ieee80211com *ic = ifp->if_l2com;
10711	uint16_t val;
10712	int i;
10713
10714	if (nstate == IEEE80211_S_INIT) {
10715		callout_stop(&sc->sc_led_blink_ch);
10716		sc->sc_led_blinking = 0;
10717	}
10718
10719	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10720		return;
10721
10722	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10723	for (i = 0; i < BWN_LED_MAX; ++i) {
10724		struct bwn_led *led = &sc->sc_leds[i];
10725		int on;
10726
10727		if (led->led_act == BWN_LED_ACT_UNKN ||
10728		    led->led_act == BWN_LED_ACT_NULL)
10729			continue;
10730
10731		if ((led->led_flags & BWN_LED_F_BLINK) &&
10732		    nstate != IEEE80211_S_INIT)
10733			continue;
10734
10735		switch (led->led_act) {
10736		case BWN_LED_ACT_ON:    /* Always on */
10737			on = 1;
10738			break;
10739		case BWN_LED_ACT_OFF:   /* Always off */
10740		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10741			on = 0;
10742			break;
10743		default:
10744			on = 1;
10745			switch (nstate) {
10746			case IEEE80211_S_INIT:
10747				on = 0;
10748				break;
10749			case IEEE80211_S_RUN:
10750				if (led->led_act == BWN_LED_ACT_11G &&
10751				    ic->ic_curmode != IEEE80211_MODE_11G)
10752					on = 0;
10753				break;
10754			default:
10755				if (led->led_act == BWN_LED_ACT_ASSOC)
10756					on = 0;
10757				break;
10758			}
10759			break;
10760		}
10761
10762		val = bwn_led_onoff(led, val, on);
10763	}
10764	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10765}
10766
10767static void
10768bwn_led_event(struct bwn_mac *mac, int event)
10769{
10770	struct bwn_softc *sc = mac->mac_sc;
10771        struct bwn_led *led = sc->sc_blink_led;
10772        int rate;
10773
10774        if (event == BWN_LED_EVENT_POLL) {
10775                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10776                        return;
10777                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10778                        return;
10779        }
10780
10781        sc->sc_led_ticks = ticks;
10782        if (sc->sc_led_blinking)
10783                return;
10784
10785        switch (event) {
10786        case BWN_LED_EVENT_RX:
10787                rate = sc->sc_rx_rate;
10788                break;
10789        case BWN_LED_EVENT_TX:
10790                rate = sc->sc_tx_rate;
10791                break;
10792        case BWN_LED_EVENT_POLL:
10793                rate = 0;
10794                break;
10795        default:
10796                panic("unknown LED event %d\n", event);
10797                break;
10798        }
10799        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10800            bwn_led_duration[rate].off_dur);
10801}
10802
10803static void
10804bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10805{
10806	struct bwn_softc *sc = mac->mac_sc;
10807        struct bwn_led *led = sc->sc_blink_led;
10808        uint16_t val;
10809
10810        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10811        val = bwn_led_onoff(led, val, 1);
10812        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10813
10814        if (led->led_flags & BWN_LED_F_SLOW) {
10815                BWN_LED_SLOWDOWN(on_dur);
10816                BWN_LED_SLOWDOWN(off_dur);
10817        }
10818
10819        sc->sc_led_blinking = 1;
10820        sc->sc_led_blink_offdur = off_dur;
10821
10822        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10823}
10824
10825static void
10826bwn_led_blink_next(void *arg)
10827{
10828	struct bwn_mac *mac = arg;
10829        struct bwn_softc *sc = mac->mac_sc;
10830        uint16_t val;
10831
10832        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10833        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10834        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10835
10836        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10837            bwn_led_blink_end, mac);
10838}
10839
10840static void
10841bwn_led_blink_end(void *arg)
10842{
10843	struct bwn_mac *mac = arg;
10844        struct bwn_softc *sc = mac->mac_sc;
10845
10846        sc->sc_led_blinking = 0;
10847}
10848
10849static int
10850bwn_suspend(device_t dev)
10851{
10852	struct bwn_softc *sc = device_get_softc(dev);
10853
10854	bwn_stop(sc, 1);
10855	return (0);
10856}
10857
10858static int
10859bwn_resume(device_t dev)
10860{
10861	struct bwn_softc *sc = device_get_softc(dev);
10862	struct ifnet *ifp = sc->sc_ifp;
10863
10864	if (ifp->if_flags & IFF_UP)
10865		bwn_init(sc);
10866	return (0);
10867}
10868
10869static void
10870bwn_rfswitch(void *arg)
10871{
10872	struct bwn_softc *sc = arg;
10873	struct bwn_mac *mac = sc->sc_curmac;
10874	int cur = 0, prev = 0;
10875
10876	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10877	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10878
10879	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10880		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10881			& BWN_RF_HWENABLED_HI_MASK))
10882			cur = 1;
10883	} else {
10884		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10885		    & BWN_RF_HWENABLED_LO_MASK)
10886			cur = 1;
10887	}
10888
10889	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10890		prev = 1;
10891
10892	if (cur != prev) {
10893		if (cur)
10894			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10895		else
10896			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10897
10898		device_printf(sc->sc_dev,
10899		    "status of RF switch is changed to %s\n",
10900		    cur ? "ON" : "OFF");
10901		if (cur != mac->mac_phy.rf_on) {
10902			if (cur)
10903				bwn_rf_turnon(mac);
10904			else
10905				bwn_rf_turnoff(mac);
10906		}
10907	}
10908
10909	callout_schedule(&sc->sc_rfswitch_ch, hz);
10910}
10911
10912static void
10913bwn_phy_lp_init_pre(struct bwn_mac *mac)
10914{
10915	struct bwn_phy *phy = &mac->mac_phy;
10916	struct bwn_phy_lp *plp = &phy->phy_lp;
10917
10918	plp->plp_antenna = BWN_ANT_DEFAULT;
10919}
10920
10921static int
10922bwn_phy_lp_init(struct bwn_mac *mac)
10923{
10924	static const struct bwn_stxtable tables[] = {
10925		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10926		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10927		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10928		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10929		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10930		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10931		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10932		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10933		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10934		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10935		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10936		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10937		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10938		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10939		{ 2, 11, 0x40, 0, 0x0f }
10940	};
10941	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10942	struct bwn_softc *sc = mac->mac_sc;
10943	const struct bwn_stxtable *st;
10944	struct ifnet *ifp = sc->sc_ifp;
10945	struct ieee80211com *ic = ifp->if_l2com;
10946	int i, error;
10947	uint16_t tmp;
10948
10949	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10950	bwn_phy_lp_bbinit(mac);
10951
10952	/* initialize RF */
10953	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10954	DELAY(1);
10955	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10956	DELAY(1);
10957
10958	if (mac->mac_phy.rf_ver == 0x2062)
10959		bwn_phy_lp_b2062_init(mac);
10960	else {
10961		bwn_phy_lp_b2063_init(mac);
10962
10963		/* synchronize stx table. */
10964		for (i = 0; i < N(tables); i++) {
10965			st = &tables[i];
10966			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10967			tmp >>= st->st_rfshift;
10968			tmp <<= st->st_physhift;
10969			BWN_PHY_SETMASK(mac,
10970			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10971			    ~(st->st_mask << st->st_physhift), tmp);
10972		}
10973
10974		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10975		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10976	}
10977
10978	/* calibrate RC */
10979	if (mac->mac_phy.rev >= 2)
10980		bwn_phy_lp_rxcal_r2(mac);
10981	else if (!plp->plp_rccap) {
10982		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10983			bwn_phy_lp_rccal_r12(mac);
10984	} else
10985		bwn_phy_lp_set_rccap(mac);
10986
10987	error = bwn_phy_lp_switch_channel(mac, 7);
10988	if (error)
10989		device_printf(sc->sc_dev,
10990		    "failed to change channel 7 (%d)\n", error);
10991	bwn_phy_lp_txpctl_init(mac);
10992	bwn_phy_lp_calib(mac);
10993	return (0);
10994}
10995
10996static uint16_t
10997bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10998{
10999
11000	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11001	return (BWN_READ_2(mac, BWN_PHYDATA));
11002}
11003
11004static void
11005bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11006{
11007
11008	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11009	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11010}
11011
11012static void
11013bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11014    uint16_t set)
11015{
11016
11017	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11018	BWN_WRITE_2(mac, BWN_PHYDATA,
11019	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11020}
11021
11022static uint16_t
11023bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11024{
11025
11026	KASSERT(reg != 1, ("unaccessible register %d", reg));
11027	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11028		reg |= 0x100;
11029	if (mac->mac_phy.rev >= 2)
11030		reg |= 0x200;
11031	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11032	return BWN_READ_2(mac, BWN_RFDATALO);
11033}
11034
11035static void
11036bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11037{
11038
11039	KASSERT(reg != 1, ("unaccessible register %d", reg));
11040	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11041	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11042}
11043
11044static void
11045bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11046{
11047
11048	if (on) {
11049		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11050		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11051		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11052		return;
11053	}
11054
11055	if (mac->mac_phy.rev >= 2) {
11056		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11057		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11058		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11059		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11060		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11061		return;
11062	}
11063
11064	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11065	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11066	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11067	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11068}
11069
11070static int
11071bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11072{
11073	struct bwn_phy *phy = &mac->mac_phy;
11074	struct bwn_phy_lp *plp = &phy->phy_lp;
11075	int error;
11076
11077	if (phy->rf_ver == 0x2063) {
11078		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11079		if (error)
11080			return (error);
11081	} else {
11082		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11083		if (error)
11084			return (error);
11085		bwn_phy_lp_set_anafilter(mac, chan);
11086		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11087	}
11088
11089	plp->plp_chan = chan;
11090	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11091	return (0);
11092}
11093
11094static uint32_t
11095bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11096{
11097	struct bwn_softc *sc = mac->mac_sc;
11098	struct ifnet *ifp = sc->sc_ifp;
11099	struct ieee80211com *ic = ifp->if_l2com;
11100
11101	device_printf(sc->sc_dev, "correct?\n");
11102
11103	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11104}
11105
11106static void
11107bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11108{
11109	struct bwn_phy *phy = &mac->mac_phy;
11110	struct bwn_phy_lp *plp = &phy->phy_lp;
11111
11112	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11113		return;
11114
11115	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11116	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11117	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11118	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11119	plp->plp_antenna = antenna;
11120}
11121
11122static void
11123bwn_phy_lp_task_60s(struct bwn_mac *mac)
11124{
11125
11126	bwn_phy_lp_calib(mac);
11127}
11128
11129static void
11130bwn_phy_lp_readsprom(struct bwn_mac *mac)
11131{
11132	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11133	struct bwn_softc *sc = mac->mac_sc;
11134	struct ifnet *ifp = sc->sc_ifp;
11135	struct ieee80211com *ic = ifp->if_l2com;
11136	struct siba_dev_softc *sd = mac->mac_sd;
11137	struct siba_softc *siba = sd->sd_bus;
11138	struct siba_sprom *sprom = &siba->siba_sprom;
11139
11140	device_printf(sc->sc_dev, "XXX using %dghz\n",
11141	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11142
11143	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11144		plp->plp_txisoband_m = sprom->tri2g;
11145		plp->plp_bxarch = sprom->bxa2g;
11146		plp->plp_rxpwroffset = sprom->rxpo2g;
11147		plp->plp_rssivf = sprom->rssismf2g;
11148		plp->plp_rssivc = sprom->rssismc2g;
11149		plp->plp_rssigs = sprom->rssisav2g;
11150		return;
11151	}
11152
11153	plp->plp_txisoband_l = sprom->tri5gl;
11154	plp->plp_txisoband_m = sprom->tri5g;
11155	plp->plp_txisoband_h = sprom->tri5gh;
11156	plp->plp_bxarch = sprom->bxa5g;
11157	plp->plp_rxpwroffset = sprom->rxpo5g;
11158	plp->plp_rssivf = sprom->rssismf5g;
11159	plp->plp_rssivc = sprom->rssismc5g;
11160	plp->plp_rssigs = sprom->rssisav5g;
11161}
11162
11163static void
11164bwn_phy_lp_bbinit(struct bwn_mac *mac)
11165{
11166
11167	bwn_phy_lp_tblinit(mac);
11168	if (mac->mac_phy.rev >= 2)
11169		bwn_phy_lp_bbinit_r2(mac);
11170	else
11171		bwn_phy_lp_bbinit_r01(mac);
11172}
11173
11174static void
11175bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11176{
11177	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11178	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11179	struct bwn_softc *sc = mac->mac_sc;
11180	struct ifnet *ifp = sc->sc_ifp;
11181	struct ieee80211com *ic = ifp->if_l2com;
11182
11183	bwn_phy_lp_set_txgain(mac,
11184	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11185	bwn_phy_lp_set_bbmult(mac, 150);
11186}
11187
11188static void
11189bwn_phy_lp_calib(struct bwn_mac *mac)
11190{
11191	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11192	struct siba_dev_softc *sd = mac->mac_sd;
11193	struct siba_softc *siba = sd->sd_bus;
11194	struct bwn_softc *sc = mac->mac_sc;
11195	struct ifnet *ifp = sc->sc_ifp;
11196	struct ieee80211com *ic = ifp->if_l2com;
11197	const struct bwn_rxcompco *rc = NULL;
11198	struct bwn_txgain ogain;
11199	int i, omode, oafeovr, orf, obbmult;
11200	uint8_t mode, fc = 0;
11201
11202	if (plp->plp_chanfullcal != plp->plp_chan) {
11203		plp->plp_chanfullcal = plp->plp_chan;
11204		fc = 1;
11205	}
11206
11207	bwn_mac_suspend(mac);
11208
11209	/* BlueTooth Coexistance Override */
11210	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11211	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11212
11213	if (mac->mac_phy.rev >= 2)
11214		bwn_phy_lp_digflt_save(mac);
11215	bwn_phy_lp_get_txpctlmode(mac);
11216	mode = plp->plp_txpctlmode;
11217	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11218	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11219		bwn_phy_lp_bugfix(mac);
11220	if (mac->mac_phy.rev >= 2 && fc == 1) {
11221		bwn_phy_lp_get_txpctlmode(mac);
11222		omode = plp->plp_txpctlmode;
11223		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11224		if (oafeovr)
11225			ogain = bwn_phy_lp_get_txgain(mac);
11226		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11227		obbmult = bwn_phy_lp_get_bbmult(mac);
11228		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11229		if (oafeovr)
11230			bwn_phy_lp_set_txgain(mac, &ogain);
11231		bwn_phy_lp_set_bbmult(mac, obbmult);
11232		bwn_phy_lp_set_txpctlmode(mac, omode);
11233		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11234	}
11235	bwn_phy_lp_set_txpctlmode(mac, mode);
11236	if (mac->mac_phy.rev >= 2)
11237		bwn_phy_lp_digflt_restore(mac);
11238
11239	/* do RX IQ Calculation; assumes that noise is true. */
11240	if (siba->siba_chipid == 0x5354) {
11241		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11242			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11243				rc = &bwn_rxcompco_5354[i];
11244		}
11245	} else if (mac->mac_phy.rev >= 2)
11246		rc = &bwn_rxcompco_r2;
11247	else {
11248		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11249			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11250				rc = &bwn_rxcompco_r12[i];
11251		}
11252	}
11253	if (rc == NULL)
11254		goto fail;
11255
11256	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11257	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11258
11259	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11260
11261	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11262		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11263		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11264	} else {
11265		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11266		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11267	}
11268
11269	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11270	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11271	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11272	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11273	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11274	bwn_phy_lp_set_deaf(mac, 0);
11275	/* XXX no checking return value? */
11276	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11277	bwn_phy_lp_clear_deaf(mac, 0);
11278	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11279	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11280	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11281
11282	/* disable RX GAIN override. */
11283	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11284	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11285	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11286	if (mac->mac_phy.rev >= 2) {
11287		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11288		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11289			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11290			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11291		}
11292	} else {
11293		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11294	}
11295
11296	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11297	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11298fail:
11299	bwn_mac_enable(mac);
11300}
11301
11302static void
11303bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11304{
11305
11306       if (on) {
11307               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11308	       return;
11309       }
11310
11311       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11312       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11313}
11314
11315static int
11316bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11317{
11318	struct siba_dev_softc *sd = mac->mac_sd;
11319	struct siba_softc *siba = sd->sd_bus;
11320	static const struct bwn_b206x_chan *bc = NULL;
11321	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11322	    tmp[6];
11323	uint16_t old, scale, tmp16;
11324	int i, div;
11325
11326	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11327		if (bwn_b2063_chantable[i].bc_chan == chan) {
11328			bc = &bwn_b2063_chantable[i];
11329			break;
11330		}
11331	}
11332	if (bc == NULL)
11333		return (EINVAL);
11334
11335	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11336	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11337	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11338	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11339	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11340	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11341	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11342	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11343	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11344	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11345	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11346	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11347
11348	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11349	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11350
11351	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11352	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11353	freqref = freqxtal * 3;
11354	div = (freqxtal <= 26000000 ? 1 : 2);
11355	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11356	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11357		999999) / 1000000) + 1;
11358
11359	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11360	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11361	    0xfff8, timeout >> 2);
11362	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11363	    0xff9f,timeout << 5);
11364	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11365
11366	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11367	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11368	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11369
11370	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11371	    (timeoutref + 1)) - 1;
11372	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11373	    0xf0, count >> 8);
11374	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11375
11376	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11377	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11378	while (tmp[1] >= freqref) {
11379		tmp[0]++;
11380		tmp[1] -= freqref;
11381	}
11382	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11383	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11384	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11385	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11386	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11387
11388	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11389	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11390	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11391	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11392
11393	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11394	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11395
11396	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11397		scale = 1;
11398		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11399	} else {
11400		scale = 0;
11401		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11402	}
11403	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11404	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11405
11406	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11407	    (scale + 1);
11408	if (tmp[5] > 150)
11409		tmp[5] = 0;
11410
11411	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11412	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11413
11414	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11415	if (freqxtal > 26000000)
11416		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11417	else
11418		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11419
11420	if (val[0] == 45)
11421		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11422	else
11423		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11424
11425	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11426	DELAY(1);
11427	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11428
11429	/* VCO Calibration */
11430	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11431	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11432	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11433	DELAY(1);
11434	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11435	DELAY(1);
11436	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11437	DELAY(1);
11438	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11439	DELAY(300);
11440	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11441
11442	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11443	return (0);
11444}
11445
11446static int
11447bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11448{
11449	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11450	struct siba_dev_softc *sd = mac->mac_sd;
11451	struct siba_softc *siba = sd->sd_bus;
11452	const struct bwn_b206x_chan *bc = NULL;
11453	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11454	uint32_t tmp[9];
11455	int i;
11456
11457	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11458		if (bwn_b2062_chantable[i].bc_chan == chan) {
11459			bc = &bwn_b2062_chantable[i];
11460			break;
11461		}
11462	}
11463
11464	if (bc == NULL)
11465		return (EINVAL);
11466
11467	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11468	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11469	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11470	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11471	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11472	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11473	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11474	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11475	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11476	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11477
11478	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11479	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11480	bwn_phy_lp_b2062_reset_pllbias(mac);
11481	tmp[0] = freqxtal / 1000;
11482	tmp[1] = plp->plp_div * 1000;
11483	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11484	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11485		tmp[2] *= 2;
11486	tmp[3] = 48 * tmp[0];
11487	tmp[5] = tmp[2] / tmp[3];
11488	tmp[6] = tmp[2] % tmp[3];
11489	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11490	tmp[4] = tmp[6] * 0x100;
11491	tmp[5] = tmp[4] / tmp[3];
11492	tmp[6] = tmp[4] % tmp[3];
11493	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11494	tmp[4] = tmp[6] * 0x100;
11495	tmp[5] = tmp[4] / tmp[3];
11496	tmp[6] = tmp[4] % tmp[3];
11497	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11498	tmp[4] = tmp[6] * 0x100;
11499	tmp[5] = tmp[4] / tmp[3];
11500	tmp[6] = tmp[4] % tmp[3];
11501	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11502	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11503	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11504	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11505	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11506	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11507
11508	bwn_phy_lp_b2062_vco_calib(mac);
11509	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11510		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11511		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11512		bwn_phy_lp_b2062_reset_pllbias(mac);
11513		bwn_phy_lp_b2062_vco_calib(mac);
11514		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11515			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11516			return (EIO);
11517		}
11518	}
11519	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11520	return (0);
11521}
11522
11523static void
11524bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11525{
11526	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11527	uint16_t tmp = (channel == 14);
11528
11529	if (mac->mac_phy.rev < 2) {
11530		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11531		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11532			bwn_phy_lp_set_rccap(mac);
11533		return;
11534	}
11535
11536	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11537}
11538
11539static void
11540bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11541{
11542	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11543	struct bwn_softc *sc = mac->mac_sc;
11544	struct ifnet *ifp = sc->sc_ifp;
11545	struct ieee80211com *ic = ifp->if_l2com;
11546	uint16_t iso, tmp[3];
11547
11548	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11549
11550	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11551		iso = plp->plp_txisoband_m;
11552	else if (freq <= 5320)
11553		iso = plp->plp_txisoband_l;
11554	else if (freq <= 5700)
11555		iso = plp->plp_txisoband_m;
11556	else
11557		iso = plp->plp_txisoband_h;
11558
11559	tmp[0] = ((iso - 26) / 12) << 12;
11560	tmp[1] = tmp[0] + 0x1000;
11561	tmp[2] = tmp[0] + 0x2000;
11562
11563	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11564	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11565}
11566
11567static void
11568bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11569{
11570	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11571	int i;
11572	static const uint16_t addr[] = {
11573		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11574		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11575		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11576		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11577		BWN_PHY_OFDM(0xcf),
11578	};
11579	static const uint16_t val[] = {
11580		0xde5e, 0xe832, 0xe331, 0x4d26,
11581		0x0026, 0x1420, 0x0020, 0xfe08,
11582		0x0008,
11583	};
11584
11585	for (i = 0; i < N(addr); i++) {
11586		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11587		BWN_PHY_WRITE(mac, addr[i], val[i]);
11588	}
11589}
11590
11591static void
11592bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11593{
11594	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11595	struct bwn_softc *sc = mac->mac_sc;
11596	uint16_t ctl;
11597
11598	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11599	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11600	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11601		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11602		break;
11603	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11604		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11605		break;
11606	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11607		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11608		break;
11609	default:
11610		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11611		device_printf(sc->sc_dev, "unknown command mode\n");
11612		break;
11613	}
11614}
11615
11616static void
11617bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11618{
11619	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11620	uint16_t ctl;
11621	uint8_t old;
11622
11623	bwn_phy_lp_get_txpctlmode(mac);
11624	old = plp->plp_txpctlmode;
11625	if (old == mode)
11626		return;
11627	plp->plp_txpctlmode = mode;
11628
11629	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11630		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11631		    plp->plp_tssiidx);
11632		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11633		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11634
11635		/* disable TX GAIN override */
11636		if (mac->mac_phy.rev < 2)
11637			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11638		else {
11639			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11640			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11641		}
11642		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11643
11644		plp->plp_txpwridx = -1;
11645	}
11646	if (mac->mac_phy.rev >= 2) {
11647		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11648			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11649		else
11650			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11651	}
11652
11653	/* writes TX Power Control mode */
11654	switch (plp->plp_txpctlmode) {
11655	case BWN_PHYLP_TXPCTL_OFF:
11656		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11657		break;
11658	case BWN_PHYLP_TXPCTL_ON_HW:
11659		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11660		break;
11661	case BWN_PHYLP_TXPCTL_ON_SW:
11662		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11663		break;
11664	default:
11665		ctl = 0;
11666		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11667	}
11668	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11669	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11670}
11671
11672static void
11673bwn_phy_lp_bugfix(struct bwn_mac *mac)
11674{
11675	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11676	struct bwn_softc *sc = mac->mac_sc;
11677	const unsigned int size = 256;
11678	struct bwn_txgain tg;
11679	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11680	uint16_t tssinpt, tssiidx, value[2];
11681	uint8_t mode;
11682	int8_t txpwridx;
11683
11684	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11685	    M_NOWAIT | M_ZERO);
11686	if (tabs == NULL) {
11687		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11688		return;
11689	}
11690
11691	bwn_phy_lp_get_txpctlmode(mac);
11692	mode = plp->plp_txpctlmode;
11693	txpwridx = plp->plp_txpwridx;
11694	tssinpt = plp->plp_tssinpt;
11695	tssiidx = plp->plp_tssiidx;
11696
11697	bwn_tab_read_multi(mac,
11698	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11699	    BWN_TAB_4(7, 0x140), size, tabs);
11700
11701	bwn_phy_lp_tblinit(mac);
11702	bwn_phy_lp_bbinit(mac);
11703	bwn_phy_lp_txpctl_init(mac);
11704	bwn_phy_lp_rf_onoff(mac, 1);
11705	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11706
11707	bwn_tab_write_multi(mac,
11708	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11709	    BWN_TAB_4(7, 0x140), size, tabs);
11710
11711	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11712	plp->plp_tssinpt = tssinpt;
11713	plp->plp_tssiidx = tssiidx;
11714	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11715	if (txpwridx != -1) {
11716		/* set TX power by index */
11717		plp->plp_txpwridx = txpwridx;
11718		bwn_phy_lp_get_txpctlmode(mac);
11719		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11720			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11721		if (mac->mac_phy.rev >= 2) {
11722			rxcomp = bwn_tab_read(mac,
11723			    BWN_TAB_4(7, txpwridx + 320));
11724			txgain = bwn_tab_read(mac,
11725			    BWN_TAB_4(7, txpwridx + 192));
11726			tg.tg_pad = (txgain >> 16) & 0xff;
11727			tg.tg_gm = txgain & 0xff;
11728			tg.tg_pga = (txgain >> 8) & 0xff;
11729			tg.tg_dac = (rxcomp >> 28) & 0xff;
11730			bwn_phy_lp_set_txgain(mac, &tg);
11731		} else {
11732			rxcomp = bwn_tab_read(mac,
11733			    BWN_TAB_4(10, txpwridx + 320));
11734			txgain = bwn_tab_read(mac,
11735			    BWN_TAB_4(10, txpwridx + 192));
11736			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11737			    0xf800, (txgain >> 4) & 0x7fff);
11738			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11739			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11740		}
11741		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11742
11743		/* set TX IQCC */
11744		value[0] = (rxcomp >> 10) & 0x3ff;
11745		value[1] = rxcomp & 0x3ff;
11746		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11747
11748		coeff = bwn_tab_read(mac,
11749		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11750		    BWN_TAB_4(10, txpwridx + 448));
11751		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11752		if (mac->mac_phy.rev >= 2) {
11753			rfpwr = bwn_tab_read(mac,
11754			    BWN_TAB_4(7, txpwridx + 576));
11755			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11756			    rfpwr & 0xffff);
11757		}
11758		bwn_phy_lp_set_txgain_override(mac);
11759	}
11760	if (plp->plp_rccap)
11761		bwn_phy_lp_set_rccap(mac);
11762	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11763	bwn_phy_lp_set_txpctlmode(mac, mode);
11764	free(tabs, M_DEVBUF);
11765}
11766
11767static void
11768bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11769{
11770	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11771	int i;
11772	static const uint16_t addr[] = {
11773		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11774		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11775		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11776		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11777		BWN_PHY_OFDM(0xcf),
11778	};
11779
11780	for (i = 0; i < N(addr); i++)
11781		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11782}
11783
11784static void
11785bwn_phy_lp_tblinit(struct bwn_mac *mac)
11786{
11787	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11788
11789	if (mac->mac_phy.rev < 2) {
11790		bwn_phy_lp_tblinit_r01(mac);
11791		bwn_phy_lp_tblinit_txgain(mac);
11792		bwn_phy_lp_set_gaintbl(mac, freq);
11793		return;
11794	}
11795
11796	bwn_phy_lp_tblinit_r2(mac);
11797	bwn_phy_lp_tblinit_txgain(mac);
11798}
11799
11800struct bwn_wpair {
11801	uint16_t		reg;
11802	uint16_t		value;
11803};
11804
11805struct bwn_smpair {
11806	uint16_t		offset;
11807	uint16_t		mask;
11808	uint16_t		set;
11809};
11810
11811static void
11812bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11813{
11814	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11815	struct siba_dev_softc *sd = mac->mac_sd;
11816	struct siba_softc *siba = sd->sd_bus;
11817	struct bwn_softc *sc = mac->mac_sc;
11818	struct ifnet *ifp = sc->sc_ifp;
11819	struct ieee80211com *ic = ifp->if_l2com;
11820	static const struct bwn_wpair v1[] = {
11821		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11822		{ BWN_PHY_AFE_CTL, 0x8800 },
11823		{ BWN_PHY_AFE_CTL_OVR, 0 },
11824		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11825		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11826		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11827		{ BWN_PHY_OFDM(0xf9), 0 },
11828		{ BWN_PHY_TR_LOOKUP_1, 0 }
11829	};
11830	static const struct bwn_smpair v2[] = {
11831		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11832		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11833		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11834		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11835		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11836	};
11837	static const struct bwn_smpair v3[] = {
11838		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11839		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11840		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11841		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11842		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11843		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11844		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11845		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11846		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11847		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11848
11849	};
11850	int i;
11851
11852	for (i = 0; i < N(v1); i++)
11853		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11854	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11855	for (i = 0; i < N(v2); i++)
11856		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11857
11858	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11859	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11860	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11861	if (siba->siba_board_rev >= 0x18) {
11862		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11863		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11864	} else {
11865		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11866	}
11867	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11868	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11869	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11870	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11871	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11872	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11873	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11874	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11875	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11876	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11878	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11879		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11880		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11881	} else {
11882		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11883		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11884	}
11885	for (i = 0; i < N(v3); i++)
11886		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11887	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11888		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11889		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11890	}
11891
11892	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11893		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11894		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11895		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11896		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11897		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11898		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11899	} else
11900		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11901
11902	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11903	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11904	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11905	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11906	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11907	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11908	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11909	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11910	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11911
11912	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11913		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11914		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11915		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11916	}
11917
11918	bwn_phy_lp_digflt_save(mac);
11919}
11920
11921static void
11922bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11923{
11924	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11925	struct siba_dev_softc *sd = mac->mac_sd;
11926	struct siba_softc *siba = sd->sd_bus;
11927	struct bwn_softc *sc = mac->mac_sc;
11928	struct ifnet *ifp = sc->sc_ifp;
11929	struct ieee80211com *ic = ifp->if_l2com;
11930	static const struct bwn_smpair v1[] = {
11931		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11932		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11933		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11934		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11935		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11936		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11937		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11938	};
11939	static const struct bwn_smpair v2[] = {
11940		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11941		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11942		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11943		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11944		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11945		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11946		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11947		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11948		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11949		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11950		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11951		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11952		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11953		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11954		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11955		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11956	};
11957	static const struct bwn_smpair v3[] = {
11958		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11959		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11960		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11961		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11962		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11963		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11964		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11965		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11966	};
11967	static const struct bwn_smpair v4[] = {
11968		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11969		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11970		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11971		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11972		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11973		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11974		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11975		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11976	};
11977	static const struct bwn_smpair v5[] = {
11978		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11979		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11980		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11981		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11982		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11983		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11984		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11985		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11986	};
11987	int i;
11988	uint16_t tmp, tmp2;
11989
11990	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11991	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11992	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11993	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11994	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11995	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11996	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11997	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11998	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11999	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12000	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12001	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12002	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12003	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12004	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12005	for (i = 0; i < N(v1); i++)
12006		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12007	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12008	    0xff00, plp->plp_rxpwroffset);
12009	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12010	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12011	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12012		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12013		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12014		if (mac->mac_phy.rev == 0)
12015			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12016			    0xffcf, 0x0010);
12017		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12018	} else {
12019		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12020		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12021		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12022	}
12023	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12024	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12025	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12026		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12027	else
12028		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12029	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12030	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12031	    0xfff9, (plp->plp_bxarch << 1));
12032	if (mac->mac_phy.rev == 1 &&
12033	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12034		for (i = 0; i < N(v2); i++)
12035			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12036			    v2[i].set);
12037	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12038	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12039	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12040		for (i = 0; i < N(v3); i++)
12041			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12042			    v3[i].set);
12043	} else if (mac->mac_phy.rev == 1 ||
12044		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12045		for (i = 0; i < N(v4); i++)
12046			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12047			    v4[i].set);
12048	} else {
12049		for (i = 0; i < N(v5); i++)
12050			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12051			    v5[i].set);
12052	}
12053	if (mac->mac_phy.rev == 1 &&
12054	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12055		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12056		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12057		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12058		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12059	}
12060	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12061	    (siba->siba_chipid == 0x5354) &&
12062	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12063		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12064		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12065		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12066		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12067	}
12068	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12069		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12070		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12071		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12072		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12073		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12074		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12075		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12076		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12077	} else {
12078		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12079		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12080	}
12081	if (mac->mac_phy.rev == 1) {
12082		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12083		tmp2 = (tmp & 0x03e0) >> 5;
12084		tmp2 |= tmp2 << 5;
12085		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12086		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12087		tmp2 = (tmp & 0x1f00) >> 8;
12088		tmp2 |= tmp2 << 5;
12089		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12090		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12091		tmp2 = tmp & 0x00ff;
12092		tmp2 |= tmp << 8;
12093		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12094	}
12095}
12096
12097struct bwn_b2062_freq {
12098	uint16_t		freq;
12099	uint8_t			value[6];
12100};
12101
12102static void
12103bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12104{
12105#define	CALC_CTL7(freq, div)						\
12106	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12107#define	CALC_CTL18(freq, div)						\
12108	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12109#define	CALC_CTL19(freq, div)						\
12110	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12111	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12112	struct siba_dev_softc *sd = mac->mac_sd;
12113	struct siba_softc *siba = sd->sd_bus;
12114	struct bwn_softc *sc = mac->mac_sc;
12115	struct ifnet *ifp = sc->sc_ifp;
12116	struct ieee80211com *ic = ifp->if_l2com;
12117	static const struct bwn_b2062_freq freqdata_tab[] = {
12118		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12119		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12120		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12121		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12122		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12123		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12124	};
12125	static const struct bwn_wpair v1[] = {
12126		{ BWN_B2062_N_TXCTL3, 0 },
12127		{ BWN_B2062_N_TXCTL4, 0 },
12128		{ BWN_B2062_N_TXCTL5, 0 },
12129		{ BWN_B2062_N_TXCTL6, 0 },
12130		{ BWN_B2062_N_PDNCTL0, 0x40 },
12131		{ BWN_B2062_N_PDNCTL0, 0 },
12132		{ BWN_B2062_N_CALIB_TS, 0x10 },
12133		{ BWN_B2062_N_CALIB_TS, 0 }
12134	};
12135	const struct bwn_b2062_freq *f = NULL;
12136	uint32_t xtalfreq, ref;
12137	unsigned int i;
12138
12139	bwn_phy_lp_b2062_tblinit(mac);
12140
12141	for (i = 0; i < N(v1); i++)
12142		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12143	if (mac->mac_phy.rev > 0)
12144		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12145		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12146	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12147		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12148	else
12149		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12150
12151	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12152	    ("%s:%d: fail", __func__, __LINE__));
12153	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12154	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12155
12156	if (xtalfreq <= 30000000) {
12157		plp->plp_div = 1;
12158		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12159	} else {
12160		plp->plp_div = 2;
12161		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12162	}
12163
12164	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12165	    CALC_CTL7(xtalfreq, plp->plp_div));
12166	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12167	    CALC_CTL18(xtalfreq, plp->plp_div));
12168	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12169	    CALC_CTL19(xtalfreq, plp->plp_div));
12170
12171	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12172	ref &= 0xffff;
12173	for (i = 0; i < N(freqdata_tab); i++) {
12174		if (ref < freqdata_tab[i].freq) {
12175			f = &freqdata_tab[i];
12176			break;
12177		}
12178	}
12179	if (f == NULL)
12180		f = &freqdata_tab[N(freqdata_tab) - 1];
12181	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12182	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12183	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12184	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12185	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12186	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12187#undef CALC_CTL7
12188#undef CALC_CTL18
12189#undef CALC_CTL19
12190}
12191
12192static void
12193bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12194{
12195
12196	bwn_phy_lp_b2063_tblinit(mac);
12197	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12198	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12199	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12200	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12201	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12202	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12203	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12204	if (mac->mac_phy.rev == 2) {
12205		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12206		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12207		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12208	} else {
12209		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12210		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12211	}
12212}
12213
12214static void
12215bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12216{
12217	struct siba_dev_softc *sd = mac->mac_sd;
12218	struct siba_softc *siba = sd->sd_bus;
12219	static const struct bwn_wpair v1[] = {
12220		{ BWN_B2063_RX_BB_SP8, 0x0 },
12221		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12222		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12223		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12224		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12225		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12226		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12227		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12228	};
12229	static const struct bwn_wpair v2[] = {
12230		{ BWN_B2063_TX_BB_SP3, 0x0 },
12231		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12232		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12233		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12234		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12235	};
12236	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12237	int i;
12238	uint8_t tmp;
12239
12240	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12241
12242	for (i = 0; i < 2; i++)
12243		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12244	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12245	for (i = 2; i < N(v1); i++)
12246		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12247	for (i = 0; i < 10000; i++) {
12248		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12249			break;
12250		DELAY(1000);
12251	}
12252
12253	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12254		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12255
12256	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12257
12258	for (i = 0; i < N(v2); i++)
12259		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12260	if (freqxtal == 24000000) {
12261		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12262		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12263	} else {
12264		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12265		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12266	}
12267	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12268	for (i = 0; i < 10000; i++) {
12269		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12270			break;
12271		DELAY(1000);
12272	}
12273	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12274		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12275	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12276}
12277
12278static void
12279bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12280{
12281	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12282	struct bwn_softc *sc = mac->mac_sc;
12283	struct bwn_phy_lp_iq_est ie;
12284	struct bwn_txgain tx_gains;
12285	static const uint32_t pwrtbl[21] = {
12286		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12287		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12288		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12289		0x0004c, 0x0002c, 0x0001a,
12290	};
12291	uint32_t npwr, ipwr, sqpwr, tmp;
12292	int loopback, i, j, sum, error;
12293	uint16_t save[7];
12294	uint8_t txo, bbmult, txpctlmode;
12295
12296	error = bwn_phy_lp_switch_channel(mac, 7);
12297	if (error)
12298		device_printf(sc->sc_dev,
12299		    "failed to change channel to 7 (%d)\n", error);
12300	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12301	bbmult = bwn_phy_lp_get_bbmult(mac);
12302	if (txo)
12303		tx_gains = bwn_phy_lp_get_txgain(mac);
12304
12305	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12306	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12307	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12308	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12309	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12310	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12311	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12312
12313	bwn_phy_lp_get_txpctlmode(mac);
12314	txpctlmode = plp->plp_txpctlmode;
12315	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12316
12317	/* disable CRS */
12318	bwn_phy_lp_set_deaf(mac, 1);
12319	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12320	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12321	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12322	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12323	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12324	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12325	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12326	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12327	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12328	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12329	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12330	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12331	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12332	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12333	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12335	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12336	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12337	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12338	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12339	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12340	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12341	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12342	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12343
12344	loopback = bwn_phy_lp_loopback(mac);
12345	if (loopback == -1)
12346		goto done;
12347	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12348	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12349	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12350	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12351	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12352
12353	tmp = 0;
12354	memset(&ie, 0, sizeof(ie));
12355	for (i = 128; i <= 159; i++) {
12356		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12357		sum = 0;
12358		for (j = 5; j <= 25; j++) {
12359			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12360			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12361				goto done;
12362			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12363			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12364			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12365			    12);
12366			sum += ((ipwr - npwr) * (ipwr - npwr));
12367			if ((i == 128) || (sum < tmp)) {
12368				plp->plp_rccap = i;
12369				tmp = sum;
12370			}
12371		}
12372	}
12373	bwn_phy_lp_ddfs_turnoff(mac);
12374done:
12375	/* restore CRS */
12376	bwn_phy_lp_clear_deaf(mac, 1);
12377	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12378	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12379
12380	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12381	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12382	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12383	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12384	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12385	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12386	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12387
12388	bwn_phy_lp_set_bbmult(mac, bbmult);
12389	if (txo)
12390		bwn_phy_lp_set_txgain(mac, &tx_gains);
12391	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12392	if (plp->plp_rccap)
12393		bwn_phy_lp_set_rccap(mac);
12394}
12395
12396static void
12397bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12398{
12399	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12400	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12401
12402	if (mac->mac_phy.rev == 1)
12403		rc_cap = MIN(rc_cap + 5, 15);
12404
12405	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12406	    MAX(plp->plp_rccap - 4, 0x80));
12407	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12408	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12409	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12410}
12411
12412static uint32_t
12413bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12414{
12415	uint32_t i, q, r;
12416
12417	if (div == 0)
12418		return (0);
12419
12420	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12421		q <<= 1;
12422		if (r << 1 >= div) {
12423			q++;
12424			r = (r << 1) - div;
12425		}
12426	}
12427	if (r << 1 >= div)
12428		q++;
12429	return (q);
12430}
12431
12432static void
12433bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12434{
12435	struct siba_dev_softc *sd = mac->mac_sd;
12436	struct siba_softc *siba = sd->sd_bus;
12437
12438	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12439	DELAY(20);
12440	if (siba->siba_chipid == 0x5354) {
12441		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12442		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12443	} else {
12444		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12445	}
12446	DELAY(5);
12447}
12448
12449static void
12450bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12451{
12452
12453	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12454	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12455	DELAY(200);
12456}
12457
12458static void
12459bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12460{
12461#define	FLAG_A	0x01
12462#define	FLAG_G	0x02
12463	struct bwn_softc *sc = mac->mac_sc;
12464	struct ifnet *ifp = sc->sc_ifp;
12465	struct ieee80211com *ic = ifp->if_l2com;
12466	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12467		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12468		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12469		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12470		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12471		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12472		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12473		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12474		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12475		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12476		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12478		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12479		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12480		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12481		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12514	};
12515	const struct bwn_b206x_rfinit_entry *br;
12516	unsigned int i;
12517
12518	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12519		br = &bwn_b2062_init_tab[i];
12520		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12521			if (br->br_flags & FLAG_G)
12522				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12523		} else {
12524			if (br->br_flags & FLAG_A)
12525				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12526		}
12527	}
12528#undef FLAG_A
12529#undef FLAG_B
12530}
12531
12532static void
12533bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12534{
12535#define	FLAG_A	0x01
12536#define	FLAG_G	0x02
12537	struct bwn_softc *sc = mac->mac_sc;
12538	struct ifnet *ifp = sc->sc_ifp;
12539	struct ieee80211com *ic = ifp->if_l2com;
12540	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12541		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12542		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12543		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12544		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12545		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12546		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12547		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12548		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12549		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12550		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12552		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12553		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12554		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12555		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12556		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12557		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12558		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12559		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12560		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12561		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12562		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12563		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12564		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12565		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12566		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12570		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12571		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12574		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12576		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12582		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12583	};
12584	const struct bwn_b206x_rfinit_entry *br;
12585	unsigned int i;
12586
12587	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12588		br = &bwn_b2063_init_tab[i];
12589		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12590			if (br->br_flags & FLAG_G)
12591				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12592		} else {
12593			if (br->br_flags & FLAG_A)
12594				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12595		}
12596	}
12597#undef FLAG_A
12598#undef FLAG_B
12599}
12600
12601static void
12602bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12603    int count, void *_data)
12604{
12605	unsigned int i;
12606	uint32_t offset, type;
12607	uint8_t *data = _data;
12608
12609	type = BWN_TAB_GETTYPE(typenoffset);
12610	offset = BWN_TAB_GETOFFSET(typenoffset);
12611	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12612
12613	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12614
12615	for (i = 0; i < count; i++) {
12616		switch (type) {
12617		case BWN_TAB_8BIT:
12618			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12619			data++;
12620			break;
12621		case BWN_TAB_16BIT:
12622			*((uint16_t *)data) = BWN_PHY_READ(mac,
12623			    BWN_PHY_TABLEDATALO);
12624			data += 2;
12625			break;
12626		case BWN_TAB_32BIT:
12627			*((uint32_t *)data) = BWN_PHY_READ(mac,
12628			    BWN_PHY_TABLEDATAHI);
12629			*((uint32_t *)data) <<= 16;
12630			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12631			    BWN_PHY_TABLEDATALO);
12632			data += 4;
12633			break;
12634		default:
12635			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12636		}
12637	}
12638}
12639
12640static void
12641bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12642    int count, const void *_data)
12643{
12644	uint32_t offset, type, value;
12645	const uint8_t *data = _data;
12646	unsigned int i;
12647
12648	type = BWN_TAB_GETTYPE(typenoffset);
12649	offset = BWN_TAB_GETOFFSET(typenoffset);
12650	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12651
12652	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12653
12654	for (i = 0; i < count; i++) {
12655		switch (type) {
12656		case BWN_TAB_8BIT:
12657			value = *data;
12658			data++;
12659			KASSERT(!(value & ~0xff),
12660			    ("%s:%d: fail", __func__, __LINE__));
12661			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12662			break;
12663		case BWN_TAB_16BIT:
12664			value = *((const uint16_t *)data);
12665			data += 2;
12666			KASSERT(!(value & ~0xffff),
12667			    ("%s:%d: fail", __func__, __LINE__));
12668			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12669			break;
12670		case BWN_TAB_32BIT:
12671			value = *((const uint32_t *)data);
12672			data += 4;
12673			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12674			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12675			break;
12676		default:
12677			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12678		}
12679	}
12680}
12681
12682static struct bwn_txgain
12683bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12684{
12685	struct bwn_txgain tg;
12686	uint16_t tmp;
12687
12688	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12689	if (mac->mac_phy.rev < 2) {
12690		tmp = BWN_PHY_READ(mac,
12691		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12692		tg.tg_gm = tmp & 0x0007;
12693		tg.tg_pga = (tmp & 0x0078) >> 3;
12694		tg.tg_pad = (tmp & 0x780) >> 7;
12695		return (tg);
12696	}
12697
12698	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12699	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12700	tg.tg_gm = tmp & 0xff;
12701	tg.tg_pga = (tmp >> 8) & 0xff;
12702	return (tg);
12703}
12704
12705static uint8_t
12706bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12707{
12708
12709	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12710}
12711
12712static void
12713bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12714{
12715	uint16_t pa;
12716
12717	if (mac->mac_phy.rev < 2) {
12718		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12719		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12720		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12721		bwn_phy_lp_set_txgain_override(mac);
12722		return;
12723	}
12724
12725	pa = bwn_phy_lp_get_pa_gain(mac);
12726	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12727	    (tg->tg_pga << 8) | tg->tg_gm);
12728	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12729	    tg->tg_pad | (pa << 6));
12730	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12731	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12732	    tg->tg_pad | (pa << 8));
12733	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12734	bwn_phy_lp_set_txgain_override(mac);
12735}
12736
12737static void
12738bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12739{
12740
12741	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12742}
12743
12744static void
12745bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12746{
12747	uint16_t trsw = (tx << 1) | rx;
12748
12749	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12750	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12751}
12752
12753static void
12754bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12755{
12756	struct bwn_softc *sc = mac->mac_sc;
12757	struct ifnet *ifp = sc->sc_ifp;
12758	struct ieee80211com *ic = ifp->if_l2com;
12759	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12760
12761	if (mac->mac_phy.rev < 2) {
12762		trsw = gain & 0x1;
12763		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12764		ext_lna = (gain & 2) >> 1;
12765
12766		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12767		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12768		    0xfbff, ext_lna << 10);
12769		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12770		    0xf7ff, ext_lna << 11);
12771		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12772	} else {
12773		low_gain = gain & 0xffff;
12774		high_gain = (gain >> 16) & 0xf;
12775		ext_lna = (gain >> 21) & 0x1;
12776		trsw = ~(gain >> 20) & 0x1;
12777
12778		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12779		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12780		    0xfdff, ext_lna << 9);
12781		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12782		    0xfbff, ext_lna << 10);
12783		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12784		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12785		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12786			tmp = (gain >> 2) & 0x3;
12787			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12788			    0xe7ff, tmp<<11);
12789			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12790			    tmp << 3);
12791		}
12792	}
12793
12794	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12795	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12796	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12797	if (mac->mac_phy.rev >= 2) {
12798		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12799		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12800			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12801			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12802		}
12803		return;
12804	}
12805	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12806}
12807
12808static void
12809bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12810{
12811	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12812
12813	if (user)
12814		plp->plp_crsusr_off = 1;
12815	else
12816		plp->plp_crssys_off = 1;
12817
12818	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12819}
12820
12821static void
12822bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12823{
12824	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12825	struct bwn_softc *sc = mac->mac_sc;
12826	struct ifnet *ifp = sc->sc_ifp;
12827	struct ieee80211com *ic = ifp->if_l2com;
12828
12829	if (user)
12830		plp->plp_crsusr_off = 0;
12831	else
12832		plp->plp_crssys_off = 0;
12833
12834	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12835		return;
12836
12837	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12838		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12839	else
12840		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12841}
12842
12843static unsigned int
12844bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12845{
12846	struct bwn_softc *sc = mac->mac_sc;
12847	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12848	static uint8_t sqrt_table[256] = {
12849		10, 14, 17, 20, 22, 24, 26, 28,
12850		30, 31, 33, 34, 36, 37, 38, 40,
12851		41, 42, 43, 44, 45, 46, 47, 48,
12852		50, 50, 51, 52, 53, 54, 55, 56,
12853		57, 58, 59, 60, 60, 61, 62, 63,
12854		64, 64, 65, 66, 67, 67, 68, 69,
12855		70, 70, 71, 72, 72, 73, 74, 74,
12856		75, 76, 76, 77, 78, 78, 79, 80,
12857		80, 81, 81, 82, 83, 83, 84, 84,
12858		85, 86, 86, 87, 87, 88, 88, 89,
12859		90, 90, 91, 91, 92, 92, 93, 93,
12860		94, 94, 95, 95, 96, 96, 97, 97,
12861		98, 98, 99, 100, 100, 100, 101, 101,
12862		102, 102, 103, 103, 104, 104, 105, 105,
12863		106, 106, 107, 107, 108, 108, 109, 109,
12864		110, 110, 110, 111, 111, 112, 112, 113,
12865		113, 114, 114, 114, 115, 115, 116, 116,
12866		117, 117, 117, 118, 118, 119, 119, 120,
12867		120, 120, 121, 121, 122, 122, 122, 123,
12868		123, 124, 124, 124, 125, 125, 126, 126,
12869		126, 127, 127, 128, 128, 128, 129, 129,
12870		130, 130, 130, 131, 131, 131, 132, 132,
12871		133, 133, 133, 134, 134, 134, 135, 135,
12872		136, 136, 136, 137, 137, 137, 138, 138,
12873		138, 139, 139, 140, 140, 140, 141, 141,
12874		141, 142, 142, 142, 143, 143, 143, 144,
12875		144, 144, 145, 145, 145, 146, 146, 146,
12876		147, 147, 147, 148, 148, 148, 149, 149,
12877		150, 150, 150, 150, 151, 151, 151, 152,
12878		152, 152, 153, 153, 153, 154, 154, 154,
12879		155, 155, 155, 156, 156, 156, 157, 157,
12880		157, 158, 158, 158, 159, 159, 159, 160
12881	};
12882
12883	if (x == 0)
12884		return (0);
12885	if (x >= 256) {
12886		device_printf(sc->sc_dev,
12887		    "out of bounds of the square-root table (%d)\n", x);
12888		return (16);
12889	}
12890	return (sqrt_table[x - 1] / 10);
12891}
12892
12893static int
12894bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12895{
12896#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12897	int _t;								\
12898	_t = _x - 20;							\
12899	if (_t >= 0) {							\
12900		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12901	} else {							\
12902		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12903	}								\
12904} while (0)
12905#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12906	int _t;								\
12907	_t = _x - 11;							\
12908	if (_t >= 0)							\
12909		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12910	else								\
12911		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12912} while (0)
12913	struct bwn_phy_lp_iq_est ie;
12914	uint16_t v0, v1;
12915	int tmp[2], ret;
12916
12917	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12918	v0 = v1 >> 8;
12919	v1 |= 0xff;
12920
12921	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12922	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12923
12924	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12925	if (ret == 0)
12926		goto done;
12927
12928	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12929		ret = 0;
12930		goto done;
12931	}
12932
12933	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12934	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12935
12936	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12937	v0 = tmp[0] >> 3;
12938	v1 = tmp[1] >> 4;
12939done:
12940	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12941	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12942	return ret;
12943#undef CALC_COEFF
12944#undef CALC_COEFF2
12945}
12946
12947static void
12948bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12949{
12950	static const uint16_t noisescale[] = {
12951		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12952		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12953		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12954		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12955		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12956	};
12957	static const uint16_t crsgainnft[] = {
12958		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12959		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12960		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12961		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12962		0x013d,
12963	};
12964	static const uint16_t filterctl[] = {
12965		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12966		0xff53, 0x0127,
12967	};
12968	static const uint32_t psctl[] = {
12969		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12970		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12971		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12972		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12973		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12974		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12975		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12976		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12977	};
12978	static const uint16_t ofdmcckgain_r0[] = {
12979		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12980		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12981		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12982		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12983		0x755d,
12984	};
12985	static const uint16_t ofdmcckgain_r1[] = {
12986		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12987		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12988		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12989		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12990		0x755d,
12991	};
12992	static const uint16_t gaindelta[] = {
12993		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12994		0x0000,
12995	};
12996	static const uint32_t txpwrctl[] = {
12997		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12998		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12999		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13000		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13001		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13002		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13003		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13004		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13005		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13006		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13007		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13008		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13009		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13010		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13011		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
13036		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13037		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13038		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13039		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13040		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13041		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13042		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13043		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13044		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13045		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13046		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13047		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13048		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13049		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13050		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13051		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13052		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13053		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13054		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13055		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13056		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13057		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13058		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13059		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13060		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13061		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13062		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
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, 0x000000ff, 0x000002fc,
13087		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13088		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13089		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13090		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13091		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13092		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13093		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13094		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13095		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13096		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13097		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13098		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13099		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13100		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13101		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13102		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13103		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13104		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13105		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13106		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13107		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13108		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13109		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13110		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13111		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13112		0x00000702,
13113	};
13114
13115	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13116
13117	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13118	    bwn_tab_sigsq_tbl);
13119	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13120	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13121	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13122	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13123	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13124	    bwn_tab_pllfrac_tbl);
13125	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13126	    bwn_tabl_iqlocal_tbl);
13127	if (mac->mac_phy.rev == 0) {
13128		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13129		    ofdmcckgain_r0);
13130		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13131		    ofdmcckgain_r0);
13132	} else {
13133		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13134		    ofdmcckgain_r1);
13135		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13136		    ofdmcckgain_r1);
13137	}
13138	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13139	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13140}
13141
13142static void
13143bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13144{
13145	struct siba_dev_softc *sd = mac->mac_sd;
13146	struct siba_softc *siba = sd->sd_bus;
13147	int i;
13148	static const uint16_t noisescale[] = {
13149		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13150		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13151		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13152		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13153		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13154		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13155		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13156	};
13157	static const uint32_t filterctl[] = {
13158		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13159		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13160	};
13161	static const uint32_t psctl[] = {
13162		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13163		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13164		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13165		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13166	};
13167	static const uint32_t gainidx[] = {
13168		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13169		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13170		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13171		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13172		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13173		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13174		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13175		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13176		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13177		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13178		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13179		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13180		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13181		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13182		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13183		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13184		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13185		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13186		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13187		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13188		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13189		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13190		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13191		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13192		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13193		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13194		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13195		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13196		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13197		0x0000001a, 0x64ca55ad, 0x0000001a
13198	};
13199	static const uint16_t auxgainidx[] = {
13200		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13202		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13203		0x0004, 0x0016
13204	};
13205	static const uint16_t swctl[] = {
13206		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13207		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13208		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13209		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13210		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13211		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13212		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13213		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13214	};
13215	static const uint8_t hf[] = {
13216		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13217		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13218	};
13219	static const uint32_t gainval[] = {
13220		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13221		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13222		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13223		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13224		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13225		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13226		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13227		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13228		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13230		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13231		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13232		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13233		0x000000f1, 0x00000000, 0x00000000
13234	};
13235	static const uint16_t gain[] = {
13236		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13237		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13238		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13239		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13240		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13241		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13242		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13243		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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	};
13249	static const uint32_t papdeps[] = {
13250		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13251		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13252		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13253		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13254		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13255		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13256		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13257		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13258		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13259		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13260		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13261		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13262		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13263	};
13264	static const uint32_t papdmult[] = {
13265		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13266		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13267		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13268		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13269		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13270		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13271		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13272		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13273		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13274		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13275		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13276		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13277		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13278	};
13279	static const uint32_t gainidx_a0[] = {
13280		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13281		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13282		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13283		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13284		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13285		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13286		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13287		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13288		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13289		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13290		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13291		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13292		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13293	};
13294	static const uint16_t auxgainidx_a0[] = {
13295		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13296		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13297		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13298		0x0002, 0x0014
13299	};
13300	static const uint32_t gainval_a0[] = {
13301		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13302		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13303		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13304		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13305		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13306		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13307		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13308		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13309		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13310		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13311		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13312		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13313		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13314		0x000000f7, 0x00000000, 0x00000000
13315	};
13316	static const uint16_t gain_a0[] = {
13317		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13318		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13319		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13320		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13321		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13322		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13323		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13324		0x0000, 0x0000, 0x0000, 0x0000, 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	};
13330
13331	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13332
13333	for (i = 0; i < 704; i++)
13334		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13335
13336	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13337	    bwn_tab_sigsq_tbl);
13338	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13339	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13340	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13341	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13342	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13343	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13344	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13345	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13346	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13347	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13348	    bwn_tab_pllfrac_tbl);
13349	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13350	    bwn_tabl_iqlocal_tbl);
13351	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13352	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13353
13354	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13355		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13356		    gainidx_a0);
13357		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13358		    auxgainidx_a0);
13359		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13360		    gainval_a0);
13361		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13362	}
13363}
13364
13365static void
13366bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13367{
13368	struct siba_dev_softc *sd = mac->mac_sd;
13369	struct siba_softc *siba = sd->sd_bus;
13370	struct bwn_softc *sc = mac->mac_sc;
13371	struct ifnet *ifp = sc->sc_ifp;
13372	struct ieee80211com *ic = ifp->if_l2com;
13373	static struct bwn_txgain_entry txgain_r2[] = {
13374		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13375		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13376		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13377		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13378		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13379		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13380		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13381		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13382		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13383		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13384		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13385		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13386		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13387		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13388		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13389		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13390		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13391		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13392		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13393		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13394		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13395		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13396		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13397		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13398		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13399		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13400		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13401		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13402		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13403		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13404		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13405		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13406		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13407		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13408		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13409		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13410		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13411		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13412		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13413		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13414		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13415		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13416		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13417		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13418		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13419		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13420		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13421		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13422		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13423		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13424		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13425		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13426		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13427		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13428		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13429		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13430		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13431		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13432		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13433		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13434		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13435		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13436		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13437		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13438	};
13439	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13440		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13441		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13442		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13443		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13444		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13445		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13446		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13447		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13448		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13449		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13450		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13451		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13452		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13453		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13454		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13455		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13456		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13457		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13458		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13459		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13460		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13461		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13462		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13463		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13464		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13465		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13466		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13467		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13468		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13469		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13470		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13471		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13472		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13473		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13474		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13475		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13476		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13477		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13478		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13479		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13480		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13481		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13482		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13483		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13484		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13485		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13486		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13487		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13488		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13489		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13490		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13491		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13492		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13493		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13494		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13495		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13496		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13497		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13498		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13499		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13500		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13501		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13502		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13503		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13504	};
13505	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13506		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13507		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13508		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13509		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13510		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13511		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13512		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13513		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13514		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13515		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13516		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13517		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13518		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13519		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13520		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13521		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13522		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13523		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13524		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13525		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13526		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13527		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13528		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13529		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13530		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13531		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13532		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13533		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13534		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13535		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13536		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13537		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13538		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13539		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13540		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13541		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13542		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13543		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13544		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13545		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13546		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13547		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13548		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13549		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13550		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13551		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13552		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13553		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13554		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13555		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13556		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13557		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13558		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13559		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13560		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13561		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13562		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13563		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13564		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13565		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13566		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13567		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13568		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13569		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13570	};
13571	static struct bwn_txgain_entry txgain_r0[] = {
13572		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13573		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13574		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13575		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13576		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13577		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13578		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13579		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13580		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13581		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13582		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13583		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13584		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13585		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13586		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13587		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13588		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13589		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13590		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13591		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13592		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13593		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13594		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13595		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13596		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13597		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13598		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13599		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13600		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13601		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13602		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13603		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13604		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13605		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13606		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13607		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13608		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13609		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13610		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13611		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13612		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13613		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13614		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13615		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13616		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13617		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13618		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13619		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13620		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13621		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13622		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13623		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13624		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13625		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13626		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13627		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13628		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13629		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13630		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13631		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13632		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13633		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13634		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13635		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13636	};
13637	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13638		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13639		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13640		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13641		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13642		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13643		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13644		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13645		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13646		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13647		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13648		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13649		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13650		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13651		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13652		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13653		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13654		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13655		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13656		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13657		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13658		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13659		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13660		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13661		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13662		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13663		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13664		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13665		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13666		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13667		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13668		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13669		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13670		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13671		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13672		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13673		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13674		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13675		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13676		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13677		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13678		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13679		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13680		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13681		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13682		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13683		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13684		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13685		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13686		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13687		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13688		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13689		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13690		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13691		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13692		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13693		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13694		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13695		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13696		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13697		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13698		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13699		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13700		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13701		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13702	};
13703	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13704		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13705		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13706		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13707		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13708		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13709		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13710		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13711		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13712		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13713		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13714		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13715		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13716		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13717		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13718		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13719		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13720		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13721		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13722		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13723		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13724		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13725		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13726		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13727		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13728		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13729		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13730		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13731		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13732		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13733		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13734		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13735		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13736		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13737		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13738		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13739		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13740		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13741		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13742		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13743		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13744		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13745		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13746		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13747		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13748		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13749		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13750		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13751		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13752		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13753		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13754		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13755		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13756		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13757		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13758		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13759		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13760		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13761		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13762		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13763		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13764		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13765		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13766		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13767		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13768	};
13769	static struct bwn_txgain_entry txgain_r1[] = {
13770		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13771		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13772		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13773		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13774		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13775		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13776		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13777		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13778		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13779		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13780		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13781		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13782		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13783		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13784		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13785		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13786		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13787		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13788		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13789		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13790		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13791		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13792		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13793		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13794		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13795		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13796		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13797		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13798		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13799		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13800		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13801		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13802		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13803		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13804		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13805		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13806		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13807		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13808		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13809		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13810		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13811		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13812		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13813		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13814		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13815		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13816		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13817		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13818		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13819		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13820		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13821		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13822		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13823		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13824		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13825		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13826		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13827		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13828		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13829		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13830		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13831		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13832		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13833		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13834		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13835		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13836		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13837		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13838		{ 7, 11, 6, 0, 71 }
13839	};
13840	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13841		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13842		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13843		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13844		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13845		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13846		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13847		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13848		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13849		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13850		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13851		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13852		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13853		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13854		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13855		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13856		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13857		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13858		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13859		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13860		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13861		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13862		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13863		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13864		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13865		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13866		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13867		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13868		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13869		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13870		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13871		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13872		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13873		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13874		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13875		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13876		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13877		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13878		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13879		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13880		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13881		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13882		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13883		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13884		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13885		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13886		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13887		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13888		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13889		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13890		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13891		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13892		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13893		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13894		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13895		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13896		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13897		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13898		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13899		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13900		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13901		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13902		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13903		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13904		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13905	};
13906	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13907		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13908		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13909		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13910		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13911		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13912		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13913		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13914		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13915		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13916		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13917		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13918		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13919		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13920		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13921		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13922		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13923		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13924		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13925		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13926		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13927		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13928		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13929		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13930		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13931		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13932		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13933		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13934		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13935		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13936		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13937		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13938		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13939		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13940		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13941		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13942		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13943		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13944		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13945		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13946		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13947		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13948		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13949		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13950		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13951		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13952		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13953		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13954		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13955		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13956		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13957		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13958		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13959		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13960		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13961		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13962		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13963		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13964		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13965		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13966		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13967		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13968		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13969		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13970		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13971	};
13972
13973	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13974		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13975			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13976		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13977			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13978			    txgain_2ghz_r2);
13979		else
13980			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13981			    txgain_5ghz_r2);
13982		return;
13983	}
13984
13985	if (mac->mac_phy.rev == 0) {
13986		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13987		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13988			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13989		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13990			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13991			    txgain_2ghz_r0);
13992		else
13993			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13994			    txgain_5ghz_r0);
13995		return;
13996	}
13997
13998	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13999	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14000		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14001	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14002		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14003	else
14004		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14005}
14006
14007static void
14008bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14009{
14010	uint32_t offset, type;
14011
14012	type = BWN_TAB_GETTYPE(typeoffset);
14013	offset = BWN_TAB_GETOFFSET(typeoffset);
14014	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14015
14016	switch (type) {
14017	case BWN_TAB_8BIT:
14018		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14019		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14020		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14021		break;
14022	case BWN_TAB_16BIT:
14023		KASSERT(!(value & ~0xffff),
14024		    ("%s:%d: fail", __func__, __LINE__));
14025		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14026		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14027		break;
14028	case BWN_TAB_32BIT:
14029		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14030		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14031		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14032		break;
14033	default:
14034		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14035	}
14036}
14037
14038static int
14039bwn_phy_lp_loopback(struct bwn_mac *mac)
14040{
14041	struct bwn_phy_lp_iq_est ie;
14042	int i, index = -1;
14043	uint32_t tmp;
14044
14045	memset(&ie, 0, sizeof(ie));
14046
14047	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14048	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14049	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14050	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14051	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14052	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14053	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14054	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14055	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14056	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14057	for (i = 0; i < 32; i++) {
14058		bwn_phy_lp_set_rxgain_idx(mac, i);
14059		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14060		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14061			continue;
14062		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14063		if ((tmp > 4000) && (tmp < 10000)) {
14064			index = i;
14065			break;
14066		}
14067	}
14068	bwn_phy_lp_ddfs_turnoff(mac);
14069	return (index);
14070}
14071
14072static void
14073bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14074{
14075
14076	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14077}
14078
14079static void
14080bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14081    int incr1, int incr2, int scale_idx)
14082{
14083
14084	bwn_phy_lp_ddfs_turnoff(mac);
14085	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14086	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14087	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14088	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14089	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14090	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14091	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14092	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14093	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14094	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14095}
14096
14097static uint8_t
14098bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14099    struct bwn_phy_lp_iq_est *ie)
14100{
14101	int i;
14102
14103	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14104	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14105	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14106	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14107	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14108
14109	for (i = 0; i < 500; i++) {
14110		if (!(BWN_PHY_READ(mac,
14111		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14112			break;
14113		DELAY(1000);
14114	}
14115	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14116		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14117		return 0;
14118	}
14119
14120	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14121	ie->ie_iqprod <<= 16;
14122	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14123	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14124	ie->ie_ipwr <<= 16;
14125	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14126	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14127	ie->ie_qpwr <<= 16;
14128	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14129
14130	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14131	return 1;
14132}
14133
14134static uint32_t
14135bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14136{
14137	uint32_t offset, type, value;
14138
14139	type = BWN_TAB_GETTYPE(typeoffset);
14140	offset = BWN_TAB_GETOFFSET(typeoffset);
14141	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14142
14143	switch (type) {
14144	case BWN_TAB_8BIT:
14145		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14146		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14147		break;
14148	case BWN_TAB_16BIT:
14149		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14150		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14151		break;
14152	case BWN_TAB_32BIT:
14153		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14154		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14155		value <<= 16;
14156		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14157		break;
14158	default:
14159		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14160		value = 0;
14161	}
14162
14163	return (value);
14164}
14165
14166static void
14167bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14168{
14169
14170	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14171	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14172}
14173
14174static void
14175bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14176{
14177	uint16_t ctl;
14178
14179	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14180	ctl |= dac << 7;
14181	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14182}
14183
14184static void
14185bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14186{
14187
14188	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14189	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14190}
14191
14192static void
14193bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14194{
14195
14196	if (mac->mac_phy.rev < 2)
14197		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14198	else {
14199		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14200		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14201	}
14202	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14203}
14204
14205static uint16_t
14206bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14207{
14208
14209	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14210}
14211
14212static uint8_t
14213bwn_nbits(int32_t val)
14214{
14215	uint32_t tmp;
14216	uint8_t nbits = 0;
14217
14218	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14219		nbits++;
14220	return (nbits);
14221}
14222
14223static void
14224bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14225    struct bwn_txgain_entry *table)
14226{
14227	int i;
14228
14229	for (i = offset; i < count; i++)
14230		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14231}
14232
14233static void
14234bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14235    struct bwn_txgain_entry data)
14236{
14237
14238	if (mac->mac_phy.rev >= 2)
14239		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14240	else
14241		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14242}
14243
14244static void
14245bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14246    struct bwn_txgain_entry te)
14247{
14248	struct bwn_softc *sc = mac->mac_sc;
14249	struct ifnet *ifp = sc->sc_ifp;
14250	struct ieee80211com *ic = ifp->if_l2com;
14251	uint32_t tmp;
14252
14253	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14254
14255	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14256	if (mac->mac_phy.rev >= 3) {
14257		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14258		    (0x10 << 24) : (0x70 << 24));
14259	} else {
14260		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14261		    (0x14 << 24) : (0x7f << 24));
14262	}
14263	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14264	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14265	    te.te_bbmult << 20 | te.te_dac << 28);
14266}
14267
14268static void
14269bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14270    struct bwn_txgain_entry te)
14271{
14272
14273	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14274
14275	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14276	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14277	    te.te_dac);
14278	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14279}
14280
14281static void
14282bwn_sysctl_node(struct bwn_softc *sc)
14283{
14284	device_t dev = sc->sc_dev;
14285	struct bwn_mac *mac;
14286	struct bwn_stats *stats;
14287
14288	/* XXX assume that count of MAC is only 1. */
14289
14290	if ((mac = sc->sc_curmac) == NULL)
14291		return;
14292	stats = &mac->mac_stats;
14293
14294	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14295	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14296	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14297	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14298	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14299	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14300	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14301	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14302	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14303
14304#ifdef BWN_DEBUG
14305	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14306	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14307	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14308#endif
14309}
14310
14311static void
14312bwn_identify(driver_t *driver, device_t parent)
14313{
14314
14315	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14316}
14317
14318static device_method_t bwn_methods[] = {
14319	/* Device interface */
14320	DEVMETHOD(device_identify,	bwn_identify),
14321	DEVMETHOD(device_probe,		bwn_probe),
14322	DEVMETHOD(device_attach,	bwn_attach),
14323	DEVMETHOD(device_detach,	bwn_detach),
14324	DEVMETHOD(device_suspend,	bwn_suspend),
14325	DEVMETHOD(device_resume,	bwn_resume),
14326	{ 0,0 }
14327};
14328static driver_t bwn_driver = {
14329	"bwn",
14330	bwn_methods,
14331	sizeof(struct bwn_softc)
14332};
14333static devclass_t bwn_devclass;
14334DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14335MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14336MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14337MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14338MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14339