if_bwn.c revision 203945
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 203945 2010-02-16 01:44:14Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(struct siba_softc *);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_fix_imcfglobug(struct bwn_mac *);
209static void	bwn_bt_disable(struct bwn_mac *);
210static int	bwn_chip_init(struct bwn_mac *);
211static uint64_t	bwn_hf_read(struct bwn_mac *);
212static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213static void	bwn_set_txretry(struct bwn_mac *, int, int);
214static void	bwn_rate_init(struct bwn_mac *);
215static void	bwn_set_phytxctl(struct bwn_mac *);
216static void	bwn_spu_setdelay(struct bwn_mac *, int);
217static void	bwn_bt_enable(struct bwn_mac *);
218static void	bwn_set_macaddr(struct bwn_mac *);
219static void	bwn_crypt_init(struct bwn_mac *);
220static void	bwn_chip_exit(struct bwn_mac *);
221static int	bwn_fw_fillinfo(struct bwn_mac *);
222static int	bwn_fw_loaducode(struct bwn_mac *);
223static int	bwn_gpio_init(struct bwn_mac *);
224static int	bwn_fw_loadinitvals(struct bwn_mac *);
225static int	bwn_phy_init(struct bwn_mac *);
226static void	bwn_set_txantenna(struct bwn_mac *, int);
227static void	bwn_set_opmode(struct bwn_mac *);
228static void	bwn_gpio_cleanup(struct bwn_mac *);
229static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230static uint8_t	bwn_plcp_getcck(const uint8_t);
231static uint8_t	bwn_plcp_getofdm(const uint8_t);
232static void	bwn_pio_init(struct bwn_mac *);
233static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    int);
236static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237		    struct bwn_pio_rxqueue *, int);
238static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240		    uint16_t);
241static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244static void	bwn_pio_handle_txeof(struct bwn_mac *,
245		    const struct bwn_txstatus *);
246static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249		    uint16_t);
250static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251		    uint32_t);
252static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253		    struct mbuf *);
254static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258		    uint16_t, uint32_t);
259static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264		    uint16_t, struct bwn_pio_txpkt **);
265static void	bwn_dma_init(struct bwn_mac *);
266static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267static int	bwn_dma_mask2type(uint64_t);
268static uint64_t	bwn_dma_mask(struct bwn_mac *);
269static uint16_t	bwn_dma_base(int, int);
270static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272		    int, struct bwn_dmadesc_generic **,
273		    struct bwn_dmadesc_meta **);
274static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276		    int, int);
277static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283		    int, struct bwn_dmadesc_generic **,
284		    struct bwn_dmadesc_meta **);
285static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287		    int, int);
288static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_setup(struct bwn_dma_ring *);
295static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_rx(struct bwn_dma_ring *);
300static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302		    struct bwn_dmadesc_meta *);
303static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304static int	bwn_dma_gettype(struct bwn_mac *);
305static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311		    int);
312static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313		    bus_size_t, int);
314static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315static void	bwn_dma_handle_txeof(struct bwn_mac *,
316		    const struct bwn_txstatus *);
317static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318		    struct mbuf *);
319static int	bwn_dma_getslot(struct bwn_dma_ring *);
320static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321		    uint8_t);
322static int	bwn_dma_attach(struct bwn_mac *);
323static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324		    int, int, int);
325static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326		    const struct bwn_txstatus *, uint16_t, int *);
327static void	bwn_dma_free(struct bwn_mac *);
328static void	bwn_phy_g_init_sub(struct bwn_mac *);
329static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330static void	bwn_phy_init_b5(struct bwn_mac *);
331static void	bwn_phy_init_b6(struct bwn_mac *);
332static void	bwn_phy_init_a(struct bwn_mac *);
333static void	bwn_loopback_calcgain(struct bwn_mac *);
334static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335static void	bwn_lo_g_init(struct bwn_mac *);
336static void	bwn_lo_g_adjust(struct bwn_mac *);
337static void	bwn_lo_get_powervector(struct bwn_mac *);
338static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345		    uint8_t);
346static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349static void	bwn_wa_init(struct bwn_mac *);
350static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354		    uint32_t);
355static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356		    uint16_t);
357static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358static void	bwn_mac_suspend(struct bwn_mac *);
359static void	bwn_mac_enable(struct bwn_mac *);
360static void	bwn_psctl(struct bwn_mac *, uint32_t);
361static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362static void	bwn_nrssi_offset(struct bwn_mac *);
363static void	bwn_nrssi_threshold(struct bwn_mac *);
364static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366		    int16_t);
367static void	bwn_set_original_gains(struct bwn_mac *);
368static void	bwn_hwpctl_early_init(struct bwn_mac *);
369static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373		    const char *, struct bwn_fwfile *);
374static void	bwn_release_firmware(struct bwn_mac *);
375static void	bwn_do_release_fw(struct bwn_fwfile *);
376static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377static int	bwn_fwinitvals_write(struct bwn_mac *,
378		    const struct bwn_fwinitvals *, size_t, size_t);
379static int	bwn_switch_channel(struct bwn_mac *, int);
380static uint16_t	bwn_ant2phy(int);
381static void	bwn_mac_write_bssid(struct bwn_mac *);
382static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383		    const uint8_t *);
384static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385		    const uint8_t *, size_t, const uint8_t *);
386static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387		    const uint8_t *);
388static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389		    const uint8_t *);
390static void	bwn_phy_exit(struct bwn_mac *);
391static void	bwn_core_stop(struct bwn_mac *);
392static int	bwn_switch_band(struct bwn_softc *,
393		    struct ieee80211_channel *);
394static void	bwn_phy_reset(struct bwn_mac *);
395static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396static void	bwn_set_pretbtt(struct bwn_mac *);
397static int	bwn_intr(void *);
398static void	bwn_intrtask(void *, int);
399static void	bwn_restart(struct bwn_mac *, const char *);
400static void	bwn_intr_ucode_debug(struct bwn_mac *);
401static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402static void	bwn_intr_atim_end(struct bwn_mac *);
403static void	bwn_intr_beacon(struct bwn_mac *);
404static void	bwn_intr_pmq(struct bwn_mac *);
405static void	bwn_intr_noise(struct bwn_mac *);
406static void	bwn_intr_txeof(struct bwn_mac *);
407static void	bwn_hwreset(void *, int);
408static void	bwn_handle_fwpanic(struct bwn_mac *);
409static void	bwn_load_beacon0(struct bwn_mac *);
410static void	bwn_load_beacon1(struct bwn_mac *);
411static uint32_t	bwn_jssi_read(struct bwn_mac *);
412static void	bwn_noise_gensample(struct bwn_mac *);
413static void	bwn_handle_txeof(struct bwn_mac *,
414		    const struct bwn_txstatus *);
415static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417static void	bwn_start_locked(struct ifnet *);
418static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419		    struct mbuf *);
420static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421static int	bwn_set_txhdr(struct bwn_mac *,
422		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423		    uint16_t);
424static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425		    const uint8_t);
426static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427static uint8_t	bwn_get_fbrate(uint8_t);
428static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430static void	bwn_phy_lock(struct bwn_mac *);
431static void	bwn_phy_unlock(struct bwn_mac *);
432static void	bwn_rf_lock(struct bwn_mac *);
433static void	bwn_rf_unlock(struct bwn_mac *);
434static void	bwn_txpwr(void *, int);
435static void	bwn_tasks(void *);
436static void	bwn_task_15s(struct bwn_mac *);
437static void	bwn_task_30s(struct bwn_mac *);
438static void	bwn_task_60s(struct bwn_mac *);
439static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440		    uint8_t);
441static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444		    int, int);
445static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448static void	bwn_watchdog(void *);
449static void	bwn_dma_stop(struct bwn_mac *);
450static void	bwn_pio_stop(struct bwn_mac *);
451static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452static void	bwn_led_attach(struct bwn_mac *);
453static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454static void	bwn_led_event(struct bwn_mac *, int);
455static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456static void	bwn_led_blink_next(void *);
457static void	bwn_led_blink_end(void *);
458static void	bwn_rfswitch(void *);
459static void	bwn_rf_turnon(struct bwn_mac *);
460static void	bwn_rf_turnoff(struct bwn_mac *);
461static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462static int	bwn_phy_lp_init(struct bwn_mac *);
463static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466		    uint16_t);
467static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477static void	bwn_phy_lp_calib(struct bwn_mac *);
478static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500		    const void *);
501static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502static struct bwn_txgain
503		bwn_phy_lp_get_txgain(struct bwn_mac *);
504static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518static int	bwn_phy_lp_loopback(struct bwn_mac *);
519static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521		    int);
522static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523		    struct bwn_phy_lp_iq_est *);
524static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530static uint8_t	bwn_nbits(int32_t);
531static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532		    struct bwn_txgain_entry *);
533static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538		    struct bwn_txgain_entry);
539
540static struct resource_spec bwn_res_spec_legacy[] = {
541	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
542	{ -1,			0,		0 }
543};
544
545static struct resource_spec bwn_res_spec_msi[] = {
546	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
547	{ -1,			0,		0 }
548};
549
550static const struct bwn_channelinfo bwn_chantable_bg = {
551	.channels = {
552		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
553		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
554		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
555		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
556		{ 2472, 13, 30 }, { 2484, 14, 30 } },
557	.nchannels = 14
558};
559
560static const struct bwn_channelinfo bwn_chantable_a = {
561	.channels = {
562		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
563		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
564		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
565		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
566		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
567		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
568		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
569		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
570		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
571		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
572		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
573		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
574		{ 6080, 216, 30 } },
575	.nchannels = 37
576};
577
578static const struct bwn_channelinfo bwn_chantable_n = {
579	.channels = {
580		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
581		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
582		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
583		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
584		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
585		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
586		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
587		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
588		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
589		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
590		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
591		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
592		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
593		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
594		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
595		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
596		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
597		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
598		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
599		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
600		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
601		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
602		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
603		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
604		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
605		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
606		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
607		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
608		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
609		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
610		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
611		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
612		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
613		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
614		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
615		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
616		{ 6130, 226, 30 }, { 6140, 228, 30 } },
617	.nchannels = 110
618};
619
620static const uint8_t bwn_b2063_chantable_data[33][12] = {
621	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
627	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
634	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
654};
655
656static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
657	{ 1, 2412, bwn_b2063_chantable_data[0] },
658	{ 2, 2417, bwn_b2063_chantable_data[0] },
659	{ 3, 2422, bwn_b2063_chantable_data[0] },
660	{ 4, 2427, bwn_b2063_chantable_data[1] },
661	{ 5, 2432, bwn_b2063_chantable_data[1] },
662	{ 6, 2437, bwn_b2063_chantable_data[1] },
663	{ 7, 2442, bwn_b2063_chantable_data[1] },
664	{ 8, 2447, bwn_b2063_chantable_data[1] },
665	{ 9, 2452, bwn_b2063_chantable_data[2] },
666	{ 10, 2457, bwn_b2063_chantable_data[2] },
667	{ 11, 2462, bwn_b2063_chantable_data[3] },
668	{ 12, 2467, bwn_b2063_chantable_data[3] },
669	{ 13, 2472, bwn_b2063_chantable_data[3] },
670	{ 14, 2484, bwn_b2063_chantable_data[4] },
671	{ 34, 5170, bwn_b2063_chantable_data[5] },
672	{ 36, 5180, bwn_b2063_chantable_data[6] },
673	{ 38, 5190, bwn_b2063_chantable_data[7] },
674	{ 40, 5200, bwn_b2063_chantable_data[8] },
675	{ 42, 5210, bwn_b2063_chantable_data[9] },
676	{ 44, 5220, bwn_b2063_chantable_data[10] },
677	{ 46, 5230, bwn_b2063_chantable_data[11] },
678	{ 48, 5240, bwn_b2063_chantable_data[12] },
679	{ 52, 5260, bwn_b2063_chantable_data[13] },
680	{ 56, 5280, bwn_b2063_chantable_data[14] },
681	{ 60, 5300, bwn_b2063_chantable_data[14] },
682	{ 64, 5320, bwn_b2063_chantable_data[15] },
683	{ 100, 5500, bwn_b2063_chantable_data[16] },
684	{ 104, 5520, bwn_b2063_chantable_data[17] },
685	{ 108, 5540, bwn_b2063_chantable_data[18] },
686	{ 112, 5560, bwn_b2063_chantable_data[19] },
687	{ 116, 5580, bwn_b2063_chantable_data[20] },
688	{ 120, 5600, bwn_b2063_chantable_data[21] },
689	{ 124, 5620, bwn_b2063_chantable_data[21] },
690	{ 128, 5640, bwn_b2063_chantable_data[22] },
691	{ 132, 5660, bwn_b2063_chantable_data[22] },
692	{ 136, 5680, bwn_b2063_chantable_data[22] },
693	{ 140, 5700, bwn_b2063_chantable_data[23] },
694	{ 149, 5745, bwn_b2063_chantable_data[23] },
695	{ 153, 5765, bwn_b2063_chantable_data[23] },
696	{ 157, 5785, bwn_b2063_chantable_data[23] },
697	{ 161, 5805, bwn_b2063_chantable_data[23] },
698	{ 165, 5825, bwn_b2063_chantable_data[23] },
699	{ 184, 4920, bwn_b2063_chantable_data[24] },
700	{ 188, 4940, bwn_b2063_chantable_data[25] },
701	{ 192, 4960, bwn_b2063_chantable_data[26] },
702	{ 196, 4980, bwn_b2063_chantable_data[27] },
703	{ 200, 5000, bwn_b2063_chantable_data[28] },
704	{ 204, 5020, bwn_b2063_chantable_data[29] },
705	{ 208, 5040, bwn_b2063_chantable_data[30] },
706	{ 212, 5060, bwn_b2063_chantable_data[31] },
707	{ 216, 5080, bwn_b2063_chantable_data[32] }
708};
709
710static const uint8_t bwn_b2062_chantable_data[22][12] = {
711	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
712	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
732	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
733};
734
735static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
736	{ 1, 2412, bwn_b2062_chantable_data[0] },
737	{ 2, 2417, bwn_b2062_chantable_data[0] },
738	{ 3, 2422, bwn_b2062_chantable_data[0] },
739	{ 4, 2427, bwn_b2062_chantable_data[0] },
740	{ 5, 2432, bwn_b2062_chantable_data[0] },
741	{ 6, 2437, bwn_b2062_chantable_data[0] },
742	{ 7, 2442, bwn_b2062_chantable_data[0] },
743	{ 8, 2447, bwn_b2062_chantable_data[0] },
744	{ 9, 2452, bwn_b2062_chantable_data[0] },
745	{ 10, 2457, bwn_b2062_chantable_data[0] },
746	{ 11, 2462, bwn_b2062_chantable_data[0] },
747	{ 12, 2467, bwn_b2062_chantable_data[0] },
748	{ 13, 2472, bwn_b2062_chantable_data[0] },
749	{ 14, 2484, bwn_b2062_chantable_data[0] },
750	{ 34, 5170, bwn_b2062_chantable_data[1] },
751	{ 38, 5190, bwn_b2062_chantable_data[2] },
752	{ 42, 5210, bwn_b2062_chantable_data[2] },
753	{ 46, 5230, bwn_b2062_chantable_data[3] },
754	{ 36, 5180, bwn_b2062_chantable_data[4] },
755	{ 40, 5200, bwn_b2062_chantable_data[5] },
756	{ 44, 5220, bwn_b2062_chantable_data[6] },
757	{ 48, 5240, bwn_b2062_chantable_data[3] },
758	{ 52, 5260, bwn_b2062_chantable_data[3] },
759	{ 56, 5280, bwn_b2062_chantable_data[3] },
760	{ 60, 5300, bwn_b2062_chantable_data[7] },
761	{ 64, 5320, bwn_b2062_chantable_data[8] },
762	{ 100, 5500, bwn_b2062_chantable_data[9] },
763	{ 104, 5520, bwn_b2062_chantable_data[10] },
764	{ 108, 5540, bwn_b2062_chantable_data[10] },
765	{ 112, 5560, bwn_b2062_chantable_data[10] },
766	{ 116, 5580, bwn_b2062_chantable_data[11] },
767	{ 120, 5600, bwn_b2062_chantable_data[12] },
768	{ 124, 5620, bwn_b2062_chantable_data[12] },
769	{ 128, 5640, bwn_b2062_chantable_data[12] },
770	{ 132, 5660, bwn_b2062_chantable_data[12] },
771	{ 136, 5680, bwn_b2062_chantable_data[12] },
772	{ 140, 5700, bwn_b2062_chantable_data[12] },
773	{ 149, 5745, bwn_b2062_chantable_data[12] },
774	{ 153, 5765, bwn_b2062_chantable_data[12] },
775	{ 157, 5785, bwn_b2062_chantable_data[12] },
776	{ 161, 5805, bwn_b2062_chantable_data[12] },
777	{ 165, 5825, bwn_b2062_chantable_data[12] },
778	{ 184, 4920, bwn_b2062_chantable_data[13] },
779	{ 188, 4940, bwn_b2062_chantable_data[14] },
780	{ 192, 4960, bwn_b2062_chantable_data[15] },
781	{ 196, 4980, bwn_b2062_chantable_data[16] },
782	{ 200, 5000, bwn_b2062_chantable_data[17] },
783	{ 204, 5020, bwn_b2062_chantable_data[18] },
784	{ 208, 5040, bwn_b2062_chantable_data[19] },
785	{ 212, 5060, bwn_b2062_chantable_data[20] },
786	{ 216, 5080, bwn_b2062_chantable_data[21] }
787};
788
789/* for LP PHY */
790static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
791	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
792	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
793	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
794	{ 13, -66, 13 }, { 14, -66, 13 },
795};
796
797/* for LP PHY */
798static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
799	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
800	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
801	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
802	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
803	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
804	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
805	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
806	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
807	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
808	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
809	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
810	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
811	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
812};
813
814static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
815
816static const uint8_t bwn_tab_sigsq_tbl[] = {
817	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
818	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
819	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
822	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
823};
824
825static const uint8_t bwn_tab_pllfrac_tbl[] = {
826	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
828};
829
830static const uint16_t bwn_tabl_iqlocal_tbl[] = {
831	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
832	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
835	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
836	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843};
844
845static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
846static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
847static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
848static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
849static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
850const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
851
852#define	VENDOR_LED_ACT(vendor)				\
853{							\
854	.vid = PCI_VENDOR_##vendor,			\
855	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
856}
857
858static const struct {
859	uint16_t	vid;
860	uint8_t		led_act[BWN_LED_MAX];
861} bwn_vendor_led_act[] = {
862	VENDOR_LED_ACT(COMPAQ),
863	VENDOR_LED_ACT(ASUSTEK)
864};
865
866static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
867	{ BWN_VENDOR_LED_ACT_DEFAULT };
868
869#undef VENDOR_LED_ACT
870
871static const struct {
872	int		on_dur;
873	int		off_dur;
874} bwn_led_duration[109] = {
875	[0]	= { 400, 100 },
876	[2]	= { 150, 75 },
877	[4]	= { 90, 45 },
878	[11]	= { 66, 34 },
879	[12]	= { 53, 26 },
880	[18]	= { 42, 21 },
881	[22]	= { 35, 17 },
882	[24]	= { 32, 16 },
883	[36]	= { 21, 10 },
884	[48]	= { 16, 8 },
885	[72]	= { 11, 5 },
886	[96]	= { 9, 4 },
887	[108]	= { 7, 3 }
888};
889
890static const uint16_t bwn_wme_shm_offsets[] = {
891	[0] = BWN_WME_BESTEFFORT,
892	[1] = BWN_WME_BACKGROUND,
893	[2] = BWN_WME_VOICE,
894	[3] = BWN_WME_VIDEO,
895};
896
897static const struct siba_devid bwn_devs[] = {
898	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
899	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
900	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
901	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
902	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
903	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
904	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
905	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
906	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
907};
908
909static int
910bwn_probe(device_t dev)
911{
912	struct siba_dev_softc *sd = device_get_ivars(dev);
913	int i;
914
915	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
916		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
917		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
918		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
919			return (BUS_PROBE_DEFAULT);
920	}
921
922	return (ENXIO);
923}
924
925static int
926bwn_attach(device_t dev)
927{
928	struct bwn_mac *mac;
929	struct bwn_softc *sc = device_get_softc(dev);
930	struct siba_dev_softc *sd = device_get_ivars(dev);
931	struct siba_softc *siba = sd->sd_bus;
932	int error, i, msic, reg;
933
934	sc->sc_dev = dev;
935	sc->sc_sd = sd;
936#ifdef BWN_DEBUG
937	sc->sc_debug = bwn_debug;
938#endif
939
940	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
941		error = bwn_attach_pre(sc);
942		if (error != 0)
943			return (error);
944		bwn_sprom_bugfixes(sd->sd_bus);
945		sc->sc_flags |= BWN_FLAG_ATTACHED;
946	}
947
948	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
949		if (siba->siba_pci_did != 0x4313 &&
950		    siba->siba_pci_did != 0x431a &&
951		    siba->siba_pci_did != 0x4321) {
952			device_printf(sc->sc_dev,
953			    "skip 802.11 cores\n");
954			return (ENODEV);
955		}
956	}
957
958	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
959	    M_NOWAIT | M_ZERO);
960	if (mac == NULL)
961		return (ENOMEM);
962	mac->mac_sc = sc;
963	mac->mac_sd = sd;
964	mac->mac_status = BWN_MAC_STATUS_UNINIT;
965	if (bwn_bfp != 0)
966		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
967
968	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
969	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
970	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
971
972	error = bwn_attach_core(mac);
973	if (error)
974		goto fail0;
975	bwn_led_attach(mac);
976
977	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
978	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
979	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
980	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
981	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
982	    mac->mac_phy.rf_rev);
983	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
984		device_printf(sc->sc_dev, "DMA (%d bits)\n",
985		    mac->mac_method.dma.dmatype);
986	else
987		device_printf(sc->sc_dev, "PIO\n");
988
989	/*
990	 * setup PCI resources and interrupt.
991	 */
992	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
993		msic = pci_msi_count(dev);
994		if (bootverbose)
995			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
996	} else
997		msic = 0;
998
999	mac->mac_intr_spec = bwn_res_spec_legacy;
1000	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1001		if (pci_alloc_msi(dev, &msic) == 0) {
1002			device_printf(sc->sc_dev,
1003			    "Using %d MSI messages\n", msic);
1004			mac->mac_intr_spec = bwn_res_spec_msi;
1005			mac->mac_msi = 1;
1006		}
1007	}
1008
1009	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1010	    mac->mac_res_irq);
1011	if (error) {
1012		device_printf(sc->sc_dev,
1013		    "couldn't allocate IRQ resources (%d)\n", error);
1014		goto fail1;
1015	}
1016
1017	if (mac->mac_msi == 0)
1018		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1019		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1020		    &mac->mac_intrhand[0]);
1021	else {
1022		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1023			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1024			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1025			    &mac->mac_intrhand[i]);
1026			if (error != 0) {
1027				device_printf(sc->sc_dev,
1028				    "couldn't setup interrupt (%d)\n", error);
1029				break;
1030			}
1031		}
1032	}
1033
1034	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1035
1036	/*
1037	 * calls attach-post routine
1038	 */
1039	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1040		bwn_attach_post(sc);
1041
1042	return (0);
1043fail1:
1044	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1045		pci_release_msi(dev);
1046fail0:
1047	free(mac, M_DEVBUF);
1048	return (error);
1049}
1050
1051static int
1052bwn_is_valid_ether_addr(uint8_t *addr)
1053{
1054	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1055
1056	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1057		return (FALSE);
1058
1059	return (TRUE);
1060}
1061
1062static int
1063bwn_attach_post(struct bwn_softc *sc)
1064{
1065	struct ieee80211com *ic;
1066	struct ifnet *ifp = sc->sc_ifp;
1067	struct siba_dev_softc *sd = sc->sc_sd;
1068	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1069#ifdef BWN_DEBUG
1070	device_t dev = sc->sc_dev;
1071#endif
1072
1073	ic = ifp->if_l2com;
1074	ic->ic_ifp = ifp;
1075	/* XXX not right but it's not used anywhere important */
1076	ic->ic_phytype = IEEE80211_T_OFDM;
1077	ic->ic_opmode = IEEE80211_M_STA;
1078	ic->ic_caps =
1079		  IEEE80211_C_STA		/* station mode supported */
1080		| IEEE80211_C_MONITOR		/* monitor mode */
1081		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1082		| IEEE80211_C_SHSLOT		/* short slot time supported */
1083		| IEEE80211_C_WME		/* WME/WMM supported */
1084		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1085		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1086		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1087		;
1088
1089	/* call MI attach routine. */
1090	ieee80211_ifattach(ic,
1091	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1092	    sprom->mac_80211bg);
1093
1094	ic->ic_headroom = sizeof(struct bwn_txhdr);
1095
1096	/* override default methods */
1097	ic->ic_raw_xmit = bwn_raw_xmit;
1098	ic->ic_newassoc = bwn_newassoc;
1099	ic->ic_updateslot = bwn_updateslot;
1100	ic->ic_update_promisc = bwn_update_promisc;
1101	ic->ic_wme.wme_update = bwn_wme_update;
1102
1103	ic->ic_node_alloc = bwn_node_alloc;
1104	sc->sc_node_cleanup = ic->ic_node_cleanup;
1105	ic->ic_node_cleanup = bwn_node_cleanup;
1106
1107	ic->ic_scan_start = bwn_scan_start;
1108	ic->ic_scan_end = bwn_scan_end;
1109	ic->ic_set_channel = bwn_set_channel;
1110
1111	ic->ic_vap_create = bwn_vap_create;
1112	ic->ic_vap_delete = bwn_vap_delete;
1113
1114	ieee80211_radiotap_attach(ic,
1115	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1116	    BWN_TX_RADIOTAP_PRESENT,
1117	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1118	    BWN_RX_RADIOTAP_PRESENT);
1119
1120#ifdef BWN_DEBUG
1121	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
1122	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1123	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
1124#endif
1125
1126	if (bootverbose)
1127		ieee80211_announce(ic);
1128	return (0);
1129}
1130
1131static void
1132bwn_phy_detach(struct bwn_mac *mac)
1133{
1134
1135	if (mac->mac_phy.detach != NULL)
1136		mac->mac_phy.detach(mac);
1137}
1138
1139static int
1140bwn_detach(device_t dev)
1141{
1142	struct bwn_softc *sc = device_get_softc(dev);
1143	struct bwn_mac *mac = sc->sc_curmac;
1144	struct ifnet *ifp = sc->sc_ifp;
1145	struct ieee80211com *ic = ifp->if_l2com;
1146	int i;
1147
1148	sc->sc_flags |= BWN_FLAG_INVALID;
1149
1150	if (device_is_attached(sc->sc_dev)) {
1151		bwn_stop(sc, 1);
1152		bwn_dma_free(mac);
1153		callout_drain(&sc->sc_led_blink_ch);
1154		callout_drain(&sc->sc_rfswitch_ch);
1155		callout_drain(&sc->sc_task_ch);
1156		callout_drain(&sc->sc_watchdog_ch);
1157		bwn_phy_detach(mac);
1158		if (ifp != NULL) {
1159			ieee80211_draintask(ic, &mac->mac_hwreset);
1160			ieee80211_draintask(ic, &mac->mac_txpower);
1161			ieee80211_ifdetach(ic);
1162			if_free(ifp);
1163		}
1164	}
1165	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1166	taskqueue_free(sc->sc_tq);
1167
1168	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1169		if (mac->mac_intrhand[i] != NULL) {
1170			bus_teardown_intr(dev, mac->mac_res_irq[i],
1171			    mac->mac_intrhand[i]);
1172			mac->mac_intrhand[i] = NULL;
1173		}
1174	}
1175	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1176	if (mac->mac_msi != 0)
1177		pci_release_msi(dev);
1178
1179	BWN_LOCK_DESTROY(sc);
1180	return (0);
1181}
1182
1183static int
1184bwn_attach_pre(struct bwn_softc *sc)
1185{
1186	struct ifnet *ifp;
1187	int error = 0;
1188
1189	BWN_LOCK_INIT(sc);
1190	TAILQ_INIT(&sc->sc_maclist);
1191	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1192	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1193	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1194
1195	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1196		taskqueue_thread_enqueue, &sc->sc_tq);
1197	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1198		"%s taskq", device_get_nameunit(sc->sc_dev));
1199
1200	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1201	if (ifp == NULL) {
1202		device_printf(sc->sc_dev, "can not if_alloc()\n");
1203		error = ENOSPC;
1204		goto fail;
1205	}
1206
1207	/* set these up early for if_printf use */
1208	if_initname(ifp, device_get_name(sc->sc_dev),
1209	    device_get_unit(sc->sc_dev));
1210
1211	ifp->if_softc = sc;
1212	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1213	ifp->if_init = bwn_init;
1214	ifp->if_ioctl = bwn_ioctl;
1215	ifp->if_start = bwn_start;
1216	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1217	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1218	IFQ_SET_READY(&ifp->if_snd);
1219
1220	return (0);
1221
1222fail:	BWN_LOCK_DESTROY(sc);
1223	return (error);
1224}
1225
1226static void
1227bwn_sprom_bugfixes(struct siba_softc *siba)
1228{
1229#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1230	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1231	 (siba->siba_pci_did == _device) &&				\
1232	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1233	 (siba->siba_pci_subdid == _subdevice))
1234
1235	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1236	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1237		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1238	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1239	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1240		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1241	if (siba->siba_type == SIBA_TYPE_PCI) {
1242		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1243		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1244		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1245		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1246		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1247		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1248		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1249			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1250	}
1251#undef	BWN_ISDEV
1252}
1253
1254static int
1255bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1256{
1257#define	IS_RUNNING(ifp) \
1258	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1259	struct bwn_softc *sc = ifp->if_softc;
1260	struct ieee80211com *ic = ifp->if_l2com;
1261	struct ifreq *ifr = (struct ifreq *)data;
1262	int error = 0, startall;
1263
1264	switch (cmd) {
1265	case SIOCSIFFLAGS:
1266		startall = 0;
1267		if (IS_RUNNING(ifp)) {
1268			bwn_update_promisc(ifp);
1269		} else if (ifp->if_flags & IFF_UP) {
1270			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1271				bwn_init(sc);
1272				startall = 1;
1273			}
1274		} else
1275			bwn_stop(sc, 1);
1276		if (startall)
1277			ieee80211_start_all(ic);
1278		break;
1279	case SIOCGIFMEDIA:
1280		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1281		break;
1282	case SIOCGIFADDR:
1283		error = ether_ioctl(ifp, cmd, data);
1284		break;
1285	default:
1286		error = EINVAL;
1287		break;
1288	}
1289	return (error);
1290}
1291
1292static void
1293bwn_start(struct ifnet *ifp)
1294{
1295	struct bwn_softc *sc = ifp->if_softc;
1296
1297	BWN_LOCK(sc);
1298	bwn_start_locked(ifp);
1299	BWN_UNLOCK(sc);
1300}
1301
1302static void
1303bwn_start_locked(struct ifnet *ifp)
1304{
1305	struct bwn_softc *sc = ifp->if_softc;
1306	struct bwn_mac *mac = sc->sc_curmac;
1307	struct ieee80211_frame *wh;
1308	struct ieee80211_node *ni;
1309	struct ieee80211_key *k;
1310	struct mbuf *m;
1311
1312	BWN_ASSERT_LOCKED(sc);
1313
1314	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1315	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1316		return;
1317
1318	for (;;) {
1319		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1320		if (m == NULL)
1321			break;
1322
1323		if (bwn_tx_isfull(sc, m))
1324			break;
1325		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1326		if (ni == NULL) {
1327			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1328			m_freem(m);
1329			ifp->if_oerrors++;
1330			continue;
1331		}
1332		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1333		wh = mtod(m, struct ieee80211_frame *);
1334		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1335			k = ieee80211_crypto_encap(ni, m);
1336			if (k == NULL) {
1337				ieee80211_free_node(ni);
1338				m_freem(m);
1339				ifp->if_oerrors++;
1340				continue;
1341			}
1342		}
1343		wh = NULL;	/* Catch any invalid use */
1344
1345		if (bwn_tx_start(sc, ni, m) != 0) {
1346			if (ni != NULL)
1347				ieee80211_free_node(ni);
1348			ifp->if_oerrors++;
1349			continue;
1350		}
1351
1352		sc->sc_watchdog_timer = 5;
1353	}
1354}
1355
1356static int
1357bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1358{
1359	struct bwn_dma_ring *dr;
1360	struct bwn_mac *mac = sc->sc_curmac;
1361	struct bwn_pio_txqueue *tq;
1362	struct ifnet *ifp = sc->sc_ifp;
1363	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1364
1365	BWN_ASSERT_LOCKED(sc);
1366
1367	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1368		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1369		if (dr->dr_stop == 1 ||
1370		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1371			dr->dr_stop = 1;
1372			goto full;
1373		}
1374	} else {
1375		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1376		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1377		    pktlen > (tq->tq_size - tq->tq_used)) {
1378			tq->tq_stop = 1;
1379			goto full;
1380		}
1381	}
1382	return (0);
1383full:
1384	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1385	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1386	return (1);
1387}
1388
1389static int
1390bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1391{
1392	struct bwn_mac *mac = sc->sc_curmac;
1393	int error;
1394
1395	BWN_ASSERT_LOCKED(sc);
1396
1397	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1398		m_freem(m);
1399		return (ENXIO);
1400	}
1401
1402	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1403	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1404	if (error) {
1405		m_freem(m);
1406		return (error);
1407	}
1408	return (0);
1409}
1410
1411static int
1412bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1413{
1414	struct bwn_pio_txpkt *tp;
1415	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1416	struct bwn_softc *sc = mac->mac_sc;
1417	struct bwn_txhdr txhdr;
1418	struct mbuf *m_new;
1419	uint32_t ctl32;
1420	int error;
1421	uint16_t ctl16;
1422
1423	BWN_ASSERT_LOCKED(sc);
1424
1425	/* XXX TODO send packets after DTIM */
1426
1427	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1428	tp = TAILQ_FIRST(&tq->tq_pktlist);
1429	tp->tp_ni = ni;
1430	tp->tp_m = m;
1431
1432	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1433	if (error) {
1434		device_printf(sc->sc_dev, "tx fail\n");
1435		return (error);
1436	}
1437
1438	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1439	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1440	tq->tq_free--;
1441
1442	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1443		/*
1444		 * XXX please removes m_defrag(9)
1445		 */
1446		m_new = m_defrag(m, M_DONTWAIT);
1447		if (m_new == NULL) {
1448			device_printf(sc->sc_dev,
1449			    "%s: can't defrag TX buffer\n",
1450			    __func__);
1451			return (ENOBUFS);
1452		}
1453		if (m_new->m_next != NULL)
1454			device_printf(sc->sc_dev,
1455			    "TODO: fragmented packets for PIO\n");
1456		tp->tp_m = m_new;
1457
1458		/* send HEADER */
1459		ctl32 = bwn_pio_write_multi_4(mac, tq,
1460		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1461			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1462		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1463		/* send BODY */
1464		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1465		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1466		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1467		    ctl32 | BWN_PIO8_TXCTL_EOF);
1468	} else {
1469		ctl16 = bwn_pio_write_multi_2(mac, tq,
1470		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1471			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1472		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1473		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1474		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1475		    ctl16 | BWN_PIO_TXCTL_EOF);
1476	}
1477
1478	return (0);
1479}
1480
1481static struct bwn_pio_txqueue *
1482bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1483{
1484
1485	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1486		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1487
1488	switch (prio) {
1489	case 0:
1490		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1491	case 1:
1492		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1493	case 2:
1494		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1495	case 3:
1496		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1497	}
1498	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1499}
1500
1501static int
1502bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1503{
1504#define	BWN_GET_TXHDRCACHE(slot)					\
1505	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1506	struct bwn_dma *dma = &mac->mac_method.dma;
1507	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1508	struct bwn_dmadesc_generic *desc;
1509	struct bwn_dmadesc_meta *mt;
1510	struct bwn_softc *sc = mac->mac_sc;
1511	struct ifnet *ifp = sc->sc_ifp;
1512	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1513	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1514
1515	BWN_ASSERT_LOCKED(sc);
1516	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1517
1518	/* XXX send after DTIM */
1519
1520	slot = bwn_dma_getslot(dr);
1521	dr->getdesc(dr, slot, &desc, &mt);
1522	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1523	    ("%s:%d: fail", __func__, __LINE__));
1524
1525	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1526	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1527	    BWN_DMA_COOKIE(dr, slot));
1528	if (error)
1529		goto fail;
1530	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1531	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1532	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1533	if (error) {
1534		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1535		    __func__, error);
1536		goto fail;
1537	}
1538	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1539	    BUS_DMASYNC_PREWRITE);
1540	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1541	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1542	    BUS_DMASYNC_PREWRITE);
1543
1544	slot = bwn_dma_getslot(dr);
1545	dr->getdesc(dr, slot, &desc, &mt);
1546	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1547	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1548	mt->mt_m = m;
1549	mt->mt_ni = ni;
1550
1551	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1552	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1553	if (error && error != EFBIG) {
1554		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1555		    __func__, error);
1556		goto fail;
1557	}
1558	if (error) {    /* error == EFBIG */
1559		struct mbuf *m_new;
1560
1561		m_new = m_defrag(m, M_DONTWAIT);
1562		if (m_new == NULL) {
1563			if_printf(ifp, "%s: can't defrag TX buffer\n",
1564			    __func__);
1565			error = ENOBUFS;
1566			goto fail;
1567		} else {
1568			m = m_new;
1569		}
1570
1571		mt->mt_m = m;
1572		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1573		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1574		if (error) {
1575			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1576			    __func__, error);
1577			goto fail;
1578		}
1579	}
1580	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1581	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1582	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1583	    BUS_DMASYNC_PREWRITE);
1584
1585	/* XXX send after DTIM */
1586
1587	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1588	return (0);
1589fail:
1590	dr->dr_curslot = backup[0];
1591	dr->dr_usedslot = backup[1];
1592	return (error);
1593#undef BWN_GET_TXHDRCACHE
1594}
1595
1596static void
1597bwn_watchdog(void *arg)
1598{
1599	struct bwn_softc *sc = arg;
1600	struct ifnet *ifp = sc->sc_ifp;
1601
1602	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1603		if_printf(ifp, "device timeout\n");
1604		ifp->if_oerrors++;
1605	}
1606	callout_schedule(&sc->sc_watchdog_ch, hz);
1607}
1608
1609static int
1610bwn_attach_core(struct bwn_mac *mac)
1611{
1612	struct bwn_softc *sc = mac->mac_sc;
1613	struct siba_dev_softc *sd = mac->mac_sd;
1614	struct siba_softc *siba = sd->sd_bus;
1615	int error, have_bg = 0, have_a = 0;
1616	uint32_t high;
1617
1618	KASSERT(sd->sd_id.sd_rev >= 5,
1619	    ("unsupported revision %d", sd->sd_id.sd_rev));
1620
1621	siba_powerup(siba, 0);
1622
1623	high = siba_read_4(sd, SIBA_TGSHIGH);
1624	bwn_reset_core(mac,
1625	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1626	error = bwn_phy_getinfo(mac, high);
1627	if (error)
1628		goto fail;
1629
1630	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1631	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1632	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1633	    siba->siba_pci_did != 0x4324) {
1634		have_a = have_bg = 0;
1635		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1636			have_a = 1;
1637		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1638		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1639		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1640			have_bg = 1;
1641		else
1642			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1643			    mac->mac_phy.type));
1644	}
1645	/* XXX turns off PHY A because it's not supported */
1646	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1647	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1648		have_a = 0;
1649		have_bg = 1;
1650	}
1651
1652	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1653		mac->mac_phy.attach = bwn_phy_g_attach;
1654		mac->mac_phy.detach = bwn_phy_g_detach;
1655		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1656		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1657		mac->mac_phy.init = bwn_phy_g_init;
1658		mac->mac_phy.exit = bwn_phy_g_exit;
1659		mac->mac_phy.phy_read = bwn_phy_g_read;
1660		mac->mac_phy.phy_write = bwn_phy_g_write;
1661		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1662		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1663		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1664		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1665		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1666		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1667		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1668		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1669		mac->mac_phy.set_im = bwn_phy_g_im;
1670		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1671		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1672		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1673		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1674	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1675		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1676		mac->mac_phy.init = bwn_phy_lp_init;
1677		mac->mac_phy.phy_read = bwn_phy_lp_read;
1678		mac->mac_phy.phy_write = bwn_phy_lp_write;
1679		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1680		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1681		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1682		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1683		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1684		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1685		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1686		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1687		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1688	} else {
1689		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1690		    mac->mac_phy.type);
1691		error = ENXIO;
1692		goto fail;
1693	}
1694
1695	mac->mac_phy.gmode = have_bg;
1696	if (mac->mac_phy.attach != NULL) {
1697		error = mac->mac_phy.attach(mac);
1698		if (error) {
1699			device_printf(sc->sc_dev, "failed\n");
1700			goto fail;
1701		}
1702	}
1703
1704	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1705
1706	error = bwn_chiptest(mac);
1707	if (error)
1708		goto fail;
1709	error = bwn_setup_channels(mac, have_bg, have_a);
1710	if (error) {
1711		device_printf(sc->sc_dev, "failed to setup channels\n");
1712		goto fail;
1713	}
1714
1715	if (sc->sc_curmac == NULL)
1716		sc->sc_curmac = mac;
1717
1718	error = bwn_dma_attach(mac);
1719	if (error != 0) {
1720		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1721		goto fail;
1722	}
1723
1724	mac->mac_phy.switch_analog(mac, 0);
1725
1726	siba_dev_down(sd, 0);
1727fail:
1728	siba_powerdown(siba);
1729	return (error);
1730}
1731
1732static void
1733bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1734{
1735	struct siba_dev_softc *sd = mac->mac_sd;
1736	uint32_t low, ctl;
1737
1738	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1739
1740	siba_dev_up(sd, flags);
1741	DELAY(2000);
1742
1743	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1744	    ~BWN_TGSLOW_PHYRESET;
1745	siba_write_4(sd, SIBA_TGSLOW, low);
1746	siba_read_4(sd, SIBA_TGSLOW);
1747	DELAY(1000);
1748	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1749	siba_read_4(sd, SIBA_TGSLOW);
1750	DELAY(1000);
1751
1752	if (mac->mac_phy.switch_analog != NULL)
1753		mac->mac_phy.switch_analog(mac, 1);
1754
1755	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1756	if (flags & BWN_TGSLOW_SUPPORT_G)
1757		ctl |= BWN_MACCTL_GMODE;
1758	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1759}
1760
1761static int
1762bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1763{
1764	struct bwn_phy *phy = &mac->mac_phy;
1765	struct bwn_softc *sc = mac->mac_sc;
1766	struct siba_dev_softc *sd = mac->mac_sd;
1767	struct siba_softc *siba = sd->sd_bus;
1768	uint32_t tmp;
1769
1770	/* PHY */
1771	tmp = BWN_READ_2(mac, BWN_PHYVER);
1772	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1773	phy->rf_on = 1;
1774	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1775	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1776	phy->rev = (tmp & BWN_PHYVER_VERSION);
1777	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1778	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1779		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1780	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1781	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1782	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1783		goto unsupphy;
1784
1785	/* RADIO */
1786	if (siba->siba_chipid == 0x4317) {
1787		if (siba->siba_chiprev == 0)
1788			tmp = 0x3205017f;
1789		else if (siba->siba_chiprev == 1)
1790			tmp = 0x4205017f;
1791		else
1792			tmp = 0x5205017f;
1793	} else {
1794		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1795		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1796		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1797		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1798	}
1799	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1800	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1801	phy->rf_manuf = (tmp & 0x00000fff);
1802	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1803		goto unsupradio;
1804	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1805	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1806	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1807	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1808	    (phy->type == BWN_PHYTYPE_N &&
1809	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1810	    (phy->type == BWN_PHYTYPE_LP &&
1811	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1812		goto unsupradio;
1813
1814	return (0);
1815unsupphy:
1816	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1817	    "analog %#x)\n",
1818	    phy->type, phy->rev, phy->analog);
1819	return (ENXIO);
1820unsupradio:
1821	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1822	    "rev %#x)\n",
1823	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1824	return (ENXIO);
1825}
1826
1827static int
1828bwn_chiptest(struct bwn_mac *mac)
1829{
1830#define	TESTVAL0	0x55aaaa55
1831#define	TESTVAL1	0xaa5555aa
1832	struct bwn_softc *sc = mac->mac_sc;
1833	struct siba_dev_softc *sd = mac->mac_sd;
1834	uint32_t v, backup;
1835
1836	BWN_LOCK(sc);
1837
1838	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1839
1840	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1841	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1842		goto error;
1843	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1844	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1845		goto error;
1846
1847	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1848
1849	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1850		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1851		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1852		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1853			goto error;
1854		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1855			goto error;
1856	}
1857	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1858
1859	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1860	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1861		goto error;
1862
1863	BWN_UNLOCK(sc);
1864	return (0);
1865error:
1866	BWN_UNLOCK(sc);
1867	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1868	return (ENODEV);
1869}
1870
1871#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1872#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1873
1874static int
1875bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1876{
1877	struct bwn_softc *sc = mac->mac_sc;
1878	struct ifnet *ifp = sc->sc_ifp;
1879	struct ieee80211com *ic = ifp->if_l2com;
1880
1881	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1882	ic->ic_nchans = 0;
1883
1884	if (have_bg)
1885		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1887	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1888		if (have_a)
1889			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1890			    &ic->ic_nchans, &bwn_chantable_n,
1891			    IEEE80211_CHAN_HTA);
1892	} else {
1893		if (have_a)
1894			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1895			    &ic->ic_nchans, &bwn_chantable_a,
1896			    IEEE80211_CHAN_A);
1897	}
1898
1899	mac->mac_phy.supports_2ghz = have_bg;
1900	mac->mac_phy.supports_5ghz = have_a;
1901
1902	return (ic->ic_nchans == 0 ? ENXIO : 0);
1903}
1904
1905static uint32_t
1906bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1907{
1908	struct bwn_softc *sc = mac->mac_sc;
1909	uint32_t ret;
1910
1911	BWN_ASSERT_LOCKED(sc);
1912
1913	if (way == BWN_SHARED) {
1914		KASSERT((offset & 0x0001) == 0,
1915		    ("%s:%d warn", __func__, __LINE__));
1916		if (offset & 0x0003) {
1917			bwn_shm_ctlword(mac, way, offset >> 2);
1918			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1919			ret <<= 16;
1920			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1921			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1922			goto out;
1923		}
1924		offset >>= 2;
1925	}
1926	bwn_shm_ctlword(mac, way, offset);
1927	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1928out:
1929	return (ret);
1930}
1931
1932static uint16_t
1933bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1934{
1935	struct bwn_softc *sc = mac->mac_sc;
1936	uint16_t ret;
1937
1938	BWN_ASSERT_LOCKED(sc);
1939
1940	if (way == BWN_SHARED) {
1941		KASSERT((offset & 0x0001) == 0,
1942		    ("%s:%d warn", __func__, __LINE__));
1943		if (offset & 0x0003) {
1944			bwn_shm_ctlword(mac, way, offset >> 2);
1945			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1946			goto out;
1947		}
1948		offset >>= 2;
1949	}
1950	bwn_shm_ctlword(mac, way, offset);
1951	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1952out:
1953
1954	return (ret);
1955}
1956
1957static void
1958bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1959    uint16_t offset)
1960{
1961	uint32_t control;
1962
1963	control = way;
1964	control <<= 16;
1965	control |= offset;
1966	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1967}
1968
1969static void
1970bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1971    uint32_t value)
1972{
1973	struct bwn_softc *sc = mac->mac_sc;
1974
1975	BWN_ASSERT_LOCKED(sc);
1976
1977	if (way == BWN_SHARED) {
1978		KASSERT((offset & 0x0001) == 0,
1979		    ("%s:%d warn", __func__, __LINE__));
1980		if (offset & 0x0003) {
1981			bwn_shm_ctlword(mac, way, offset >> 2);
1982			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1983				    (value >> 16) & 0xffff);
1984			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1985			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1986			return;
1987		}
1988		offset >>= 2;
1989	}
1990	bwn_shm_ctlword(mac, way, offset);
1991	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1992}
1993
1994static void
1995bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1996    uint16_t value)
1997{
1998	struct bwn_softc *sc = mac->mac_sc;
1999
2000	BWN_ASSERT_LOCKED(sc);
2001
2002	if (way == BWN_SHARED) {
2003		KASSERT((offset & 0x0001) == 0,
2004		    ("%s:%d warn", __func__, __LINE__));
2005		if (offset & 0x0003) {
2006			bwn_shm_ctlword(mac, way, offset >> 2);
2007			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
2008			return;
2009		}
2010		offset >>= 2;
2011	}
2012	bwn_shm_ctlword(mac, way, offset);
2013	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2014}
2015
2016static void
2017bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2018    int txpow)
2019{
2020
2021	c->ic_freq = freq;
2022	c->ic_flags = flags;
2023	c->ic_ieee = ieee;
2024	c->ic_minpower = 0;
2025	c->ic_maxpower = 2 * txpow;
2026	c->ic_maxregpower = txpow;
2027}
2028
2029static void
2030bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2031    const struct bwn_channelinfo *ci, int flags)
2032{
2033	struct ieee80211_channel *c;
2034	int i;
2035
2036	c = &chans[*nchans];
2037
2038	for (i = 0; i < ci->nchannels; i++) {
2039		const struct bwn_channel *hc;
2040
2041		hc = &ci->channels[i];
2042		if (*nchans >= maxchans)
2043			break;
2044		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2045		c++, (*nchans)++;
2046		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2047			/* g channel have a separate b-only entry */
2048			if (*nchans >= maxchans)
2049				break;
2050			c[0] = c[-1];
2051			c[-1].ic_flags = IEEE80211_CHAN_B;
2052			c++, (*nchans)++;
2053		}
2054		if (flags == IEEE80211_CHAN_HTG) {
2055			/* HT g channel have a separate g-only entry */
2056			if (*nchans >= maxchans)
2057				break;
2058			c[-1].ic_flags = IEEE80211_CHAN_G;
2059			c[0] = c[-1];
2060			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2061			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2062			c++, (*nchans)++;
2063		}
2064		if (flags == IEEE80211_CHAN_HTA) {
2065			/* HT a channel have a separate a-only entry */
2066			if (*nchans >= maxchans)
2067				break;
2068			c[-1].ic_flags = IEEE80211_CHAN_A;
2069			c[0] = c[-1];
2070			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2071			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2072			c++, (*nchans)++;
2073		}
2074	}
2075}
2076
2077static int
2078bwn_phy_g_attach(struct bwn_mac *mac)
2079{
2080	struct bwn_softc *sc = mac->mac_sc;
2081	struct bwn_phy *phy = &mac->mac_phy;
2082	struct bwn_phy_g *pg = &phy->phy_g;
2083	struct siba_dev_softc *sd = mac->mac_sd;
2084	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2085	unsigned int i;
2086	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2087	    pab2 = (int16_t)(sprom->pa0b2);
2088	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2089	int8_t bg = (int8_t)sprom->tssi_bg;
2090
2091	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2092		device_printf(sc->sc_dev, "not supported anymore\n");
2093
2094	pg->pg_flags = 0;
2095	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2096	    pab2 == -1) {
2097		pg->pg_idletssi = 52;
2098		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2099		return (0);
2100	}
2101
2102	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2103	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2104	if (pg->pg_tssi2dbm == NULL) {
2105		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2106		return (ENOMEM);
2107	}
2108	for (i = 0; i < 64; i++) {
2109		int32_t m1, m2, f, q, delta;
2110		int8_t j = 0;
2111
2112		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2113		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2114		f = 256;
2115
2116		do {
2117			if (j > 15) {
2118				device_printf(sc->sc_dev,
2119				    "failed to generate tssi2dBm\n");
2120				free(pg->pg_tssi2dbm, M_DEVBUF);
2121				return (ENOMEM);
2122			}
2123			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2124			    f, 2048);
2125			delta = abs(q - f);
2126			f = q;
2127			j++;
2128		} while (delta >= 2);
2129
2130		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2131		    128);
2132	}
2133
2134	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2135	return (0);
2136}
2137
2138static void
2139bwn_phy_g_detach(struct bwn_mac *mac)
2140{
2141	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2142
2143	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2144		free(pg->pg_tssi2dbm, M_DEVBUF);
2145		pg->pg_tssi2dbm = NULL;
2146	}
2147	pg->pg_flags = 0;
2148}
2149
2150static void
2151bwn_phy_g_init_pre(struct bwn_mac *mac)
2152{
2153	struct bwn_phy *phy = &mac->mac_phy;
2154	struct bwn_phy_g *pg = &phy->phy_g;
2155	void *tssi2dbm;
2156	int idletssi;
2157	unsigned int i;
2158
2159	tssi2dbm = pg->pg_tssi2dbm;
2160	idletssi = pg->pg_idletssi;
2161
2162	memset(pg, 0, sizeof(*pg));
2163
2164	pg->pg_tssi2dbm = tssi2dbm;
2165	pg->pg_idletssi = idletssi;
2166
2167	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2168
2169	for (i = 0; i < N(pg->pg_nrssi); i++)
2170		pg->pg_nrssi[i] = -1000;
2171	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2172		pg->pg_nrssi_lt[i] = i;
2173	pg->pg_lofcal = 0xffff;
2174	pg->pg_initval = 0xffff;
2175	pg->pg_immode = BWN_IMMODE_NONE;
2176	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2177	pg->pg_avgtssi = 0xff;
2178
2179	pg->pg_loctl.tx_bias = 0xff;
2180	TAILQ_INIT(&pg->pg_loctl.calib_list);
2181}
2182
2183static int
2184bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2185{
2186	struct bwn_phy *phy = &mac->mac_phy;
2187	struct bwn_phy_g *pg = &phy->phy_g;
2188	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2189	struct siba_softc *bus = mac->mac_sd->sd_bus;
2190	static const struct bwn_rfatt rfatt0[] = {
2191		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2192		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2193		{ 3, 1 }, { 4, 1 }
2194	};
2195	static const struct bwn_rfatt rfatt1[] = {
2196		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2197		{ 14, 1 }
2198	};
2199	static const struct bwn_rfatt rfatt2[] = {
2200		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2201		{ 9, 1 }
2202	};
2203	static const struct bwn_bbatt bbatt_0[] = {
2204		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2205	};
2206
2207	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2208
2209	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2210		pg->pg_bbatt.att = 0;
2211	else
2212		pg->pg_bbatt.att = 2;
2213
2214	/* prepare Radio Attenuation */
2215	pg->pg_rfatt.padmix = 0;
2216
2217	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2218	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2219		if (bus->siba_board_rev < 0x43) {
2220			pg->pg_rfatt.att = 2;
2221			goto done;
2222		} else if (bus->siba_board_rev < 0x51) {
2223			pg->pg_rfatt.att = 3;
2224			goto done;
2225		}
2226	}
2227
2228	if (phy->type == BWN_PHYTYPE_A) {
2229		pg->pg_rfatt.att = 0x60;
2230		goto done;
2231	}
2232
2233	switch (phy->rf_ver) {
2234	case 0x2050:
2235		switch (phy->rf_rev) {
2236		case 0:
2237			pg->pg_rfatt.att = 5;
2238			goto done;
2239		case 1:
2240			if (phy->type == BWN_PHYTYPE_G) {
2241				if (bus->siba_board_vendor ==
2242				    SIBA_BOARDVENDOR_BCM &&
2243				    bus->siba_board_type ==
2244				    SIBA_BOARD_BCM4309G &&
2245				    bus->siba_board_rev >= 30)
2246					pg->pg_rfatt.att = 3;
2247				else if (bus->siba_board_vendor ==
2248				    SIBA_BOARDVENDOR_BCM &&
2249				    bus->siba_board_type == SIBA_BOARD_BU4306)
2250					pg->pg_rfatt.att = 3;
2251				else
2252					pg->pg_rfatt.att = 1;
2253			} else {
2254				if (bus->siba_board_vendor ==
2255				    SIBA_BOARDVENDOR_BCM &&
2256				    bus->siba_board_type ==
2257				    SIBA_BOARD_BCM4309G &&
2258				    bus->siba_board_rev >= 30)
2259					pg->pg_rfatt.att = 7;
2260				else
2261					pg->pg_rfatt.att = 6;
2262			}
2263			goto done;
2264		case 2:
2265			if (phy->type == BWN_PHYTYPE_G) {
2266				if (bus->siba_board_vendor ==
2267				    SIBA_BOARDVENDOR_BCM &&
2268				    bus->siba_board_type ==
2269				    SIBA_BOARD_BCM4309G &&
2270				    bus->siba_board_rev >= 30)
2271					pg->pg_rfatt.att = 3;
2272				else if (bus->siba_board_vendor ==
2273				    SIBA_BOARDVENDOR_BCM &&
2274				    bus->siba_board_type == SIBA_BOARD_BU4306)
2275					pg->pg_rfatt.att = 5;
2276				else if (bus->siba_chipid == 0x4320)
2277					pg->pg_rfatt.att = 4;
2278				else
2279					pg->pg_rfatt.att = 3;
2280			} else
2281				pg->pg_rfatt.att = 6;
2282			goto done;
2283		case 3:
2284			pg->pg_rfatt.att = 5;
2285			goto done;
2286		case 4:
2287		case 5:
2288			pg->pg_rfatt.att = 1;
2289			goto done;
2290		case 6:
2291		case 7:
2292			pg->pg_rfatt.att = 5;
2293			goto done;
2294		case 8:
2295			pg->pg_rfatt.att = 0xa;
2296			pg->pg_rfatt.padmix = 1;
2297			goto done;
2298		case 9:
2299		default:
2300			pg->pg_rfatt.att = 5;
2301			goto done;
2302		}
2303		break;
2304	case 0x2053:
2305		switch (phy->rf_rev) {
2306		case 1:
2307			pg->pg_rfatt.att = 6;
2308			goto done;
2309		}
2310		break;
2311	}
2312	pg->pg_rfatt.att = 5;
2313done:
2314	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2315
2316	if (!bwn_has_hwpctl(mac)) {
2317		lo->rfatt.array = rfatt0;
2318		lo->rfatt.len = N(rfatt0);
2319		lo->rfatt.min = 0;
2320		lo->rfatt.max = 9;
2321		goto genbbatt;
2322	}
2323	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2324		lo->rfatt.array = rfatt1;
2325		lo->rfatt.len = N(rfatt1);
2326		lo->rfatt.min = 0;
2327		lo->rfatt.max = 14;
2328		goto genbbatt;
2329	}
2330	lo->rfatt.array = rfatt2;
2331	lo->rfatt.len = N(rfatt2);
2332	lo->rfatt.min = 0;
2333	lo->rfatt.max = 9;
2334genbbatt:
2335	lo->bbatt.array = bbatt_0;
2336	lo->bbatt.len = N(bbatt_0);
2337	lo->bbatt.min = 0;
2338	lo->bbatt.max = 8;
2339
2340	BWN_READ_4(mac, BWN_MACCTL);
2341	if (phy->rev == 1) {
2342		phy->gmode = 0;
2343		bwn_reset_core(mac, 0);
2344		bwn_phy_g_init_sub(mac);
2345		phy->gmode = 1;
2346		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2347	}
2348	return (0);
2349}
2350
2351static uint16_t
2352bwn_phy_g_txctl(struct bwn_mac *mac)
2353{
2354	struct bwn_phy *phy = &mac->mac_phy;
2355
2356	if (phy->rf_ver != 0x2050)
2357		return (0);
2358	if (phy->rf_rev == 1)
2359		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2360	if (phy->rf_rev < 6)
2361		return (BWN_TXCTL_PA2DB);
2362	if (phy->rf_rev == 8)
2363		return (BWN_TXCTL_TXMIX);
2364	return (0);
2365}
2366
2367static int
2368bwn_phy_g_init(struct bwn_mac *mac)
2369{
2370
2371	bwn_phy_g_init_sub(mac);
2372	return (0);
2373}
2374
2375static void
2376bwn_phy_g_exit(struct bwn_mac *mac)
2377{
2378	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2379	struct bwn_lo_calib *cal, *tmp;
2380
2381	if (lo == NULL)
2382		return;
2383	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2384		TAILQ_REMOVE(&lo->calib_list, cal, list);
2385		free(cal, M_DEVBUF);
2386	}
2387}
2388
2389static uint16_t
2390bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2391{
2392
2393	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2394	return (BWN_READ_2(mac, BWN_PHYDATA));
2395}
2396
2397static void
2398bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2399{
2400
2401	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2402	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2403}
2404
2405static uint16_t
2406bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2407{
2408
2409	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2410	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2411	return (BWN_READ_2(mac, BWN_RFDATALO));
2412}
2413
2414static void
2415bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2416{
2417
2418	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2419	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2420	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2421}
2422
2423static int
2424bwn_phy_g_hwpctl(struct bwn_mac *mac)
2425{
2426
2427	return (mac->mac_phy.rev >= 6);
2428}
2429
2430static void
2431bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2432{
2433	struct bwn_phy *phy = &mac->mac_phy;
2434	struct bwn_phy_g *pg = &phy->phy_g;
2435	unsigned int channel;
2436	uint16_t rfover, rfoverval;
2437
2438	if (on) {
2439		if (phy->rf_on)
2440			return;
2441
2442		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2443		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2444		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2445		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2446			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2447			    pg->pg_radioctx_over);
2448			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2449			    pg->pg_radioctx_overval);
2450			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2451		}
2452		channel = phy->chan;
2453		bwn_phy_g_switch_chan(mac, 6, 1);
2454		bwn_phy_g_switch_chan(mac, channel, 0);
2455		return;
2456	}
2457
2458	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2459	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2460	pg->pg_radioctx_over = rfover;
2461	pg->pg_radioctx_overval = rfoverval;
2462	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2463	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2464	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2465}
2466
2467static int
2468bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2469{
2470
2471	if ((newchan < 1) || (newchan > 14))
2472		return (EINVAL);
2473	bwn_phy_g_switch_chan(mac, newchan, 0);
2474
2475	return (0);
2476}
2477
2478static uint32_t
2479bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2480{
2481
2482	return (1);
2483}
2484
2485static void
2486bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2487{
2488	struct bwn_phy *phy = &mac->mac_phy;
2489	uint64_t hf;
2490	int autodiv = 0;
2491	uint16_t tmp;
2492
2493	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2494		autodiv = 1;
2495
2496	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2497	bwn_hf_write(mac, hf);
2498
2499	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2500	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2501	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2502		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2503
2504	if (autodiv) {
2505		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2506		if (antenna == BWN_ANTAUTO1)
2507			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2508		else
2509			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2510		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2511	}
2512	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2513	if (autodiv)
2514		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2515	else
2516		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2517	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2518	if (phy->rev >= 2) {
2519		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2520		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2521		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2522		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2523		    0x15);
2524		if (phy->rev == 2)
2525			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2526		else
2527			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2528			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2529			    8);
2530	}
2531	if (phy->rev >= 6)
2532		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2533
2534	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2535	bwn_hf_write(mac, hf);
2536}
2537
2538static int
2539bwn_phy_g_im(struct bwn_mac *mac, int mode)
2540{
2541	struct bwn_phy *phy = &mac->mac_phy;
2542	struct bwn_phy_g *pg = &phy->phy_g;
2543
2544	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2545	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2546
2547	if (phy->rev == 0 || !phy->gmode)
2548		return (ENODEV);
2549
2550	pg->pg_aci_wlan_automatic = 0;
2551	return (0);
2552}
2553
2554static int
2555bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2556{
2557	struct bwn_phy *phy = &mac->mac_phy;
2558	struct bwn_phy_g *pg = &phy->phy_g;
2559	struct bwn_softc *sc = mac->mac_sc;
2560	struct siba_softc *siba = mac->mac_sd->sd_bus;
2561	unsigned int tssi;
2562	int cck, ofdm;
2563	int power;
2564	int rfatt, bbatt;
2565	unsigned int max;
2566
2567	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2568
2569	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2570	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2571	if (cck < 0 && ofdm < 0) {
2572		if (ignore_tssi == 0)
2573			return (BWN_TXPWR_RES_DONE);
2574		cck = 0;
2575		ofdm = 0;
2576	}
2577	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2578	if (pg->pg_avgtssi != 0xff)
2579		tssi = (tssi + pg->pg_avgtssi) / 2;
2580	pg->pg_avgtssi = tssi;
2581	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2582
2583	max = siba->siba_sprom.maxpwr_bg;
2584	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2585		max -= 3;
2586	if (max >= 120) {
2587		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2588		siba->siba_sprom.maxpwr_bg = max = 80;
2589	}
2590
2591	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2592	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2593	     tssi, 0x00), 0x3f)]);
2594	if (power == 0)
2595		return (BWN_TXPWR_RES_DONE);
2596
2597	rfatt = -((power + 7) / 8);
2598	bbatt = (-(power / 2)) - (4 * rfatt);
2599	if ((rfatt == 0) && (bbatt == 0))
2600		return (BWN_TXPWR_RES_DONE);
2601	pg->pg_bbatt_delta = bbatt;
2602	pg->pg_rfatt_delta = rfatt;
2603	return (BWN_TXPWR_RES_NEED_ADJUST);
2604}
2605
2606static void
2607bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2608{
2609	struct bwn_phy *phy = &mac->mac_phy;
2610	struct bwn_phy_g *pg = &phy->phy_g;
2611	struct bwn_softc *sc = mac->mac_sc;
2612	int rfatt, bbatt;
2613	uint8_t txctl;
2614
2615	bwn_mac_suspend(mac);
2616
2617	BWN_ASSERT_LOCKED(sc);
2618
2619	bbatt = pg->pg_bbatt.att;
2620	bbatt += pg->pg_bbatt_delta;
2621	rfatt = pg->pg_rfatt.att;
2622	rfatt += pg->pg_rfatt_delta;
2623
2624	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2625	txctl = pg->pg_txctl;
2626	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2627		if (rfatt <= 1) {
2628			if (txctl == 0) {
2629				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2630				rfatt += 2;
2631				bbatt += 2;
2632			} else if (mac->mac_sd->sd_bus->siba_sprom.
2633				   bf_lo &
2634				   BWN_BFL_PACTRL) {
2635				bbatt += 4 * (rfatt - 2);
2636				rfatt = 2;
2637			}
2638		} else if (rfatt > 4 && txctl) {
2639			txctl = 0;
2640			if (bbatt < 3) {
2641				rfatt -= 3;
2642				bbatt += 2;
2643			} else {
2644				rfatt -= 2;
2645				bbatt -= 2;
2646			}
2647		}
2648	}
2649	pg->pg_txctl = txctl;
2650	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2651	pg->pg_rfatt.att = rfatt;
2652	pg->pg_bbatt.att = bbatt;
2653
2654	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2655
2656	bwn_phy_lock(mac);
2657	bwn_rf_lock(mac);
2658	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2659	    pg->pg_txctl);
2660	bwn_rf_unlock(mac);
2661	bwn_phy_unlock(mac);
2662
2663	bwn_mac_enable(mac);
2664}
2665
2666static void
2667bwn_phy_g_task_15s(struct bwn_mac *mac)
2668{
2669	struct bwn_phy *phy = &mac->mac_phy;
2670	struct bwn_phy_g *pg = &phy->phy_g;
2671	struct bwn_softc *sc = mac->mac_sc;
2672	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2673	unsigned long expire, now;
2674	struct bwn_lo_calib *cal, *tmp;
2675	uint8_t expired = 0;
2676
2677	bwn_mac_suspend(mac);
2678
2679	if (lo == NULL)
2680		goto fail;
2681
2682	BWN_GETTIME(now);
2683	if (bwn_has_hwpctl(mac)) {
2684		expire = now - BWN_LO_PWRVEC_EXPIRE;
2685		if (time_before(lo->pwr_vec_read_time, expire)) {
2686			bwn_lo_get_powervector(mac);
2687			bwn_phy_g_dc_lookup_init(mac, 0);
2688		}
2689		goto fail;
2690	}
2691
2692	expire = now - BWN_LO_CALIB_EXPIRE;
2693	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2694		if (!time_before(cal->calib_time, expire))
2695			continue;
2696		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2697		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2698			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2699			expired = 1;
2700		}
2701
2702		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2703		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2704		    cal->ctl.i, cal->ctl.q);
2705
2706		TAILQ_REMOVE(&lo->calib_list, cal, list);
2707		free(cal, M_DEVBUF);
2708	}
2709	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2710		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2711		    &pg->pg_rfatt);
2712		if (cal == NULL) {
2713			device_printf(sc->sc_dev,
2714			    "failed to recalibrate LO\n");
2715			goto fail;
2716		}
2717		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2718		bwn_lo_write(mac, &cal->ctl);
2719	}
2720
2721fail:
2722	bwn_mac_enable(mac);
2723}
2724
2725static void
2726bwn_phy_g_task_60s(struct bwn_mac *mac)
2727{
2728	struct bwn_phy *phy = &mac->mac_phy;
2729	uint8_t old = phy->chan;
2730
2731	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2732		return;
2733
2734	bwn_mac_suspend(mac);
2735	bwn_nrssi_slope_11g(mac);
2736	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2737		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2738		bwn_switch_channel(mac, old);
2739	}
2740	bwn_mac_enable(mac);
2741}
2742
2743static void
2744bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2745{
2746
2747	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2748}
2749
2750static int
2751bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2752	const struct ieee80211_bpf_params *params)
2753{
2754	struct ieee80211com *ic = ni->ni_ic;
2755	struct ifnet *ifp = ic->ic_ifp;
2756	struct bwn_softc *sc = ifp->if_softc;
2757	struct bwn_mac *mac = sc->sc_curmac;
2758
2759	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2760	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2761		ieee80211_free_node(ni);
2762		m_freem(m);
2763		return (ENETDOWN);
2764	}
2765
2766	BWN_LOCK(sc);
2767	if (bwn_tx_isfull(sc, m)) {
2768		ieee80211_free_node(ni);
2769		m_freem(m);
2770		ifp->if_oerrors++;
2771		BWN_UNLOCK(sc);
2772		return (ENOBUFS);
2773	}
2774
2775	if (bwn_tx_start(sc, ni, m) != 0) {
2776		if (ni != NULL)
2777			ieee80211_free_node(ni);
2778		ifp->if_oerrors++;
2779	}
2780	sc->sc_watchdog_timer = 5;
2781	BWN_UNLOCK(sc);
2782	return (0);
2783}
2784
2785/*
2786 * Setup driver-specific state for a newly associated node.
2787 * Note that we're called also on a re-associate, the isnew
2788 * param tells us if this is the first time or not.
2789 */
2790static void
2791bwn_newassoc(struct ieee80211_node *ni, int isnew)
2792{
2793	struct ieee80211vap *vap = ni->ni_vap;
2794
2795	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2796	    &BWN_NODE(ni)->bn_amn, ni);
2797}
2798
2799/*
2800 * Callback from the 802.11 layer to update the slot time
2801 * based on the current setting.  We use it to notify the
2802 * firmware of ERP changes and the f/w takes care of things
2803 * like slot time and preamble.
2804 */
2805static void
2806bwn_updateslot(struct ifnet *ifp)
2807{
2808	struct bwn_softc *sc = ifp->if_softc;
2809	struct ieee80211com *ic = ifp->if_l2com;
2810	struct bwn_mac *mac;
2811
2812	BWN_LOCK(sc);
2813	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2814		mac = (struct bwn_mac *)sc->sc_curmac;
2815		bwn_set_slot_time(mac,
2816		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2817	}
2818	BWN_UNLOCK(sc);
2819}
2820
2821/*
2822 * Callback from the 802.11 layer after a promiscuous mode change.
2823 * Note this interface does not check the operating mode as this
2824 * is an internal callback and we are expected to honor the current
2825 * state (e.g. this is used for setting the interface in promiscuous
2826 * mode when operating in hostap mode to do ACS).
2827 */
2828static void
2829bwn_update_promisc(struct ifnet *ifp)
2830{
2831	struct bwn_softc *sc = ifp->if_softc;
2832	struct bwn_mac *mac = sc->sc_curmac;
2833
2834	BWN_LOCK(sc);
2835	mac = sc->sc_curmac;
2836	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2837		if (ifp->if_flags & IFF_PROMISC)
2838			sc->sc_filters |= BWN_MACCTL_PROMISC;
2839		else
2840			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2841		bwn_set_opmode(mac);
2842	}
2843	BWN_UNLOCK(sc);
2844}
2845
2846/*
2847 * Callback from the 802.11 layer to update WME parameters.
2848 */
2849static int
2850bwn_wme_update(struct ieee80211com *ic)
2851{
2852	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2853	struct bwn_mac *mac = sc->sc_curmac;
2854	struct wmeParams *wmep;
2855	int i;
2856
2857	BWN_LOCK(sc);
2858	mac = sc->sc_curmac;
2859	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2860		bwn_mac_suspend(mac);
2861		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2862			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2863			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2864		}
2865		bwn_mac_enable(mac);
2866	}
2867	BWN_UNLOCK(sc);
2868	return (0);
2869}
2870
2871static struct ieee80211_node *
2872bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2873{
2874	struct ieee80211com *ic = vap->iv_ic;
2875	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2876	const size_t space = sizeof(struct bwn_node);
2877	struct bwn_node *bn;
2878
2879	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2880	if (bn == NULL) {
2881		/* XXX stat+msg */
2882		return (NULL);
2883	}
2884	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2885	return (&bn->bn_node);
2886}
2887
2888static void
2889bwn_node_cleanup(struct ieee80211_node *ni)
2890{
2891	struct ieee80211com *ic = ni->ni_ic;
2892	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2893
2894	sc->sc_node_cleanup(ni);
2895}
2896
2897static void
2898bwn_scan_start(struct ieee80211com *ic)
2899{
2900	struct ifnet *ifp = ic->ic_ifp;
2901	struct bwn_softc *sc = ifp->if_softc;
2902	struct bwn_mac *mac;
2903
2904	BWN_LOCK(sc);
2905	mac = sc->sc_curmac;
2906	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2907		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2908		bwn_set_opmode(mac);
2909		/* disable CFP update during scan */
2910		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2911	}
2912	BWN_UNLOCK(sc);
2913}
2914
2915static void
2916bwn_scan_end(struct ieee80211com *ic)
2917{
2918	struct ifnet *ifp = ic->ic_ifp;
2919	struct bwn_softc *sc = ifp->if_softc;
2920	struct bwn_mac *mac;
2921
2922	BWN_LOCK(sc);
2923	mac = sc->sc_curmac;
2924	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2925		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2926		bwn_set_opmode(mac);
2927		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2928	}
2929	BWN_UNLOCK(sc);
2930}
2931
2932static void
2933bwn_set_channel(struct ieee80211com *ic)
2934{
2935	struct ifnet *ifp = ic->ic_ifp;
2936	struct bwn_softc *sc = ifp->if_softc;
2937	struct bwn_mac *mac = sc->sc_curmac;
2938	struct bwn_phy *phy = &mac->mac_phy;
2939	int chan, error;
2940
2941	BWN_LOCK(sc);
2942
2943	error = bwn_switch_band(sc, ic->ic_curchan);
2944	if (error)
2945		goto fail;;
2946	bwn_mac_suspend(mac);
2947	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2948	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2949	if (chan != phy->chan)
2950		bwn_switch_channel(mac, chan);
2951
2952	/* TX power level */
2953	if (ic->ic_curchan->ic_maxpower != 0 &&
2954	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2955		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2956		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2957		    BWN_TXPWR_IGNORE_TSSI);
2958	}
2959
2960	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2961	if (phy->set_antenna)
2962		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2963
2964	if (sc->sc_rf_enabled != phy->rf_on) {
2965		if (sc->sc_rf_enabled) {
2966			bwn_rf_turnon(mac);
2967			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2968				device_printf(sc->sc_dev,
2969				    "please turns on the RF switch\n");
2970		} else
2971			bwn_rf_turnoff(mac);
2972	}
2973
2974	bwn_mac_enable(mac);
2975
2976fail:
2977	/*
2978	 * Setup radio tap channel freq and flags
2979	 */
2980	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2981		htole16(ic->ic_curchan->ic_freq);
2982	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2983		htole16(ic->ic_curchan->ic_flags & 0xffff);
2984
2985	BWN_UNLOCK(sc);
2986}
2987
2988static struct ieee80211vap *
2989bwn_vap_create(struct ieee80211com *ic,
2990	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2991	const uint8_t bssid[IEEE80211_ADDR_LEN],
2992	const uint8_t mac0[IEEE80211_ADDR_LEN])
2993{
2994	struct ifnet *ifp = ic->ic_ifp;
2995	struct bwn_softc *sc = ifp->if_softc;
2996	struct ieee80211vap *vap;
2997	struct bwn_vap *bvp;
2998	uint8_t mac[IEEE80211_ADDR_LEN];
2999
3000	IEEE80211_ADDR_COPY(mac, mac0);
3001	switch (opmode) {
3002	case IEEE80211_M_HOSTAP:
3003	case IEEE80211_M_MBSS:
3004	case IEEE80211_M_STA:
3005	case IEEE80211_M_WDS:
3006	case IEEE80211_M_MONITOR:
3007	case IEEE80211_M_IBSS:
3008	case IEEE80211_M_AHDEMO:
3009		break;
3010	default:
3011		return (NULL);
3012	}
3013
3014	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3015
3016	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3017	    M_80211_VAP, M_NOWAIT | M_ZERO);
3018	if (bvp == NULL) {
3019		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3020		return (NULL);
3021	}
3022	vap = &bvp->bv_vap;
3023	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3024	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3025	/* override with driver methods */
3026	bvp->bv_newstate = vap->iv_newstate;
3027	vap->iv_newstate = bwn_newstate;
3028
3029	/* override max aid so sta's cannot assoc when we're out of sta id's */
3030	vap->iv_max_aid = BWN_STAID_MAX;
3031
3032	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3033	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3034	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3035	    500 /*ms*/);
3036
3037	/* complete setup */
3038	ieee80211_vap_attach(vap, ieee80211_media_change,
3039	    ieee80211_media_status);
3040	return (vap);
3041}
3042
3043static void
3044bwn_vap_delete(struct ieee80211vap *vap)
3045{
3046	struct bwn_vap *bvp = BWN_VAP(vap);
3047
3048	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3049	ieee80211_vap_detach(vap);
3050	free(bvp, M_80211_VAP);
3051}
3052
3053static void
3054bwn_init(void *arg)
3055{
3056	struct bwn_softc *sc = arg;
3057	struct ifnet *ifp = sc->sc_ifp;
3058	struct ieee80211com *ic = ifp->if_l2com;
3059	int error = 0;
3060
3061	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3062		__func__, ifp->if_flags);
3063
3064	BWN_LOCK(sc);
3065	error = bwn_init_locked(sc);
3066	BWN_UNLOCK(sc);
3067
3068	if (error == 0)
3069		ieee80211_start_all(ic);	/* start all vap's */
3070}
3071
3072static int
3073bwn_init_locked(struct bwn_softc *sc)
3074{
3075	struct bwn_mac *mac;
3076	struct ifnet *ifp = sc->sc_ifp;
3077	int error;
3078
3079	BWN_ASSERT_LOCKED(sc);
3080
3081	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3082	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3083	sc->sc_filters = 0;
3084	bwn_wme_clear(sc);
3085	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3086	sc->sc_rf_enabled = 1;
3087
3088	mac = sc->sc_curmac;
3089	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3090		error = bwn_core_init(mac);
3091		if (error != 0)
3092			return (error);
3093	}
3094	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3095		bwn_core_start(mac);
3096
3097	bwn_set_opmode(mac);
3098	bwn_set_pretbtt(mac);
3099	bwn_spu_setdelay(mac, 0);
3100	bwn_set_macaddr(mac);
3101
3102	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3103	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3104	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3105
3106	return (0);
3107}
3108
3109static void
3110bwn_stop(struct bwn_softc *sc, int statechg)
3111{
3112
3113	BWN_LOCK(sc);
3114	bwn_stop_locked(sc, statechg);
3115	BWN_UNLOCK(sc);
3116}
3117
3118static void
3119bwn_stop_locked(struct bwn_softc *sc, int statechg)
3120{
3121	struct bwn_mac *mac = sc->sc_curmac;
3122	struct ifnet *ifp = sc->sc_ifp;
3123
3124	BWN_ASSERT_LOCKED(sc);
3125
3126	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3127		/* XXX FIXME opmode not based on VAP */
3128		bwn_set_opmode(mac);
3129		bwn_set_macaddr(mac);
3130	}
3131
3132	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3133		bwn_core_stop(mac);
3134
3135	callout_stop(&sc->sc_led_blink_ch);
3136	sc->sc_led_blinking = 0;
3137
3138	bwn_core_exit(mac);
3139	sc->sc_rf_enabled = 0;
3140
3141	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3142}
3143
3144static void
3145bwn_wme_clear(struct bwn_softc *sc)
3146{
3147#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3148	struct wmeParams *p;
3149	unsigned int i;
3150
3151	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3152	    ("%s:%d: fail", __func__, __LINE__));
3153
3154	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3155		p = &(sc->sc_wmeParams[i]);
3156
3157		switch (bwn_wme_shm_offsets[i]) {
3158		case BWN_WME_VOICE:
3159			p->wmep_txopLimit = 0;
3160			p->wmep_aifsn = 2;
3161			/* XXX FIXME: log2(cwmin) */
3162			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3163			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3164			break;
3165		case BWN_WME_VIDEO:
3166			p->wmep_txopLimit = 0;
3167			p->wmep_aifsn = 2;
3168			/* XXX FIXME: log2(cwmin) */
3169			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3170			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3171			break;
3172		case BWN_WME_BESTEFFORT:
3173			p->wmep_txopLimit = 0;
3174			p->wmep_aifsn = 3;
3175			/* XXX FIXME: log2(cwmin) */
3176			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3177			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3178			break;
3179		case BWN_WME_BACKGROUND:
3180			p->wmep_txopLimit = 0;
3181			p->wmep_aifsn = 7;
3182			/* XXX FIXME: log2(cwmin) */
3183			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3184			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3185			break;
3186		default:
3187			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3188		}
3189	}
3190}
3191
3192static int
3193bwn_core_init(struct bwn_mac *mac)
3194{
3195#ifdef BWN_DEBUG
3196	struct bwn_softc *sc = mac->mac_sc;
3197#endif
3198	struct siba_dev_softc *sd = mac->mac_sd;
3199	struct siba_softc *siba = sd->sd_bus;
3200	struct siba_sprom *sprom = &siba->siba_sprom;
3201	uint64_t hf;
3202	int error;
3203
3204	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3205	    ("%s:%d: fail", __func__, __LINE__));
3206
3207	siba_powerup(siba, 0);
3208	if (!siba_dev_isup(sd))
3209		bwn_reset_core(mac,
3210		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3211
3212	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3213	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3214	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3215	BWN_GETTIME(mac->mac_phy.nexttime);
3216	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3217	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3218	mac->mac_stats.link_noise = -95;
3219	mac->mac_reason_intr = 0;
3220	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3221	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3222#ifdef BWN_DEBUG
3223	if (sc->sc_debug & BWN_DEBUG_XMIT)
3224		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3225#endif
3226	mac->mac_suspended = 1;
3227	mac->mac_task_state = 0;
3228	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3229
3230	mac->mac_phy.init_pre(mac);
3231
3232	siba_pcicore_intr(&siba->siba_pci, sd);
3233
3234	bwn_fix_imcfglobug(mac);
3235	bwn_bt_disable(mac);
3236	if (mac->mac_phy.prepare_hw) {
3237		error = mac->mac_phy.prepare_hw(mac);
3238		if (error)
3239			goto fail0;
3240	}
3241	error = bwn_chip_init(mac);
3242	if (error)
3243		goto fail0;
3244	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3245	    mac->mac_sd->sd_id.sd_rev);
3246	hf = bwn_hf_read(mac);
3247	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3248		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3249		if (sprom->bf_lo & BWN_BFL_PACTRL)
3250			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3251		if (mac->mac_phy.rev == 1)
3252			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3253	}
3254	if (mac->mac_phy.rf_ver == 0x2050) {
3255		if (mac->mac_phy.rf_rev < 6)
3256			hf |= BWN_HF_FORCE_VCO_RECALC;
3257		if (mac->mac_phy.rf_rev == 6)
3258			hf |= BWN_HF_4318_TSSI;
3259	}
3260	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3261		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3262	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3263	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3264		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3265	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3266	bwn_hf_write(mac, hf);
3267
3268	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3269	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3270	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3271	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3272
3273	bwn_rate_init(mac);
3274	bwn_set_phytxctl(mac);
3275
3276	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3277	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3278	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3279
3280	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3281		bwn_pio_init(mac);
3282	else
3283		bwn_dma_init(mac);
3284	if (error)
3285		goto fail1;
3286	bwn_wme_init(mac);
3287	bwn_spu_setdelay(mac, 1);
3288	bwn_bt_enable(mac);
3289
3290	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3291	bwn_set_macaddr(mac);
3292	bwn_crypt_init(mac);
3293
3294	/* XXX LED initializatin */
3295
3296	mac->mac_status = BWN_MAC_STATUS_INITED;
3297
3298	return (error);
3299
3300fail1:
3301	bwn_chip_exit(mac);
3302fail0:
3303	siba_powerdown(siba);
3304	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3305	    ("%s:%d: fail", __func__, __LINE__));
3306	return (error);
3307}
3308
3309static void
3310bwn_core_start(struct bwn_mac *mac)
3311{
3312	struct bwn_softc *sc = mac->mac_sc;
3313	uint32_t tmp;
3314
3315	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3316	    ("%s:%d: fail", __func__, __LINE__));
3317
3318	if (mac->mac_sd->sd_id.sd_rev < 5)
3319		return;
3320
3321	while (1) {
3322		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3323		if (!(tmp & 0x00000001))
3324			break;
3325		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3326	}
3327
3328	bwn_mac_enable(mac);
3329	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3330	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3331
3332	mac->mac_status = BWN_MAC_STATUS_STARTED;
3333}
3334
3335static void
3336bwn_core_exit(struct bwn_mac *mac)
3337{
3338	struct bwn_softc *sc = mac->mac_sc;
3339	uint32_t macctl;
3340
3341	BWN_ASSERT_LOCKED(sc);
3342
3343	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3344	    ("%s:%d: fail", __func__, __LINE__));
3345
3346	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3347		return;
3348	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3349
3350	macctl = BWN_READ_4(mac, BWN_MACCTL);
3351	macctl &= ~BWN_MACCTL_MCODE_RUN;
3352	macctl |= BWN_MACCTL_MCODE_JMP0;
3353	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3354
3355	bwn_dma_stop(mac);
3356	bwn_pio_stop(mac);
3357	bwn_chip_exit(mac);
3358	mac->mac_phy.switch_analog(mac, 0);
3359	siba_dev_down(mac->mac_sd, 0);
3360	siba_powerdown(mac->mac_sd->sd_bus);
3361}
3362
3363static void
3364bwn_fix_imcfglobug(struct bwn_mac *mac)
3365{
3366	struct siba_dev_softc *sd = mac->mac_sd;
3367	struct siba_softc *siba = sd->sd_bus;
3368	uint32_t tmp;
3369
3370	if (siba->siba_pci.spc_dev == NULL)
3371		return;
3372	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3373	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3374		return;
3375
3376	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3377	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3378	switch (siba->siba_type) {
3379	case SIBA_TYPE_PCI:
3380	case SIBA_TYPE_PCMCIA:
3381		tmp |= 0x32;
3382		break;
3383	case SIBA_TYPE_SSB:
3384		tmp |= 0x53;
3385		break;
3386	}
3387	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3388}
3389
3390static void
3391bwn_bt_disable(struct bwn_mac *mac)
3392{
3393	struct bwn_softc *sc = mac->mac_sc;
3394
3395	(void)sc;
3396	/* XXX do nothing yet */
3397}
3398
3399static int
3400bwn_chip_init(struct bwn_mac *mac)
3401{
3402	struct bwn_phy *phy = &mac->mac_phy;
3403	uint32_t macctl;
3404	int error;
3405
3406	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3407	if (phy->gmode)
3408		macctl |= BWN_MACCTL_GMODE;
3409	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3410
3411	error = bwn_fw_fillinfo(mac);
3412	if (error)
3413		return (error);
3414	error = bwn_fw_loaducode(mac);
3415	if (error)
3416		return (error);
3417
3418	error = bwn_gpio_init(mac);
3419	if (error)
3420		return (error);
3421
3422	error = bwn_fw_loadinitvals(mac);
3423	if (error) {
3424		bwn_gpio_cleanup(mac);
3425		return (error);
3426	}
3427	phy->switch_analog(mac, 1);
3428	error = bwn_phy_init(mac);
3429	if (error) {
3430		bwn_gpio_cleanup(mac);
3431		return (error);
3432	}
3433	if (phy->set_im)
3434		phy->set_im(mac, BWN_IMMODE_NONE);
3435	if (phy->set_antenna)
3436		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3437	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3438
3439	if (phy->type == BWN_PHYTYPE_B)
3440		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3441	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3442	if (mac->mac_sd->sd_id.sd_rev < 5)
3443		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3444
3445	BWN_WRITE_4(mac, BWN_MACCTL,
3446	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3447	BWN_WRITE_4(mac, BWN_MACCTL,
3448	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3449	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3450
3451	bwn_set_opmode(mac);
3452	if (mac->mac_sd->sd_id.sd_rev < 3) {
3453		BWN_WRITE_2(mac, 0x060e, 0x0000);
3454		BWN_WRITE_2(mac, 0x0610, 0x8000);
3455		BWN_WRITE_2(mac, 0x0604, 0x0000);
3456		BWN_WRITE_2(mac, 0x0606, 0x0200);
3457	} else {
3458		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3459		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3460	}
3461	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3462	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3463	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3464	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3465	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3466	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3467	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3468	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3469	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3470	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3471	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3472	return (error);
3473}
3474
3475/* read hostflags */
3476static uint64_t
3477bwn_hf_read(struct bwn_mac *mac)
3478{
3479	uint64_t ret;
3480
3481	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3482	ret <<= 16;
3483	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3484	ret <<= 16;
3485	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3486	return (ret);
3487}
3488
3489static void
3490bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3491{
3492
3493	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3494	    (value & 0x00000000ffffull));
3495	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3496	    (value & 0x0000ffff0000ull) >> 16);
3497	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3498	    (value & 0xffff00000000ULL) >> 32);
3499}
3500
3501static void
3502bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3503{
3504
3505	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3506	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3507}
3508
3509static void
3510bwn_rate_init(struct bwn_mac *mac)
3511{
3512
3513	switch (mac->mac_phy.type) {
3514	case BWN_PHYTYPE_A:
3515	case BWN_PHYTYPE_G:
3516	case BWN_PHYTYPE_LP:
3517	case BWN_PHYTYPE_N:
3518		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3519		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3520		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3521		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3522		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3523		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3524		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3525		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3526			break;
3527		/* FALLTHROUGH */
3528	case BWN_PHYTYPE_B:
3529		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3530		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3531		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3532		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3533		break;
3534	default:
3535		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3536	}
3537}
3538
3539static void
3540bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3541{
3542	uint16_t offset;
3543
3544	if (ofdm) {
3545		offset = 0x480;
3546		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3547	} else {
3548		offset = 0x4c0;
3549		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3550	}
3551	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3552	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3553}
3554
3555static uint8_t
3556bwn_plcp_getcck(const uint8_t bitrate)
3557{
3558
3559	switch (bitrate) {
3560	case BWN_CCK_RATE_1MB:
3561		return (0x0a);
3562	case BWN_CCK_RATE_2MB:
3563		return (0x14);
3564	case BWN_CCK_RATE_5MB:
3565		return (0x37);
3566	case BWN_CCK_RATE_11MB:
3567		return (0x6e);
3568	}
3569	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3570	return (0);
3571}
3572
3573static uint8_t
3574bwn_plcp_getofdm(const uint8_t bitrate)
3575{
3576
3577	switch (bitrate) {
3578	case BWN_OFDM_RATE_6MB:
3579		return (0xb);
3580	case BWN_OFDM_RATE_9MB:
3581		return (0xf);
3582	case BWN_OFDM_RATE_12MB:
3583		return (0xa);
3584	case BWN_OFDM_RATE_18MB:
3585		return (0xe);
3586	case BWN_OFDM_RATE_24MB:
3587		return (0x9);
3588	case BWN_OFDM_RATE_36MB:
3589		return (0xd);
3590	case BWN_OFDM_RATE_48MB:
3591		return (0x8);
3592	case BWN_OFDM_RATE_54MB:
3593		return (0xc);
3594	}
3595	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3596	return (0);
3597}
3598
3599static void
3600bwn_set_phytxctl(struct bwn_mac *mac)
3601{
3602	uint16_t ctl;
3603
3604	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3605	    BWN_TX_PHY_TXPWR);
3606	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3607	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3608	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3609}
3610
3611static void
3612bwn_pio_init(struct bwn_mac *mac)
3613{
3614	struct bwn_pio *pio = &mac->mac_method.pio;
3615
3616	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3617	    & ~BWN_MACCTL_BIGENDIAN);
3618	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3619
3620	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3621	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3622	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3623	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3624	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3625	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3626}
3627
3628static void
3629bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3630    int index)
3631{
3632	struct bwn_pio_txpkt *tp;
3633	unsigned int i;
3634
3635	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3636	tq->tq_index = index;
3637
3638	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3639	if (mac->mac_sd->sd_id.sd_rev >= 8)
3640		tq->tq_size = 1920;
3641	else {
3642		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3643		tq->tq_size -= 80;
3644	}
3645
3646	TAILQ_INIT(&tq->tq_pktlist);
3647	for (i = 0; i < N(tq->tq_pkts); i++) {
3648		tp = &(tq->tq_pkts[i]);
3649		tp->tp_index = i;
3650		tp->tp_queue = tq;
3651		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3652	}
3653}
3654
3655static uint16_t
3656bwn_pio_idx2base(struct bwn_mac *mac, int index)
3657{
3658	struct bwn_softc *sc = mac->mac_sc;
3659	static const uint16_t bases[] = {
3660		BWN_PIO_BASE0,
3661		BWN_PIO_BASE1,
3662		BWN_PIO_BASE2,
3663		BWN_PIO_BASE3,
3664		BWN_PIO_BASE4,
3665		BWN_PIO_BASE5,
3666		BWN_PIO_BASE6,
3667		BWN_PIO_BASE7,
3668	};
3669	static const uint16_t bases_rev11[] = {
3670		BWN_PIO11_BASE0,
3671		BWN_PIO11_BASE1,
3672		BWN_PIO11_BASE2,
3673		BWN_PIO11_BASE3,
3674		BWN_PIO11_BASE4,
3675		BWN_PIO11_BASE5,
3676	};
3677
3678	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3679		if (index >= N(bases_rev11))
3680			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3681		return (bases_rev11[index]);
3682	}
3683	if (index >= N(bases))
3684		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3685	return (bases[index]);
3686}
3687
3688static void
3689bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3690    int index)
3691{
3692
3693	prq->prq_mac = mac;
3694	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3695	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3696	bwn_dma_rxdirectfifo(mac, index, 1);
3697}
3698
3699static void
3700bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3701{
3702	if (tq == NULL)
3703		return;
3704	bwn_pio_cancel_tx_packets(tq);
3705}
3706
3707static void
3708bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3709{
3710
3711	bwn_destroy_pioqueue_tx(pio);
3712}
3713
3714static uint16_t
3715bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3716    uint16_t offset)
3717{
3718
3719	return (BWN_READ_2(mac, tq->tq_base + offset));
3720}
3721
3722static void
3723bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3724{
3725	uint32_t ctl;
3726	int type;
3727	uint16_t base;
3728
3729	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3730	base = bwn_dma_base(type, idx);
3731	if (type == BWN_DMA_64BIT) {
3732		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3733		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3734		if (enable)
3735			ctl |= BWN_DMA64_RXDIRECTFIFO;
3736		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3737	} else {
3738		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3739		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3740		if (enable)
3741			ctl |= BWN_DMA32_RXDIRECTFIFO;
3742		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3743	}
3744}
3745
3746static uint64_t
3747bwn_dma_mask(struct bwn_mac *mac)
3748{
3749	uint32_t tmp;
3750	uint16_t base;
3751
3752	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3753	if (tmp & SIBA_TGSHIGH_DMA64)
3754		return (BWN_DMA_BIT_MASK(64));
3755	base = bwn_dma_base(0, 0);
3756	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3757	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3758	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3759		return (BWN_DMA_BIT_MASK(32));
3760
3761	return (BWN_DMA_BIT_MASK(30));
3762}
3763
3764static int
3765bwn_dma_mask2type(uint64_t dmamask)
3766{
3767
3768	if (dmamask == BWN_DMA_BIT_MASK(30))
3769		return (BWN_DMA_30BIT);
3770	if (dmamask == BWN_DMA_BIT_MASK(32))
3771		return (BWN_DMA_32BIT);
3772	if (dmamask == BWN_DMA_BIT_MASK(64))
3773		return (BWN_DMA_64BIT);
3774	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3775	return (BWN_DMA_30BIT);
3776}
3777
3778static void
3779bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3780{
3781	struct bwn_pio_txpkt *tp;
3782	unsigned int i;
3783
3784	for (i = 0; i < N(tq->tq_pkts); i++) {
3785		tp = &(tq->tq_pkts[i]);
3786		if (tp->tp_m) {
3787			m_freem(tp->tp_m);
3788			tp->tp_m = NULL;
3789		}
3790	}
3791}
3792
3793static uint16_t
3794bwn_dma_base(int type, int controller_idx)
3795{
3796	static const uint16_t map64[] = {
3797		BWN_DMA64_BASE0,
3798		BWN_DMA64_BASE1,
3799		BWN_DMA64_BASE2,
3800		BWN_DMA64_BASE3,
3801		BWN_DMA64_BASE4,
3802		BWN_DMA64_BASE5,
3803	};
3804	static const uint16_t map32[] = {
3805		BWN_DMA32_BASE0,
3806		BWN_DMA32_BASE1,
3807		BWN_DMA32_BASE2,
3808		BWN_DMA32_BASE3,
3809		BWN_DMA32_BASE4,
3810		BWN_DMA32_BASE5,
3811	};
3812
3813	if (type == BWN_DMA_64BIT) {
3814		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3815		    ("%s:%d: fail", __func__, __LINE__));
3816		return (map64[controller_idx]);
3817	}
3818	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3819	    ("%s:%d: fail", __func__, __LINE__));
3820	return (map32[controller_idx]);
3821}
3822
3823static void
3824bwn_dma_init(struct bwn_mac *mac)
3825{
3826	struct bwn_dma *dma = &mac->mac_method.dma;
3827
3828	/* setup TX DMA channels. */
3829	bwn_dma_setup(dma->wme[WME_AC_BK]);
3830	bwn_dma_setup(dma->wme[WME_AC_BE]);
3831	bwn_dma_setup(dma->wme[WME_AC_VI]);
3832	bwn_dma_setup(dma->wme[WME_AC_VO]);
3833	bwn_dma_setup(dma->mcast);
3834	/* setup RX DMA channel. */
3835	bwn_dma_setup(dma->rx);
3836}
3837
3838static struct bwn_dma_ring *
3839bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3840    int for_tx, int type)
3841{
3842	struct bwn_dma *dma = &mac->mac_method.dma;
3843	struct bwn_dma_ring *dr;
3844	struct bwn_dmadesc_generic *desc;
3845	struct bwn_dmadesc_meta *mt;
3846	struct bwn_softc *sc = mac->mac_sc;
3847	int error, i;
3848
3849	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3850	if (dr == NULL)
3851		goto out;
3852	dr->dr_numslots = BWN_RXRING_SLOTS;
3853	if (for_tx)
3854		dr->dr_numslots = BWN_TXRING_SLOTS;
3855
3856	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3857	    M_DEVBUF, M_NOWAIT | M_ZERO);
3858	if (dr->dr_meta == NULL)
3859		goto fail0;
3860
3861	dr->dr_type = type;
3862	dr->dr_mac = mac;
3863	dr->dr_base = bwn_dma_base(type, controller_index);
3864	dr->dr_index = controller_index;
3865	if (type == BWN_DMA_64BIT) {
3866		dr->getdesc = bwn_dma_64_getdesc;
3867		dr->setdesc = bwn_dma_64_setdesc;
3868		dr->start_transfer = bwn_dma_64_start_transfer;
3869		dr->suspend = bwn_dma_64_suspend;
3870		dr->resume = bwn_dma_64_resume;
3871		dr->get_curslot = bwn_dma_64_get_curslot;
3872		dr->set_curslot = bwn_dma_64_set_curslot;
3873	} else {
3874		dr->getdesc = bwn_dma_32_getdesc;
3875		dr->setdesc = bwn_dma_32_setdesc;
3876		dr->start_transfer = bwn_dma_32_start_transfer;
3877		dr->suspend = bwn_dma_32_suspend;
3878		dr->resume = bwn_dma_32_resume;
3879		dr->get_curslot = bwn_dma_32_get_curslot;
3880		dr->set_curslot = bwn_dma_32_set_curslot;
3881	}
3882	if (for_tx) {
3883		dr->dr_tx = 1;
3884		dr->dr_curslot = -1;
3885	} else {
3886		if (dr->dr_index == 0) {
3887			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3888			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3889		} else
3890			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3891	}
3892
3893	error = bwn_dma_allocringmemory(dr);
3894	if (error)
3895		goto fail2;
3896
3897	if (for_tx) {
3898		/*
3899		 * Assumption: BWN_TXRING_SLOTS can be divided by
3900		 * BWN_TX_SLOTS_PER_FRAME
3901		 */
3902		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3903		    ("%s:%d: fail", __func__, __LINE__));
3904
3905		dr->dr_txhdr_cache =
3906		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3907			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3908		KASSERT(dr->dr_txhdr_cache != NULL,
3909		    ("%s:%d: fail", __func__, __LINE__));
3910
3911		/*
3912		 * Create TX ring DMA stuffs
3913		 */
3914		error = bus_dma_tag_create(dma->parent_dtag,
3915				    BWN_ALIGN, 0,
3916				    BUS_SPACE_MAXADDR,
3917				    BUS_SPACE_MAXADDR,
3918				    NULL, NULL,
3919				    BWN_HDRSIZE(mac),
3920				    1,
3921				    BUS_SPACE_MAXSIZE_32BIT,
3922				    0,
3923				    NULL, NULL,
3924				    &dr->dr_txring_dtag);
3925		if (error) {
3926			device_printf(sc->sc_dev,
3927			    "can't create TX ring DMA tag: TODO frees\n");
3928			goto fail1;
3929		}
3930
3931		for (i = 0; i < dr->dr_numslots; i += 2) {
3932			dr->getdesc(dr, i, &desc, &mt);
3933
3934			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3935			mt->mt_m = NULL;
3936			mt->mt_ni = NULL;
3937			mt->mt_islast = 0;
3938			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3939			    &mt->mt_dmap);
3940			if (error) {
3941				device_printf(sc->sc_dev,
3942				     "can't create RX buf DMA map\n");
3943				goto fail1;
3944			}
3945
3946			dr->getdesc(dr, i + 1, &desc, &mt);
3947
3948			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3949			mt->mt_m = NULL;
3950			mt->mt_ni = NULL;
3951			mt->mt_islast = 1;
3952			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3953			    &mt->mt_dmap);
3954			if (error) {
3955				device_printf(sc->sc_dev,
3956				     "can't create RX buf DMA map\n");
3957				goto fail1;
3958			}
3959		}
3960	} else {
3961		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3962		    &dr->dr_spare_dmap);
3963		if (error) {
3964			device_printf(sc->sc_dev,
3965			    "can't create RX buf DMA map\n");
3966			goto out;		/* XXX wrong! */
3967		}
3968
3969		for (i = 0; i < dr->dr_numslots; i++) {
3970			dr->getdesc(dr, i, &desc, &mt);
3971
3972			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3973			    &mt->mt_dmap);
3974			if (error) {
3975				device_printf(sc->sc_dev,
3976				    "can't create RX buf DMA map\n");
3977				goto out;	/* XXX wrong! */
3978			}
3979			error = bwn_dma_newbuf(dr, desc, mt, 1);
3980			if (error) {
3981				device_printf(sc->sc_dev,
3982				    "failed to allocate RX buf\n");
3983				goto out;	/* XXX wrong! */
3984			}
3985		}
3986
3987		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3988		    BUS_DMASYNC_PREWRITE);
3989
3990		dr->dr_usedslot = dr->dr_numslots;
3991	}
3992
3993      out:
3994	return (dr);
3995
3996fail2:
3997	free(dr->dr_txhdr_cache, M_DEVBUF);
3998fail1:
3999	free(dr->dr_meta, M_DEVBUF);
4000fail0:
4001	free(dr, M_DEVBUF);
4002	return (NULL);
4003}
4004
4005static void
4006bwn_dma_ringfree(struct bwn_dma_ring **dr)
4007{
4008
4009	if (dr == NULL)
4010		return;
4011
4012	bwn_dma_free_descbufs(*dr);
4013	bwn_dma_free_ringmemory(*dr);
4014
4015	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4016	free((*dr)->dr_meta, M_DEVBUF);
4017	free(*dr, M_DEVBUF);
4018
4019	*dr = NULL;
4020}
4021
4022static void
4023bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4024    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4025{
4026	struct bwn_dmadesc32 *desc;
4027
4028	*meta = &(dr->dr_meta[slot]);
4029	desc = dr->dr_ring_descbase;
4030	desc = &(desc[slot]);
4031
4032	*gdesc = (struct bwn_dmadesc_generic *)desc;
4033}
4034
4035static void
4036bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4037    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4038    int start, int end, int irq)
4039{
4040	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4041	uint32_t addr, addrext, ctl;
4042	int slot;
4043
4044	slot = (int)(&(desc->dma.dma32) - descbase);
4045	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4046	    ("%s:%d: fail", __func__, __LINE__));
4047
4048	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4049	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4050	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4051	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4052	if (slot == dr->dr_numslots - 1)
4053		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4054	if (start)
4055		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4056	if (end)
4057		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4058	if (irq)
4059		ctl |= BWN_DMA32_DCTL_IRQ;
4060	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4061	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4062
4063	desc->dma.dma32.control = htole32(ctl);
4064	desc->dma.dma32.address = htole32(addr);
4065}
4066
4067static void
4068bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4069{
4070
4071	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4072	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4073}
4074
4075static void
4076bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4077{
4078
4079	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4080	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4081}
4082
4083static void
4084bwn_dma_32_resume(struct bwn_dma_ring *dr)
4085{
4086
4087	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4088	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4089}
4090
4091static int
4092bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4093{
4094	uint32_t val;
4095
4096	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4097	val &= BWN_DMA32_RXDPTR;
4098
4099	return (val / sizeof(struct bwn_dmadesc32));
4100}
4101
4102static void
4103bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4104{
4105
4106	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4107	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4108}
4109
4110static void
4111bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4112    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4113{
4114	struct bwn_dmadesc64 *desc;
4115
4116	*meta = &(dr->dr_meta[slot]);
4117	desc = dr->dr_ring_descbase;
4118	desc = &(desc[slot]);
4119
4120	*gdesc = (struct bwn_dmadesc_generic *)desc;
4121}
4122
4123static void
4124bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4125    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4126    int start, int end, int irq)
4127{
4128	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4129	int slot;
4130	uint32_t ctl0 = 0, ctl1 = 0;
4131	uint32_t addrlo, addrhi;
4132	uint32_t addrext;
4133
4134	slot = (int)(&(desc->dma.dma64) - descbase);
4135	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4136	    ("%s:%d: fail", __func__, __LINE__));
4137
4138	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4139	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4140	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4141	    30;
4142	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4143	if (slot == dr->dr_numslots - 1)
4144		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4145	if (start)
4146		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4147	if (end)
4148		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4149	if (irq)
4150		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4151	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4152	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4153	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4154
4155	desc->dma.dma64.control0 = htole32(ctl0);
4156	desc->dma.dma64.control1 = htole32(ctl1);
4157	desc->dma.dma64.address_low = htole32(addrlo);
4158	desc->dma.dma64.address_high = htole32(addrhi);
4159}
4160
4161static void
4162bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4163{
4164
4165	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4166	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4167}
4168
4169static void
4170bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4171{
4172
4173	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4174	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4175}
4176
4177static void
4178bwn_dma_64_resume(struct bwn_dma_ring *dr)
4179{
4180
4181	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4182	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4183}
4184
4185static int
4186bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4187{
4188	uint32_t val;
4189
4190	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4191	val &= BWN_DMA64_RXSTATDPTR;
4192
4193	return (val / sizeof(struct bwn_dmadesc64));
4194}
4195
4196static void
4197bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4198{
4199
4200	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4201	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4202}
4203
4204static int
4205bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4206{
4207	struct bwn_mac *mac = dr->dr_mac;
4208	struct bwn_dma *dma = &mac->mac_method.dma;
4209	struct bwn_softc *sc = mac->mac_sc;
4210	int error;
4211
4212	error = bus_dma_tag_create(dma->parent_dtag,
4213			    BWN_ALIGN, 0,
4214			    BUS_SPACE_MAXADDR,
4215			    BUS_SPACE_MAXADDR,
4216			    NULL, NULL,
4217			    BWN_DMA_RINGMEMSIZE,
4218			    1,
4219			    BUS_SPACE_MAXSIZE_32BIT,
4220			    0,
4221			    NULL, NULL,
4222			    &dr->dr_ring_dtag);
4223	if (error) {
4224		device_printf(sc->sc_dev,
4225		    "can't create TX ring DMA tag: TODO frees\n");
4226		return (-1);
4227	}
4228
4229	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4230	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4231	    &dr->dr_ring_dmap);
4232	if (error) {
4233		device_printf(sc->sc_dev,
4234		    "can't allocate DMA mem: TODO frees\n");
4235		return (-1);
4236	}
4237	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4238	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4239	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4240	if (error) {
4241		device_printf(sc->sc_dev,
4242		    "can't load DMA mem: TODO free\n");
4243		return (-1);
4244	}
4245
4246	return (0);
4247}
4248
4249static void
4250bwn_dma_setup(struct bwn_dma_ring *dr)
4251{
4252	uint64_t ring64;
4253	uint32_t addrext, ring32, value;
4254	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4255
4256	if (dr->dr_tx) {
4257		dr->dr_curslot = -1;
4258
4259		if (dr->dr_type == BWN_DMA_64BIT) {
4260			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4261			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4262			    >> 30;
4263			value = BWN_DMA64_TXENABLE;
4264			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4265			    & BWN_DMA64_TXADDREXT_MASK;
4266			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4267			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4268			    (ring64 & 0xffffffff));
4269			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4270			    ((ring64 >> 32) &
4271			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4272		} else {
4273			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4274			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4275			value = BWN_DMA32_TXENABLE;
4276			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4277			    & BWN_DMA32_TXADDREXT_MASK;
4278			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4279			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4280			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4281		}
4282		return;
4283	}
4284
4285	/*
4286	 * set for RX
4287	 */
4288	dr->dr_usedslot = dr->dr_numslots;
4289
4290	if (dr->dr_type == BWN_DMA_64BIT) {
4291		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4292		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4293		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4294		value |= BWN_DMA64_RXENABLE;
4295		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4296		    & BWN_DMA64_RXADDREXT_MASK;
4297		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4298		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4299		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4300		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4301		    | (trans << 1));
4302		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4303		    sizeof(struct bwn_dmadesc64));
4304	} else {
4305		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4306		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4307		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4308		value |= BWN_DMA32_RXENABLE;
4309		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4310		    & BWN_DMA32_RXADDREXT_MASK;
4311		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4312		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4313		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4314		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4315		    sizeof(struct bwn_dmadesc32));
4316	}
4317}
4318
4319static void
4320bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4321{
4322
4323	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4324	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4325	    dr->dr_ring_dmap);
4326}
4327
4328static void
4329bwn_dma_cleanup(struct bwn_dma_ring *dr)
4330{
4331
4332	if (dr->dr_tx) {
4333		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4334		if (dr->dr_type == BWN_DMA_64BIT) {
4335			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4336			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4337		} else
4338			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4339	} else {
4340		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4341		if (dr->dr_type == BWN_DMA_64BIT) {
4342			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4343			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4344		} else
4345			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4346	}
4347}
4348
4349static void
4350bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4351{
4352	struct bwn_dmadesc_generic *desc;
4353	struct bwn_dmadesc_meta *meta;
4354	struct bwn_mac *mac = dr->dr_mac;
4355	struct bwn_dma *dma = &mac->mac_method.dma;
4356	struct bwn_softc *sc = mac->mac_sc;
4357	int i;
4358
4359	if (!dr->dr_usedslot)
4360		return;
4361	for (i = 0; i < dr->dr_numslots; i++) {
4362		dr->getdesc(dr, i, &desc, &meta);
4363
4364		if (meta->mt_m == NULL) {
4365			if (!dr->dr_tx)
4366				device_printf(sc->sc_dev, "%s: not TX?\n",
4367				    __func__);
4368			continue;
4369		}
4370		if (dr->dr_tx) {
4371			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4372				bus_dmamap_unload(dr->dr_txring_dtag,
4373				    meta->mt_dmap);
4374			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4375				bus_dmamap_unload(dma->txbuf_dtag,
4376				    meta->mt_dmap);
4377		} else
4378			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4379		bwn_dma_free_descbuf(dr, meta);
4380	}
4381}
4382
4383static int
4384bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4385    int type)
4386{
4387	struct bwn_softc *sc = mac->mac_sc;
4388	uint32_t value;
4389	int i;
4390	uint16_t offset;
4391
4392	for (i = 0; i < 10; i++) {
4393		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4394		    BWN_DMA32_TXSTATUS;
4395		value = BWN_READ_4(mac, base + offset);
4396		if (type == BWN_DMA_64BIT) {
4397			value &= BWN_DMA64_TXSTAT;
4398			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4399			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4400			    value == BWN_DMA64_TXSTAT_STOPPED)
4401				break;
4402		} else {
4403			value &= BWN_DMA32_TXSTATE;
4404			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4405			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4406			    value == BWN_DMA32_TXSTAT_STOPPED)
4407				break;
4408		}
4409		DELAY(1000);
4410	}
4411	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4412	BWN_WRITE_4(mac, base + offset, 0);
4413	for (i = 0; i < 10; i++) {
4414		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4415						   BWN_DMA32_TXSTATUS;
4416		value = BWN_READ_4(mac, base + offset);
4417		if (type == BWN_DMA_64BIT) {
4418			value &= BWN_DMA64_TXSTAT;
4419			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4420				i = -1;
4421				break;
4422			}
4423		} else {
4424			value &= BWN_DMA32_TXSTATE;
4425			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4426				i = -1;
4427				break;
4428			}
4429		}
4430		DELAY(1000);
4431	}
4432	if (i != -1) {
4433		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4434		return (ENODEV);
4435	}
4436	DELAY(1000);
4437
4438	return (0);
4439}
4440
4441static int
4442bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4443    int type)
4444{
4445	struct bwn_softc *sc = mac->mac_sc;
4446	uint32_t value;
4447	int i;
4448	uint16_t offset;
4449
4450	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4451	BWN_WRITE_4(mac, base + offset, 0);
4452	for (i = 0; i < 10; i++) {
4453		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4454		    BWN_DMA32_RXSTATUS;
4455		value = BWN_READ_4(mac, base + offset);
4456		if (type == BWN_DMA_64BIT) {
4457			value &= BWN_DMA64_RXSTAT;
4458			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4459				i = -1;
4460				break;
4461			}
4462		} else {
4463			value &= BWN_DMA32_RXSTATE;
4464			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4465				i = -1;
4466				break;
4467			}
4468		}
4469		DELAY(1000);
4470	}
4471	if (i != -1) {
4472		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4473		return (ENODEV);
4474	}
4475
4476	return (0);
4477}
4478
4479static void
4480bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4481    struct bwn_dmadesc_meta *meta)
4482{
4483
4484	if (meta->mt_m != NULL) {
4485		m_freem(meta->mt_m);
4486		meta->mt_m = NULL;
4487	}
4488	if (meta->mt_ni != NULL) {
4489		ieee80211_free_node(meta->mt_ni);
4490		meta->mt_ni = NULL;
4491	}
4492}
4493
4494static void
4495bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4496{
4497	struct bwn_rxhdr4 *rxhdr;
4498	unsigned char *frame;
4499
4500	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4501	rxhdr->frame_len = 0;
4502
4503	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4504	    sizeof(struct bwn_plcp6) + 2,
4505	    ("%s:%d: fail", __func__, __LINE__));
4506	frame = mtod(m, char *) + dr->dr_frameoffset;
4507	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4508}
4509
4510static uint8_t
4511bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4512{
4513	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4514
4515	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4516	    == 0xff);
4517}
4518
4519static void
4520bwn_wme_init(struct bwn_mac *mac)
4521{
4522
4523	bwn_wme_load(mac);
4524
4525	/* enable WME support. */
4526	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4527	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4528	    BWN_IFSCTL_USE_EDCF);
4529}
4530
4531static void
4532bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4533{
4534	struct bwn_softc *sc = mac->mac_sc;
4535	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4536	uint16_t delay;	/* microsec */
4537
4538	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4539	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4540		delay = 500;
4541	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4542		delay = max(delay, (uint16_t)2400);
4543
4544	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4545}
4546
4547static void
4548bwn_bt_enable(struct bwn_mac *mac)
4549{
4550	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4551	uint64_t hf;
4552
4553	if (bwn_bluetooth == 0)
4554		return;
4555	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4556		return;
4557	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4558		return;
4559
4560	hf = bwn_hf_read(mac);
4561	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4562		hf |= BWN_HF_BT_COEXISTALT;
4563	else
4564		hf |= BWN_HF_BT_COEXIST;
4565	bwn_hf_write(mac, hf);
4566}
4567
4568static void
4569bwn_set_macaddr(struct bwn_mac *mac)
4570{
4571
4572	bwn_mac_write_bssid(mac);
4573	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4574}
4575
4576static void
4577bwn_clear_keys(struct bwn_mac *mac)
4578{
4579	int i;
4580
4581	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4582		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4583		    ("%s:%d: fail", __func__, __LINE__));
4584
4585		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4586		    NULL, BWN_SEC_KEYSIZE, NULL);
4587		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4588			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4589			    NULL, BWN_SEC_KEYSIZE, NULL);
4590		}
4591		mac->mac_key[i].keyconf = NULL;
4592	}
4593}
4594
4595static void
4596bwn_crypt_init(struct bwn_mac *mac)
4597{
4598
4599	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4600	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4601	    ("%s:%d: fail", __func__, __LINE__));
4602	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4603	mac->mac_ktp *= 2;
4604	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4605		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4606		    mac->mac_max_nr_keys - 8);
4607	}
4608	bwn_clear_keys(mac);
4609}
4610
4611static void
4612bwn_chip_exit(struct bwn_mac *mac)
4613{
4614
4615	bwn_phy_exit(mac);
4616	bwn_gpio_cleanup(mac);
4617}
4618
4619static int
4620bwn_fw_fillinfo(struct bwn_mac *mac)
4621{
4622	int error;
4623
4624	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4625	if (error == 0)
4626		return (0);
4627	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4628	if (error == 0)
4629		return (0);
4630	return (error);
4631}
4632
4633static int
4634bwn_gpio_init(struct bwn_mac *mac)
4635{
4636	struct siba_softc *bus = mac->mac_sd->sd_bus;
4637	struct siba_dev_softc *sd;
4638	uint32_t mask = 0x0000001f, set = 0x0000000f;
4639
4640	BWN_WRITE_4(mac, BWN_MACCTL,
4641	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4642	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4643	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4644
4645	if (bus->siba_chipid == 0x4301) {
4646		mask |= 0x0060;
4647		set |= 0x0060;
4648	}
4649	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4650		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4651		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4652		mask |= 0x0200;
4653		set |= 0x0200;
4654	}
4655	if (mac->mac_sd->sd_id.sd_rev >= 2)
4656		mask |= 0x0010;
4657	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4658	    bus->siba_pci.spc_dev;
4659	if (sd == NULL)
4660		return (0);
4661	siba_write_4(sd, BWN_GPIOCTL,
4662	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4663
4664	return (0);
4665}
4666
4667static int
4668bwn_fw_loadinitvals(struct bwn_mac *mac)
4669{
4670#define	GETFWOFFSET(fwp, offset)				\
4671	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4672	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4673	const struct bwn_fwhdr *hdr;
4674	struct bwn_fw *fw = &mac->mac_fw;
4675	int error;
4676
4677	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4678	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4679	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4680	if (error)
4681		return (error);
4682	if (fw->initvals_band.fw) {
4683		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4684		error = bwn_fwinitvals_write(mac,
4685		    GETFWOFFSET(fw->initvals_band, hdr_len),
4686		    be32toh(hdr->size),
4687		    fw->initvals_band.fw->datasize - hdr_len);
4688	}
4689	return (error);
4690#undef GETFWOFFSET
4691}
4692
4693static int
4694bwn_phy_init(struct bwn_mac *mac)
4695{
4696	struct bwn_softc *sc = mac->mac_sc;
4697	int error;
4698
4699	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4700	mac->mac_phy.rf_onoff(mac, 1);
4701	error = mac->mac_phy.init(mac);
4702	if (error) {
4703		device_printf(sc->sc_dev, "PHY init failed\n");
4704		goto fail0;
4705	}
4706	error = bwn_switch_channel(mac,
4707	    mac->mac_phy.get_default_chan(mac));
4708	if (error) {
4709		device_printf(sc->sc_dev,
4710		    "failed to switch default channel\n");
4711		goto fail1;
4712	}
4713	return (0);
4714fail1:
4715	if (mac->mac_phy.exit)
4716		mac->mac_phy.exit(mac);
4717fail0:
4718	mac->mac_phy.rf_onoff(mac, 0);
4719
4720	return (error);
4721}
4722
4723static void
4724bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4725{
4726	uint16_t ant;
4727	uint16_t tmp;
4728
4729	ant = bwn_ant2phy(antenna);
4730
4731	/* For ACK/CTS */
4732	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4733	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4734	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4735	/* For Probe Resposes */
4736	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4737	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4738	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4739}
4740
4741static void
4742bwn_set_opmode(struct bwn_mac *mac)
4743{
4744	struct bwn_softc *sc = mac->mac_sc;
4745	struct ifnet *ifp = sc->sc_ifp;
4746	struct ieee80211com *ic = ifp->if_l2com;
4747	uint32_t ctl;
4748	uint16_t cfp_pretbtt;
4749
4750	ctl = BWN_READ_4(mac, BWN_MACCTL);
4751	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4752	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4753	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4754	ctl |= BWN_MACCTL_STA;
4755
4756	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4757	    ic->ic_opmode == IEEE80211_M_MBSS)
4758		ctl |= BWN_MACCTL_HOSTAP;
4759	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4760		ctl &= ~BWN_MACCTL_STA;
4761	ctl |= sc->sc_filters;
4762
4763	if (mac->mac_sd->sd_id.sd_rev <= 4)
4764		ctl |= BWN_MACCTL_PROMISC;
4765
4766	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4767
4768	cfp_pretbtt = 2;
4769	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4770		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4771		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4772			cfp_pretbtt = 100;
4773		else
4774			cfp_pretbtt = 50;
4775	}
4776	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4777}
4778
4779static void
4780bwn_gpio_cleanup(struct bwn_mac *mac)
4781{
4782	struct siba_softc *bus = mac->mac_sd->sd_bus;
4783	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4784
4785	pcidev = bus->siba_pci.spc_dev;
4786	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4787	if (!gpiodev)
4788		return;
4789	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4790}
4791
4792static int
4793bwn_dma_gettype(struct bwn_mac *mac)
4794{
4795	uint32_t tmp;
4796	uint16_t base;
4797
4798	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4799	if (tmp & SIBA_TGSHIGH_DMA64)
4800		return (BWN_DMA_64BIT);
4801	base = bwn_dma_base(0, 0);
4802	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4803	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4804	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4805		return (BWN_DMA_32BIT);
4806
4807	return (BWN_DMA_30BIT);
4808}
4809
4810static void
4811bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4812{
4813	if (!error) {
4814		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4815		*((bus_addr_t *)arg) = seg->ds_addr;
4816	}
4817}
4818
4819static void
4820bwn_phy_g_init_sub(struct bwn_mac *mac)
4821{
4822	struct bwn_phy *phy = &mac->mac_phy;
4823	struct bwn_phy_g *pg = &phy->phy_g;
4824	uint16_t i, tmp;
4825
4826	if (phy->rev == 1)
4827		bwn_phy_init_b5(mac);
4828	else
4829		bwn_phy_init_b6(mac);
4830
4831	if (phy->rev >= 2 || phy->gmode)
4832		bwn_phy_init_a(mac);
4833
4834	if (phy->rev >= 2) {
4835		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4836		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4837	}
4838	if (phy->rev == 2) {
4839		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4840		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4841	}
4842	if (phy->rev > 5) {
4843		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4844		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4845	}
4846	if (phy->gmode || phy->rev >= 2) {
4847		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4848		tmp &= BWN_PHYVER_VERSION;
4849		if (tmp == 3 || tmp == 5) {
4850			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4851			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4852		}
4853		if (tmp == 5) {
4854			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4855			    0x1f00);
4856		}
4857	}
4858	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4859		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4860	if (phy->rf_rev == 8) {
4861		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4862		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4863	}
4864	if (BWN_HAS_LOOPBACK(phy))
4865		bwn_loopback_calcgain(mac);
4866
4867	if (phy->rf_rev != 8) {
4868		if (pg->pg_initval == 0xffff)
4869			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4870		else
4871			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4872	}
4873	bwn_lo_g_init(mac);
4874	if (BWN_HAS_TXMAG(phy)) {
4875		BWN_RF_WRITE(mac, 0x52,
4876		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4877		    | pg->pg_loctl.tx_bias |
4878		    pg->pg_loctl.tx_magn);
4879	} else {
4880		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4881	}
4882	if (phy->rev >= 6) {
4883		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4884		    (pg->pg_loctl.tx_bias << 12));
4885	}
4886	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4887		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4888	else
4889		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4890	if (phy->rev < 2)
4891		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4892	else
4893		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4894	if (phy->gmode || phy->rev >= 2) {
4895		bwn_lo_g_adjust(mac);
4896		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4897	}
4898
4899	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4900		for (i = 0; i < 64; i++) {
4901			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4902			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4903			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4904			    -32), 31));
4905		}
4906		bwn_nrssi_threshold(mac);
4907	} else if (phy->gmode || phy->rev >= 2) {
4908		if (pg->pg_nrssi[0] == -1000) {
4909			KASSERT(pg->pg_nrssi[1] == -1000,
4910			    ("%s:%d: fail", __func__, __LINE__));
4911			bwn_nrssi_slope_11g(mac);
4912		} else
4913			bwn_nrssi_threshold(mac);
4914	}
4915	if (phy->rf_rev == 8)
4916		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4917	bwn_phy_hwpctl_init(mac);
4918	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4919	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4920		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4921		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4922	}
4923}
4924
4925static uint8_t
4926bwn_has_hwpctl(struct bwn_mac *mac)
4927{
4928
4929	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4930		return (0);
4931	return (mac->mac_phy.use_hwpctl(mac));
4932}
4933
4934static void
4935bwn_phy_init_b5(struct bwn_mac *mac)
4936{
4937	struct siba_softc *bus = mac->mac_sd->sd_bus;
4938	struct bwn_phy *phy = &mac->mac_phy;
4939	struct bwn_phy_g *pg = &phy->phy_g;
4940	uint16_t offset, value;
4941	uint8_t old_channel;
4942
4943	if (phy->analog == 1)
4944		BWN_RF_SET(mac, 0x007a, 0x0050);
4945	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4946	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4947		value = 0x2120;
4948		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4949			BWN_PHY_WRITE(mac, offset, value);
4950			value += 0x202;
4951		}
4952	}
4953	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4954	if (phy->rf_ver == 0x2050)
4955		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4956
4957	if (phy->gmode || phy->rev >= 2) {
4958		if (phy->rf_ver == 0x2050) {
4959			BWN_RF_SET(mac, 0x007a, 0x0020);
4960			BWN_RF_SET(mac, 0x0051, 0x0004);
4961		}
4962		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4963
4964		BWN_PHY_SET(mac, 0x0802, 0x0100);
4965		BWN_PHY_SET(mac, 0x042b, 0x2000);
4966
4967		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4968
4969		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4970		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4971		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4972	}
4973
4974	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4975		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4976
4977	if (phy->analog == 1) {
4978		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4979		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4980		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4981		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4982		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4983	} else
4984		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4985	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4986	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4987
4988	if (phy->analog == 1)
4989		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4990	else
4991		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4992
4993	if (phy->analog == 0)
4994		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4995
4996	old_channel = phy->chan;
4997	bwn_phy_g_switch_chan(mac, 7, 0);
4998
4999	if (phy->rf_ver != 0x2050) {
5000		BWN_RF_WRITE(mac, 0x0075, 0x0080);
5001		BWN_RF_WRITE(mac, 0x0079, 0x0081);
5002	}
5003
5004	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5005	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5006
5007	if (phy->rf_ver == 0x2050) {
5008		BWN_RF_WRITE(mac, 0x0050, 0x0020);
5009		BWN_RF_WRITE(mac, 0x005a, 0x0070);
5010	}
5011
5012	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5013	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5014	BWN_RF_SET(mac, 0x007a, 0x0007);
5015
5016	bwn_phy_g_switch_chan(mac, old_channel, 0);
5017	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5018	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5019	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5020
5021	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5022	    pg->pg_txctl);
5023
5024	if (phy->rf_ver == 0x2050)
5025		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5026
5027	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5028}
5029
5030static void
5031bwn_loopback_calcgain(struct bwn_mac *mac)
5032{
5033	struct bwn_phy *phy = &mac->mac_phy;
5034	struct bwn_phy_g *pg = &phy->phy_g;
5035	uint16_t backup_phy[16] = { 0 };
5036	uint16_t backup_radio[3];
5037	uint16_t backup_bband;
5038	uint16_t i, j, loop_i_max;
5039	uint16_t trsw_rx;
5040	uint16_t loop1_outer_done, loop1_inner_done;
5041
5042	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5043	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5044	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5045	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5046	if (phy->rev != 1) {
5047		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5048		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5049	}
5050	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5051	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5052	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5053	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5054	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5055	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5056	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5057	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5058	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5059	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5060	backup_bband = pg->pg_bbatt.att;
5061	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5062	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5063	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5064
5065	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5066	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5067	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5068	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5069	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5070	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5071	if (phy->rev != 1) {
5072		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5073		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5074		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5075		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5076	}
5077	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5078	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5079	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5080	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5081
5082	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5083	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5084	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5085
5086	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5087	if (phy->rev != 1) {
5088		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5089		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5090	}
5091	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5092
5093	if (phy->rf_rev == 8)
5094		BWN_RF_WRITE(mac, 0x43, 0x000f);
5095	else {
5096		BWN_RF_WRITE(mac, 0x52, 0);
5097		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5098	}
5099	bwn_phy_g_set_bbatt(mac, 11);
5100
5101	if (phy->rev >= 3)
5102		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5103	else
5104		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5105	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5106
5107	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5108	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5109
5110	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5111	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5112
5113	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5114		if (phy->rev >= 7) {
5115			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5116			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5117		}
5118	}
5119	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5120
5121	j = 0;
5122	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5123	for (i = 0; i < loop_i_max; i++) {
5124		for (j = 0; j < 16; j++) {
5125			BWN_RF_WRITE(mac, 0x43, i);
5126			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5127			    (j << 8));
5128			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5129			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5130			DELAY(20);
5131			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5132				goto done0;
5133		}
5134	}
5135done0:
5136	loop1_outer_done = i;
5137	loop1_inner_done = j;
5138	if (j >= 8) {
5139		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5140		trsw_rx = 0x1b;
5141		for (j = j - 8; j < 16; j++) {
5142			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5143			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5144			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5145			DELAY(20);
5146			trsw_rx -= 3;
5147			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5148				goto done1;
5149		}
5150	} else
5151		trsw_rx = 0x18;
5152done1:
5153
5154	if (phy->rev != 1) {
5155		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5156		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5157	}
5158	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5159	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5160	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5161	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5162	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5163	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5164	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5165	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5166	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5167
5168	bwn_phy_g_set_bbatt(mac, backup_bband);
5169
5170	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5171	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5172	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5173
5174	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5175	DELAY(10);
5176	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5177	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5178	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5179	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5180
5181	pg->pg_max_lb_gain =
5182	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5183	pg->pg_trsw_rx_gain = trsw_rx * 2;
5184}
5185
5186static uint16_t
5187bwn_rf_init_bcm2050(struct bwn_mac *mac)
5188{
5189	struct bwn_phy *phy = &mac->mac_phy;
5190	uint32_t tmp1 = 0, tmp2 = 0;
5191	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5192	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5193	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5194	static const uint8_t rcc_table[] = {
5195		0x02, 0x03, 0x01, 0x0f,
5196		0x06, 0x07, 0x05, 0x0f,
5197		0x0a, 0x0b, 0x09, 0x0f,
5198		0x0e, 0x0f, 0x0d, 0x0f,
5199	};
5200
5201	radio0 = BWN_RF_READ(mac, 0x43);
5202	radio1 = BWN_RF_READ(mac, 0x51);
5203	radio2 = BWN_RF_READ(mac, 0x52);
5204	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5205	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5206	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5207	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5208
5209	if (phy->type == BWN_PHYTYPE_B) {
5210		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5211		reg0 = BWN_READ_2(mac, 0x3ec);
5212
5213		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5214		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5215	} else if (phy->gmode || phy->rev >= 2) {
5216		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5217		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5218		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5219		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5220		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5221		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5222
5223		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5224		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5225		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5226		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5227		if (BWN_HAS_LOOPBACK(phy)) {
5228			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5229			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5230			if (phy->rev >= 3)
5231				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5232			else
5233				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5234			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5235		}
5236
5237		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5239			BWN_LPD(0, 1, 1)));
5240		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5241		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5242	}
5243	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5244
5245	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5246	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5247	reg1 = BWN_READ_2(mac, 0x3e6);
5248	reg2 = BWN_READ_2(mac, 0x3f4);
5249
5250	if (phy->analog == 0)
5251		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5252	else {
5253		if (phy->analog >= 2)
5254			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5255		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5256		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5257	}
5258
5259	reg = BWN_RF_READ(mac, 0x60);
5260	index = (reg & 0x001e) >> 1;
5261	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5262
5263	if (phy->type == BWN_PHYTYPE_B)
5264		BWN_RF_WRITE(mac, 0x78, 0x26);
5265	if (phy->gmode || phy->rev >= 2) {
5266		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5267		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5268			BWN_LPD(0, 1, 1)));
5269	}
5270	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5271	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5272	if (phy->gmode || phy->rev >= 2) {
5273		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5274		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5275			BWN_LPD(0, 0, 1)));
5276	}
5277	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5278	BWN_RF_SET(mac, 0x51, 0x0004);
5279	if (phy->rf_rev == 8)
5280		BWN_RF_WRITE(mac, 0x43, 0x1f);
5281	else {
5282		BWN_RF_WRITE(mac, 0x52, 0);
5283		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5284	}
5285	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5286
5287	for (i = 0; i < 16; i++) {
5288		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5289		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5290		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5291		if (phy->gmode || phy->rev >= 2) {
5292			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5293			    bwn_rf_2050_rfoverval(mac,
5294				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5295		}
5296		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5297		DELAY(10);
5298		if (phy->gmode || phy->rev >= 2) {
5299			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5300			    bwn_rf_2050_rfoverval(mac,
5301				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5302		}
5303		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5304		DELAY(10);
5305		if (phy->gmode || phy->rev >= 2) {
5306			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5307			    bwn_rf_2050_rfoverval(mac,
5308				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5309		}
5310		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5311		DELAY(20);
5312		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5313		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5314		if (phy->gmode || phy->rev >= 2) {
5315			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5316			    bwn_rf_2050_rfoverval(mac,
5317				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5318		}
5319		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5320	}
5321	DELAY(10);
5322
5323	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5324	tmp1++;
5325	tmp1 >>= 9;
5326
5327	for (i = 0; i < 16; i++) {
5328		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5329		BWN_RF_WRITE(mac, 0x78, radio78);
5330		DELAY(10);
5331		for (j = 0; j < 16; j++) {
5332			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5333			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5334			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5335			if (phy->gmode || phy->rev >= 2) {
5336				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5337				    bwn_rf_2050_rfoverval(mac,
5338					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5339			}
5340			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5341			DELAY(10);
5342			if (phy->gmode || phy->rev >= 2) {
5343				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5344				    bwn_rf_2050_rfoverval(mac,
5345					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5346			}
5347			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5348			DELAY(10);
5349			if (phy->gmode || phy->rev >= 2) {
5350				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5351				    bwn_rf_2050_rfoverval(mac,
5352					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5353			}
5354			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5355			DELAY(10);
5356			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5357			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5358			if (phy->gmode || phy->rev >= 2) {
5359				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5360				    bwn_rf_2050_rfoverval(mac,
5361					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5362			}
5363			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5364		}
5365		tmp2++;
5366		tmp2 >>= 8;
5367		if (tmp1 < tmp2)
5368			break;
5369	}
5370
5371	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5372	BWN_RF_WRITE(mac, 0x51, radio1);
5373	BWN_RF_WRITE(mac, 0x52, radio2);
5374	BWN_RF_WRITE(mac, 0x43, radio0);
5375	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5376	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5377	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5378	BWN_WRITE_2(mac, 0x3e6, reg1);
5379	if (phy->analog != 0)
5380		BWN_WRITE_2(mac, 0x3f4, reg2);
5381	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5382	bwn_spu_workaround(mac, phy->chan);
5383	if (phy->type == BWN_PHYTYPE_B) {
5384		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5385		BWN_WRITE_2(mac, 0x3ec, reg0);
5386	} else if (phy->gmode) {
5387		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5388			    BWN_READ_2(mac, BWN_PHY_RADIO)
5389			    & 0x7fff);
5390		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5391		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5392		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5393		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5394			      analogoverval);
5395		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5396		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5397		if (BWN_HAS_LOOPBACK(phy)) {
5398			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5399			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5400		}
5401	}
5402
5403	return ((i > 15) ? radio78 : rcc);
5404}
5405
5406static void
5407bwn_phy_init_b6(struct bwn_mac *mac)
5408{
5409	struct bwn_phy *phy = &mac->mac_phy;
5410	struct bwn_phy_g *pg = &phy->phy_g;
5411	uint16_t offset, val;
5412	uint8_t old_channel;
5413
5414	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5415	    ("%s:%d: fail", __func__, __LINE__));
5416
5417	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5418	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5419	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5420		BWN_RF_WRITE(mac, 0x51, 0x37);
5421		BWN_RF_WRITE(mac, 0x52, 0x70);
5422		BWN_RF_WRITE(mac, 0x53, 0xb3);
5423		BWN_RF_WRITE(mac, 0x54, 0x9b);
5424		BWN_RF_WRITE(mac, 0x5a, 0x88);
5425		BWN_RF_WRITE(mac, 0x5b, 0x88);
5426		BWN_RF_WRITE(mac, 0x5d, 0x88);
5427		BWN_RF_WRITE(mac, 0x5e, 0x88);
5428		BWN_RF_WRITE(mac, 0x7d, 0x88);
5429		bwn_hf_write(mac,
5430		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5431	}
5432	if (phy->rf_rev == 8) {
5433		BWN_RF_WRITE(mac, 0x51, 0);
5434		BWN_RF_WRITE(mac, 0x52, 0x40);
5435		BWN_RF_WRITE(mac, 0x53, 0xb7);
5436		BWN_RF_WRITE(mac, 0x54, 0x98);
5437		BWN_RF_WRITE(mac, 0x5a, 0x88);
5438		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5439		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5440		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5441			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5442			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5443		} else {
5444			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5445			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5446		}
5447		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5448		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5449		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5450		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5451	}
5452	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5453		BWN_PHY_WRITE(mac, offset, val);
5454		val -= 0x0202;
5455	}
5456	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5457		BWN_PHY_WRITE(mac, offset, val);
5458		val -= 0x0202;
5459	}
5460	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5461		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5462		val += 0x0202;
5463	}
5464	if (phy->type == BWN_PHYTYPE_G) {
5465		BWN_RF_SET(mac, 0x007a, 0x0020);
5466		BWN_RF_SET(mac, 0x0051, 0x0004);
5467		BWN_PHY_SET(mac, 0x0802, 0x0100);
5468		BWN_PHY_SET(mac, 0x042b, 0x2000);
5469		BWN_PHY_WRITE(mac, 0x5b, 0);
5470		BWN_PHY_WRITE(mac, 0x5c, 0);
5471	}
5472
5473	old_channel = phy->chan;
5474	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5475
5476	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5477	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5478	DELAY(40);
5479	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5480		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5481		BWN_RF_WRITE(mac, 0x50, 0x20);
5482	}
5483	if (phy->rf_rev <= 2) {
5484		BWN_RF_WRITE(mac, 0x7c, 0x20);
5485		BWN_RF_WRITE(mac, 0x5a, 0x70);
5486		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5487		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5488	}
5489	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5490
5491	bwn_phy_g_switch_chan(mac, old_channel, 0);
5492
5493	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5494	if (phy->rf_rev >= 6)
5495		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5496	else
5497		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5498	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5499	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5500	    pg->pg_txctl);
5501	if (phy->rf_rev <= 5)
5502		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5503	if (phy->rf_rev <= 2)
5504		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5505
5506	if (phy->analog == 4) {
5507		BWN_WRITE_2(mac, 0x3e4, 9);
5508		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5509	} else
5510		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5511	if (phy->type == BWN_PHYTYPE_B)
5512		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5513	else if (phy->type == BWN_PHYTYPE_G)
5514		BWN_WRITE_2(mac, 0x03e6, 0x0);
5515}
5516
5517static void
5518bwn_phy_init_a(struct bwn_mac *mac)
5519{
5520	struct bwn_phy *phy = &mac->mac_phy;
5521
5522	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5523	    ("%s:%d: fail", __func__, __LINE__));
5524
5525	if (phy->rev >= 6) {
5526		if (phy->type == BWN_PHYTYPE_A)
5527			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5528		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5529			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5530		else
5531			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5532	}
5533
5534	bwn_wa_init(mac);
5535
5536	if (phy->type == BWN_PHYTYPE_G &&
5537	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5538		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5539}
5540
5541static void
5542bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5543{
5544	int i;
5545
5546	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5547		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5548}
5549
5550static void
5551bwn_wa_agc(struct bwn_mac *mac)
5552{
5553	struct bwn_phy *phy = &mac->mac_phy;
5554
5555	if (phy->rev == 1) {
5556		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5560		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5561		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5562		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5563		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5564		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5565	} else {
5566		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5567		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5568		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5569		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5570	}
5571
5572	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5573	    0x5700);
5574	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5577	BWN_RF_SET(mac, 0x7a, 0x0008);
5578	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5579	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5582	if (phy->rev == 1)
5583		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5584	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5585	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5586	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5587	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5588	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5589	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5590	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5591	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5592	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5593	if (phy->rev == 1) {
5594		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5595		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5596	} else {
5597		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5598		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5599		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5600		if (phy->rev >= 6) {
5601			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5602			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5603			    (uint16_t)~0xf000, 0x3000);
5604		}
5605	}
5606	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5607	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5608	if (phy->rev == 1) {
5609		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5610		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5611		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5612		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5613		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5614		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5615		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5616		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5617	} else {
5618		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5619		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5620		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5621		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5622	}
5623	if (phy->rev >= 6) {
5624		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5625		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5626	}
5627	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5628}
5629
5630static void
5631bwn_wa_grev1(struct bwn_mac *mac)
5632{
5633	struct bwn_phy *phy = &mac->mac_phy;
5634	int i;
5635	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5636	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5637	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5638
5639	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5640
5641	/* init CRSTHRES and ANTDWELL */
5642	if (phy->rev == 1) {
5643		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5644	} else if (phy->rev == 2) {
5645		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5646		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5647		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5648	} else {
5649		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5650		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5651		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5652		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5653	}
5654	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5655	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5656	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5657
5658	/* XXX support PHY-A??? */
5659	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5660		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5661		    bwn_tab_finefreqg[i]);
5662
5663	/* XXX support PHY-A??? */
5664	if (phy->rev == 1)
5665		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5666			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5667			    bwn_tab_noise_g1[i]);
5668	else
5669		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5670			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5671			    bwn_tab_noise_g2[i]);
5672
5673
5674	for (i = 0; i < N(bwn_tab_rotor); i++)
5675		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5676		    bwn_tab_rotor[i]);
5677
5678	/* XXX support PHY-A??? */
5679	if (phy->rev >= 6) {
5680		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5681		    BWN_PHY_ENCORE_EN)
5682			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5683		else
5684			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5685	} else
5686		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5687
5688	for (i = 0; i < N(bwn_tab_retard); i++)
5689		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5690		    bwn_tab_retard[i]);
5691
5692	if (phy->rev == 1) {
5693		for (i = 0; i < 16; i++)
5694			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5695			    i, 0x0020);
5696	} else {
5697		for (i = 0; i < 32; i++)
5698			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5699	}
5700
5701	bwn_wa_agc(mac);
5702}
5703
5704static void
5705bwn_wa_grev26789(struct bwn_mac *mac)
5706{
5707	struct bwn_phy *phy = &mac->mac_phy;
5708	int i;
5709	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5710	uint16_t ofdmrev;
5711
5712	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5713
5714	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5715
5716	/* init CRSTHRES and ANTDWELL */
5717	if (phy->rev == 1)
5718		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5719	else if (phy->rev == 2) {
5720		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5721		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5722		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5723	} else {
5724		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5725		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5726		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5727		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5728	}
5729
5730	for (i = 0; i < 64; i++)
5731		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5732
5733	/* XXX support PHY-A??? */
5734	if (phy->rev == 1)
5735		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5736			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5737			    bwn_tab_noise_g1[i]);
5738	else
5739		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5740			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5741			    bwn_tab_noise_g2[i]);
5742
5743	/* XXX support PHY-A??? */
5744	if (phy->rev >= 6) {
5745		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5746		    BWN_PHY_ENCORE_EN)
5747			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5748		else
5749			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5750	} else
5751		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5752
5753	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5754		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5755		    bwn_tab_sigmasqr2[i]);
5756
5757	if (phy->rev == 1) {
5758		for (i = 0; i < 16; i++)
5759			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5760			    0x0020);
5761	} else {
5762		for (i = 0; i < 32; i++)
5763			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5764	}
5765
5766	bwn_wa_agc(mac);
5767
5768	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5769	if (ofdmrev > 2) {
5770		if (phy->type == BWN_PHYTYPE_A)
5771			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5772		else
5773			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5774	} else {
5775		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5776		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5777		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5778	}
5779
5780	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5781	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5782}
5783
5784static void
5785bwn_wa_init(struct bwn_mac *mac)
5786{
5787	struct bwn_phy *phy = &mac->mac_phy;
5788	struct siba_softc *bus = mac->mac_sd->sd_bus;
5789
5790	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5791
5792	switch (phy->rev) {
5793	case 1:
5794		bwn_wa_grev1(mac);
5795		break;
5796	case 2:
5797	case 6:
5798	case 7:
5799	case 8:
5800	case 9:
5801		bwn_wa_grev26789(mac);
5802		break;
5803	default:
5804		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5805	}
5806
5807	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5808	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5809	    bus->siba_board_rev != 0x17) {
5810		if (phy->rev < 2) {
5811			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5812			    0x0002);
5813			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5814			    0x0001);
5815		} else {
5816			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5817			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5818			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5819			    (phy->rev >= 7)) {
5820				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5821				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5822				    0x0020, 0x0001);
5823				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5824				    0x0021, 0x0001);
5825				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5826				    0x0022, 0x0001);
5827				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5828				    0x0023, 0x0000);
5829				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5830				    0x0000, 0x0000);
5831				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5832				    0x0003, 0x0002);
5833			}
5834		}
5835	}
5836	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5837		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5838		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5839	}
5840
5841	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5842	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5843}
5844
5845static void
5846bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5847    uint16_t value)
5848{
5849	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5850	uint16_t addr;
5851
5852	addr = table + offset;
5853	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5854	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5855		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5856		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5857	}
5858	pg->pg_ofdmtab_addr = addr;
5859	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5860}
5861
5862static void
5863bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5864    uint32_t value)
5865{
5866	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5867	uint16_t addr;
5868
5869	addr = table + offset;
5870	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5871	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5872		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5873		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5874	}
5875	pg->pg_ofdmtab_addr = addr;
5876
5877	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5878	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5879}
5880
5881static void
5882bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5883    uint16_t value)
5884{
5885
5886	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5887	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5888}
5889
5890static void
5891bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5892{
5893	struct bwn_phy *phy = &mac->mac_phy;
5894	struct bwn_softc *sc = mac->mac_sc;
5895	unsigned int i, max_loop;
5896	uint16_t value;
5897	uint32_t buffer[5] = {
5898		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5899	};
5900
5901	if (ofdm) {
5902		max_loop = 0x1e;
5903		buffer[0] = 0x000201cc;
5904	} else {
5905		max_loop = 0xfa;
5906		buffer[0] = 0x000b846e;
5907	}
5908
5909	BWN_ASSERT_LOCKED(sc);
5910
5911	for (i = 0; i < 5; i++)
5912		bwn_ram_write(mac, i * 4, buffer[i]);
5913
5914	BWN_WRITE_2(mac, 0x0568, 0x0000);
5915	BWN_WRITE_2(mac, 0x07c0,
5916	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5917	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5918	BWN_WRITE_2(mac, 0x050c, value);
5919	if (phy->type == BWN_PHYTYPE_LP)
5920		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5921	BWN_WRITE_2(mac, 0x0508, 0x0000);
5922	BWN_WRITE_2(mac, 0x050a, 0x0000);
5923	BWN_WRITE_2(mac, 0x054c, 0x0000);
5924	BWN_WRITE_2(mac, 0x056a, 0x0014);
5925	BWN_WRITE_2(mac, 0x0568, 0x0826);
5926	BWN_WRITE_2(mac, 0x0500, 0x0000);
5927	if (phy->type == BWN_PHYTYPE_LP)
5928		BWN_WRITE_2(mac, 0x0502, 0x0050);
5929	else
5930		BWN_WRITE_2(mac, 0x0502, 0x0030);
5931
5932	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5933		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5934	for (i = 0x00; i < max_loop; i++) {
5935		value = BWN_READ_2(mac, 0x050e);
5936		if (value & 0x0080)
5937			break;
5938		DELAY(10);
5939	}
5940	for (i = 0x00; i < 0x0a; i++) {
5941		value = BWN_READ_2(mac, 0x050e);
5942		if (value & 0x0400)
5943			break;
5944		DELAY(10);
5945	}
5946	for (i = 0x00; i < 0x19; i++) {
5947		value = BWN_READ_2(mac, 0x0690);
5948		if (!(value & 0x0100))
5949			break;
5950		DELAY(10);
5951	}
5952	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5953		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5954}
5955
5956static void
5957bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5958{
5959	uint32_t macctl;
5960
5961	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5962
5963	macctl = BWN_READ_4(mac, BWN_MACCTL);
5964	if (macctl & BWN_MACCTL_BIGENDIAN)
5965		printf("TODO: need swap\n");
5966
5967	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5968	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5969	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5970}
5971
5972static void
5973bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5974{
5975	struct bwn_phy *phy = &mac->mac_phy;
5976	uint16_t value;
5977
5978	KASSERT(phy->type == BWN_PHYTYPE_G,
5979	    ("%s:%d: fail", __func__, __LINE__));
5980
5981	value = (uint8_t) (ctl->q);
5982	value |= ((uint8_t) (ctl->i)) << 8;
5983	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5984}
5985
5986static uint16_t
5987bwn_lo_calcfeed(struct bwn_mac *mac,
5988    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5989{
5990	struct bwn_phy *phy = &mac->mac_phy;
5991	uint16_t rfover;
5992	uint16_t feedthrough;
5993
5994	if (phy->gmode) {
5995		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5996		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5997
5998		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5999		    ("%s:%d: fail", __func__, __LINE__));
6000		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
6001		    ("%s:%d: fail", __func__, __LINE__));
6002
6003		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
6004
6005		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
6006		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
6007		    && phy->rev > 6)
6008			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
6009
6010		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6011		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6012		DELAY(10);
6013		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6014		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6015		DELAY(10);
6016		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6017		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6018		DELAY(10);
6019		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6020	} else {
6021		pga |= BWN_PHY_PGACTL_UNKNOWN;
6022		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6023		DELAY(10);
6024		pga |= BWN_PHY_PGACTL_LOWBANDW;
6025		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6026		DELAY(10);
6027		pga |= BWN_PHY_PGACTL_LPF;
6028		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6029	}
6030	DELAY(21);
6031	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6032
6033	return (feedthrough);
6034}
6035
6036static uint16_t
6037bwn_lo_txctl_regtable(struct bwn_mac *mac,
6038    uint16_t *value, uint16_t *pad_mix_gain)
6039{
6040	struct bwn_phy *phy = &mac->mac_phy;
6041	uint16_t reg, v, padmix;
6042
6043	if (phy->type == BWN_PHYTYPE_B) {
6044		v = 0x30;
6045		if (phy->rf_rev <= 5) {
6046			reg = 0x43;
6047			padmix = 0;
6048		} else {
6049			reg = 0x52;
6050			padmix = 5;
6051		}
6052	} else {
6053		if (phy->rev >= 2 && phy->rf_rev == 8) {
6054			reg = 0x43;
6055			v = 0x10;
6056			padmix = 2;
6057		} else {
6058			reg = 0x52;
6059			v = 0x30;
6060			padmix = 5;
6061		}
6062	}
6063	if (value)
6064		*value = v;
6065	if (pad_mix_gain)
6066		*pad_mix_gain = padmix;
6067
6068	return (reg);
6069}
6070
6071static void
6072bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6073{
6074	struct bwn_phy *phy = &mac->mac_phy;
6075	struct bwn_phy_g *pg = &phy->phy_g;
6076	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6077	uint16_t reg, mask;
6078	uint16_t trsw_rx, pga;
6079	uint16_t rf_pctl_reg;
6080
6081	static const uint8_t tx_bias_values[] = {
6082		0x09, 0x08, 0x0a, 0x01, 0x00,
6083		0x02, 0x05, 0x04, 0x06,
6084	};
6085	static const uint8_t tx_magn_values[] = {
6086		0x70, 0x40,
6087	};
6088
6089	if (!BWN_HAS_LOOPBACK(phy)) {
6090		rf_pctl_reg = 6;
6091		trsw_rx = 2;
6092		pga = 0;
6093	} else {
6094		int lb_gain;
6095
6096		trsw_rx = 0;
6097		lb_gain = pg->pg_max_lb_gain / 2;
6098		if (lb_gain > 10) {
6099			rf_pctl_reg = 0;
6100			pga = abs(10 - lb_gain) / 6;
6101			pga = MIN(MAX(pga, 0), 15);
6102		} else {
6103			int cmp_val;
6104			int tmp;
6105
6106			pga = 0;
6107			cmp_val = 0x24;
6108			if ((phy->rev >= 2) &&
6109			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6110				cmp_val = 0x3c;
6111			tmp = lb_gain;
6112			if ((10 - lb_gain) < cmp_val)
6113				tmp = (10 - lb_gain);
6114			if (tmp < 0)
6115				tmp += 6;
6116			else
6117				tmp += 3;
6118			cmp_val /= 4;
6119			tmp /= 4;
6120			if (tmp >= cmp_val)
6121				rf_pctl_reg = cmp_val;
6122			else
6123				rf_pctl_reg = tmp;
6124		}
6125	}
6126	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6127	bwn_phy_g_set_bbatt(mac, 2);
6128
6129	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6130	mask = ~mask;
6131	BWN_RF_MASK(mac, reg, mask);
6132
6133	if (BWN_HAS_TXMAG(phy)) {
6134		int i, j;
6135		int feedthrough;
6136		int min_feedth = 0xffff;
6137		uint8_t tx_magn, tx_bias;
6138
6139		for (i = 0; i < N(tx_magn_values); i++) {
6140			tx_magn = tx_magn_values[i];
6141			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6142			for (j = 0; j < N(tx_bias_values); j++) {
6143				tx_bias = tx_bias_values[j];
6144				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6145				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6146				    trsw_rx);
6147				if (feedthrough < min_feedth) {
6148					lo->tx_bias = tx_bias;
6149					lo->tx_magn = tx_magn;
6150					min_feedth = feedthrough;
6151				}
6152				if (lo->tx_bias == 0)
6153					break;
6154			}
6155			BWN_RF_WRITE(mac, 0x52,
6156					  (BWN_RF_READ(mac, 0x52)
6157					   & 0xff00) | lo->tx_bias | lo->
6158					  tx_magn);
6159		}
6160	} else {
6161		lo->tx_magn = 0;
6162		lo->tx_bias = 0;
6163		BWN_RF_MASK(mac, 0x52, 0xfff0);
6164	}
6165
6166	BWN_GETTIME(lo->txctl_measured_time);
6167}
6168
6169static void
6170bwn_lo_get_powervector(struct bwn_mac *mac)
6171{
6172	struct bwn_phy *phy = &mac->mac_phy;
6173	struct bwn_phy_g *pg = &phy->phy_g;
6174	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6175	int i;
6176	uint64_t tmp;
6177	uint64_t power_vector = 0;
6178
6179	for (i = 0; i < 8; i += 2) {
6180		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6181		power_vector |= (tmp << (i * 8));
6182		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6183	}
6184	if (power_vector)
6185		lo->power_vector = power_vector;
6186
6187	BWN_GETTIME(lo->pwr_vec_read_time);
6188}
6189
6190static void
6191bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6192    int use_trsw_rx)
6193{
6194	struct bwn_phy *phy = &mac->mac_phy;
6195	struct bwn_phy_g *pg = &phy->phy_g;
6196	uint16_t tmp;
6197
6198	if (max_rx_gain < 0)
6199		max_rx_gain = 0;
6200
6201	if (BWN_HAS_LOOPBACK(phy)) {
6202		int trsw_rx = 0;
6203		int trsw_rx_gain;
6204
6205		if (use_trsw_rx) {
6206			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6207			if (max_rx_gain >= trsw_rx_gain) {
6208				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6209				trsw_rx = 0x20;
6210			}
6211		} else
6212			trsw_rx_gain = max_rx_gain;
6213		if (trsw_rx_gain < 9) {
6214			pg->pg_lna_lod_gain = 0;
6215		} else {
6216			pg->pg_lna_lod_gain = 1;
6217			trsw_rx_gain -= 8;
6218		}
6219		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6220		pg->pg_pga_gain = trsw_rx_gain / 3;
6221		if (pg->pg_pga_gain >= 5) {
6222			pg->pg_pga_gain -= 5;
6223			pg->pg_lna_gain = 2;
6224		} else
6225			pg->pg_lna_gain = 0;
6226	} else {
6227		pg->pg_lna_gain = 0;
6228		pg->pg_trsw_rx_gain = 0x20;
6229		if (max_rx_gain >= 0x14) {
6230			pg->pg_lna_lod_gain = 1;
6231			pg->pg_pga_gain = 2;
6232		} else if (max_rx_gain >= 0x12) {
6233			pg->pg_lna_lod_gain = 1;
6234			pg->pg_pga_gain = 1;
6235		} else if (max_rx_gain >= 0xf) {
6236			pg->pg_lna_lod_gain = 1;
6237			pg->pg_pga_gain = 0;
6238		} else {
6239			pg->pg_lna_lod_gain = 0;
6240			pg->pg_pga_gain = 0;
6241		}
6242	}
6243
6244	tmp = BWN_RF_READ(mac, 0x7a);
6245	if (pg->pg_lna_lod_gain == 0)
6246		tmp &= ~0x0008;
6247	else
6248		tmp |= 0x0008;
6249	BWN_RF_WRITE(mac, 0x7a, tmp);
6250}
6251
6252static void
6253bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6254{
6255	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6256	struct bwn_phy *phy = &mac->mac_phy;
6257	struct bwn_phy_g *pg = &phy->phy_g;
6258	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6259	struct timespec ts;
6260	uint16_t tmp;
6261
6262	if (bwn_has_hwpctl(mac)) {
6263		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6264		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6265		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6266		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6267		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6268
6269		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6270		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6271		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6272		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6273	}
6274	if (phy->type == BWN_PHYTYPE_B &&
6275	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6276		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6277		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6278	}
6279	if (phy->rev >= 2) {
6280		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6281		sav->phy_analogoverval =
6282		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6283		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6284		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6285		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6286		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6287		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6288
6289		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6290		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6291		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6292		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6293		if (phy->type == BWN_PHYTYPE_G) {
6294			if ((phy->rev >= 7) &&
6295			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6296				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6297			} else {
6298				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6299			}
6300		} else {
6301			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6302		}
6303		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6304	}
6305	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6306	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6307	sav->rf0 = BWN_RF_READ(mac, 0x43);
6308	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6309	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6310	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6311	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6312	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6313
6314	if (!BWN_HAS_TXMAG(phy)) {
6315		sav->rf2 = BWN_RF_READ(mac, 0x52);
6316		sav->rf2 &= 0x00f0;
6317	}
6318	if (phy->type == BWN_PHYTYPE_B) {
6319		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6320		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6321		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6322		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6323	} else {
6324		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6325			    | 0x8000);
6326	}
6327	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6328		    & 0xf000);
6329
6330	tmp =
6331	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6332	BWN_PHY_WRITE(mac, tmp, 0x007f);
6333
6334	tmp = sav->phy_syncctl;
6335	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6336	tmp = sav->rf1;
6337	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6338
6339	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6340	if (phy->type == BWN_PHYTYPE_G ||
6341	    (phy->type == BWN_PHYTYPE_B &&
6342	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6343		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6344	} else
6345		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6346	if (phy->rev >= 2)
6347		bwn_dummy_transmission(mac, 0, 1);
6348	bwn_phy_g_switch_chan(mac, 6, 0);
6349	BWN_RF_READ(mac, 0x51);
6350	if (phy->type == BWN_PHYTYPE_G)
6351		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6352
6353	nanouptime(&ts);
6354	if (time_before(lo->txctl_measured_time,
6355	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6356		bwn_lo_measure_txctl_values(mac);
6357
6358	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6359		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6360	else {
6361		if (phy->type == BWN_PHYTYPE_B)
6362			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6363		else
6364			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6365	}
6366}
6367
6368static void
6369bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6370{
6371	struct bwn_phy *phy = &mac->mac_phy;
6372	struct bwn_phy_g *pg = &phy->phy_g;
6373	uint16_t tmp;
6374
6375	if (phy->rev >= 2) {
6376		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6377		tmp = (pg->pg_pga_gain << 8);
6378		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6379		DELAY(5);
6380		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6381		DELAY(2);
6382		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6383	} else {
6384		tmp = (pg->pg_pga_gain | 0xefa0);
6385		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6386	}
6387	if (phy->type == BWN_PHYTYPE_G) {
6388		if (phy->rev >= 3)
6389			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6390		else
6391			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6392		if (phy->rev >= 2)
6393			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6394		else
6395			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6396	}
6397	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6398	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6399	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6400	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6401	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6402	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6403	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6404	if (!BWN_HAS_TXMAG(phy)) {
6405		tmp = sav->rf2;
6406		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6407	}
6408	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6409	if (phy->type == BWN_PHYTYPE_B &&
6410	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6411		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6412		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6413	}
6414	if (phy->rev >= 2) {
6415		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6416		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6417			      sav->phy_analogoverval);
6418		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6419		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6420		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6421		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6422		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6423	}
6424	if (bwn_has_hwpctl(mac)) {
6425		tmp = (sav->phy_lomask & 0xbfff);
6426		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6427		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6428		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6429		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6430		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6431	}
6432	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6433}
6434
6435static int
6436bwn_lo_probe_loctl(struct bwn_mac *mac,
6437    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6438{
6439	struct bwn_phy *phy = &mac->mac_phy;
6440	struct bwn_phy_g *pg = &phy->phy_g;
6441	struct bwn_loctl orig, test;
6442	struct bwn_loctl prev = { -100, -100 };
6443	static const struct bwn_loctl modifiers[] = {
6444		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6445		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6446	};
6447	int begin, end, lower = 0, i;
6448	uint16_t feedth;
6449
6450	if (d->curstate == 0) {
6451		begin = 1;
6452		end = 8;
6453	} else if (d->curstate % 2 == 0) {
6454		begin = d->curstate - 1;
6455		end = d->curstate + 1;
6456	} else {
6457		begin = d->curstate - 2;
6458		end = d->curstate + 2;
6459	}
6460	if (begin < 1)
6461		begin += 8;
6462	if (end > 8)
6463		end -= 8;
6464
6465	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6466	i = begin;
6467	d->curstate = i;
6468	while (1) {
6469		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6470		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6471		test.i += modifiers[i - 1].i * d->multipler;
6472		test.q += modifiers[i - 1].q * d->multipler;
6473		if ((test.i != prev.i || test.q != prev.q) &&
6474		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6475			bwn_lo_write(mac, &test);
6476			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6477			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6478			if (feedth < d->feedth) {
6479				memcpy(probe, &test,
6480				    sizeof(struct bwn_loctl));
6481				lower = 1;
6482				d->feedth = feedth;
6483				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6484					break;
6485			}
6486		}
6487		memcpy(&prev, &test, sizeof(prev));
6488		if (i == end)
6489			break;
6490		if (i == 8)
6491			i = 1;
6492		else
6493			i++;
6494		d->curstate = i;
6495	}
6496
6497	return (lower);
6498}
6499
6500static void
6501bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6502{
6503	struct bwn_phy *phy = &mac->mac_phy;
6504	struct bwn_phy_g *pg = &phy->phy_g;
6505	struct bwn_lo_g_sm d;
6506	struct bwn_loctl probe;
6507	int lower, repeat, cnt = 0;
6508	uint16_t feedth;
6509
6510	d.nmeasure = 0;
6511	d.multipler = 1;
6512	if (BWN_HAS_LOOPBACK(phy))
6513		d.multipler = 3;
6514
6515	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6516	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6517
6518	do {
6519		bwn_lo_write(mac, &d.loctl);
6520		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6521		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6522		if (feedth < 0x258) {
6523			if (feedth >= 0x12c)
6524				*rxgain += 6;
6525			else
6526				*rxgain += 3;
6527			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6528			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6529		}
6530		d.feedth = feedth;
6531		d.curstate = 0;
6532		do {
6533			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6534			    ("%s:%d: fail", __func__, __LINE__));
6535			memcpy(&probe, &d.loctl,
6536			       sizeof(struct bwn_loctl));
6537			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6538			if (!lower)
6539				break;
6540			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6541				break;
6542			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6543			d.nmeasure++;
6544		} while (d.nmeasure < 24);
6545		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6546
6547		if (BWN_HAS_LOOPBACK(phy)) {
6548			if (d.feedth > 0x1194)
6549				*rxgain -= 6;
6550			else if (d.feedth < 0x5dc)
6551				*rxgain += 3;
6552			if (cnt == 0) {
6553				if (d.feedth <= 0x5dc) {
6554					d.multipler = 1;
6555					cnt++;
6556				} else
6557					d.multipler = 2;
6558			} else if (cnt == 2)
6559				d.multipler = 1;
6560		}
6561		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6562	} while (++cnt < repeat);
6563}
6564
6565static struct bwn_lo_calib *
6566bwn_lo_calibset(struct bwn_mac *mac,
6567    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6568{
6569	struct bwn_phy *phy = &mac->mac_phy;
6570	struct bwn_phy_g *pg = &phy->phy_g;
6571	struct bwn_loctl loctl = { 0, 0 };
6572	struct bwn_lo_calib *cal;
6573	struct bwn_lo_g_value sval;
6574	int rxgain;
6575	uint16_t pad, reg, value;
6576
6577	sval.old_channel = phy->chan;
6578	bwn_mac_suspend(mac);
6579	bwn_lo_save(mac, &sval);
6580
6581	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6582	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6583	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6584
6585	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6586	if (rfatt->padmix)
6587		rxgain -= pad;
6588	if (BWN_HAS_LOOPBACK(phy))
6589		rxgain += pg->pg_max_lb_gain;
6590	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6591	bwn_phy_g_set_bbatt(mac, bbatt->att);
6592	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6593
6594	bwn_lo_restore(mac, &sval);
6595	bwn_mac_enable(mac);
6596
6597	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6598	if (!cal) {
6599		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6600		return (NULL);
6601	}
6602	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6603	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6604	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6605
6606	BWN_GETTIME(cal->calib_time);
6607
6608	return (cal);
6609}
6610
6611static struct bwn_lo_calib *
6612bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6613    const struct bwn_rfatt *rfatt)
6614{
6615	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6616	struct bwn_lo_calib *c;
6617
6618	TAILQ_FOREACH(c, &lo->calib_list, list) {
6619		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6620			continue;
6621		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6622			continue;
6623		return (c);
6624	}
6625
6626	c = bwn_lo_calibset(mac, bbatt, rfatt);
6627	if (!c)
6628		return (NULL);
6629	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6630
6631	return (c);
6632}
6633
6634static void
6635bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6636{
6637	struct bwn_phy *phy = &mac->mac_phy;
6638	struct bwn_phy_g *pg = &phy->phy_g;
6639	struct bwn_softc *sc = mac->mac_sc;
6640	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6641	const struct bwn_rfatt *rfatt;
6642	const struct bwn_bbatt *bbatt;
6643	uint64_t pvector;
6644	int i;
6645	int rf_offset, bb_offset;
6646	uint8_t changed = 0;
6647
6648	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6649	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6650	    ("%s:%d: fail", __func__, __LINE__));
6651
6652	pvector = lo->power_vector;
6653	if (!update && !pvector)
6654		return;
6655
6656	bwn_mac_suspend(mac);
6657
6658	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6659		struct bwn_lo_calib *cal;
6660		int idx;
6661		uint16_t val;
6662
6663		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6664			continue;
6665		bb_offset = i / lo->rfatt.len;
6666		rf_offset = i % lo->rfatt.len;
6667		bbatt = &(lo->bbatt.array[bb_offset]);
6668		rfatt = &(lo->rfatt.array[rf_offset]);
6669
6670		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6671		if (!cal) {
6672			device_printf(sc->sc_dev, "LO: Could not "
6673			    "calibrate DC table entry\n");
6674			continue;
6675		}
6676		val = (uint8_t)(cal->ctl.q);
6677		val |= ((uint8_t)(cal->ctl.i)) << 4;
6678		free(cal, M_DEVBUF);
6679
6680		idx = i / 2;
6681		if (i % 2)
6682			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6683			    | ((val & 0x00ff) << 8);
6684		else
6685			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6686			    | (val & 0x00ff);
6687		changed = 1;
6688	}
6689	if (changed) {
6690		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6691			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6692	}
6693	bwn_mac_enable(mac);
6694}
6695
6696static void
6697bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6698{
6699
6700	if (!rf->padmix)
6701		return;
6702	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6703		rf->att = 4;
6704}
6705
6706static void
6707bwn_lo_g_adjust(struct bwn_mac *mac)
6708{
6709	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6710	struct bwn_lo_calib *cal;
6711	struct bwn_rfatt rf;
6712
6713	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6714	bwn_lo_fixup_rfatt(&rf);
6715
6716	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6717	if (!cal)
6718		return;
6719	bwn_lo_write(mac, &cal->ctl);
6720}
6721
6722static void
6723bwn_lo_g_init(struct bwn_mac *mac)
6724{
6725
6726	if (!bwn_has_hwpctl(mac))
6727		return;
6728
6729	bwn_lo_get_powervector(mac);
6730	bwn_phy_g_dc_lookup_init(mac, 1);
6731}
6732
6733static void
6734bwn_mac_suspend(struct bwn_mac *mac)
6735{
6736	struct bwn_softc *sc = mac->mac_sc;
6737	int i;
6738	uint32_t tmp;
6739
6740	KASSERT(mac->mac_suspended >= 0,
6741	    ("%s:%d: fail", __func__, __LINE__));
6742
6743	if (mac->mac_suspended == 0) {
6744		bwn_psctl(mac, BWN_PS_AWAKE);
6745		BWN_WRITE_4(mac, BWN_MACCTL,
6746			    BWN_READ_4(mac, BWN_MACCTL)
6747			    & ~BWN_MACCTL_ON);
6748		BWN_READ_4(mac, BWN_MACCTL);
6749		for (i = 35; i; i--) {
6750			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6751			if (tmp & BWN_INTR_MAC_SUSPENDED)
6752				goto out;
6753			DELAY(10);
6754		}
6755		for (i = 40; i; i--) {
6756			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6757			if (tmp & BWN_INTR_MAC_SUSPENDED)
6758				goto out;
6759			DELAY(1000);
6760		}
6761		device_printf(sc->sc_dev, "MAC suspend failed\n");
6762	}
6763out:
6764	mac->mac_suspended++;
6765}
6766
6767static void
6768bwn_mac_enable(struct bwn_mac *mac)
6769{
6770	struct bwn_softc *sc = mac->mac_sc;
6771	uint16_t state;
6772
6773	state = bwn_shm_read_2(mac, BWN_SHARED,
6774	    BWN_SHARED_UCODESTAT);
6775	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6776	    state != BWN_SHARED_UCODESTAT_SLEEP)
6777		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6778
6779	mac->mac_suspended--;
6780	KASSERT(mac->mac_suspended >= 0,
6781	    ("%s:%d: fail", __func__, __LINE__));
6782	if (mac->mac_suspended == 0) {
6783		BWN_WRITE_4(mac, BWN_MACCTL,
6784		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6785		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6786		BWN_READ_4(mac, BWN_MACCTL);
6787		BWN_READ_4(mac, BWN_INTR_REASON);
6788		bwn_psctl(mac, 0);
6789	}
6790}
6791
6792static void
6793bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6794{
6795	int i;
6796	uint16_t ucstat;
6797
6798	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6799	    ("%s:%d: fail", __func__, __LINE__));
6800	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6801	    ("%s:%d: fail", __func__, __LINE__));
6802
6803	/* XXX forcibly awake and hwps-off */
6804
6805	BWN_WRITE_4(mac, BWN_MACCTL,
6806	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6807	    ~BWN_MACCTL_HWPS);
6808	BWN_READ_4(mac, BWN_MACCTL);
6809	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6810		for (i = 0; i < 100; i++) {
6811			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6812			    BWN_SHARED_UCODESTAT);
6813			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6814				break;
6815			DELAY(10);
6816		}
6817	}
6818}
6819
6820static int16_t
6821bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6822{
6823
6824	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6825	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6826}
6827
6828static void
6829bwn_nrssi_threshold(struct bwn_mac *mac)
6830{
6831	struct bwn_phy *phy = &mac->mac_phy;
6832	struct bwn_phy_g *pg = &phy->phy_g;
6833	struct siba_softc *siba = mac->mac_sd->sd_bus;
6834	int32_t a, b;
6835	int16_t tmp16;
6836	uint16_t tmpu16;
6837
6838	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6839
6840	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6841		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6842			a = 0x13;
6843			b = 0x12;
6844		} else {
6845			a = 0xe;
6846			b = 0x11;
6847		}
6848
6849		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6850		a += (pg->pg_nrssi[0] << 6);
6851		a += (a < 32) ? 31 : 32;
6852		a = a >> 6;
6853		a = MIN(MAX(a, -31), 31);
6854
6855		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6856		b += (pg->pg_nrssi[0] << 6);
6857		if (b < 32)
6858			b += 31;
6859		else
6860			b += 32;
6861		b = b >> 6;
6862		b = MIN(MAX(b, -31), 31);
6863
6864		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6865		tmpu16 |= ((uint32_t)b & 0x0000003f);
6866		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6867		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6868		return;
6869	}
6870
6871	tmp16 = bwn_nrssi_read(mac, 0x20);
6872	if (tmp16 >= 0x20)
6873		tmp16 -= 0x40;
6874	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6875}
6876
6877static void
6878bwn_nrssi_slope_11g(struct bwn_mac *mac)
6879{
6880#define	SAVE_RF_MAX		3
6881#define	SAVE_PHY_COMM_MAX	4
6882#define	SAVE_PHY3_MAX		8
6883	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6884		{ 0x7a, 0x52, 0x43 };
6885	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6886		{ 0x15, 0x5a, 0x59, 0x58 };
6887	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6888		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6889		0x0801, 0x0060, 0x0014, 0x0478
6890	};
6891	struct bwn_phy *phy = &mac->mac_phy;
6892	struct bwn_phy_g *pg = &phy->phy_g;
6893	int32_t i, tmp32, phy3_idx = 0;
6894	uint16_t delta, tmp;
6895	uint16_t save_rf[SAVE_RF_MAX];
6896	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6897	uint16_t save_phy3[SAVE_PHY3_MAX];
6898	uint16_t ant_div, phy0, chan_ex;
6899	int16_t nrssi0, nrssi1;
6900
6901	KASSERT(phy->type == BWN_PHYTYPE_G,
6902	    ("%s:%d: fail", __func__, __LINE__));
6903
6904	if (phy->rf_rev >= 9)
6905		return;
6906	if (phy->rf_rev == 8)
6907		bwn_nrssi_offset(mac);
6908
6909	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6910	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6911
6912	/*
6913	 * Save RF/PHY registers for later restoration
6914	 */
6915	ant_div = BWN_READ_2(mac, 0x03e2);
6916	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6917	for (i = 0; i < SAVE_RF_MAX; ++i)
6918		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6919	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6920		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6921
6922	phy0 = BWN_READ_2(mac, BWN_PHY0);
6923	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6924	if (phy->rev >= 3) {
6925		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6926			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6927		BWN_PHY_WRITE(mac, 0x002e, 0);
6928		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6929		switch (phy->rev) {
6930		case 4:
6931		case 6:
6932		case 7:
6933			BWN_PHY_SET(mac, 0x0478, 0x0100);
6934			BWN_PHY_SET(mac, 0x0801, 0x0040);
6935			break;
6936		case 3:
6937		case 5:
6938			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6939			break;
6940		}
6941		BWN_PHY_SET(mac, 0x0060, 0x0040);
6942		BWN_PHY_SET(mac, 0x0014, 0x0200);
6943	}
6944	/*
6945	 * Calculate nrssi0
6946	 */
6947	BWN_RF_SET(mac, 0x007a, 0x0070);
6948	bwn_set_all_gains(mac, 0, 8, 0);
6949	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6950	if (phy->rev >= 2) {
6951		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6952		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6953	}
6954	BWN_RF_SET(mac, 0x007a, 0x0080);
6955	DELAY(20);
6956
6957	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6958	if (nrssi0 >= 0x0020)
6959		nrssi0 -= 0x0040;
6960
6961	/*
6962	 * Calculate nrssi1
6963	 */
6964	BWN_RF_MASK(mac, 0x007a, 0x007f);
6965	if (phy->rev >= 2)
6966		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6967
6968	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6969	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6970	BWN_RF_SET(mac, 0x007a, 0x000f);
6971	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6972	if (phy->rev >= 2) {
6973		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6974		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6975	}
6976
6977	bwn_set_all_gains(mac, 3, 0, 1);
6978	if (phy->rf_rev == 8) {
6979		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6980	} else {
6981		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6982		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6983		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6984		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6985	}
6986	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6987	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6988	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6989	DELAY(20);
6990	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6991
6992	/*
6993	 * Install calculated narrow RSSI values
6994	 */
6995	if (nrssi1 >= 0x0020)
6996		nrssi1 -= 0x0040;
6997	if (nrssi0 == nrssi1)
6998		pg->pg_nrssi_slope = 0x00010000;
6999	else
7000		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
7001	if (nrssi0 >= -4) {
7002		pg->pg_nrssi[0] = nrssi1;
7003		pg->pg_nrssi[1] = nrssi0;
7004	}
7005
7006	/*
7007	 * Restore saved RF/PHY registers
7008	 */
7009	if (phy->rev >= 3) {
7010		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7011			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7012			    save_phy3[phy3_idx]);
7013		}
7014	}
7015	if (phy->rev >= 2) {
7016		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7017		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7018	}
7019
7020	for (i = 0; i < SAVE_RF_MAX; ++i)
7021		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7022
7023	BWN_WRITE_2(mac, 0x03e2, ant_div);
7024	BWN_WRITE_2(mac, 0x03e6, phy0);
7025	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7026
7027	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7028		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7029
7030	bwn_spu_workaround(mac, phy->chan);
7031	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7032	bwn_set_original_gains(mac);
7033	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7034	if (phy->rev >= 3) {
7035		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7036			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7037			    save_phy3[phy3_idx]);
7038		}
7039	}
7040
7041	delta = 0x1f - pg->pg_nrssi[0];
7042	for (i = 0; i < 64; i++) {
7043		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7044		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7045		pg->pg_nrssi_lt[i] = tmp32;
7046	}
7047
7048	bwn_nrssi_threshold(mac);
7049#undef SAVE_RF_MAX
7050#undef SAVE_PHY_COMM_MAX
7051#undef SAVE_PHY3_MAX
7052}
7053
7054static void
7055bwn_nrssi_offset(struct bwn_mac *mac)
7056{
7057#define	SAVE_RF_MAX		2
7058#define	SAVE_PHY_COMM_MAX	10
7059#define	SAVE_PHY6_MAX		8
7060	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7061		{ 0x7a, 0x43 };
7062	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7063		0x0001, 0x0811, 0x0812, 0x0814,
7064		0x0815, 0x005a, 0x0059, 0x0058,
7065		0x000a, 0x0003
7066	};
7067	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7068		0x002e, 0x002f, 0x080f, 0x0810,
7069		0x0801, 0x0060, 0x0014, 0x0478
7070	};
7071	struct bwn_phy *phy = &mac->mac_phy;
7072	int i, phy6_idx = 0;
7073	uint16_t save_rf[SAVE_RF_MAX];
7074	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7075	uint16_t save_phy6[SAVE_PHY6_MAX];
7076	int16_t nrssi;
7077	uint16_t saved = 0xffff;
7078
7079	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7080		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7081	for (i = 0; i < SAVE_RF_MAX; ++i)
7082		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7083
7084	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7085	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7086	BWN_PHY_SET(mac, 0x0811, 0x000c);
7087	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7088	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7089	if (phy->rev >= 6) {
7090		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7091			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7092
7093		BWN_PHY_WRITE(mac, 0x002e, 0);
7094		BWN_PHY_WRITE(mac, 0x002f, 0);
7095		BWN_PHY_WRITE(mac, 0x080f, 0);
7096		BWN_PHY_WRITE(mac, 0x0810, 0);
7097		BWN_PHY_SET(mac, 0x0478, 0x0100);
7098		BWN_PHY_SET(mac, 0x0801, 0x0040);
7099		BWN_PHY_SET(mac, 0x0060, 0x0040);
7100		BWN_PHY_SET(mac, 0x0014, 0x0200);
7101	}
7102	BWN_RF_SET(mac, 0x007a, 0x0070);
7103	BWN_RF_SET(mac, 0x007a, 0x0080);
7104	DELAY(30);
7105
7106	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7107	if (nrssi >= 0x20)
7108		nrssi -= 0x40;
7109	if (nrssi == 31) {
7110		for (i = 7; i >= 4; i--) {
7111			BWN_RF_WRITE(mac, 0x007b, i);
7112			DELAY(20);
7113			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7114			    0x003f);
7115			if (nrssi >= 0x20)
7116				nrssi -= 0x40;
7117			if (nrssi < 31 && saved == 0xffff)
7118				saved = i;
7119		}
7120		if (saved == 0xffff)
7121			saved = 4;
7122	} else {
7123		BWN_RF_MASK(mac, 0x007a, 0x007f);
7124		if (phy->rev != 1) {
7125			BWN_PHY_SET(mac, 0x0814, 0x0001);
7126			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7127		}
7128		BWN_PHY_SET(mac, 0x0811, 0x000c);
7129		BWN_PHY_SET(mac, 0x0812, 0x000c);
7130		BWN_PHY_SET(mac, 0x0811, 0x0030);
7131		BWN_PHY_SET(mac, 0x0812, 0x0030);
7132		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7133		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7134		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7135		if (phy->rev == 0)
7136			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7137		else
7138			BWN_PHY_SET(mac, 0x000a, 0x2000);
7139		if (phy->rev != 1) {
7140			BWN_PHY_SET(mac, 0x0814, 0x0004);
7141			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7142		}
7143		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7144		BWN_RF_SET(mac, 0x007a, 0x000f);
7145		bwn_set_all_gains(mac, 3, 0, 1);
7146		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7147		DELAY(30);
7148		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7149		if (nrssi >= 0x20)
7150			nrssi -= 0x40;
7151		if (nrssi == -32) {
7152			for (i = 0; i < 4; i++) {
7153				BWN_RF_WRITE(mac, 0x007b, i);
7154				DELAY(20);
7155				nrssi = (int16_t)((BWN_PHY_READ(mac,
7156				    0x047f) >> 8) & 0x003f);
7157				if (nrssi >= 0x20)
7158					nrssi -= 0x40;
7159				if (nrssi > -31 && saved == 0xffff)
7160					saved = i;
7161			}
7162			if (saved == 0xffff)
7163				saved = 3;
7164		} else
7165			saved = 0;
7166	}
7167	BWN_RF_WRITE(mac, 0x007b, saved);
7168
7169	/*
7170	 * Restore saved RF/PHY registers
7171	 */
7172	if (phy->rev >= 6) {
7173		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7174			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7175			    save_phy6[phy6_idx]);
7176		}
7177	}
7178	if (phy->rev != 1) {
7179		for (i = 3; i < 5; i++)
7180			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7181			    save_phy_comm[i]);
7182	}
7183	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7184		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7185
7186	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7187		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7188
7189	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7190	BWN_PHY_SET(mac, 0x0429, 0x8000);
7191	bwn_set_original_gains(mac);
7192	if (phy->rev >= 6) {
7193		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7194			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7195			    save_phy6[phy6_idx]);
7196		}
7197	}
7198
7199	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7200	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7201	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7202}
7203
7204static void
7205bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7206    int16_t third)
7207{
7208	struct bwn_phy *phy = &mac->mac_phy;
7209	uint16_t i;
7210	uint16_t start = 0x08, end = 0x18;
7211	uint16_t tmp;
7212	uint16_t table;
7213
7214	if (phy->rev <= 1) {
7215		start = 0x10;
7216		end = 0x20;
7217	}
7218
7219	table = BWN_OFDMTAB_GAINX;
7220	if (phy->rev <= 1)
7221		table = BWN_OFDMTAB_GAINX_R1;
7222	for (i = 0; i < 4; i++)
7223		bwn_ofdmtab_write_2(mac, table, i, first);
7224
7225	for (i = start; i < end; i++)
7226		bwn_ofdmtab_write_2(mac, table, i, second);
7227
7228	if (third != -1) {
7229		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7230		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7231		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7232		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7233	}
7234	bwn_dummy_transmission(mac, 0, 1);
7235}
7236
7237static void
7238bwn_set_original_gains(struct bwn_mac *mac)
7239{
7240	struct bwn_phy *phy = &mac->mac_phy;
7241	uint16_t i, tmp;
7242	uint16_t table;
7243	uint16_t start = 0x0008, end = 0x0018;
7244
7245	if (phy->rev <= 1) {
7246		start = 0x0010;
7247		end = 0x0020;
7248	}
7249
7250	table = BWN_OFDMTAB_GAINX;
7251	if (phy->rev <= 1)
7252		table = BWN_OFDMTAB_GAINX_R1;
7253	for (i = 0; i < 4; i++) {
7254		tmp = (i & 0xfffc);
7255		tmp |= (i & 0x0001) << 1;
7256		tmp |= (i & 0x0002) >> 1;
7257
7258		bwn_ofdmtab_write_2(mac, table, i, tmp);
7259	}
7260
7261	for (i = start; i < end; i++)
7262		bwn_ofdmtab_write_2(mac, table, i, i - start);
7263
7264	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7265	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7266	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7267	bwn_dummy_transmission(mac, 0, 1);
7268}
7269
7270static void
7271bwn_phy_hwpctl_init(struct bwn_mac *mac)
7272{
7273	struct siba_softc *bus = mac->mac_sd->sd_bus;
7274	struct bwn_phy *phy = &mac->mac_phy;
7275	struct bwn_phy_g *pg = &phy->phy_g;
7276	struct bwn_rfatt old_rfatt, rfatt;
7277	struct bwn_bbatt old_bbatt, bbatt;
7278	uint8_t old_txctl = 0;
7279
7280	KASSERT(phy->type == BWN_PHYTYPE_G,
7281	    ("%s:%d: fail", __func__, __LINE__));
7282
7283	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7284	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7285		return;
7286
7287	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7288
7289	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7290
7291	if (!phy->gmode)
7292		return;
7293	bwn_hwpctl_early_init(mac);
7294	if (pg->pg_curtssi == 0) {
7295		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7296			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7297		} else {
7298			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7299			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7300			old_txctl = pg->pg_txctl;
7301
7302			bbatt.att = 11;
7303			if (phy->rf_rev == 8) {
7304				rfatt.att = 15;
7305				rfatt.padmix = 1;
7306			} else {
7307				rfatt.att = 9;
7308				rfatt.padmix = 0;
7309			}
7310			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7311		}
7312		bwn_dummy_transmission(mac, 0, 1);
7313		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7314		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7315			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7316		else
7317			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7318			    &old_rfatt, old_txctl);
7319	}
7320	bwn_hwpctl_init_gphy(mac);
7321
7322	/* clear TSSI */
7323	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7324	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7325	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7326	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7327}
7328
7329static void
7330bwn_hwpctl_early_init(struct bwn_mac *mac)
7331{
7332	struct bwn_phy *phy = &mac->mac_phy;
7333
7334	if (!bwn_has_hwpctl(mac)) {
7335		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7336		return;
7337	}
7338
7339	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7340	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7341	BWN_PHY_SET(mac, 0x047c, 0x0002);
7342	BWN_PHY_SET(mac, 0x047a, 0xf000);
7343	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7344		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7345		BWN_PHY_SET(mac, 0x005d, 0x8000);
7346		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7347		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7348		BWN_PHY_SET(mac, 0x0036, 0x0400);
7349	} else {
7350		BWN_PHY_SET(mac, 0x0036, 0x0200);
7351		BWN_PHY_SET(mac, 0x0036, 0x0400);
7352		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7353		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7354		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7355		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7356		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7357	}
7358}
7359
7360static void
7361bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7362{
7363	struct bwn_phy *phy = &mac->mac_phy;
7364	struct bwn_phy_g *pg = &phy->phy_g;
7365	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7366	int i;
7367	uint16_t nr_written = 0, tmp, value;
7368	uint8_t rf, bb;
7369
7370	if (!bwn_has_hwpctl(mac)) {
7371		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7372		return;
7373	}
7374
7375	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7376	    (pg->pg_idletssi - pg->pg_curtssi));
7377	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7378	    (pg->pg_idletssi - pg->pg_curtssi));
7379
7380	for (i = 0; i < 32; i++)
7381		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7382	for (i = 32; i < 64; i++)
7383		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7384	for (i = 0; i < 64; i += 2) {
7385		value = (uint16_t) pg->pg_tssi2dbm[i];
7386		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7387		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7388	}
7389
7390	for (rf = 0; rf < lo->rfatt.len; rf++) {
7391		for (bb = 0; bb < lo->bbatt.len; bb++) {
7392			if (nr_written >= 0x40)
7393				return;
7394			tmp = lo->bbatt.array[bb].att;
7395			tmp <<= 8;
7396			if (phy->rf_rev == 8)
7397				tmp |= 0x50;
7398			else
7399				tmp |= 0x40;
7400			tmp |= lo->rfatt.array[rf].att;
7401			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7402			nr_written++;
7403		}
7404	}
7405
7406	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7407	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7408
7409	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7410	BWN_PHY_SET(mac, 0x0478, 0x0800);
7411	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7412	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7413
7414	bwn_phy_g_dc_lookup_init(mac, 1);
7415	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7416}
7417
7418static void
7419bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7420{
7421	struct siba_softc *siba = mac->mac_sd->sd_bus;
7422
7423	if (spu != 0)
7424		bwn_spu_workaround(mac, channel);
7425
7426	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7427
7428	if (channel == 14) {
7429		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7430			bwn_hf_write(mac,
7431			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7432		else
7433			bwn_hf_write(mac,
7434			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7435		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7436		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7437		return;
7438	}
7439
7440	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7441	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7442}
7443
7444static uint16_t
7445bwn_phy_g_chan2freq(uint8_t channel)
7446{
7447	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7448
7449	KASSERT(channel >= 1 && channel <= 14,
7450	    ("%s:%d: fail", __func__, __LINE__));
7451
7452	return (bwn_phy_g_rf_channels[channel - 1]);
7453}
7454
7455static void
7456bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7457    const struct bwn_rfatt *rfatt, uint8_t txctl)
7458{
7459	struct bwn_phy *phy = &mac->mac_phy;
7460	struct bwn_phy_g *pg = &phy->phy_g;
7461	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7462	uint16_t bb, rf;
7463	uint16_t tx_bias, tx_magn;
7464
7465	bb = bbatt->att;
7466	rf = rfatt->att;
7467	tx_bias = lo->tx_bias;
7468	tx_magn = lo->tx_magn;
7469	if (tx_bias == 0xff)
7470		tx_bias = 0;
7471
7472	pg->pg_txctl = txctl;
7473	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7474	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7475	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7476	bwn_phy_g_set_bbatt(mac, bb);
7477	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7478	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7479		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7480	else {
7481		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7482		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7483	}
7484	if (BWN_HAS_TXMAG(phy))
7485		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7486	else
7487		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7488	bwn_lo_g_adjust(mac);
7489}
7490
7491static void
7492bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7493    uint16_t bbatt)
7494{
7495	struct bwn_phy *phy = &mac->mac_phy;
7496
7497	if (phy->analog == 0) {
7498		BWN_WRITE_2(mac, BWN_PHY0,
7499		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7500		return;
7501	}
7502	if (phy->analog > 1) {
7503		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7504		return;
7505	}
7506	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7507}
7508
7509static uint16_t
7510bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7511{
7512	struct bwn_phy *phy = &mac->mac_phy;
7513	struct bwn_phy_g *pg = &phy->phy_g;
7514	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7515	int max_lb_gain;
7516	uint16_t extlna;
7517	uint16_t i;
7518
7519	if (phy->gmode == 0)
7520		return (0);
7521
7522	if (BWN_HAS_LOOPBACK(phy)) {
7523		max_lb_gain = pg->pg_max_lb_gain;
7524		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7525		if (max_lb_gain >= 0x46) {
7526			extlna = 0x3000;
7527			max_lb_gain -= 0x46;
7528		} else if (max_lb_gain >= 0x3a) {
7529			extlna = 0x1000;
7530			max_lb_gain -= 0x3a;
7531		} else if (max_lb_gain >= 0x2e) {
7532			extlna = 0x2000;
7533			max_lb_gain -= 0x2e;
7534		} else {
7535			extlna = 0;
7536			max_lb_gain -= 0x10;
7537		}
7538
7539		for (i = 0; i < 16; i++) {
7540			max_lb_gain -= (i * 6);
7541			if (max_lb_gain < 6)
7542				break;
7543		}
7544
7545		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7546			if (reg == BWN_PHY_RFOVER) {
7547				return (0x1b3);
7548			} else if (reg == BWN_PHY_RFOVERVAL) {
7549				extlna |= (i << 8);
7550				switch (lpd) {
7551				case BWN_LPD(0, 1, 1):
7552					return (0x0f92);
7553				case BWN_LPD(0, 0, 1):
7554				case BWN_LPD(1, 0, 1):
7555					return (0x0092 | extlna);
7556				case BWN_LPD(1, 0, 0):
7557					return (0x0093 | extlna);
7558				}
7559				KASSERT(0 == 1,
7560				    ("%s:%d: fail", __func__, __LINE__));
7561			}
7562			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7563		} else {
7564			if (reg == BWN_PHY_RFOVER)
7565				return (0x9b3);
7566			if (reg == BWN_PHY_RFOVERVAL) {
7567				if (extlna)
7568					extlna |= 0x8000;
7569				extlna |= (i << 8);
7570				switch (lpd) {
7571				case BWN_LPD(0, 1, 1):
7572					return (0x8f92);
7573				case BWN_LPD(0, 0, 1):
7574					return (0x8092 | extlna);
7575				case BWN_LPD(1, 0, 1):
7576					return (0x2092 | extlna);
7577				case BWN_LPD(1, 0, 0):
7578					return (0x2093 | extlna);
7579				}
7580				KASSERT(0 == 1,
7581				    ("%s:%d: fail", __func__, __LINE__));
7582			}
7583			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7584		}
7585		return (0);
7586	}
7587
7588	if ((phy->rev < 7) ||
7589	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7590		if (reg == BWN_PHY_RFOVER) {
7591			return (0x1b3);
7592		} else if (reg == BWN_PHY_RFOVERVAL) {
7593			switch (lpd) {
7594			case BWN_LPD(0, 1, 1):
7595				return (0x0fb2);
7596			case BWN_LPD(0, 0, 1):
7597				return (0x00b2);
7598			case BWN_LPD(1, 0, 1):
7599				return (0x30b2);
7600			case BWN_LPD(1, 0, 0):
7601				return (0x30b3);
7602			}
7603			KASSERT(0 == 1,
7604			    ("%s:%d: fail", __func__, __LINE__));
7605		}
7606		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7607	} else {
7608		if (reg == BWN_PHY_RFOVER) {
7609			return (0x9b3);
7610		} else if (reg == BWN_PHY_RFOVERVAL) {
7611			switch (lpd) {
7612			case BWN_LPD(0, 1, 1):
7613				return (0x8fb2);
7614			case BWN_LPD(0, 0, 1):
7615				return (0x80b2);
7616			case BWN_LPD(1, 0, 1):
7617				return (0x20b2);
7618			case BWN_LPD(1, 0, 0):
7619				return (0x20b3);
7620			}
7621			KASSERT(0 == 1,
7622			    ("%s:%d: fail", __func__, __LINE__));
7623		}
7624		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7625	}
7626	return (0);
7627}
7628
7629static void
7630bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7631{
7632
7633	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7634		return;
7635	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7636	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7637	DELAY(1000);
7638	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7639}
7640
7641static int
7642bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7643{
7644	struct bwn_softc *sc = mac->mac_sc;
7645	struct bwn_fw *fw = &mac->mac_fw;
7646	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7647	const char *filename;
7648	uint32_t high;
7649	int error;
7650
7651	/* microcode */
7652	if (rev >= 5 && rev <= 10)
7653		filename = "ucode5";
7654	else if (rev >= 11 && rev <= 12)
7655		filename = "ucode11";
7656	else if (rev == 13)
7657		filename = "ucode13";
7658	else if (rev == 14)
7659		filename = "ucode14";
7660	else if (rev >= 15)
7661		filename = "ucode15";
7662	else {
7663		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7664		bwn_release_firmware(mac);
7665		return (EOPNOTSUPP);
7666	}
7667	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7668	if (error) {
7669		bwn_release_firmware(mac);
7670		return (error);
7671	}
7672
7673	/* PCM */
7674	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7675	if (rev >= 5 && rev <= 10) {
7676		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7677		if (error == ENOENT)
7678			fw->no_pcmfile = 1;
7679		else if (error) {
7680			bwn_release_firmware(mac);
7681			return (error);
7682		}
7683	} else if (rev < 11) {
7684		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7685		return (EOPNOTSUPP);
7686	}
7687
7688	/* initvals */
7689	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7690	switch (mac->mac_phy.type) {
7691	case BWN_PHYTYPE_A:
7692		if (rev < 5 || rev > 10)
7693			goto fail1;
7694		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7695			filename = "a0g1initvals5";
7696		else
7697			filename = "a0g0initvals5";
7698		break;
7699	case BWN_PHYTYPE_G:
7700		if (rev >= 5 && rev <= 10)
7701			filename = "b0g0initvals5";
7702		else if (rev >= 13)
7703			filename = "b0g0initvals13";
7704		else
7705			goto fail1;
7706		break;
7707	case BWN_PHYTYPE_LP:
7708		if (rev == 13)
7709			filename = "lp0initvals13";
7710		else if (rev == 14)
7711			filename = "lp0initvals14";
7712		else if (rev >= 15)
7713			filename = "lp0initvals15";
7714		else
7715			goto fail1;
7716		break;
7717	case BWN_PHYTYPE_N:
7718		if (rev >= 11 && rev <= 12)
7719			filename = "n0initvals11";
7720		else
7721			goto fail1;
7722		break;
7723	default:
7724		goto fail1;
7725	}
7726	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7727	if (error) {
7728		bwn_release_firmware(mac);
7729		return (error);
7730	}
7731
7732	/* bandswitch initvals */
7733	switch (mac->mac_phy.type) {
7734	case BWN_PHYTYPE_A:
7735		if (rev >= 5 && rev <= 10) {
7736			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7737				filename = "a0g1bsinitvals5";
7738			else
7739				filename = "a0g0bsinitvals5";
7740		} else if (rev >= 11)
7741			filename = NULL;
7742		else
7743			goto fail1;
7744		break;
7745	case BWN_PHYTYPE_G:
7746		if (rev >= 5 && rev <= 10)
7747			filename = "b0g0bsinitvals5";
7748		else if (rev >= 11)
7749			filename = NULL;
7750		else
7751			goto fail1;
7752		break;
7753	case BWN_PHYTYPE_LP:
7754		if (rev == 13)
7755			filename = "lp0bsinitvals13";
7756		else if (rev == 14)
7757			filename = "lp0bsinitvals14";
7758		else if (rev >= 15)
7759			filename = "lp0bsinitvals15";
7760		else
7761			goto fail1;
7762		break;
7763	case BWN_PHYTYPE_N:
7764		if (rev >= 11 && rev <= 12)
7765			filename = "n0bsinitvals11";
7766		else
7767			goto fail1;
7768		break;
7769	default:
7770		goto fail1;
7771	}
7772	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7773	if (error) {
7774		bwn_release_firmware(mac);
7775		return (error);
7776	}
7777	return (0);
7778fail1:
7779	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7780	bwn_release_firmware(mac);
7781	return (EOPNOTSUPP);
7782}
7783
7784static int
7785bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7786    const char *name, struct bwn_fwfile *bfw)
7787{
7788	const struct bwn_fwhdr *hdr;
7789	struct bwn_softc *sc = mac->mac_sc;
7790	const struct firmware *fw;
7791	char namebuf[64];
7792
7793	if (name == NULL) {
7794		bwn_do_release_fw(bfw);
7795		return (0);
7796	}
7797	if (bfw->filename != NULL) {
7798		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7799			return (0);
7800		bwn_do_release_fw(bfw);
7801	}
7802
7803	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s",
7804	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", name);
7805	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7806	fw = firmware_get(namebuf);
7807	if (fw == NULL) {
7808		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7809		    namebuf);
7810		return (ENOENT);
7811	}
7812	if (fw->datasize < sizeof(struct bwn_fwhdr))
7813		goto fail;
7814	hdr = (const struct bwn_fwhdr *)(fw->data);
7815	switch (hdr->type) {
7816	case BWN_FWTYPE_UCODE:
7817	case BWN_FWTYPE_PCM:
7818		if (be32toh(hdr->size) !=
7819		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7820			goto fail;
7821		/* FALLTHROUGH */
7822	case BWN_FWTYPE_IV:
7823		if (hdr->ver != 1)
7824			goto fail;
7825		break;
7826	default:
7827		goto fail;
7828	}
7829	bfw->filename = name;
7830	bfw->fw = fw;
7831	bfw->type = type;
7832	return (0);
7833fail:
7834	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7835	if (fw != NULL)
7836		firmware_put(fw, FIRMWARE_UNLOAD);
7837	return (EPROTO);
7838}
7839
7840static void
7841bwn_release_firmware(struct bwn_mac *mac)
7842{
7843
7844	bwn_do_release_fw(&mac->mac_fw.ucode);
7845	bwn_do_release_fw(&mac->mac_fw.pcm);
7846	bwn_do_release_fw(&mac->mac_fw.initvals);
7847	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7848}
7849
7850static void
7851bwn_do_release_fw(struct bwn_fwfile *bfw)
7852{
7853
7854	if (bfw->fw != NULL)
7855		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7856	bfw->fw = NULL;
7857	bfw->filename = NULL;
7858}
7859
7860static int
7861bwn_fw_loaducode(struct bwn_mac *mac)
7862{
7863#define	GETFWOFFSET(fwp, offset)	\
7864	((const uint32_t *)((const char *)fwp.fw->data + offset))
7865#define	GETFWSIZE(fwp, offset)	\
7866	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7867	struct bwn_softc *sc = mac->mac_sc;
7868	const uint32_t *data;
7869	unsigned int i;
7870	uint32_t ctl;
7871	uint16_t date, fwcaps, time;
7872	int error = 0;
7873
7874	ctl = BWN_READ_4(mac, BWN_MACCTL);
7875	ctl |= BWN_MACCTL_MCODE_JMP0;
7876	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7877	    __LINE__));
7878	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7879	for (i = 0; i < 64; i++)
7880		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7881	for (i = 0; i < 4096; i += 2)
7882		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7883
7884	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7885	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7886	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7887	     i++) {
7888		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7889		DELAY(10);
7890	}
7891
7892	if (mac->mac_fw.pcm.fw) {
7893		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7894		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7895		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7896		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7897		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7898		    sizeof(struct bwn_fwhdr)); i++) {
7899			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7900			DELAY(10);
7901		}
7902	}
7903
7904	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7905	BWN_WRITE_4(mac, BWN_MACCTL,
7906	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7907	    BWN_MACCTL_MCODE_RUN);
7908
7909	for (i = 0; i < 21; i++) {
7910		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7911			break;
7912		if (i >= 20) {
7913			device_printf(sc->sc_dev, "ucode timeout\n");
7914			error = ENXIO;
7915			goto error;
7916		}
7917		DELAY(50000);
7918	}
7919	BWN_READ_4(mac, BWN_INTR_REASON);
7920
7921	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7922	if (mac->mac_fw.rev <= 0x128) {
7923		device_printf(sc->sc_dev, "the firmware is too old\n");
7924		error = EOPNOTSUPP;
7925		goto error;
7926	}
7927	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7928	    BWN_SHARED_UCODE_PATCH);
7929	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7930	mac->mac_fw.opensource = (date == 0xffff);
7931	if (bwn_wme != 0)
7932		mac->mac_flags |= BWN_MAC_FLAG_WME;
7933	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7934
7935	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7936	if (mac->mac_fw.opensource == 0) {
7937		device_printf(sc->sc_dev,
7938		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7939		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7940		if (mac->mac_fw.no_pcmfile)
7941			device_printf(sc->sc_dev,
7942			    "no HW crypto acceleration due to pcm5\n");
7943	} else {
7944		mac->mac_fw.patch = time;
7945		fwcaps = bwn_fwcaps_read(mac);
7946		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7947			device_printf(sc->sc_dev,
7948			    "disabling HW crypto acceleration\n");
7949			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7950		}
7951		if (!(fwcaps & BWN_FWCAPS_WME)) {
7952			device_printf(sc->sc_dev, "disabling WME support\n");
7953			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7954		}
7955	}
7956
7957	if (BWN_ISOLDFMT(mac))
7958		device_printf(sc->sc_dev, "using old firmware image\n");
7959
7960	return (0);
7961
7962error:
7963	BWN_WRITE_4(mac, BWN_MACCTL,
7964	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7965	    BWN_MACCTL_MCODE_JMP0);
7966
7967	return (error);
7968#undef GETFWSIZE
7969#undef GETFWOFFSET
7970}
7971
7972/* OpenFirmware only */
7973static uint16_t
7974bwn_fwcaps_read(struct bwn_mac *mac)
7975{
7976
7977	KASSERT(mac->mac_fw.opensource == 1,
7978	    ("%s:%d: fail", __func__, __LINE__));
7979	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7980}
7981
7982static int
7983bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7984    size_t count, size_t array_size)
7985{
7986#define	GET_NEXTIV16(iv)						\
7987	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7988	    sizeof(uint16_t) + sizeof(uint16_t)))
7989#define	GET_NEXTIV32(iv)						\
7990	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7991	    sizeof(uint16_t) + sizeof(uint32_t)))
7992	struct bwn_softc *sc = mac->mac_sc;
7993	const struct bwn_fwinitvals *iv;
7994	uint16_t offset;
7995	size_t i;
7996	uint8_t bit32;
7997
7998	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7999	    ("%s:%d: fail", __func__, __LINE__));
8000	iv = ivals;
8001	for (i = 0; i < count; i++) {
8002		if (array_size < sizeof(iv->offset_size))
8003			goto fail;
8004		array_size -= sizeof(iv->offset_size);
8005		offset = be16toh(iv->offset_size);
8006		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
8007		offset &= BWN_FWINITVALS_OFFSET_MASK;
8008		if (offset >= 0x1000)
8009			goto fail;
8010		if (bit32) {
8011			if (array_size < sizeof(iv->data.d32))
8012				goto fail;
8013			array_size -= sizeof(iv->data.d32);
8014			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8015			iv = GET_NEXTIV32(iv);
8016		} else {
8017
8018			if (array_size < sizeof(iv->data.d16))
8019				goto fail;
8020			array_size -= sizeof(iv->data.d16);
8021			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8022
8023			iv = GET_NEXTIV16(iv);
8024		}
8025	}
8026	if (array_size != 0)
8027		goto fail;
8028	return (0);
8029fail:
8030	device_printf(sc->sc_dev, "initvals: invalid format\n");
8031	return (EPROTO);
8032#undef GET_NEXTIV16
8033#undef GET_NEXTIV32
8034}
8035
8036static int
8037bwn_switch_channel(struct bwn_mac *mac, int chan)
8038{
8039	struct bwn_phy *phy = &(mac->mac_phy);
8040	struct bwn_softc *sc = mac->mac_sc;
8041	struct ifnet *ifp = sc->sc_ifp;
8042	struct ieee80211com *ic = ifp->if_l2com;
8043	uint16_t channelcookie, savedcookie;
8044	int error;
8045
8046	if (chan == 0xffff)
8047		chan = phy->get_default_chan(mac);
8048
8049	channelcookie = chan;
8050	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8051		channelcookie |= 0x100;
8052	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8053	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8054	error = phy->switch_channel(mac, chan);
8055	if (error)
8056		goto fail;
8057
8058	mac->mac_phy.chan = chan;
8059	DELAY(8000);
8060	return (0);
8061fail:
8062	device_printf(sc->sc_dev, "failed to switch channel\n");
8063	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8064	return (error);
8065}
8066
8067static uint16_t
8068bwn_ant2phy(int antenna)
8069{
8070
8071	switch (antenna) {
8072	case BWN_ANT0:
8073		return (BWN_TX_PHY_ANT0);
8074	case BWN_ANT1:
8075		return (BWN_TX_PHY_ANT1);
8076	case BWN_ANT2:
8077		return (BWN_TX_PHY_ANT2);
8078	case BWN_ANT3:
8079		return (BWN_TX_PHY_ANT3);
8080	case BWN_ANTAUTO:
8081		return (BWN_TX_PHY_ANT01AUTO);
8082	}
8083	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8084	return (0);
8085}
8086
8087static void
8088bwn_wme_load(struct bwn_mac *mac)
8089{
8090	struct bwn_softc *sc = mac->mac_sc;
8091	int i;
8092
8093	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8094	    ("%s:%d: fail", __func__, __LINE__));
8095
8096	bwn_mac_suspend(mac);
8097	for (i = 0; i < N(sc->sc_wmeParams); i++)
8098		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8099		    bwn_wme_shm_offsets[i]);
8100	bwn_mac_enable(mac);
8101}
8102
8103static void
8104bwn_wme_loadparams(struct bwn_mac *mac,
8105    const struct wmeParams *p, uint16_t shm_offset)
8106{
8107#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8108	struct bwn_softc *sc = mac->mac_sc;
8109	uint16_t params[BWN_NR_WMEPARAMS];
8110	int slot, tmp;
8111	unsigned int i;
8112
8113	slot = BWN_READ_2(mac, BWN_RNG) &
8114	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8115
8116	memset(&params, 0, sizeof(params));
8117
8118	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8119	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8120	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8121
8122	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8123	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8124	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8125	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8126	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8127	params[BWN_WMEPARAM_BSLOTS] = slot;
8128	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8129
8130	for (i = 0; i < N(params); i++) {
8131		if (i == BWN_WMEPARAM_STATUS) {
8132			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8133			    shm_offset + (i * 2));
8134			tmp |= 0x100;
8135			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8136			    tmp);
8137		} else {
8138			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8139			    params[i]);
8140		}
8141	}
8142}
8143
8144static void
8145bwn_mac_write_bssid(struct bwn_mac *mac)
8146{
8147	struct bwn_softc *sc = mac->mac_sc;
8148	uint32_t tmp;
8149	int i;
8150	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8151
8152	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8153	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8154	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8155	    IEEE80211_ADDR_LEN);
8156
8157	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8158		tmp = (uint32_t) (mac_bssid[i + 0]);
8159		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8160		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8161		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8162		bwn_ram_write(mac, 0x20 + i, tmp);
8163	}
8164}
8165
8166static void
8167bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8168    const uint8_t *macaddr)
8169{
8170	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8171	uint16_t data;
8172
8173	if (!mac)
8174		macaddr = zero;
8175
8176	offset |= 0x0020;
8177	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8178
8179	data = macaddr[0];
8180	data |= macaddr[1] << 8;
8181	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8182	data = macaddr[2];
8183	data |= macaddr[3] << 8;
8184	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8185	data = macaddr[4];
8186	data |= macaddr[5] << 8;
8187	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8188}
8189
8190static void
8191bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8192    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8193{
8194	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8195	uint8_t per_sta_keys_start = 8;
8196
8197	if (BWN_SEC_NEWAPI(mac))
8198		per_sta_keys_start = 4;
8199
8200	KASSERT(index < mac->mac_max_nr_keys,
8201	    ("%s:%d: fail", __func__, __LINE__));
8202	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8203	    ("%s:%d: fail", __func__, __LINE__));
8204
8205	if (index >= per_sta_keys_start)
8206		bwn_key_macwrite(mac, index, NULL);
8207	if (key)
8208		memcpy(buf, key, key_len);
8209	bwn_key_write(mac, index, algorithm, buf);
8210	if (index >= per_sta_keys_start)
8211		bwn_key_macwrite(mac, index, mac_addr);
8212
8213	mac->mac_key[index].algorithm = algorithm;
8214}
8215
8216static void
8217bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8218{
8219	uint32_t addrtmp[2] = { 0, 0 };
8220	uint8_t start = 8;
8221
8222	if (BWN_SEC_NEWAPI(mac))
8223		start = 4;
8224
8225	KASSERT(index >= start,
8226	    ("%s:%d: fail", __func__, __LINE__));
8227	index -= start;
8228
8229	if (addr) {
8230		addrtmp[0] = addr[0];
8231		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8232		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8233		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8234		addrtmp[1] = addr[4];
8235		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8236	}
8237
8238	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8239		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8240		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8241	} else {
8242		if (index >= 8) {
8243			bwn_shm_write_4(mac, BWN_SHARED,
8244			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8245			bwn_shm_write_2(mac, BWN_SHARED,
8246			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8247		}
8248	}
8249}
8250
8251static void
8252bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8253    const uint8_t *key)
8254{
8255	unsigned int i;
8256	uint32_t offset;
8257	uint16_t kidx, value;
8258
8259	kidx = BWN_SEC_KEY2FW(mac, index);
8260	bwn_shm_write_2(mac, BWN_SHARED,
8261	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8262
8263	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8264	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8265		value = key[i];
8266		value |= (uint16_t)(key[i + 1]) << 8;
8267		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8268	}
8269}
8270
8271static void
8272bwn_phy_exit(struct bwn_mac *mac)
8273{
8274
8275	mac->mac_phy.rf_onoff(mac, 0);
8276	if (mac->mac_phy.exit != NULL)
8277		mac->mac_phy.exit(mac);
8278}
8279
8280static void
8281bwn_dma_free(struct bwn_mac *mac)
8282{
8283	struct bwn_dma *dma;
8284
8285	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8286		return;
8287	dma = &mac->mac_method.dma;
8288
8289	bwn_dma_ringfree(&dma->rx);
8290	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8291	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8292	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8293	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8294	bwn_dma_ringfree(&dma->mcast);
8295}
8296
8297static void
8298bwn_core_stop(struct bwn_mac *mac)
8299{
8300	struct bwn_softc *sc = mac->mac_sc;
8301
8302	BWN_ASSERT_LOCKED(sc);
8303
8304	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8305		return;
8306
8307	callout_stop(&sc->sc_rfswitch_ch);
8308	callout_stop(&sc->sc_task_ch);
8309	callout_stop(&sc->sc_watchdog_ch);
8310	sc->sc_watchdog_timer = 0;
8311	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8312	BWN_READ_4(mac, BWN_INTR_MASK);
8313	bwn_mac_suspend(mac);
8314
8315	mac->mac_status = BWN_MAC_STATUS_INITED;
8316}
8317
8318static int
8319bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8320{
8321	struct bwn_mac *up_dev = NULL;
8322	struct bwn_mac *down_dev;
8323	struct bwn_mac *mac;
8324	int err, status;
8325	uint8_t gmode;
8326
8327	BWN_ASSERT_LOCKED(sc);
8328
8329	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8330		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8331		    mac->mac_phy.supports_2ghz) {
8332			up_dev = mac;
8333			gmode = 1;
8334		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8335		    mac->mac_phy.supports_5ghz) {
8336			up_dev = mac;
8337			gmode = 0;
8338		} else {
8339			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8340			return (EINVAL);
8341		}
8342		if (up_dev != NULL)
8343			break;
8344	}
8345	if (up_dev == NULL) {
8346		device_printf(sc->sc_dev, "Could not find a device\n");
8347		return (ENODEV);
8348	}
8349	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8350		return (0);
8351
8352	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8353	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8354
8355	down_dev = sc->sc_curmac;;
8356	status = down_dev->mac_status;
8357	if (status >= BWN_MAC_STATUS_STARTED)
8358		bwn_core_stop(down_dev);
8359	if (status >= BWN_MAC_STATUS_INITED)
8360		bwn_core_exit(down_dev);
8361
8362	if (down_dev != up_dev)
8363		bwn_phy_reset(down_dev);
8364
8365	up_dev->mac_phy.gmode = gmode;
8366	if (status >= BWN_MAC_STATUS_INITED) {
8367		err = bwn_core_init(up_dev);
8368		if (err) {
8369			device_printf(sc->sc_dev,
8370			    "fatal: failed to initialize for %s-GHz\n",
8371			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8372			goto fail;
8373		}
8374	}
8375	if (status >= BWN_MAC_STATUS_STARTED)
8376		bwn_core_start(up_dev);
8377	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8378	sc->sc_curmac = up_dev;
8379
8380	return (0);
8381fail:
8382	sc->sc_curmac = NULL;
8383	return (err);
8384}
8385
8386static void
8387bwn_rf_turnon(struct bwn_mac *mac)
8388{
8389
8390	bwn_mac_suspend(mac);
8391	mac->mac_phy.rf_onoff(mac, 1);
8392	mac->mac_phy.rf_on = 1;
8393	bwn_mac_enable(mac);
8394}
8395
8396static void
8397bwn_rf_turnoff(struct bwn_mac *mac)
8398{
8399
8400	bwn_mac_suspend(mac);
8401	mac->mac_phy.rf_onoff(mac, 0);
8402	mac->mac_phy.rf_on = 0;
8403	bwn_mac_enable(mac);
8404}
8405
8406static void
8407bwn_phy_reset(struct bwn_mac *mac)
8408{
8409	struct siba_dev_softc *sd = mac->mac_sd;
8410
8411	siba_write_4(sd, SIBA_TGSLOW,
8412	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8413	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8414	DELAY(1000);
8415	siba_write_4(sd, SIBA_TGSLOW,
8416	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8417	    BWN_TGSLOW_PHYRESET);
8418	DELAY(1000);
8419}
8420
8421static int
8422bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8423{
8424	struct bwn_vap *bvp = BWN_VAP(vap);
8425	struct ieee80211com *ic= vap->iv_ic;
8426	struct ifnet *ifp = ic->ic_ifp;
8427	enum ieee80211_state ostate = vap->iv_state;
8428	struct bwn_softc *sc = ifp->if_softc;
8429	struct bwn_mac *mac = sc->sc_curmac;
8430	int error;
8431
8432	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8433	    ieee80211_state_name[vap->iv_state],
8434	    ieee80211_state_name[nstate]);
8435
8436	error = bvp->bv_newstate(vap, nstate, arg);
8437	if (error != 0)
8438		return (error);
8439
8440	BWN_LOCK(sc);
8441
8442	bwn_led_newstate(mac, nstate);
8443
8444	/*
8445	 * Clear the BSSID when we stop a STA
8446	 */
8447	if (vap->iv_opmode == IEEE80211_M_STA) {
8448		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8449			/*
8450			 * Clear out the BSSID.  If we reassociate to
8451			 * the same AP, this will reinialize things
8452			 * correctly...
8453			 */
8454			if (ic->ic_opmode == IEEE80211_M_STA &&
8455			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8456				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8457				bwn_set_macaddr(mac);
8458			}
8459		}
8460	}
8461
8462	if (vap->iv_opmode == IEEE80211_M_MONITOR) {
8463		/* XXX nothing to do? */
8464	} else if (nstate == IEEE80211_S_RUN) {
8465		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8466		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8467		bwn_set_opmode(mac);
8468		bwn_set_pretbtt(mac);
8469		bwn_spu_setdelay(mac, 0);
8470		bwn_set_macaddr(mac);
8471	}
8472
8473	BWN_UNLOCK(sc);
8474
8475	return (error);
8476}
8477
8478static void
8479bwn_set_pretbtt(struct bwn_mac *mac)
8480{
8481	struct bwn_softc *sc = mac->mac_sc;
8482	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8483	uint16_t pretbtt;
8484
8485	if (ic->ic_opmode == IEEE80211_M_IBSS)
8486		pretbtt = 2;
8487	else
8488		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8489	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8490	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8491}
8492
8493static int
8494bwn_intr(void *arg)
8495{
8496	struct bwn_mac *mac = arg;
8497	struct bwn_softc *sc = mac->mac_sc;
8498	struct siba_softc *siba = mac->mac_sd->sd_bus;
8499	uint32_t reason;
8500
8501	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8502		return (FILTER_STRAY);
8503
8504	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8505	if (reason == 0xffffffff)	/* shared IRQ */
8506		return (FILTER_STRAY);
8507	reason &= mac->mac_intr_mask;
8508	if (reason == 0)
8509		return (FILTER_HANDLED);
8510
8511	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8512	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8513	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8514	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8515	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8516	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8517	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8518	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8519	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8520	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8521	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8522
8523	/* Disable interrupts. */
8524	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8525
8526	mac->mac_reason_intr = reason;
8527
8528	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8529	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8530
8531	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8532	return (FILTER_HANDLED);
8533}
8534
8535static void
8536bwn_intrtask(void *arg, int npending)
8537{
8538	struct bwn_mac *mac = arg;
8539	struct bwn_softc *sc = mac->mac_sc;
8540	struct ifnet *ifp = sc->sc_ifp;
8541	struct siba_softc *siba = mac->mac_sd->sd_bus;
8542	uint32_t merged = 0;
8543	int i, tx = 0, rx = 0;
8544
8545	BWN_LOCK(sc);
8546	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8547		BWN_UNLOCK(sc);
8548		return;
8549	}
8550
8551	for (i = 0; i < N(mac->mac_reason); i++)
8552		merged |= mac->mac_reason[i];
8553
8554	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8555		device_printf(sc->sc_dev, "MAC trans error\n");
8556
8557	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8558		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8559		mac->mac_phy.txerrors--;
8560		if (mac->mac_phy.txerrors == 0) {
8561			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8562			bwn_restart(mac, "PHY TX errors");
8563		}
8564	}
8565
8566	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8567		if (merged & BWN_DMAINTR_FATALMASK) {
8568			device_printf(sc->sc_dev,
8569			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8570			    mac->mac_reason[0], mac->mac_reason[1],
8571			    mac->mac_reason[2], mac->mac_reason[3],
8572			    mac->mac_reason[4], mac->mac_reason[5]);
8573			bwn_restart(mac, "DMA error");
8574			BWN_UNLOCK(sc);
8575			return;
8576		}
8577		if (merged & BWN_DMAINTR_NONFATALMASK) {
8578			device_printf(sc->sc_dev,
8579			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8580			    mac->mac_reason[0], mac->mac_reason[1],
8581			    mac->mac_reason[2], mac->mac_reason[3],
8582			    mac->mac_reason[4], mac->mac_reason[5]);
8583		}
8584	}
8585
8586	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8587		bwn_intr_ucode_debug(mac);
8588	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8589		bwn_intr_tbtt_indication(mac);
8590	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8591		bwn_intr_atim_end(mac);
8592	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8593		bwn_intr_beacon(mac);
8594	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8595		bwn_intr_pmq(mac);
8596	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8597		bwn_intr_noise(mac);
8598
8599	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8600		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8601			bwn_dma_rx(mac->mac_method.dma.rx);
8602			rx = 1;
8603		}
8604	} else
8605		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8606
8607	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8608	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8609	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8610	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8611	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8612
8613	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8614		bwn_intr_txeof(mac);
8615		tx = 1;
8616	}
8617
8618	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8619
8620	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8621		int evt = BWN_LED_EVENT_NONE;
8622
8623		if (tx && rx) {
8624			if (sc->sc_rx_rate > sc->sc_tx_rate)
8625				evt = BWN_LED_EVENT_RX;
8626			else
8627				evt = BWN_LED_EVENT_TX;
8628		} else if (tx) {
8629			evt = BWN_LED_EVENT_TX;
8630		} else if (rx) {
8631			evt = BWN_LED_EVENT_RX;
8632		} else if (rx == 0) {
8633			evt = BWN_LED_EVENT_POLL;
8634		}
8635
8636		if (evt != BWN_LED_EVENT_NONE)
8637			bwn_led_event(mac, evt);
8638       }
8639
8640	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8641		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8642			bwn_start_locked(ifp);
8643	}
8644
8645	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8646	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8647
8648	BWN_UNLOCK(sc);
8649}
8650
8651static void
8652bwn_restart(struct bwn_mac *mac, const char *msg)
8653{
8654	struct bwn_softc *sc = mac->mac_sc;
8655	struct ifnet *ifp = sc->sc_ifp;
8656	struct ieee80211com *ic = ifp->if_l2com;
8657
8658	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8659		return;
8660
8661	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8662	ieee80211_runtask(ic, &mac->mac_hwreset);
8663}
8664
8665static void
8666bwn_intr_ucode_debug(struct bwn_mac *mac)
8667{
8668	struct bwn_softc *sc = mac->mac_sc;
8669	uint16_t reason;
8670
8671	if (mac->mac_fw.opensource == 0)
8672		return;
8673
8674	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8675	switch (reason) {
8676	case BWN_DEBUGINTR_PANIC:
8677		bwn_handle_fwpanic(mac);
8678		break;
8679	case BWN_DEBUGINTR_DUMP_SHM:
8680		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8681		break;
8682	case BWN_DEBUGINTR_DUMP_REGS:
8683		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8684		break;
8685	case BWN_DEBUGINTR_MARKER:
8686		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8687		break;
8688	default:
8689		device_printf(sc->sc_dev,
8690		    "ucode debug unknown reason: %#x\n", reason);
8691	}
8692
8693	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8694	    BWN_DEBUGINTR_ACK);
8695}
8696
8697static void
8698bwn_intr_tbtt_indication(struct bwn_mac *mac)
8699{
8700	struct bwn_softc *sc = mac->mac_sc;
8701	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8702
8703	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8704		bwn_psctl(mac, 0);
8705	if (ic->ic_opmode == IEEE80211_M_IBSS)
8706		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8707}
8708
8709static void
8710bwn_intr_atim_end(struct bwn_mac *mac)
8711{
8712
8713	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8714		BWN_WRITE_4(mac, BWN_MACCMD,
8715		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8716		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8717	}
8718}
8719
8720static void
8721bwn_intr_beacon(struct bwn_mac *mac)
8722{
8723	struct bwn_softc *sc = mac->mac_sc;
8724	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8725	uint32_t cmd, beacon0, beacon1;
8726
8727	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8728	    ic->ic_opmode == IEEE80211_M_MBSS)
8729		return;
8730
8731	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8732
8733	cmd = BWN_READ_4(mac, BWN_MACCMD);
8734	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8735	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8736
8737	if (beacon0 && beacon1) {
8738		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8739		mac->mac_intr_mask |= BWN_INTR_BEACON;
8740		return;
8741	}
8742
8743	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8744		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8745		bwn_load_beacon0(mac);
8746		bwn_load_beacon1(mac);
8747		cmd = BWN_READ_4(mac, BWN_MACCMD);
8748		cmd |= BWN_MACCMD_BEACON0_VALID;
8749		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8750	} else {
8751		if (!beacon0) {
8752			bwn_load_beacon0(mac);
8753			cmd = BWN_READ_4(mac, BWN_MACCMD);
8754			cmd |= BWN_MACCMD_BEACON0_VALID;
8755			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8756		} else if (!beacon1) {
8757			bwn_load_beacon1(mac);
8758			cmd = BWN_READ_4(mac, BWN_MACCMD);
8759			cmd |= BWN_MACCMD_BEACON1_VALID;
8760			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8761		}
8762	}
8763}
8764
8765static void
8766bwn_intr_pmq(struct bwn_mac *mac)
8767{
8768	uint32_t tmp;
8769
8770	while (1) {
8771		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8772		if (!(tmp & 0x00000008))
8773			break;
8774	}
8775	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8776}
8777
8778static void
8779bwn_intr_noise(struct bwn_mac *mac)
8780{
8781	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8782	uint16_t tmp;
8783	uint8_t noise[4];
8784	uint8_t i, j;
8785	int32_t average;
8786
8787	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8788		return;
8789
8790	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8791	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8792	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8793	    noise[3] == 0x7f)
8794		goto new;
8795
8796	KASSERT(mac->mac_noise.noi_nsamples < 8,
8797	    ("%s:%d: fail", __func__, __LINE__));
8798	i = mac->mac_noise.noi_nsamples;
8799	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8800	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8801	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8802	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8803	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8804	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8805	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8806	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8807	mac->mac_noise.noi_nsamples++;
8808	if (mac->mac_noise.noi_nsamples == 8) {
8809		average = 0;
8810		for (i = 0; i < 8; i++) {
8811			for (j = 0; j < 4; j++)
8812				average += mac->mac_noise.noi_samples[i][j];
8813		}
8814		average = (((average / 32) * 125) + 64) / 128;
8815		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8816		if (tmp >= 8)
8817			average += 2;
8818		else
8819			average -= 25;
8820		average -= (tmp == 8) ? 72 : 48;
8821
8822		mac->mac_stats.link_noise = average;
8823		mac->mac_noise.noi_running = 0;
8824		return;
8825	}
8826new:
8827	bwn_noise_gensample(mac);
8828}
8829
8830static int
8831bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8832{
8833	struct bwn_mac *mac = prq->prq_mac;
8834	struct bwn_softc *sc = mac->mac_sc;
8835	unsigned int i;
8836
8837	BWN_ASSERT_LOCKED(sc);
8838
8839	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8840		return (0);
8841
8842	for (i = 0; i < 5000; i++) {
8843		if (bwn_pio_rxeof(prq) == 0)
8844			break;
8845	}
8846	if (i >= 5000)
8847		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8848	return ((i > 0) ? 1 : 0);
8849}
8850
8851static void
8852bwn_dma_rx(struct bwn_dma_ring *dr)
8853{
8854	int slot, curslot;
8855
8856	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8857	curslot = dr->get_curslot(dr);
8858	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8859	    ("%s:%d: fail", __func__, __LINE__));
8860
8861	slot = dr->dr_curslot;
8862	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8863		bwn_dma_rxeof(dr, &slot);
8864
8865	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8866	    BUS_DMASYNC_PREWRITE);
8867
8868	dr->set_curslot(dr, slot);
8869	dr->dr_curslot = slot;
8870}
8871
8872static void
8873bwn_intr_txeof(struct bwn_mac *mac)
8874{
8875	struct bwn_txstatus stat;
8876	uint32_t stat0, stat1;
8877	uint16_t tmp;
8878
8879	BWN_ASSERT_LOCKED(mac->mac_sc);
8880
8881	while (1) {
8882		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8883		if (!(stat0 & 0x00000001))
8884			break;
8885		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8886
8887		stat.cookie = (stat0 >> 16);
8888		stat.seq = (stat1 & 0x0000ffff);
8889		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8890		tmp = (stat0 & 0x0000ffff);
8891		stat.framecnt = ((tmp & 0xf000) >> 12);
8892		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8893		stat.sreason = ((tmp & 0x001c) >> 2);
8894		stat.pm = (tmp & 0x0080) ? 1 : 0;
8895		stat.im = (tmp & 0x0040) ? 1 : 0;
8896		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8897		stat.ack = (tmp & 0x0002) ? 1 : 0;
8898
8899		bwn_handle_txeof(mac, &stat);
8900	}
8901}
8902
8903static void
8904bwn_hwreset(void *arg, int npending)
8905{
8906	struct bwn_mac *mac = arg;
8907	struct bwn_softc *sc = mac->mac_sc;
8908	int error = 0;
8909	int prev_status;
8910
8911	BWN_LOCK(sc);
8912
8913	prev_status = mac->mac_status;
8914	if (prev_status >= BWN_MAC_STATUS_STARTED)
8915		bwn_core_stop(mac);
8916	if (prev_status >= BWN_MAC_STATUS_INITED)
8917		bwn_core_exit(mac);
8918
8919	if (prev_status >= BWN_MAC_STATUS_INITED) {
8920		error = bwn_core_init(mac);
8921		if (error)
8922			goto out;
8923	}
8924	if (prev_status >= BWN_MAC_STATUS_STARTED)
8925		bwn_core_start(mac);
8926out:
8927	if (error) {
8928		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8929		sc->sc_curmac = NULL;
8930	}
8931	BWN_UNLOCK(sc);
8932}
8933
8934static void
8935bwn_handle_fwpanic(struct bwn_mac *mac)
8936{
8937	struct bwn_softc *sc = mac->mac_sc;
8938	uint16_t reason;
8939
8940	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8941	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8942
8943	if (reason == BWN_FWPANIC_RESTART)
8944		bwn_restart(mac, "ucode panic");
8945}
8946
8947static void
8948bwn_load_beacon0(struct bwn_mac *mac)
8949{
8950
8951	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8952}
8953
8954static void
8955bwn_load_beacon1(struct bwn_mac *mac)
8956{
8957
8958	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8959}
8960
8961static uint32_t
8962bwn_jssi_read(struct bwn_mac *mac)
8963{
8964	uint32_t val = 0;
8965
8966	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8967	val <<= 16;
8968	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8969
8970	return (val);
8971}
8972
8973static void
8974bwn_noise_gensample(struct bwn_mac *mac)
8975{
8976	uint32_t jssi = 0x7f7f7f7f;
8977
8978	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8979	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8980	BWN_WRITE_4(mac, BWN_MACCMD,
8981	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8982}
8983
8984static int
8985bwn_dma_freeslot(struct bwn_dma_ring *dr)
8986{
8987	struct bwn_mac *mac = dr->dr_mac;
8988
8989	BWN_ASSERT_LOCKED(mac->mac_sc);
8990
8991	return (dr->dr_numslots - dr->dr_usedslot);
8992}
8993
8994static int
8995bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8996{
8997	struct bwn_mac *mac = dr->dr_mac;
8998
8999	BWN_ASSERT_LOCKED(mac->mac_sc);
9000
9001	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
9002	    ("%s:%d: fail", __func__, __LINE__));
9003	if (slot == dr->dr_numslots - 1)
9004		return (0);
9005	return (slot + 1);
9006}
9007
9008static void
9009bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
9010{
9011	struct bwn_mac *mac = dr->dr_mac;
9012	struct bwn_softc *sc = mac->mac_sc;
9013	struct bwn_dma *dma = &mac->mac_method.dma;
9014	struct bwn_dmadesc_generic *desc;
9015	struct bwn_dmadesc_meta *meta;
9016	struct bwn_rxhdr4 *rxhdr;
9017	struct ifnet *ifp = sc->sc_ifp;
9018	struct mbuf *m;
9019	uint32_t macstat;
9020	int32_t tmp;
9021	int cnt = 0;
9022	uint16_t len;
9023
9024	dr->getdesc(dr, *slot, &desc, &meta);
9025
9026	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9027	m = meta->mt_m;
9028
9029	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9030		ifp->if_ierrors++;
9031		return;
9032	}
9033
9034	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9035	len = le16toh(rxhdr->frame_len);
9036	if (len <= 0) {
9037		ifp->if_ierrors++;
9038		return;
9039	}
9040	if (bwn_dma_check_redzone(dr, m)) {
9041		device_printf(sc->sc_dev, "redzone error.\n");
9042		bwn_dma_set_redzone(dr, m);
9043		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9044		    BUS_DMASYNC_PREWRITE);
9045		return;
9046	}
9047	if (len > dr->dr_rx_bufsize) {
9048		tmp = len;
9049		while (1) {
9050			dr->getdesc(dr, *slot, &desc, &meta);
9051			bwn_dma_set_redzone(dr, meta->mt_m);
9052			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9053			    BUS_DMASYNC_PREWRITE);
9054			*slot = bwn_dma_nextslot(dr, *slot);
9055			cnt++;
9056			tmp -= dr->dr_rx_bufsize;
9057			if (tmp <= 0)
9058				break;
9059		}
9060		device_printf(sc->sc_dev, "too small buffer "
9061		       "(len %u buffer %u dropped %d)\n",
9062		       len, dr->dr_rx_bufsize, cnt);
9063		return;
9064	}
9065	macstat = le32toh(rxhdr->mac_status);
9066	if (macstat & BWN_RX_MAC_FCSERR) {
9067		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9068			device_printf(sc->sc_dev, "RX drop\n");
9069			return;
9070		}
9071	}
9072
9073	m->m_pkthdr.rcvif = ifp;
9074	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9075	m_adj(m, dr->dr_frameoffset);
9076
9077	bwn_rxeof(dr->dr_mac, m, rxhdr);
9078}
9079
9080static void
9081bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9082{
9083	struct bwn_dma_ring *dr;
9084	struct bwn_dmadesc_generic *desc;
9085	struct bwn_dmadesc_meta *meta;
9086	struct bwn_node *bn;
9087	struct bwn_pio_txqueue *tq;
9088	struct bwn_pio_txpkt *tp = NULL;
9089	struct bwn_softc *sc = mac->mac_sc;
9090	struct ieee80211_node *ni;
9091	int slot;
9092
9093	BWN_ASSERT_LOCKED(mac->mac_sc);
9094
9095	if (status->im)
9096		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9097	if (status->ampdu)
9098		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9099	if (status->rtscnt) {
9100		if (status->rtscnt == 0xf)
9101			device_printf(sc->sc_dev, "TODO: RTS fail\n");
9102		else
9103			device_printf(sc->sc_dev, "TODO: RTS ok\n");
9104	}
9105
9106	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9107		if (status->ack) {
9108			dr = bwn_dma_parse_cookie(mac, status,
9109			    status->cookie, &slot);
9110			if (dr == NULL) {
9111				device_printf(sc->sc_dev,
9112				    "failed to parse cookie\n");
9113				return;
9114			}
9115			while (1) {
9116				dr->getdesc(dr, slot, &desc, &meta);
9117				if (meta->mt_islast) {
9118					ni = meta->mt_ni;
9119					bn = (struct bwn_node *)ni;
9120					ieee80211_amrr_tx_complete(&bn->bn_amn,
9121					    status->ack, 0);
9122					break;
9123				}
9124				slot = bwn_dma_nextslot(dr, slot);
9125			}
9126		}
9127		bwn_dma_handle_txeof(mac, status);
9128	} else {
9129		if (status->ack) {
9130			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9131			if (tq == NULL) {
9132				device_printf(sc->sc_dev,
9133				    "failed to parse cookie\n");
9134				return;
9135			}
9136			ni = tp->tp_ni;
9137			bn = (struct bwn_node *)ni;
9138			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9139		}
9140		bwn_pio_handle_txeof(mac, status);
9141	}
9142
9143	bwn_phy_txpower_check(mac, 0);
9144}
9145
9146static uint8_t
9147bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9148{
9149	struct bwn_mac *mac = prq->prq_mac;
9150	struct bwn_softc *sc = mac->mac_sc;
9151	struct bwn_rxhdr4 rxhdr;
9152	struct ifnet *ifp = sc->sc_ifp;
9153	struct mbuf *m;
9154	uint32_t ctl32, macstat, v32;
9155	unsigned int i, padding;
9156	uint16_t ctl16, len, v16;
9157	unsigned char *mp;
9158	char *data;
9159
9160	memset(&rxhdr, 0, sizeof(rxhdr));
9161
9162	if (prq->prq_rev >= 8) {
9163		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9164		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9165			return (0);
9166		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9167		    BWN_PIO8_RXCTL_FRAMEREADY);
9168		for (i = 0; i < 10; i++) {
9169			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9170			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9171				goto ready;
9172			DELAY(10);
9173		}
9174	} else {
9175		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9176		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9177			return (0);
9178		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9179		    BWN_PIO_RXCTL_FRAMEREADY);
9180		for (i = 0; i < 10; i++) {
9181			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9182			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9183				goto ready;
9184			DELAY(10);
9185		}
9186	}
9187	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9188	return (1);
9189ready:
9190	if (prq->prq_rev >= 8)
9191		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9192		    prq->prq_base + BWN_PIO8_RXDATA);
9193	else
9194		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9195		    prq->prq_base + BWN_PIO_RXDATA);
9196	len = le16toh(rxhdr.frame_len);
9197	if (len > 0x700) {
9198		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9199		goto error;
9200	}
9201	if (len == 0) {
9202		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9203		goto error;
9204	}
9205
9206	macstat = le32toh(rxhdr.mac_status);
9207	if (macstat & BWN_RX_MAC_FCSERR) {
9208		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9209			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9210			goto error;
9211		}
9212	}
9213
9214	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9215	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9216	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9217	if (m == NULL) {
9218		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9219		goto error;
9220	}
9221	mp = mtod(m, unsigned char *);
9222	if (prq->prq_rev >= 8) {
9223		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9224		    prq->prq_base + BWN_PIO8_RXDATA);
9225		if (len & 3) {
9226			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9227			data = &(mp[len + padding - 1]);
9228			switch (len & 3) {
9229			case 3:
9230				*data = (v32 >> 16);
9231				data--;
9232			case 2:
9233				*data = (v32 >> 8);
9234				data--;
9235			case 1:
9236				*data = v32;
9237			}
9238		}
9239	} else {
9240		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9241		    prq->prq_base + BWN_PIO_RXDATA);
9242		if (len & 1) {
9243			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9244			mp[len + padding - 1] = v16;
9245		}
9246	}
9247
9248	m->m_pkthdr.rcvif = ifp;
9249	m->m_len = m->m_pkthdr.len = len + padding;
9250
9251	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9252
9253	return (1);
9254error:
9255	if (prq->prq_rev >= 8)
9256		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9257		    BWN_PIO8_RXCTL_DATAREADY);
9258	else
9259		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9260	return (1);
9261}
9262
9263static int
9264bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9265    struct bwn_dmadesc_meta *meta, int init)
9266{
9267	struct bwn_mac *mac = dr->dr_mac;
9268	struct bwn_dma *dma = &mac->mac_method.dma;
9269	struct bwn_rxhdr4 *hdr;
9270	bus_dmamap_t map;
9271	bus_addr_t paddr;
9272	struct mbuf *m;
9273	int error;
9274
9275	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9276	if (m == NULL) {
9277		error = ENOBUFS;
9278
9279		/*
9280		 * If the NIC is up and running, we need to:
9281		 * - Clear RX buffer's header.
9282		 * - Restore RX descriptor settings.
9283		 */
9284		if (init)
9285			return (error);
9286		else
9287			goto back;
9288	}
9289	m->m_len = m->m_pkthdr.len = MCLBYTES;
9290
9291	bwn_dma_set_redzone(dr, m);
9292
9293	/*
9294	 * Try to load RX buf into temporary DMA map
9295	 */
9296	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9297	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9298	if (error) {
9299		m_freem(m);
9300
9301		/*
9302		 * See the comment above
9303		 */
9304		if (init)
9305			return (error);
9306		else
9307			goto back;
9308	}
9309
9310	if (!init)
9311		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9312	meta->mt_m = m;
9313	meta->mt_paddr = paddr;
9314
9315	/*
9316	 * Swap RX buf's DMA map with the loaded temporary one
9317	 */
9318	map = meta->mt_dmap;
9319	meta->mt_dmap = dr->dr_spare_dmap;
9320	dr->dr_spare_dmap = map;
9321
9322back:
9323	/*
9324	 * Clear RX buf header
9325	 */
9326	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9327	bzero(hdr, sizeof(*hdr));
9328	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9329	    BUS_DMASYNC_PREWRITE);
9330
9331	/*
9332	 * Setup RX buf descriptor
9333	 */
9334	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9335	    sizeof(*hdr), 0, 0, 0);
9336	return (error);
9337}
9338
9339static void
9340bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9341		 bus_size_t mapsz __unused, int error)
9342{
9343
9344	if (!error) {
9345		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9346		*((bus_addr_t *)arg) = seg->ds_addr;
9347	}
9348}
9349
9350static int
9351bwn_hwrate2ieeerate(int rate)
9352{
9353
9354	switch (rate) {
9355	case BWN_CCK_RATE_1MB:
9356		return (2);
9357	case BWN_CCK_RATE_2MB:
9358		return (4);
9359	case BWN_CCK_RATE_5MB:
9360		return (11);
9361	case BWN_CCK_RATE_11MB:
9362		return (22);
9363	case BWN_OFDM_RATE_6MB:
9364		return (12);
9365	case BWN_OFDM_RATE_9MB:
9366		return (18);
9367	case BWN_OFDM_RATE_12MB:
9368		return (24);
9369	case BWN_OFDM_RATE_18MB:
9370		return (36);
9371	case BWN_OFDM_RATE_24MB:
9372		return (48);
9373	case BWN_OFDM_RATE_36MB:
9374		return (72);
9375	case BWN_OFDM_RATE_48MB:
9376		return (96);
9377	case BWN_OFDM_RATE_54MB:
9378		return (108);
9379	default:
9380		printf("Ooops\n");
9381		return (0);
9382	}
9383}
9384
9385static void
9386bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9387{
9388	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9389	struct bwn_plcp6 *plcp;
9390	struct bwn_softc *sc = mac->mac_sc;
9391	struct ieee80211_frame_min *wh;
9392	struct ieee80211_node *ni;
9393	struct ifnet *ifp = sc->sc_ifp;
9394	struct ieee80211com *ic = ifp->if_l2com;
9395	uint32_t macstat;
9396	int padding, rate, rssi, noise, type;
9397	uint16_t phytype, phystat0, phystat3, chanstat;
9398	unsigned char *mp = mtod(m, unsigned char *);
9399
9400	BWN_ASSERT_LOCKED(sc);
9401
9402	phystat0 = le16toh(rxhdr->phy_status0);
9403	phystat3 = le16toh(rxhdr->phy_status3);
9404	macstat = le32toh(rxhdr->mac_status);
9405	chanstat = le16toh(rxhdr->channel);
9406	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9407
9408	if (macstat & BWN_RX_MAC_FCSERR)
9409		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9410	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9411		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9412	if (phystat0 & BWN_RX_PHYST0_SHORTPRMBL)
9413		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_SHORTPRE\n");
9414	if (macstat & BWN_RX_MAC_DECERR)
9415		goto drop;
9416
9417	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9418	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9419		device_printf(sc->sc_dev, "RX: Packet size underrun (1)\n");
9420		goto drop;
9421	}
9422	plcp = (struct bwn_plcp6 *)(mp + padding);
9423	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9424	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9425		device_printf(sc->sc_dev, "RX: Packet size underrun (2)\n");
9426		goto drop;
9427	}
9428	wh = mtod(m, struct ieee80211_frame_min *);
9429
9430	if (macstat & BWN_RX_MAC_DEC)
9431		device_printf(sc->sc_dev, "TODO: BWN_RX_MAC_DEC\n");
9432
9433	/* XXX calculating RSSI & noise & antenna */
9434
9435	if (phystat0 & BWN_RX_PHYST0_OFDM)
9436		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9437		    phytype == BWN_PHYTYPE_A);
9438	else
9439		rate = bwn_plcp_get_cckrate(mac, plcp);
9440	if (rate == -1) {
9441		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9442			goto drop;
9443	}
9444	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9445
9446	/* RX radio tap */
9447	if (ieee80211_radiotap_active(ic))
9448		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9449	m_adj(m, -IEEE80211_CRC_LEN);
9450
9451	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9452	noise = mac->mac_stats.link_noise;
9453
9454	BWN_UNLOCK(sc);
9455
9456	ni = ieee80211_find_rxnode(ic, wh);
9457	if (ni != NULL) {
9458		type = ieee80211_input(ni, m, rssi, noise);
9459		ieee80211_free_node(ni);
9460	} else
9461		type = ieee80211_input_all(ic, m, rssi, noise);
9462
9463	BWN_LOCK(sc);
9464	return;
9465drop:
9466	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9467}
9468
9469static void
9470bwn_dma_handle_txeof(struct bwn_mac *mac,
9471    const struct bwn_txstatus *status)
9472{
9473	struct bwn_dma *dma = &mac->mac_method.dma;
9474	struct bwn_dma_ring *dr;
9475	struct bwn_dmadesc_generic *desc;
9476	struct bwn_dmadesc_meta *meta;
9477	struct bwn_softc *sc = mac->mac_sc;
9478	struct ieee80211_node *ni;
9479	struct ifnet *ifp = sc->sc_ifp;
9480	struct mbuf *m;
9481	int slot;
9482
9483	BWN_ASSERT_LOCKED(sc);
9484
9485	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9486	if (dr == NULL) {
9487		device_printf(sc->sc_dev, "failed to parse cookie\n");
9488		return;
9489	}
9490	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9491
9492	while (1) {
9493		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9494		    ("%s:%d: fail", __func__, __LINE__));
9495		dr->getdesc(dr, slot, &desc, &meta);
9496
9497		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9498			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9499		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9500			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9501
9502		if (meta->mt_islast) {
9503			KASSERT(meta->mt_m != NULL,
9504			    ("%s:%d: fail", __func__, __LINE__));
9505
9506			ni = meta->mt_ni;
9507			m = meta->mt_m;
9508			if (ni != NULL) {
9509				/*
9510				 * Do any tx complete callback. Note this must
9511				 * be done before releasing the node reference.
9512				 */
9513				if (m->m_flags & M_TXCB)
9514					ieee80211_process_callback(ni, m, 0);
9515				ieee80211_free_node(ni);
9516				meta->mt_ni = NULL;
9517			}
9518			m_freem(m);
9519			meta->mt_m = NULL;
9520		} else {
9521			KASSERT(meta->mt_m == NULL,
9522			    ("%s:%d: fail", __func__, __LINE__));
9523		}
9524
9525		dr->dr_usedslot--;
9526		if (meta->mt_islast) {
9527			ifp->if_opackets++;
9528			break;
9529		}
9530		slot = bwn_dma_nextslot(dr, slot);
9531	}
9532	sc->sc_watchdog_timer = 0;
9533	if (dr->dr_stop) {
9534		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9535		    ("%s:%d: fail", __func__, __LINE__));
9536		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9537		dr->dr_stop = 0;
9538	}
9539}
9540
9541static void
9542bwn_pio_handle_txeof(struct bwn_mac *mac,
9543    const struct bwn_txstatus *status)
9544{
9545	struct bwn_pio_txqueue *tq;
9546	struct bwn_pio_txpkt *tp = NULL;
9547	struct bwn_softc *sc = mac->mac_sc;
9548	struct ifnet *ifp = sc->sc_ifp;
9549
9550	BWN_ASSERT_LOCKED(sc);
9551
9552	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9553	if (tq == NULL)
9554		return;
9555
9556	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9557	tq->tq_free++;
9558
9559	if (tp->tp_ni != NULL) {
9560		/*
9561		 * Do any tx complete callback.  Note this must
9562		 * be done before releasing the node reference.
9563		 */
9564		if (tp->tp_m->m_flags & M_TXCB)
9565			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9566		ieee80211_free_node(tp->tp_ni);
9567		tp->tp_ni = NULL;
9568	}
9569	m_freem(tp->tp_m);
9570	tp->tp_m = NULL;
9571	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9572
9573	ifp->if_opackets++;
9574
9575	sc->sc_watchdog_timer = 0;
9576	if (tq->tq_stop) {
9577		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9578		tq->tq_stop = 0;
9579	}
9580}
9581
9582static void
9583bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9584{
9585	struct bwn_softc *sc = mac->mac_sc;
9586	struct bwn_phy *phy = &mac->mac_phy;
9587	struct ifnet *ifp = sc->sc_ifp;
9588	struct ieee80211com *ic = ifp->if_l2com;
9589	struct siba_softc *siba = mac->mac_sd->sd_bus;
9590	unsigned long now;
9591	int result;
9592
9593	BWN_GETTIME(now);
9594
9595	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9596		return;
9597	phy->nexttime = now + 2 * 1000;
9598
9599	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9600	    siba->siba_board_type == SIBA_BOARD_BU4306)
9601		return;
9602
9603	if (phy->recalc_txpwr != NULL) {
9604		result = phy->recalc_txpwr(mac,
9605		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9606		if (result == BWN_TXPWR_RES_DONE)
9607			return;
9608		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9609		    ("%s: fail", __func__));
9610		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9611
9612		ieee80211_runtask(ic, &mac->mac_txpower);
9613	}
9614}
9615
9616static uint16_t
9617bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9618{
9619
9620	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9621}
9622
9623static uint32_t
9624bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9625{
9626
9627	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9628}
9629
9630static void
9631bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9632{
9633
9634	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9635}
9636
9637static void
9638bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9639{
9640
9641	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9642}
9643
9644static int
9645bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9646{
9647
9648	switch (rate) {
9649	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9650	case 12:
9651		return (BWN_OFDM_RATE_6MB);
9652	case 18:
9653		return (BWN_OFDM_RATE_9MB);
9654	case 24:
9655		return (BWN_OFDM_RATE_12MB);
9656	case 36:
9657		return (BWN_OFDM_RATE_18MB);
9658	case 48:
9659		return (BWN_OFDM_RATE_24MB);
9660	case 72:
9661		return (BWN_OFDM_RATE_36MB);
9662	case 96:
9663		return (BWN_OFDM_RATE_48MB);
9664	case 108:
9665		return (BWN_OFDM_RATE_54MB);
9666	/* CCK rates (NB: not IEEE std, device-specific) */
9667	case 2:
9668		return (BWN_CCK_RATE_1MB);
9669	case 4:
9670		return (BWN_CCK_RATE_2MB);
9671	case 11:
9672		return (BWN_CCK_RATE_5MB);
9673	case 22:
9674		return (BWN_CCK_RATE_11MB);
9675	}
9676
9677	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9678	return (BWN_CCK_RATE_1MB);
9679}
9680
9681static int
9682bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9683    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9684{
9685	const struct bwn_phy *phy = &mac->mac_phy;
9686	struct bwn_softc *sc = mac->mac_sc;
9687	struct ieee80211_frame *wh;
9688	struct ieee80211_frame *protwh;
9689	struct ieee80211_frame_cts *cts;
9690	struct ieee80211_frame_rts *rts;
9691	const struct ieee80211_txparam *tp;
9692	struct ieee80211vap *vap = ni->ni_vap;
9693	struct ifnet *ifp = sc->sc_ifp;
9694	struct ieee80211com *ic = ifp->if_l2com;
9695	struct mbuf *mprot;
9696	unsigned int len;
9697	uint32_t macctl = 0;
9698	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9699	uint16_t phyctl = 0;
9700	uint8_t rate, rate_fb;
9701
9702	wh = mtod(m, struct ieee80211_frame *);
9703	memset(txhdr, 0, sizeof(*txhdr));
9704
9705	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9706	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9707	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9708
9709	/*
9710	 * Find TX rate
9711	 */
9712	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9713	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9714		rate = rate_fb = tp->mgmtrate;
9715	else if (ismcast)
9716		rate = rate_fb = tp->mcastrate;
9717	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9718		rate = rate_fb = tp->ucastrate;
9719	else {
9720		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9721		rate = ni->ni_txrate;
9722
9723		if (rix > 0)
9724			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9725			    IEEE80211_RATE_VAL;
9726		else
9727			rate_fb = rate;
9728	}
9729
9730	sc->sc_tx_rate = rate;
9731
9732	rate = bwn_ieeerate2hwrate(sc, rate);
9733	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9734
9735	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9736	    bwn_plcp_getcck(rate);
9737	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9738	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9739
9740	if ((rate_fb == rate) ||
9741	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9742	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9743		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9744	else
9745		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9746		    m->m_pkthdr.len, rate, isshort);
9747
9748	/* XXX TX encryption */
9749	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9750	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9751	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9752	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9753	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9754	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9755
9756	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9757	    BWN_TX_EFT_FB_CCK;
9758	txhdr->chan = phy->chan;
9759	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9760	    BWN_TX_PHY_ENC_CCK;
9761	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9762	     rate == BWN_CCK_RATE_11MB))
9763		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9764
9765	/* XXX TX antenna selection */
9766
9767	switch (bwn_antenna_sanitize(mac, 0)) {
9768	case 0:
9769		phyctl |= BWN_TX_PHY_ANT01AUTO;
9770		break;
9771	case 1:
9772		phyctl |= BWN_TX_PHY_ANT0;
9773		break;
9774	case 2:
9775		phyctl |= BWN_TX_PHY_ANT1;
9776		break;
9777	case 3:
9778		phyctl |= BWN_TX_PHY_ANT2;
9779		break;
9780	case 4:
9781		phyctl |= BWN_TX_PHY_ANT3;
9782		break;
9783	default:
9784		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9785	}
9786
9787	if (!ismcast)
9788		macctl |= BWN_TX_MAC_ACK;
9789
9790	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9791	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9792	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9793		macctl |= BWN_TX_MAC_LONGFRAME;
9794
9795	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9796		/* XXX RTS rate is always 1MB??? */
9797		rts_rate = BWN_CCK_RATE_1MB;
9798		rts_rate_fb = bwn_get_fbrate(rts_rate);
9799
9800		protdur = ieee80211_compute_duration(ic->ic_rt,
9801		    m->m_pkthdr.len, rate, isshort) +
9802		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9803
9804		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9805			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9806			    (txhdr->body.old.rts_frame) :
9807			    (txhdr->body.new.rts_frame));
9808			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9809			    protdur);
9810			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9811			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9812			    mprot->m_pkthdr.len);
9813			m_freem(mprot);
9814			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9815			len = sizeof(struct ieee80211_frame_cts);
9816		} else {
9817			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9818			    (txhdr->body.old.rts_frame) :
9819			    (txhdr->body.new.rts_frame));
9820			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9821			    isshort);
9822			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9823			    wh->i_addr2, protdur);
9824			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9825			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9826			    mprot->m_pkthdr.len);
9827			m_freem(mprot);
9828			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9829			len = sizeof(struct ieee80211_frame_rts);
9830		}
9831		len += IEEE80211_CRC_LEN;
9832		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9833		    &txhdr->body.old.rts_plcp :
9834		    &txhdr->body.new.rts_plcp), len, rts_rate);
9835		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9836		    rts_rate_fb);
9837
9838		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9839		    (&txhdr->body.old.rts_frame) :
9840		    (&txhdr->body.new.rts_frame));
9841		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9842
9843		if (BWN_ISOFDMRATE(rts_rate)) {
9844			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9845			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9846		} else {
9847			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9848			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9849		}
9850		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9851		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9852	}
9853
9854	if (BWN_ISOLDFMT(mac))
9855		txhdr->body.old.cookie = htole16(cookie);
9856	else
9857		txhdr->body.new.cookie = htole16(cookie);
9858
9859	txhdr->macctl = htole32(macctl);
9860	txhdr->phyctl = htole16(phyctl);
9861
9862	/*
9863	 * TX radio tap
9864	 */
9865	if (ieee80211_radiotap_active_vap(vap)) {
9866		sc->sc_tx_th.wt_flags = 0;
9867		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9868			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9869		if (isshort &&
9870		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9871		     rate == BWN_CCK_RATE_11MB))
9872			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9873		sc->sc_tx_th.wt_rate = rate;
9874
9875		ieee80211_radiotap_tx(vap, m);
9876	}
9877
9878	return (0);
9879}
9880
9881static void
9882bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9883    const uint8_t rate)
9884{
9885	uint32_t d, plen;
9886	uint8_t *raw = plcp->o.raw;
9887
9888	if (BWN_ISOFDMRATE(rate)) {
9889		d = bwn_plcp_getofdm(rate);
9890		KASSERT(!(octets & 0xf000),
9891		    ("%s:%d: fail", __func__, __LINE__));
9892		d |= (octets << 5);
9893		plcp->o.data = htole32(d);
9894	} else {
9895		plen = octets * 16 / rate;
9896		if ((octets * 16 % rate) > 0) {
9897			plen++;
9898			if ((rate == BWN_CCK_RATE_11MB)
9899			    && ((octets * 8 % 11) < 4)) {
9900				raw[1] = 0x84;
9901			} else
9902				raw[1] = 0x04;
9903		} else
9904			raw[1] = 0x04;
9905		plcp->o.data |= htole32(plen << 16);
9906		raw[0] = bwn_plcp_getcck(rate);
9907	}
9908}
9909
9910static uint8_t
9911bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9912{
9913	uint8_t mask;
9914
9915	if (n == 0)
9916		return (0);
9917	if (mac->mac_phy.gmode)
9918		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9919	else
9920		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9921	if (!(mask & (1 << (n - 1))))
9922		return (0);
9923	return (n);
9924}
9925
9926static uint8_t
9927bwn_get_fbrate(uint8_t bitrate)
9928{
9929	switch (bitrate) {
9930	case BWN_CCK_RATE_1MB:
9931		return (BWN_CCK_RATE_1MB);
9932	case BWN_CCK_RATE_2MB:
9933		return (BWN_CCK_RATE_1MB);
9934	case BWN_CCK_RATE_5MB:
9935		return (BWN_CCK_RATE_2MB);
9936	case BWN_CCK_RATE_11MB:
9937		return (BWN_CCK_RATE_5MB);
9938	case BWN_OFDM_RATE_6MB:
9939		return (BWN_CCK_RATE_5MB);
9940	case BWN_OFDM_RATE_9MB:
9941		return (BWN_OFDM_RATE_6MB);
9942	case BWN_OFDM_RATE_12MB:
9943		return (BWN_OFDM_RATE_9MB);
9944	case BWN_OFDM_RATE_18MB:
9945		return (BWN_OFDM_RATE_12MB);
9946	case BWN_OFDM_RATE_24MB:
9947		return (BWN_OFDM_RATE_18MB);
9948	case BWN_OFDM_RATE_36MB:
9949		return (BWN_OFDM_RATE_24MB);
9950	case BWN_OFDM_RATE_48MB:
9951		return (BWN_OFDM_RATE_36MB);
9952	case BWN_OFDM_RATE_54MB:
9953		return (BWN_OFDM_RATE_48MB);
9954	}
9955	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9956	return (0);
9957}
9958
9959static uint32_t
9960bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9961    uint32_t ctl, const void *_data, int len)
9962{
9963	uint32_t value = 0;
9964	const uint8_t *data = _data;
9965
9966	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9967	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9968	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9969
9970	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9971	    tq->tq_base + BWN_PIO8_TXDATA);
9972	if (len & 3) {
9973		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9974		    BWN_PIO8_TXCTL_24_31);
9975		data = &(data[len - 1]);
9976		switch (len & 3) {
9977		case 3:
9978			ctl |= BWN_PIO8_TXCTL_16_23;
9979			value |= (uint32_t)(*data) << 16;
9980			data--;
9981		case 2:
9982			ctl |= BWN_PIO8_TXCTL_8_15;
9983			value |= (uint32_t)(*data) << 8;
9984			data--;
9985		case 1:
9986			value |= (uint32_t)(*data);
9987		}
9988		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9989		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9990	}
9991
9992	return (ctl);
9993}
9994
9995static void
9996bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9997    uint16_t offset, uint32_t value)
9998{
9999
10000	BWN_WRITE_4(mac, tq->tq_base + offset, value);
10001}
10002
10003static uint16_t
10004bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10005    uint16_t ctl, const void *_data, int len)
10006{
10007	const uint8_t *data = _data;
10008
10009	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10010	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10011
10012	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10013	    tq->tq_base + BWN_PIO_TXDATA);
10014	if (len & 1) {
10015		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10016		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10017		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10018	}
10019
10020	return (ctl);
10021}
10022
10023static uint16_t
10024bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10025    uint16_t ctl, struct mbuf *m0)
10026{
10027	int i, j = 0;
10028	uint16_t data = 0;
10029	const uint8_t *buf;
10030	struct mbuf *m = m0;
10031
10032	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10033	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10034
10035	for (; m != NULL; m = m->m_next) {
10036		buf = mtod(m, const uint8_t *);
10037		for (i = 0; i < m->m_len; i++) {
10038			if (!((j++) % 2))
10039				data |= buf[i];
10040			else {
10041				data |= (buf[i] << 8);
10042				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10043				data = 0;
10044			}
10045		}
10046	}
10047	if (m0->m_pkthdr.len % 2) {
10048		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10049		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10050		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10051	}
10052
10053	return (ctl);
10054}
10055
10056static void
10057bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10058{
10059
10060	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10061		return;
10062	BWN_WRITE_2(mac, 0x684, 510 + time);
10063	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10064}
10065
10066static struct bwn_dma_ring *
10067bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10068{
10069
10070	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10071		return (mac->mac_method.dma.wme[WME_AC_BE]);
10072
10073	switch (prio) {
10074	case 3:
10075		return (mac->mac_method.dma.wme[WME_AC_VO]);
10076	case 2:
10077		return (mac->mac_method.dma.wme[WME_AC_VI]);
10078	case 0:
10079		return (mac->mac_method.dma.wme[WME_AC_BE]);
10080	case 1:
10081		return (mac->mac_method.dma.wme[WME_AC_BK]);
10082	}
10083	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10084}
10085
10086static int
10087bwn_dma_getslot(struct bwn_dma_ring *dr)
10088{
10089	struct bwn_mac *mac = dr->dr_mac;
10090	int slot;
10091
10092	BWN_ASSERT_LOCKED(mac->mac_sc);
10093
10094	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10095	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10096	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10097
10098	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10099	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10100	dr->dr_curslot = slot;
10101	dr->dr_usedslot++;
10102
10103	return (slot);
10104}
10105
10106static int
10107bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10108{
10109	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10110	unsigned int a, b, c, d;
10111	unsigned int avg;
10112	uint32_t tmp;
10113
10114	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10115	a = tmp & 0xff;
10116	b = (tmp >> 8) & 0xff;
10117	c = (tmp >> 16) & 0xff;
10118	d = (tmp >> 24) & 0xff;
10119	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10120	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10121		return (ENOENT);
10122	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10123	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10124	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10125
10126	if (ofdm) {
10127		a = (a + 32) & 0x3f;
10128		b = (b + 32) & 0x3f;
10129		c = (c + 32) & 0x3f;
10130		d = (d + 32) & 0x3f;
10131	}
10132
10133	avg = (a + b + c + d + 2) / 4;
10134	if (ofdm) {
10135		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10136		    & BWN_HF_4DB_CCK_POWERBOOST)
10137			avg = (avg >= 13) ? (avg - 13) : 0;
10138	}
10139	return (avg);
10140}
10141
10142static void
10143bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10144{
10145	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10146	int rfatt = *rfattp;
10147	int bbatt = *bbattp;
10148
10149	while (1) {
10150		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10151			break;
10152		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10153			break;
10154		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10155			break;
10156		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10157			break;
10158		if (bbatt > lo->bbatt.max) {
10159			bbatt -= 4;
10160			rfatt += 1;
10161			continue;
10162		}
10163		if (bbatt < lo->bbatt.min) {
10164			bbatt += 4;
10165			rfatt -= 1;
10166			continue;
10167		}
10168		if (rfatt > lo->rfatt.max) {
10169			rfatt -= 1;
10170			bbatt += 4;
10171			continue;
10172		}
10173		if (rfatt < lo->rfatt.min) {
10174			rfatt += 1;
10175			bbatt -= 4;
10176			continue;
10177		}
10178		break;
10179	}
10180
10181	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10182	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10183}
10184
10185static void
10186bwn_phy_lock(struct bwn_mac *mac)
10187{
10188	struct bwn_softc *sc = mac->mac_sc;
10189	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10190
10191	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10192	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10193
10194	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10195		bwn_psctl(mac, BWN_PS_AWAKE);
10196}
10197
10198static void
10199bwn_phy_unlock(struct bwn_mac *mac)
10200{
10201	struct bwn_softc *sc = mac->mac_sc;
10202	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10203
10204	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10205	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10206
10207	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10208		bwn_psctl(mac, 0);
10209}
10210
10211static void
10212bwn_rf_lock(struct bwn_mac *mac)
10213{
10214
10215	BWN_WRITE_4(mac, BWN_MACCTL,
10216	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10217	BWN_READ_4(mac, BWN_MACCTL);
10218	DELAY(10);
10219}
10220
10221static void
10222bwn_rf_unlock(struct bwn_mac *mac)
10223{
10224
10225	BWN_READ_2(mac, BWN_PHYVER);
10226	BWN_WRITE_4(mac, BWN_MACCTL,
10227	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10228}
10229
10230static struct bwn_pio_txqueue *
10231bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10232    struct bwn_pio_txpkt **pack)
10233{
10234	struct bwn_pio *pio = &mac->mac_method.pio;
10235	struct bwn_pio_txqueue *tq = NULL;
10236	unsigned int index;
10237
10238	switch (cookie & 0xf000) {
10239	case 0x1000:
10240		tq = &pio->wme[WME_AC_BK];
10241		break;
10242	case 0x2000:
10243		tq = &pio->wme[WME_AC_BE];
10244		break;
10245	case 0x3000:
10246		tq = &pio->wme[WME_AC_VI];
10247		break;
10248	case 0x4000:
10249		tq = &pio->wme[WME_AC_VO];
10250		break;
10251	case 0x5000:
10252		tq = &pio->mcast;
10253		break;
10254	}
10255	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10256	if (tq == NULL)
10257		return (NULL);
10258	index = (cookie & 0x0fff);
10259	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10260	if (index >= N(tq->tq_pkts))
10261		return (NULL);
10262	*pack = &tq->tq_pkts[index];
10263	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10264	return (tq);
10265}
10266
10267static void
10268bwn_txpwr(void *arg, int npending)
10269{
10270	struct bwn_mac *mac = arg;
10271	struct bwn_softc *sc = mac->mac_sc;
10272
10273	BWN_LOCK(sc);
10274	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10275	    mac->mac_phy.set_txpwr != NULL)
10276		mac->mac_phy.set_txpwr(mac);
10277	BWN_UNLOCK(sc);
10278}
10279
10280static void
10281bwn_task_15s(struct bwn_mac *mac)
10282{
10283	uint16_t reg;
10284
10285	if (mac->mac_fw.opensource) {
10286		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10287		if (reg) {
10288			bwn_restart(mac, "fw watchdog");
10289			return;
10290		}
10291		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10292	}
10293	if (mac->mac_phy.task_15s)
10294		mac->mac_phy.task_15s(mac);
10295
10296	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10297}
10298
10299static void
10300bwn_task_30s(struct bwn_mac *mac)
10301{
10302
10303	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10304		return;
10305	mac->mac_noise.noi_running = 1;
10306	mac->mac_noise.noi_nsamples = 0;
10307
10308	bwn_noise_gensample(mac);
10309}
10310
10311static void
10312bwn_task_60s(struct bwn_mac *mac)
10313{
10314
10315	if (mac->mac_phy.task_60s)
10316		mac->mac_phy.task_60s(mac);
10317	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10318}
10319
10320static void
10321bwn_tasks(void *arg)
10322{
10323	struct bwn_mac *mac = arg;
10324	struct bwn_softc *sc = mac->mac_sc;
10325
10326	BWN_ASSERT_LOCKED(sc);
10327	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10328		return;
10329
10330	if (mac->mac_task_state % 4 == 0)
10331		bwn_task_60s(mac);
10332	if (mac->mac_task_state % 2 == 0)
10333		bwn_task_30s(mac);
10334	bwn_task_15s(mac);
10335
10336	mac->mac_task_state++;
10337	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10338}
10339
10340static int
10341bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10342{
10343	struct bwn_softc *sc = mac->mac_sc;
10344
10345	KASSERT(a == 0, ("not support APHY\n"));
10346
10347	switch (plcp->o.raw[0] & 0xf) {
10348	case 0xb:
10349		return (BWN_OFDM_RATE_6MB);
10350	case 0xf:
10351		return (BWN_OFDM_RATE_9MB);
10352	case 0xa:
10353		return (BWN_OFDM_RATE_12MB);
10354	case 0xe:
10355		return (BWN_OFDM_RATE_18MB);
10356	case 0x9:
10357		return (BWN_OFDM_RATE_24MB);
10358	case 0xd:
10359		return (BWN_OFDM_RATE_36MB);
10360	case 0x8:
10361		return (BWN_OFDM_RATE_48MB);
10362	case 0xc:
10363		return (BWN_OFDM_RATE_54MB);
10364	}
10365	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10366	    plcp->o.raw[0] & 0xf);
10367	return (-1);
10368}
10369
10370static int
10371bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10372{
10373	struct bwn_softc *sc = mac->mac_sc;
10374
10375	switch (plcp->o.raw[0]) {
10376	case 0x0a:
10377		return (BWN_CCK_RATE_1MB);
10378	case 0x14:
10379		return (BWN_CCK_RATE_2MB);
10380	case 0x37:
10381		return (BWN_CCK_RATE_5MB);
10382	case 0x6e:
10383		return (BWN_CCK_RATE_11MB);
10384	}
10385	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10386	return (-1);
10387}
10388
10389static void
10390bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10391    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10392    int rssi, int noise)
10393{
10394	struct bwn_softc *sc = mac->mac_sc;
10395	const struct ieee80211_frame_min *wh;
10396	uint64_t tsf;
10397	uint16_t low_mactime_now;
10398
10399	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10400		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10401
10402	wh = mtod(m, const struct ieee80211_frame_min *);
10403	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10404		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10405
10406	bwn_tsf_read(mac, &tsf);
10407	low_mactime_now = tsf;
10408	tsf = tsf & ~0xffffULL;
10409	tsf += le16toh(rxhdr->mac_time);
10410	if (low_mactime_now < le16toh(rxhdr->mac_time))
10411		tsf -= 0x10000;
10412
10413	sc->sc_rx_th.wr_tsf = tsf;
10414	sc->sc_rx_th.wr_rate = rate;
10415	sc->sc_rx_th.wr_antsignal = rssi;
10416	sc->sc_rx_th.wr_antnoise = noise;
10417}
10418
10419static void
10420bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10421{
10422	uint32_t low, high;
10423
10424	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10425	    ("%s:%d: fail", __func__, __LINE__));
10426
10427	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10428	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10429	*tsf = high;
10430	*tsf <<= 32;
10431	*tsf |= low;
10432}
10433
10434static int
10435bwn_dma_attach(struct bwn_mac *mac)
10436{
10437	struct bwn_dma *dma = &mac->mac_method.dma;
10438	struct bwn_softc *sc = mac->mac_sc;
10439	struct siba_dev_softc *sd = mac->mac_sd;
10440	struct siba_softc *siba = sd->sd_bus;
10441	bus_addr_t lowaddr = 0;
10442	int error;
10443
10444	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10445		return (0);
10446
10447	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10448
10449	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10450
10451	dma->dmatype = bwn_dma_gettype(mac);
10452	if (dma->dmatype == BWN_DMA_30BIT)
10453		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10454	else if (dma->dmatype == BWN_DMA_32BIT)
10455		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10456	else
10457		lowaddr = BUS_SPACE_MAXADDR;
10458
10459	/*
10460	 * Create top level DMA tag
10461	 */
10462	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10463			       BWN_ALIGN, 0,		/* alignment, bounds */
10464			       lowaddr,			/* lowaddr */
10465			       BUS_SPACE_MAXADDR,	/* highaddr */
10466			       NULL, NULL,		/* filter, filterarg */
10467			       MAXBSIZE,		/* maxsize */
10468			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10469			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10470			       0,			/* flags */
10471			       NULL, NULL,		/* lockfunc, lockarg */
10472			       &dma->parent_dtag);
10473	if (error) {
10474		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10475		return (error);
10476	}
10477
10478	/*
10479	 * Create TX/RX mbuf DMA tag
10480	 */
10481	error = bus_dma_tag_create(dma->parent_dtag,
10482				1,
10483				0,
10484				BUS_SPACE_MAXADDR,
10485				BUS_SPACE_MAXADDR,
10486				NULL, NULL,
10487				MCLBYTES,
10488				1,
10489				BUS_SPACE_MAXSIZE_32BIT,
10490				0,
10491				NULL, NULL,
10492				&dma->rxbuf_dtag);
10493	if (error) {
10494		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10495		goto fail0;
10496	}
10497	error = bus_dma_tag_create(dma->parent_dtag,
10498				1,
10499				0,
10500				BUS_SPACE_MAXADDR,
10501				BUS_SPACE_MAXADDR,
10502				NULL, NULL,
10503				MCLBYTES,
10504				1,
10505				BUS_SPACE_MAXSIZE_32BIT,
10506				0,
10507				NULL, NULL,
10508				&dma->txbuf_dtag);
10509	if (error) {
10510		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10511		goto fail1;
10512	}
10513
10514	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10515	if (!dma->wme[WME_AC_BK])
10516		goto fail2;
10517
10518	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10519	if (!dma->wme[WME_AC_BE])
10520		goto fail3;
10521
10522	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10523	if (!dma->wme[WME_AC_VI])
10524		goto fail4;
10525
10526	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10527	if (!dma->wme[WME_AC_VO])
10528		goto fail5;
10529
10530	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10531	if (!dma->mcast)
10532		goto fail6;
10533	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10534	if (!dma->rx)
10535		goto fail7;
10536
10537	return (error);
10538
10539fail7:	bwn_dma_ringfree(&dma->mcast);
10540fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10541fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10542fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10543fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10544fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10545fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10546fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10547	return (error);
10548}
10549
10550static struct bwn_dma_ring *
10551bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10552    uint16_t cookie, int *slot)
10553{
10554	struct bwn_dma *dma = &mac->mac_method.dma;
10555	struct bwn_dma_ring *dr;
10556	struct bwn_softc *sc = mac->mac_sc;
10557
10558	BWN_ASSERT_LOCKED(mac->mac_sc);
10559
10560	switch (cookie & 0xf000) {
10561	case 0x1000:
10562		dr = dma->wme[WME_AC_BK];
10563		break;
10564	case 0x2000:
10565		dr = dma->wme[WME_AC_BE];
10566		break;
10567	case 0x3000:
10568		dr = dma->wme[WME_AC_VI];
10569		break;
10570	case 0x4000:
10571		dr = dma->wme[WME_AC_VO];
10572		break;
10573	case 0x5000:
10574		dr = dma->mcast;
10575		break;
10576	default:
10577		KASSERT(0 == 1,
10578		    ("invalid cookie value %d", cookie & 0xf000));
10579	}
10580	*slot = (cookie & 0x0fff);
10581	if (*slot < 0 || *slot >= dr->dr_numslots) {
10582		/*
10583		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10584		 * that it occurs events which have same H/W sequence numbers.
10585		 * When it's occurred just prints a WARNING msgs and ignores.
10586		 */
10587		KASSERT(status->seq == dma->lastseq,
10588		    ("%s:%d: fail", __func__, __LINE__));
10589		device_printf(sc->sc_dev,
10590		    "out of slot ranges (0 < %d < %d)\n", *slot,
10591		    dr->dr_numslots);
10592		return (NULL);
10593	}
10594	dma->lastseq = status->seq;
10595	return (dr);
10596}
10597
10598static void
10599bwn_dma_stop(struct bwn_mac *mac)
10600{
10601	struct bwn_dma *dma;
10602
10603	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10604		return;
10605	dma = &mac->mac_method.dma;
10606
10607	bwn_dma_ringstop(&dma->rx);
10608	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10609	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10610	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10611	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10612	bwn_dma_ringstop(&dma->mcast);
10613}
10614
10615static void
10616bwn_dma_ringstop(struct bwn_dma_ring **dr)
10617{
10618
10619	if (dr == NULL)
10620		return;
10621
10622	bwn_dma_cleanup(*dr);
10623}
10624
10625static void
10626bwn_pio_stop(struct bwn_mac *mac)
10627{
10628	struct bwn_pio *pio;
10629
10630	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10631		return;
10632	pio = &mac->mac_method.pio;
10633
10634	bwn_destroy_queue_tx(&pio->mcast);
10635	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10636	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10637	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10638	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10639}
10640
10641static void
10642bwn_led_attach(struct bwn_mac *mac)
10643{
10644	struct bwn_softc *sc = mac->mac_sc;
10645	struct siba_softc *siba = mac->mac_sd->sd_bus;
10646	const uint8_t *led_act = NULL;
10647	uint16_t val[BWN_LED_MAX];
10648	int i;
10649
10650	sc->sc_led_idle = (2350 * hz) / 1000;
10651	sc->sc_led_blink = 1;
10652
10653	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10654		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10655			led_act = bwn_vendor_led_act[i].led_act;
10656			break;
10657		}
10658	}
10659	if (led_act == NULL)
10660		led_act = bwn_default_led_act;
10661
10662	val[0] = siba->siba_sprom.gpio0;
10663	val[1] = siba->siba_sprom.gpio1;
10664	val[2] = siba->siba_sprom.gpio2;
10665	val[3] = siba->siba_sprom.gpio3;
10666
10667	for (i = 0; i < BWN_LED_MAX; ++i) {
10668		struct bwn_led *led = &sc->sc_leds[i];
10669
10670		if (val[i] == 0xff) {
10671			led->led_act = led_act[i];
10672		} else {
10673			if (val[i] & BWN_LED_ACT_LOW)
10674				led->led_flags |= BWN_LED_F_ACTLOW;
10675			led->led_act = val[i] & BWN_LED_ACT_MASK;
10676		}
10677		led->led_mask = (1 << i);
10678
10679		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10680		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10681		    led->led_act == BWN_LED_ACT_BLINK) {
10682			led->led_flags |= BWN_LED_F_BLINK;
10683			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10684				led->led_flags |= BWN_LED_F_POLLABLE;
10685			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10686				led->led_flags |= BWN_LED_F_SLOW;
10687
10688			if (sc->sc_blink_led == NULL) {
10689				sc->sc_blink_led = led;
10690				if (led->led_flags & BWN_LED_F_SLOW)
10691					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10692			}
10693		}
10694
10695		DPRINTF(sc, BWN_DEBUG_LED,
10696		    "%dth led, act %d, lowact %d\n", i,
10697		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10698	}
10699	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10700}
10701
10702static __inline uint16_t
10703bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10704{
10705
10706	if (led->led_flags & BWN_LED_F_ACTLOW)
10707		on = !on;
10708	if (on)
10709		val |= led->led_mask;
10710	else
10711		val &= ~led->led_mask;
10712	return val;
10713}
10714
10715static void
10716bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10717{
10718	struct bwn_softc *sc = mac->mac_sc;
10719	struct ifnet *ifp = sc->sc_ifp;
10720	struct ieee80211com *ic = ifp->if_l2com;
10721	uint16_t val;
10722	int i;
10723
10724	if (nstate == IEEE80211_S_INIT) {
10725		callout_stop(&sc->sc_led_blink_ch);
10726		sc->sc_led_blinking = 0;
10727	}
10728
10729	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10730		return;
10731
10732	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10733	for (i = 0; i < BWN_LED_MAX; ++i) {
10734		struct bwn_led *led = &sc->sc_leds[i];
10735		int on;
10736
10737		if (led->led_act == BWN_LED_ACT_UNKN ||
10738		    led->led_act == BWN_LED_ACT_NULL)
10739			continue;
10740
10741		if ((led->led_flags & BWN_LED_F_BLINK) &&
10742		    nstate != IEEE80211_S_INIT)
10743			continue;
10744
10745		switch (led->led_act) {
10746		case BWN_LED_ACT_ON:    /* Always on */
10747			on = 1;
10748			break;
10749		case BWN_LED_ACT_OFF:   /* Always off */
10750		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10751			on = 0;
10752			break;
10753		default:
10754			on = 1;
10755			switch (nstate) {
10756			case IEEE80211_S_INIT:
10757				on = 0;
10758				break;
10759			case IEEE80211_S_RUN:
10760				if (led->led_act == BWN_LED_ACT_11G &&
10761				    ic->ic_curmode != IEEE80211_MODE_11G)
10762					on = 0;
10763				break;
10764			default:
10765				if (led->led_act == BWN_LED_ACT_ASSOC)
10766					on = 0;
10767				break;
10768			}
10769			break;
10770		}
10771
10772		val = bwn_led_onoff(led, val, on);
10773	}
10774	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10775}
10776
10777static void
10778bwn_led_event(struct bwn_mac *mac, int event)
10779{
10780	struct bwn_softc *sc = mac->mac_sc;
10781        struct bwn_led *led = sc->sc_blink_led;
10782        int rate;
10783
10784        if (event == BWN_LED_EVENT_POLL) {
10785                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10786                        return;
10787                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10788                        return;
10789        }
10790
10791        sc->sc_led_ticks = ticks;
10792        if (sc->sc_led_blinking)
10793                return;
10794
10795        switch (event) {
10796        case BWN_LED_EVENT_RX:
10797                rate = sc->sc_rx_rate;
10798                break;
10799        case BWN_LED_EVENT_TX:
10800                rate = sc->sc_tx_rate;
10801                break;
10802        case BWN_LED_EVENT_POLL:
10803                rate = 0;
10804                break;
10805        default:
10806                panic("unknown LED event %d\n", event);
10807                break;
10808        }
10809        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10810            bwn_led_duration[rate].off_dur);
10811}
10812
10813static void
10814bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10815{
10816	struct bwn_softc *sc = mac->mac_sc;
10817        struct bwn_led *led = sc->sc_blink_led;
10818        uint16_t val;
10819
10820        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10821        val = bwn_led_onoff(led, val, 1);
10822        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10823
10824        if (led->led_flags & BWN_LED_F_SLOW) {
10825                BWN_LED_SLOWDOWN(on_dur);
10826                BWN_LED_SLOWDOWN(off_dur);
10827        }
10828
10829        sc->sc_led_blinking = 1;
10830        sc->sc_led_blink_offdur = off_dur;
10831
10832        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10833}
10834
10835static void
10836bwn_led_blink_next(void *arg)
10837{
10838	struct bwn_mac *mac = arg;
10839        struct bwn_softc *sc = mac->mac_sc;
10840        uint16_t val;
10841
10842        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10843        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10844        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10845
10846        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10847            bwn_led_blink_end, mac);
10848}
10849
10850static void
10851bwn_led_blink_end(void *arg)
10852{
10853	struct bwn_mac *mac = arg;
10854        struct bwn_softc *sc = mac->mac_sc;
10855
10856        sc->sc_led_blinking = 0;
10857}
10858
10859static int
10860bwn_suspend(device_t dev)
10861{
10862	struct bwn_softc *sc = device_get_softc(dev);
10863
10864	bwn_stop(sc, 1);
10865	return (0);
10866}
10867
10868static int
10869bwn_resume(device_t dev)
10870{
10871	struct bwn_softc *sc = device_get_softc(dev);
10872	struct ifnet *ifp = sc->sc_ifp;
10873
10874	if (ifp->if_flags & IFF_UP)
10875		bwn_init(sc);
10876	return (0);
10877}
10878
10879static void
10880bwn_rfswitch(void *arg)
10881{
10882	struct bwn_softc *sc = arg;
10883	struct bwn_mac *mac = sc->sc_curmac;
10884	int cur = 0, prev = 0;
10885
10886	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10887	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10888
10889	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10890		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10891			& BWN_RF_HWENABLED_HI_MASK))
10892			cur = 1;
10893	} else {
10894		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10895		    & BWN_RF_HWENABLED_LO_MASK)
10896			cur = 1;
10897	}
10898
10899	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10900		prev = 1;
10901
10902	if (cur != prev) {
10903		if (cur)
10904			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10905		else
10906			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10907
10908		device_printf(sc->sc_dev,
10909		    "status of RF switch is changed to %s\n",
10910		    cur ? "ON" : "OFF");
10911		if (cur != mac->mac_phy.rf_on) {
10912			if (cur)
10913				bwn_rf_turnon(mac);
10914			else
10915				bwn_rf_turnoff(mac);
10916		}
10917	}
10918
10919	callout_schedule(&sc->sc_rfswitch_ch, hz);
10920}
10921
10922static void
10923bwn_phy_lp_init_pre(struct bwn_mac *mac)
10924{
10925	struct bwn_phy *phy = &mac->mac_phy;
10926	struct bwn_phy_lp *plp = &phy->phy_lp;
10927
10928	plp->plp_antenna = BWN_ANT_DEFAULT;
10929}
10930
10931static int
10932bwn_phy_lp_init(struct bwn_mac *mac)
10933{
10934	static const struct bwn_stxtable tables[] = {
10935		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10936		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10937		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10938		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10939		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10940		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10941		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10942		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10943		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10944		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10945		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10946		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10947		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10948		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10949		{ 2, 11, 0x40, 0, 0x0f }
10950	};
10951	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10952	struct bwn_softc *sc = mac->mac_sc;
10953	const struct bwn_stxtable *st;
10954	struct ifnet *ifp = sc->sc_ifp;
10955	struct ieee80211com *ic = ifp->if_l2com;
10956	int i, error;
10957	uint16_t tmp;
10958
10959	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10960	bwn_phy_lp_bbinit(mac);
10961
10962	/* initialize RF */
10963	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10964	DELAY(1);
10965	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10966	DELAY(1);
10967
10968	if (mac->mac_phy.rf_ver == 0x2062)
10969		bwn_phy_lp_b2062_init(mac);
10970	else {
10971		bwn_phy_lp_b2063_init(mac);
10972
10973		/* synchronize stx table. */
10974		for (i = 0; i < N(tables); i++) {
10975			st = &tables[i];
10976			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10977			tmp >>= st->st_rfshift;
10978			tmp <<= st->st_physhift;
10979			BWN_PHY_SETMASK(mac,
10980			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10981			    ~(st->st_mask << st->st_physhift), tmp);
10982		}
10983
10984		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10985		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10986	}
10987
10988	/* calibrate RC */
10989	if (mac->mac_phy.rev >= 2)
10990		bwn_phy_lp_rxcal_r2(mac);
10991	else if (!plp->plp_rccap) {
10992		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10993			bwn_phy_lp_rccal_r12(mac);
10994	} else
10995		bwn_phy_lp_set_rccap(mac);
10996
10997	error = bwn_phy_lp_switch_channel(mac, 7);
10998	if (error)
10999		device_printf(sc->sc_dev,
11000		    "failed to change channel 7 (%d)\n", error);
11001	bwn_phy_lp_txpctl_init(mac);
11002	bwn_phy_lp_calib(mac);
11003	return (0);
11004}
11005
11006static uint16_t
11007bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11008{
11009
11010	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11011	return (BWN_READ_2(mac, BWN_PHYDATA));
11012}
11013
11014static void
11015bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11016{
11017
11018	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11019	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11020}
11021
11022static void
11023bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11024    uint16_t set)
11025{
11026
11027	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11028	BWN_WRITE_2(mac, BWN_PHYDATA,
11029	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11030}
11031
11032static uint16_t
11033bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11034{
11035
11036	KASSERT(reg != 1, ("unaccessible register %d", reg));
11037	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11038		reg |= 0x100;
11039	if (mac->mac_phy.rev >= 2)
11040		reg |= 0x200;
11041	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11042	return BWN_READ_2(mac, BWN_RFDATALO);
11043}
11044
11045static void
11046bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11047{
11048
11049	KASSERT(reg != 1, ("unaccessible register %d", reg));
11050	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11051	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11052}
11053
11054static void
11055bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11056{
11057
11058	if (on) {
11059		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11060		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11061		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11062		return;
11063	}
11064
11065	if (mac->mac_phy.rev >= 2) {
11066		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11067		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11068		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11069		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11070		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11071		return;
11072	}
11073
11074	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11075	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11076	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11077	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11078}
11079
11080static int
11081bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11082{
11083	struct bwn_phy *phy = &mac->mac_phy;
11084	struct bwn_phy_lp *plp = &phy->phy_lp;
11085	int error;
11086
11087	if (phy->rf_ver == 0x2063) {
11088		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11089		if (error)
11090			return (error);
11091	} else {
11092		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11093		if (error)
11094			return (error);
11095		bwn_phy_lp_set_anafilter(mac, chan);
11096		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11097	}
11098
11099	plp->plp_chan = chan;
11100	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11101	return (0);
11102}
11103
11104static uint32_t
11105bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11106{
11107	struct bwn_softc *sc = mac->mac_sc;
11108	struct ifnet *ifp = sc->sc_ifp;
11109	struct ieee80211com *ic = ifp->if_l2com;
11110
11111	device_printf(sc->sc_dev, "correct?\n");
11112
11113	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11114}
11115
11116static void
11117bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11118{
11119	struct bwn_phy *phy = &mac->mac_phy;
11120	struct bwn_phy_lp *plp = &phy->phy_lp;
11121
11122	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11123		return;
11124
11125	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11126	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11127	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11128	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11129	plp->plp_antenna = antenna;
11130}
11131
11132static void
11133bwn_phy_lp_task_60s(struct bwn_mac *mac)
11134{
11135
11136	bwn_phy_lp_calib(mac);
11137}
11138
11139static void
11140bwn_phy_lp_readsprom(struct bwn_mac *mac)
11141{
11142	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11143	struct bwn_softc *sc = mac->mac_sc;
11144	struct ifnet *ifp = sc->sc_ifp;
11145	struct ieee80211com *ic = ifp->if_l2com;
11146	struct siba_dev_softc *sd = mac->mac_sd;
11147	struct siba_softc *siba = sd->sd_bus;
11148	struct siba_sprom *sprom = &siba->siba_sprom;
11149
11150	device_printf(sc->sc_dev, "XXX using %dghz\n",
11151	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11152
11153	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11154		plp->plp_txisoband_m = sprom->tri2g;
11155		plp->plp_bxarch = sprom->bxa2g;
11156		plp->plp_rxpwroffset = sprom->rxpo2g;
11157		plp->plp_rssivf = sprom->rssismf2g;
11158		plp->plp_rssivc = sprom->rssismc2g;
11159		plp->plp_rssigs = sprom->rssisav2g;
11160		return;
11161	}
11162
11163	plp->plp_txisoband_l = sprom->tri5gl;
11164	plp->plp_txisoband_m = sprom->tri5g;
11165	plp->plp_txisoband_h = sprom->tri5gh;
11166	plp->plp_bxarch = sprom->bxa5g;
11167	plp->plp_rxpwroffset = sprom->rxpo5g;
11168	plp->plp_rssivf = sprom->rssismf5g;
11169	plp->plp_rssivc = sprom->rssismc5g;
11170	plp->plp_rssigs = sprom->rssisav5g;
11171}
11172
11173static void
11174bwn_phy_lp_bbinit(struct bwn_mac *mac)
11175{
11176
11177	bwn_phy_lp_tblinit(mac);
11178	if (mac->mac_phy.rev >= 2)
11179		bwn_phy_lp_bbinit_r2(mac);
11180	else
11181		bwn_phy_lp_bbinit_r01(mac);
11182}
11183
11184static void
11185bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11186{
11187	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11188	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11189	struct bwn_softc *sc = mac->mac_sc;
11190	struct ifnet *ifp = sc->sc_ifp;
11191	struct ieee80211com *ic = ifp->if_l2com;
11192
11193	bwn_phy_lp_set_txgain(mac,
11194	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11195	bwn_phy_lp_set_bbmult(mac, 150);
11196}
11197
11198static void
11199bwn_phy_lp_calib(struct bwn_mac *mac)
11200{
11201	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11202	struct siba_dev_softc *sd = mac->mac_sd;
11203	struct siba_softc *siba = sd->sd_bus;
11204	struct bwn_softc *sc = mac->mac_sc;
11205	struct ifnet *ifp = sc->sc_ifp;
11206	struct ieee80211com *ic = ifp->if_l2com;
11207	const struct bwn_rxcompco *rc = NULL;
11208	struct bwn_txgain ogain;
11209	int i, omode, oafeovr, orf, obbmult;
11210	uint8_t mode, fc = 0;
11211
11212	if (plp->plp_chanfullcal != plp->plp_chan) {
11213		plp->plp_chanfullcal = plp->plp_chan;
11214		fc = 1;
11215	}
11216
11217	bwn_mac_suspend(mac);
11218
11219	/* BlueTooth Coexistance Override */
11220	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11221	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11222
11223	if (mac->mac_phy.rev >= 2)
11224		bwn_phy_lp_digflt_save(mac);
11225	bwn_phy_lp_get_txpctlmode(mac);
11226	mode = plp->plp_txpctlmode;
11227	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11228	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11229		bwn_phy_lp_bugfix(mac);
11230	if (mac->mac_phy.rev >= 2 && fc == 1) {
11231		bwn_phy_lp_get_txpctlmode(mac);
11232		omode = plp->plp_txpctlmode;
11233		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11234		if (oafeovr)
11235			ogain = bwn_phy_lp_get_txgain(mac);
11236		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11237		obbmult = bwn_phy_lp_get_bbmult(mac);
11238		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11239		if (oafeovr)
11240			bwn_phy_lp_set_txgain(mac, &ogain);
11241		bwn_phy_lp_set_bbmult(mac, obbmult);
11242		bwn_phy_lp_set_txpctlmode(mac, omode);
11243		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11244	}
11245	bwn_phy_lp_set_txpctlmode(mac, mode);
11246	if (mac->mac_phy.rev >= 2)
11247		bwn_phy_lp_digflt_restore(mac);
11248
11249	/* do RX IQ Calculation; assumes that noise is true. */
11250	if (siba->siba_chipid == 0x5354) {
11251		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11252			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11253				rc = &bwn_rxcompco_5354[i];
11254		}
11255	} else if (mac->mac_phy.rev >= 2)
11256		rc = &bwn_rxcompco_r2;
11257	else {
11258		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11259			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11260				rc = &bwn_rxcompco_r12[i];
11261		}
11262	}
11263	if (rc == NULL)
11264		goto fail;
11265
11266	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11267	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11268
11269	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11270
11271	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11272		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11273		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11274	} else {
11275		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11276		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11277	}
11278
11279	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11280	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11281	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11282	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11283	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11284	bwn_phy_lp_set_deaf(mac, 0);
11285	/* XXX no checking return value? */
11286	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11287	bwn_phy_lp_clear_deaf(mac, 0);
11288	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11289	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11290	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11291
11292	/* disable RX GAIN override. */
11293	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11294	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11295	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11296	if (mac->mac_phy.rev >= 2) {
11297		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11298		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11299			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11300			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11301		}
11302	} else {
11303		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11304	}
11305
11306	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11307	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11308fail:
11309	bwn_mac_enable(mac);
11310}
11311
11312static void
11313bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11314{
11315
11316       if (on) {
11317               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11318	       return;
11319       }
11320
11321       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11322       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11323}
11324
11325static int
11326bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11327{
11328	struct siba_dev_softc *sd = mac->mac_sd;
11329	struct siba_softc *siba = sd->sd_bus;
11330	static const struct bwn_b206x_chan *bc = NULL;
11331	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11332	    tmp[6];
11333	uint16_t old, scale, tmp16;
11334	int i, div;
11335
11336	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11337		if (bwn_b2063_chantable[i].bc_chan == chan) {
11338			bc = &bwn_b2063_chantable[i];
11339			break;
11340		}
11341	}
11342	if (bc == NULL)
11343		return (EINVAL);
11344
11345	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11346	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11347	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11348	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11349	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11350	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11351	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11352	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11353	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11354	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11355	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11356	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11357
11358	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11359	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11360
11361	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11362	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11363	freqref = freqxtal * 3;
11364	div = (freqxtal <= 26000000 ? 1 : 2);
11365	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11366	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11367		999999) / 1000000) + 1;
11368
11369	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11370	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11371	    0xfff8, timeout >> 2);
11372	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11373	    0xff9f,timeout << 5);
11374	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11375
11376	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11377	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11378	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11379
11380	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11381	    (timeoutref + 1)) - 1;
11382	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11383	    0xf0, count >> 8);
11384	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11385
11386	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11387	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11388	while (tmp[1] >= freqref) {
11389		tmp[0]++;
11390		tmp[1] -= freqref;
11391	}
11392	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11393	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11394	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11395	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11396	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11397
11398	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11399	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11400	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11401	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11402
11403	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11404	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11405
11406	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11407		scale = 1;
11408		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11409	} else {
11410		scale = 0;
11411		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11412	}
11413	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11414	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11415
11416	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11417	    (scale + 1);
11418	if (tmp[5] > 150)
11419		tmp[5] = 0;
11420
11421	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11422	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11423
11424	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11425	if (freqxtal > 26000000)
11426		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11427	else
11428		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11429
11430	if (val[0] == 45)
11431		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11432	else
11433		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11434
11435	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11436	DELAY(1);
11437	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11438
11439	/* VCO Calibration */
11440	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11441	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11442	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11443	DELAY(1);
11444	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11445	DELAY(1);
11446	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11447	DELAY(1);
11448	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11449	DELAY(300);
11450	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11451
11452	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11453	return (0);
11454}
11455
11456static int
11457bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11458{
11459	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11460	struct siba_dev_softc *sd = mac->mac_sd;
11461	struct siba_softc *siba = sd->sd_bus;
11462	const struct bwn_b206x_chan *bc = NULL;
11463	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11464	uint32_t tmp[9];
11465	int i;
11466
11467	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11468		if (bwn_b2062_chantable[i].bc_chan == chan) {
11469			bc = &bwn_b2062_chantable[i];
11470			break;
11471		}
11472	}
11473
11474	if (bc == NULL)
11475		return (EINVAL);
11476
11477	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11478	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11479	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11480	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11481	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11482	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11483	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11484	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11485	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11486	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11487
11488	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11489	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11490	bwn_phy_lp_b2062_reset_pllbias(mac);
11491	tmp[0] = freqxtal / 1000;
11492	tmp[1] = plp->plp_div * 1000;
11493	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11494	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11495		tmp[2] *= 2;
11496	tmp[3] = 48 * tmp[0];
11497	tmp[5] = tmp[2] / tmp[3];
11498	tmp[6] = tmp[2] % tmp[3];
11499	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11500	tmp[4] = tmp[6] * 0x100;
11501	tmp[5] = tmp[4] / tmp[3];
11502	tmp[6] = tmp[4] % tmp[3];
11503	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11504	tmp[4] = tmp[6] * 0x100;
11505	tmp[5] = tmp[4] / tmp[3];
11506	tmp[6] = tmp[4] % tmp[3];
11507	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11508	tmp[4] = tmp[6] * 0x100;
11509	tmp[5] = tmp[4] / tmp[3];
11510	tmp[6] = tmp[4] % tmp[3];
11511	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11512	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11513	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11514	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11515	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11516	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11517
11518	bwn_phy_lp_b2062_vco_calib(mac);
11519	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11520		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11521		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11522		bwn_phy_lp_b2062_reset_pllbias(mac);
11523		bwn_phy_lp_b2062_vco_calib(mac);
11524		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11525			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11526			return (EIO);
11527		}
11528	}
11529	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11530	return (0);
11531}
11532
11533static void
11534bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11535{
11536	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11537	uint16_t tmp = (channel == 14);
11538
11539	if (mac->mac_phy.rev < 2) {
11540		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11541		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11542			bwn_phy_lp_set_rccap(mac);
11543		return;
11544	}
11545
11546	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11547}
11548
11549static void
11550bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11551{
11552	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11553	struct bwn_softc *sc = mac->mac_sc;
11554	struct ifnet *ifp = sc->sc_ifp;
11555	struct ieee80211com *ic = ifp->if_l2com;
11556	uint16_t iso, tmp[3];
11557
11558	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11559
11560	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11561		iso = plp->plp_txisoband_m;
11562	else if (freq <= 5320)
11563		iso = plp->plp_txisoband_l;
11564	else if (freq <= 5700)
11565		iso = plp->plp_txisoband_m;
11566	else
11567		iso = plp->plp_txisoband_h;
11568
11569	tmp[0] = ((iso - 26) / 12) << 12;
11570	tmp[1] = tmp[0] + 0x1000;
11571	tmp[2] = tmp[0] + 0x2000;
11572
11573	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11574	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11575}
11576
11577static void
11578bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11579{
11580	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11581	int i;
11582	static const uint16_t addr[] = {
11583		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11584		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11585		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11586		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11587		BWN_PHY_OFDM(0xcf),
11588	};
11589	static const uint16_t val[] = {
11590		0xde5e, 0xe832, 0xe331, 0x4d26,
11591		0x0026, 0x1420, 0x0020, 0xfe08,
11592		0x0008,
11593	};
11594
11595	for (i = 0; i < N(addr); i++) {
11596		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11597		BWN_PHY_WRITE(mac, addr[i], val[i]);
11598	}
11599}
11600
11601static void
11602bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11603{
11604	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11605	struct bwn_softc *sc = mac->mac_sc;
11606	uint16_t ctl;
11607
11608	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11609	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11610	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11611		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11612		break;
11613	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11614		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11615		break;
11616	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11617		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11618		break;
11619	default:
11620		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11621		device_printf(sc->sc_dev, "unknown command mode\n");
11622		break;
11623	}
11624}
11625
11626static void
11627bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11628{
11629	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11630	uint16_t ctl;
11631	uint8_t old;
11632
11633	bwn_phy_lp_get_txpctlmode(mac);
11634	old = plp->plp_txpctlmode;
11635	if (old == mode)
11636		return;
11637	plp->plp_txpctlmode = mode;
11638
11639	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11640		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11641		    plp->plp_tssiidx);
11642		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11643		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11644
11645		/* disable TX GAIN override */
11646		if (mac->mac_phy.rev < 2)
11647			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11648		else {
11649			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11650			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11651		}
11652		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11653
11654		plp->plp_txpwridx = -1;
11655	}
11656	if (mac->mac_phy.rev >= 2) {
11657		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11658			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11659		else
11660			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11661	}
11662
11663	/* writes TX Power Control mode */
11664	switch (plp->plp_txpctlmode) {
11665	case BWN_PHYLP_TXPCTL_OFF:
11666		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11667		break;
11668	case BWN_PHYLP_TXPCTL_ON_HW:
11669		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11670		break;
11671	case BWN_PHYLP_TXPCTL_ON_SW:
11672		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11673		break;
11674	default:
11675		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11676	}
11677	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11678	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11679}
11680
11681static void
11682bwn_phy_lp_bugfix(struct bwn_mac *mac)
11683{
11684	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11685	struct bwn_softc *sc = mac->mac_sc;
11686	const unsigned int size = 256;
11687	struct bwn_txgain tg;
11688	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11689	uint16_t tssinpt, tssiidx, value[2];
11690	uint8_t mode;
11691	int8_t txpwridx;
11692
11693	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11694	    M_NOWAIT | M_ZERO);
11695	if (tabs == NULL) {
11696		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11697		return;
11698	}
11699
11700	bwn_phy_lp_get_txpctlmode(mac);
11701	mode = plp->plp_txpctlmode;
11702	txpwridx = plp->plp_txpwridx;
11703	tssinpt = plp->plp_tssinpt;
11704	tssiidx = plp->plp_tssiidx;
11705
11706	bwn_tab_read_multi(mac,
11707	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11708	    BWN_TAB_4(7, 0x140), size, tabs);
11709
11710	bwn_phy_lp_tblinit(mac);
11711	bwn_phy_lp_bbinit(mac);
11712	bwn_phy_lp_txpctl_init(mac);
11713	bwn_phy_lp_rf_onoff(mac, 1);
11714	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11715
11716	bwn_tab_write_multi(mac,
11717	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11718	    BWN_TAB_4(7, 0x140), size, tabs);
11719
11720	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11721	plp->plp_tssinpt = tssinpt;
11722	plp->plp_tssiidx = tssiidx;
11723	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11724	if (txpwridx != -1) {
11725		/* set TX power by index */
11726		plp->plp_txpwridx = txpwridx;
11727		bwn_phy_lp_get_txpctlmode(mac);
11728		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11729			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11730		if (mac->mac_phy.rev >= 2) {
11731			rxcomp = bwn_tab_read(mac,
11732			    BWN_TAB_4(7, txpwridx + 320));
11733			txgain = bwn_tab_read(mac,
11734			    BWN_TAB_4(7, txpwridx + 192));
11735			tg.tg_pad = (txgain >> 16) & 0xff;
11736			tg.tg_gm = txgain & 0xff;
11737			tg.tg_pga = (txgain >> 8) & 0xff;
11738			tg.tg_dac = (rxcomp >> 28) & 0xff;
11739			bwn_phy_lp_set_txgain(mac, &tg);
11740		} else {
11741			rxcomp = bwn_tab_read(mac,
11742			    BWN_TAB_4(10, txpwridx + 320));
11743			txgain = bwn_tab_read(mac,
11744			    BWN_TAB_4(10, txpwridx + 192));
11745			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11746			    0xf800, (txgain >> 4) & 0x7fff);
11747			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11748			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11749		}
11750		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11751
11752		/* set TX IQCC */
11753		value[0] = (rxcomp >> 10) & 0x3ff;
11754		value[1] = rxcomp & 0x3ff;
11755		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11756
11757		coeff = bwn_tab_read(mac,
11758		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11759		    BWN_TAB_4(10, txpwridx + 448));
11760		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11761		if (mac->mac_phy.rev >= 2) {
11762			rfpwr = bwn_tab_read(mac,
11763			    BWN_TAB_4(7, txpwridx + 576));
11764			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11765			    rfpwr & 0xffff);
11766		}
11767		bwn_phy_lp_set_txgain_override(mac);
11768	}
11769	if (plp->plp_rccap)
11770		bwn_phy_lp_set_rccap(mac);
11771	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11772	bwn_phy_lp_set_txpctlmode(mac, mode);
11773	free(tabs, M_DEVBUF);
11774}
11775
11776static void
11777bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11778{
11779	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11780	int i;
11781	static const uint16_t addr[] = {
11782		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11783		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11784		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11785		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11786		BWN_PHY_OFDM(0xcf),
11787	};
11788
11789	for (i = 0; i < N(addr); i++)
11790		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11791}
11792
11793static void
11794bwn_phy_lp_tblinit(struct bwn_mac *mac)
11795{
11796	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11797
11798	if (mac->mac_phy.rev < 2) {
11799		bwn_phy_lp_tblinit_r01(mac);
11800		bwn_phy_lp_tblinit_txgain(mac);
11801		bwn_phy_lp_set_gaintbl(mac, freq);
11802		return;
11803	}
11804
11805	bwn_phy_lp_tblinit_r2(mac);
11806	bwn_phy_lp_tblinit_txgain(mac);
11807}
11808
11809struct bwn_wpair {
11810	uint16_t		reg;
11811	uint16_t		value;
11812};
11813
11814struct bwn_smpair {
11815	uint16_t		offset;
11816	uint16_t		mask;
11817	uint16_t		set;
11818};
11819
11820static void
11821bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11822{
11823	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11824	struct siba_dev_softc *sd = mac->mac_sd;
11825	struct siba_softc *siba = sd->sd_bus;
11826	struct bwn_softc *sc = mac->mac_sc;
11827	struct ifnet *ifp = sc->sc_ifp;
11828	struct ieee80211com *ic = ifp->if_l2com;
11829	static const struct bwn_wpair v1[] = {
11830		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11831		{ BWN_PHY_AFE_CTL, 0x8800 },
11832		{ BWN_PHY_AFE_CTL_OVR, 0 },
11833		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11834		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11835		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11836		{ BWN_PHY_OFDM(0xf9), 0 },
11837		{ BWN_PHY_TR_LOOKUP_1, 0 }
11838	};
11839	static const struct bwn_smpair v2[] = {
11840		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11841		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11842		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11843		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11844		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11845	};
11846	static const struct bwn_smpair v3[] = {
11847		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11848		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11849		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11850		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11851		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11852		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11853		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11854		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11855		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11856		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11857
11858	};
11859	int i;
11860
11861	for (i = 0; i < N(v1); i++)
11862		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11863	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11864	for (i = 0; i < N(v2); i++)
11865		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11866
11867	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11868	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11869	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11870	if (siba->siba_board_rev >= 0x18) {
11871		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11872		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11873	} else {
11874		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11875	}
11876	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11878	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11879	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11880	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11881	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11882	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11883	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11884	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11885	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11886	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11887	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11888		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11889		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11890	} else {
11891		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11892		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11893	}
11894	for (i = 0; i < N(v3); i++)
11895		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11896	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11897		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11898		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11899	}
11900
11901	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11902		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11903		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11904		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11905		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11906		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11907		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11908	} else
11909		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11910
11911	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11912	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11913	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11914	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11915	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11916	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11917	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11918	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11919	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11920
11921	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11922		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11923		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11924		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11925	}
11926
11927	bwn_phy_lp_digflt_save(mac);
11928}
11929
11930static void
11931bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11932{
11933	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11934	struct siba_dev_softc *sd = mac->mac_sd;
11935	struct siba_softc *siba = sd->sd_bus;
11936	struct bwn_softc *sc = mac->mac_sc;
11937	struct ifnet *ifp = sc->sc_ifp;
11938	struct ieee80211com *ic = ifp->if_l2com;
11939	static const struct bwn_smpair v1[] = {
11940		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11941		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11942		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11943		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11944		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11945		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11946		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11947	};
11948	static const struct bwn_smpair v2[] = {
11949		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11950		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11951		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11952		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11953		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11954		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11955		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11956		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11957		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11958		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11959		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11960		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11961		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11962		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11963		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11964		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11965	};
11966	static const struct bwn_smpair v3[] = {
11967		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11968		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11969		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11970		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11971		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11972		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11973		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11974		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11975	};
11976	static const struct bwn_smpair v4[] = {
11977		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11978		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11979		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11980		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11981		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11982		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11983		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11984		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11985	};
11986	static const struct bwn_smpair v5[] = {
11987		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11988		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11989		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11990		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11991		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11992		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11993		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11994		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11995	};
11996	int i;
11997	uint16_t tmp, tmp2;
11998
11999	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
12000	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
12001	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
12002	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
12003	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
12004	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
12005	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
12006	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12007	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12008	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12009	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12010	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12011	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12012	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12013	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12014	for (i = 0; i < N(v1); i++)
12015		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12016	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12017	    0xff00, plp->plp_rxpwroffset);
12018	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12019	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12020	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12021		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12022		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12023		if (mac->mac_phy.rev == 0)
12024			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12025			    0xffcf, 0x0010);
12026		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12027	} else {
12028		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12029		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12030		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12031	}
12032	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12033	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12034	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12035		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12036	else
12037		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12038	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12039	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12040	    0xfff9, (plp->plp_bxarch << 1));
12041	if (mac->mac_phy.rev == 1 &&
12042	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12043		for (i = 0; i < N(v2); i++)
12044			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12045			    v2[i].set);
12046	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12047	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12048	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12049		for (i = 0; i < N(v3); i++)
12050			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12051			    v3[i].set);
12052	} else if (mac->mac_phy.rev == 1 ||
12053		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12054		for (i = 0; i < N(v4); i++)
12055			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12056			    v4[i].set);
12057	} else {
12058		for (i = 0; i < N(v5); i++)
12059			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12060			    v5[i].set);
12061	}
12062	if (mac->mac_phy.rev == 1 &&
12063	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12064		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12065		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12066		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12067		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12068	}
12069	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12070	    (siba->siba_chipid == 0x5354) &&
12071	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12072		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12073		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12074		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12075		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12076	}
12077	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12078		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12079		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12080		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12081		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12082		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12083		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12084		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12085		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12086	} else {
12087		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12088		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12089	}
12090	if (mac->mac_phy.rev == 1) {
12091		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12092		tmp2 = (tmp & 0x03e0) >> 5;
12093		tmp2 |= tmp2 << 5;
12094		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12095		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12096		tmp2 = (tmp & 0x1f00) >> 8;
12097		tmp2 |= tmp2 << 5;
12098		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12099		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12100		tmp2 = tmp & 0x00ff;
12101		tmp2 |= tmp << 8;
12102		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12103	}
12104}
12105
12106struct bwn_b2062_freq {
12107	uint16_t		freq;
12108	uint8_t			value[6];
12109};
12110
12111static void
12112bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12113{
12114#define	CALC_CTL7(freq, div)						\
12115	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12116#define	CALC_CTL18(freq, div)						\
12117	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12118#define	CALC_CTL19(freq, div)						\
12119	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12120	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12121	struct siba_dev_softc *sd = mac->mac_sd;
12122	struct siba_softc *siba = sd->sd_bus;
12123	struct bwn_softc *sc = mac->mac_sc;
12124	struct ifnet *ifp = sc->sc_ifp;
12125	struct ieee80211com *ic = ifp->if_l2com;
12126	static const struct bwn_b2062_freq freqdata_tab[] = {
12127		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12128		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12129		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12130		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12131		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12132		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12133	};
12134	static const struct bwn_wpair v1[] = {
12135		{ BWN_B2062_N_TXCTL3, 0 },
12136		{ BWN_B2062_N_TXCTL4, 0 },
12137		{ BWN_B2062_N_TXCTL5, 0 },
12138		{ BWN_B2062_N_TXCTL6, 0 },
12139		{ BWN_B2062_N_PDNCTL0, 0x40 },
12140		{ BWN_B2062_N_PDNCTL0, 0 },
12141		{ BWN_B2062_N_CALIB_TS, 0x10 },
12142		{ BWN_B2062_N_CALIB_TS, 0 }
12143	};
12144	const struct bwn_b2062_freq *f = NULL;
12145	uint32_t xtalfreq, ref;
12146	unsigned int i;
12147
12148	bwn_phy_lp_b2062_tblinit(mac);
12149
12150	for (i = 0; i < N(v1); i++)
12151		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12152	if (mac->mac_phy.rev > 0)
12153		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12154		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12155	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12156		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12157	else
12158		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12159
12160	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12161	    ("%s:%d: fail", __func__, __LINE__));
12162	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12163	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12164
12165	if (xtalfreq <= 30000000) {
12166		plp->plp_div = 1;
12167		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12168	} else {
12169		plp->plp_div = 2;
12170		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12171	}
12172
12173	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12174	    CALC_CTL7(xtalfreq, plp->plp_div));
12175	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12176	    CALC_CTL18(xtalfreq, plp->plp_div));
12177	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12178	    CALC_CTL19(xtalfreq, plp->plp_div));
12179
12180	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12181	ref &= 0xffff;
12182	for (i = 0; i < N(freqdata_tab); i++) {
12183		if (ref < freqdata_tab[i].freq) {
12184			f = &freqdata_tab[i];
12185			break;
12186		}
12187	}
12188	if (f == NULL)
12189		f = &freqdata_tab[N(freqdata_tab) - 1];
12190	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12191	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12192	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12193	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12194	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12195	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12196#undef CALC_CTL7
12197#undef CALC_CTL18
12198#undef CALC_CTL19
12199}
12200
12201static void
12202bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12203{
12204
12205	bwn_phy_lp_b2063_tblinit(mac);
12206	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12207	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12208	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12209	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12210	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12211	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12212	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12213	if (mac->mac_phy.rev == 2) {
12214		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12215		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12216		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12217	} else {
12218		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12219		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12220	}
12221}
12222
12223static void
12224bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12225{
12226	struct siba_dev_softc *sd = mac->mac_sd;
12227	struct siba_softc *siba = sd->sd_bus;
12228	static const struct bwn_wpair v1[] = {
12229		{ BWN_B2063_RX_BB_SP8, 0x0 },
12230		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12231		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12232		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12233		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12234		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12235		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12236		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12237	};
12238	static const struct bwn_wpair v2[] = {
12239		{ BWN_B2063_TX_BB_SP3, 0x0 },
12240		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12241		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12242		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12243		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12244	};
12245	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12246	int i;
12247	uint8_t tmp;
12248
12249	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12250
12251	for (i = 0; i < 2; i++)
12252		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12253	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12254	for (i = 2; i < N(v1); i++)
12255		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12256	for (i = 0; i < 10000; i++) {
12257		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12258			break;
12259		DELAY(1000);
12260	}
12261
12262	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12263		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12264
12265	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12266
12267	for (i = 0; i < N(v2); i++)
12268		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12269	if (freqxtal == 24000000) {
12270		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12271		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12272	} else {
12273		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12274		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12275	}
12276	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12277	for (i = 0; i < 10000; i++) {
12278		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12279			break;
12280		DELAY(1000);
12281	}
12282	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12283		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12284	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12285}
12286
12287static void
12288bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12289{
12290	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12291	struct bwn_softc *sc = mac->mac_sc;
12292	struct bwn_phy_lp_iq_est ie;
12293	struct bwn_txgain tx_gains;
12294	static const uint32_t pwrtbl[21] = {
12295		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12296		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12297		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12298		0x0004c, 0x0002c, 0x0001a,
12299	};
12300	uint32_t npwr, ipwr, sqpwr, tmp;
12301	int loopback, i, j, sum, error;
12302	uint16_t save[7];
12303	uint8_t txo, bbmult, txpctlmode;
12304
12305	error = bwn_phy_lp_switch_channel(mac, 7);
12306	if (error)
12307		device_printf(sc->sc_dev,
12308		    "failed to change channel to 7 (%d)\n", error);
12309	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12310	bbmult = bwn_phy_lp_get_bbmult(mac);
12311	if (txo)
12312		tx_gains = bwn_phy_lp_get_txgain(mac);
12313
12314	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12315	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12316	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12317	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12318	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12319	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12320	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12321
12322	bwn_phy_lp_get_txpctlmode(mac);
12323	txpctlmode = plp->plp_txpctlmode;
12324	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12325
12326	/* disable CRS */
12327	bwn_phy_lp_set_deaf(mac, 1);
12328	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12329	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12330	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12331	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12332	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12333	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12334	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12335	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12336	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12337	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12338	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12339	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12340	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12341	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12342	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12343	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12344	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12345	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12346	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12347	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12348	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12349	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12350	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12351	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12352
12353	loopback = bwn_phy_lp_loopback(mac);
12354	if (loopback == -1)
12355		goto done;
12356	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12357	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12358	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12359	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12360	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12361
12362	tmp = 0;
12363	memset(&ie, 0, sizeof(ie));
12364	for (i = 128; i <= 159; i++) {
12365		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12366		sum = 0;
12367		for (j = 5; j <= 25; j++) {
12368			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12369			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12370				goto done;
12371			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12372			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12373			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12374			    12);
12375			sum += ((ipwr - npwr) * (ipwr - npwr));
12376			if ((i == 128) || (sum < tmp)) {
12377				plp->plp_rccap = i;
12378				tmp = sum;
12379			}
12380		}
12381	}
12382	bwn_phy_lp_ddfs_turnoff(mac);
12383done:
12384	/* restore CRS */
12385	bwn_phy_lp_clear_deaf(mac, 1);
12386	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12387	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12388
12389	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12390	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12391	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12392	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12393	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12394	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12395	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12396
12397	bwn_phy_lp_set_bbmult(mac, bbmult);
12398	if (txo)
12399		bwn_phy_lp_set_txgain(mac, &tx_gains);
12400	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12401	if (plp->plp_rccap)
12402		bwn_phy_lp_set_rccap(mac);
12403}
12404
12405static void
12406bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12407{
12408	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12409	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12410
12411	if (mac->mac_phy.rev == 1)
12412		rc_cap = MIN(rc_cap + 5, 15);
12413
12414	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12415	    MAX(plp->plp_rccap - 4, 0x80));
12416	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12417	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12418	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12419}
12420
12421static uint32_t
12422bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12423{
12424	uint32_t i, q, r;
12425
12426	if (div == 0)
12427		return (0);
12428
12429	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12430		q <<= 1;
12431		if (r << 1 >= div) {
12432			q++;
12433			r = (r << 1) - div;
12434		}
12435	}
12436	if (r << 1 >= div)
12437		q++;
12438	return (q);
12439}
12440
12441static void
12442bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12443{
12444	struct siba_dev_softc *sd = mac->mac_sd;
12445	struct siba_softc *siba = sd->sd_bus;
12446
12447	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12448	DELAY(20);
12449	if (siba->siba_chipid == 0x5354) {
12450		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12451		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12452	} else {
12453		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12454	}
12455	DELAY(5);
12456}
12457
12458static void
12459bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12460{
12461
12462	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12463	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12464	DELAY(200);
12465}
12466
12467static void
12468bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12469{
12470#define	FLAG_A	0x01
12471#define	FLAG_G	0x02
12472	struct bwn_softc *sc = mac->mac_sc;
12473	struct ifnet *ifp = sc->sc_ifp;
12474	struct ieee80211com *ic = ifp->if_l2com;
12475	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12476		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12478		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12479		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12480		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12481		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12487		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12516		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12517		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12518		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12519		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12520		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12521		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12522		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12523	};
12524	const struct bwn_b206x_rfinit_entry *br;
12525	unsigned int i;
12526
12527	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12528		br = &bwn_b2062_init_tab[i];
12529		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12530			if (br->br_flags & FLAG_G)
12531				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12532		} else {
12533			if (br->br_flags & FLAG_A)
12534				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12535		}
12536	}
12537#undef FLAG_A
12538#undef FLAG_B
12539}
12540
12541static void
12542bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12543{
12544#define	FLAG_A	0x01
12545#define	FLAG_G	0x02
12546	struct bwn_softc *sc = mac->mac_sc;
12547	struct ifnet *ifp = sc->sc_ifp;
12548	struct ieee80211com *ic = ifp->if_l2com;
12549	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12550		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12552		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12553		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12554		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12555		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12556		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12557		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12558		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12559		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12560		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12561		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12562		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12563		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12564		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12565		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12566		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12567		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12570		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12571		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12576		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12577		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12583		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12584		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12585		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12586		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12587		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12588		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12589		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12590		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12591		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12592	};
12593	const struct bwn_b206x_rfinit_entry *br;
12594	unsigned int i;
12595
12596	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12597		br = &bwn_b2063_init_tab[i];
12598		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12599			if (br->br_flags & FLAG_G)
12600				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12601		} else {
12602			if (br->br_flags & FLAG_A)
12603				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12604		}
12605	}
12606#undef FLAG_A
12607#undef FLAG_B
12608}
12609
12610static void
12611bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12612    int count, void *_data)
12613{
12614	unsigned int i;
12615	uint32_t offset, type;
12616	uint8_t *data = _data;
12617
12618	type = BWN_TAB_GETTYPE(typenoffset);
12619	offset = BWN_TAB_GETOFFSET(typenoffset);
12620	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12621
12622	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12623
12624	for (i = 0; i < count; i++) {
12625		switch (type) {
12626		case BWN_TAB_8BIT:
12627			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12628			data++;
12629			break;
12630		case BWN_TAB_16BIT:
12631			*((uint16_t *)data) = BWN_PHY_READ(mac,
12632			    BWN_PHY_TABLEDATALO);
12633			data += 2;
12634			break;
12635		case BWN_TAB_32BIT:
12636			*((uint32_t *)data) = BWN_PHY_READ(mac,
12637			    BWN_PHY_TABLEDATAHI);
12638			*((uint32_t *)data) <<= 16;
12639			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12640			    BWN_PHY_TABLEDATALO);
12641			data += 4;
12642			break;
12643		default:
12644			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12645		}
12646	}
12647}
12648
12649static void
12650bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12651    int count, const void *_data)
12652{
12653	uint32_t offset, type, value;
12654	const uint8_t *data = _data;
12655	unsigned int i;
12656
12657	type = BWN_TAB_GETTYPE(typenoffset);
12658	offset = BWN_TAB_GETOFFSET(typenoffset);
12659	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12660
12661	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12662
12663	for (i = 0; i < count; i++) {
12664		switch (type) {
12665		case BWN_TAB_8BIT:
12666			value = *data;
12667			data++;
12668			KASSERT(!(value & ~0xff),
12669			    ("%s:%d: fail", __func__, __LINE__));
12670			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12671			break;
12672		case BWN_TAB_16BIT:
12673			value = *((const uint16_t *)data);
12674			data += 2;
12675			KASSERT(!(value & ~0xffff),
12676			    ("%s:%d: fail", __func__, __LINE__));
12677			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12678			break;
12679		case BWN_TAB_32BIT:
12680			value = *((const uint32_t *)data);
12681			data += 4;
12682			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12683			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12684			break;
12685		default:
12686			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12687		}
12688	}
12689}
12690
12691static struct bwn_txgain
12692bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12693{
12694	struct bwn_txgain tg;
12695	uint16_t tmp;
12696
12697	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12698	if (mac->mac_phy.rev < 2) {
12699		tmp = BWN_PHY_READ(mac,
12700		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12701		tg.tg_gm = tmp & 0x0007;
12702		tg.tg_pga = (tmp & 0x0078) >> 3;
12703		tg.tg_pad = (tmp & 0x780) >> 7;
12704		return (tg);
12705	}
12706
12707	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12708	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12709	tg.tg_gm = tmp & 0xff;
12710	tg.tg_pga = (tmp >> 8) & 0xff;
12711	return (tg);
12712}
12713
12714static uint8_t
12715bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12716{
12717
12718	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12719}
12720
12721static void
12722bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12723{
12724	uint16_t pa;
12725
12726	if (mac->mac_phy.rev < 2) {
12727		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12728		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12729		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12730		bwn_phy_lp_set_txgain_override(mac);
12731		return;
12732	}
12733
12734	pa = bwn_phy_lp_get_pa_gain(mac);
12735	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12736	    (tg->tg_pga << 8) | tg->tg_gm);
12737	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12738	    tg->tg_pad | (pa << 6));
12739	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12740	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12741	    tg->tg_pad | (pa << 8));
12742	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12743	bwn_phy_lp_set_txgain_override(mac);
12744}
12745
12746static void
12747bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12748{
12749
12750	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12751}
12752
12753static void
12754bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12755{
12756	uint16_t trsw = (tx << 1) | rx;
12757
12758	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12759	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12760}
12761
12762static void
12763bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12764{
12765	struct bwn_softc *sc = mac->mac_sc;
12766	struct ifnet *ifp = sc->sc_ifp;
12767	struct ieee80211com *ic = ifp->if_l2com;
12768	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12769
12770	if (mac->mac_phy.rev < 2) {
12771		trsw = gain & 0x1;
12772		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12773		ext_lna = (gain & 2) >> 1;
12774
12775		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12776		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12777		    0xfbff, ext_lna << 10);
12778		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12779		    0xf7ff, ext_lna << 11);
12780		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12781	} else {
12782		low_gain = gain & 0xffff;
12783		high_gain = (gain >> 16) & 0xf;
12784		ext_lna = (gain >> 21) & 0x1;
12785		trsw = ~(gain >> 20) & 0x1;
12786
12787		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12788		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12789		    0xfdff, ext_lna << 9);
12790		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12791		    0xfbff, ext_lna << 10);
12792		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12793		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12794		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12795			tmp = (gain >> 2) & 0x3;
12796			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12797			    0xe7ff, tmp<<11);
12798			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12799			    tmp << 3);
12800		}
12801	}
12802
12803	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12804	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12805	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12806	if (mac->mac_phy.rev >= 2) {
12807		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12808		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12809			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12810			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12811		}
12812		return;
12813	}
12814	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12815}
12816
12817static void
12818bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12819{
12820	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12821
12822	if (user)
12823		plp->plp_crsusr_off = 1;
12824	else
12825		plp->plp_crssys_off = 1;
12826
12827	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12828}
12829
12830static void
12831bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12832{
12833	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12834	struct bwn_softc *sc = mac->mac_sc;
12835	struct ifnet *ifp = sc->sc_ifp;
12836	struct ieee80211com *ic = ifp->if_l2com;
12837
12838	if (user)
12839		plp->plp_crsusr_off = 0;
12840	else
12841		plp->plp_crssys_off = 0;
12842
12843	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12844		return;
12845
12846	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12847		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12848	else
12849		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12850}
12851
12852static unsigned int
12853bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12854{
12855	struct bwn_softc *sc = mac->mac_sc;
12856	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12857	static uint8_t sqrt_table[256] = {
12858		10, 14, 17, 20, 22, 24, 26, 28,
12859		30, 31, 33, 34, 36, 37, 38, 40,
12860		41, 42, 43, 44, 45, 46, 47, 48,
12861		50, 50, 51, 52, 53, 54, 55, 56,
12862		57, 58, 59, 60, 60, 61, 62, 63,
12863		64, 64, 65, 66, 67, 67, 68, 69,
12864		70, 70, 71, 72, 72, 73, 74, 74,
12865		75, 76, 76, 77, 78, 78, 79, 80,
12866		80, 81, 81, 82, 83, 83, 84, 84,
12867		85, 86, 86, 87, 87, 88, 88, 89,
12868		90, 90, 91, 91, 92, 92, 93, 93,
12869		94, 94, 95, 95, 96, 96, 97, 97,
12870		98, 98, 99, 100, 100, 100, 101, 101,
12871		102, 102, 103, 103, 104, 104, 105, 105,
12872		106, 106, 107, 107, 108, 108, 109, 109,
12873		110, 110, 110, 111, 111, 112, 112, 113,
12874		113, 114, 114, 114, 115, 115, 116, 116,
12875		117, 117, 117, 118, 118, 119, 119, 120,
12876		120, 120, 121, 121, 122, 122, 122, 123,
12877		123, 124, 124, 124, 125, 125, 126, 126,
12878		126, 127, 127, 128, 128, 128, 129, 129,
12879		130, 130, 130, 131, 131, 131, 132, 132,
12880		133, 133, 133, 134, 134, 134, 135, 135,
12881		136, 136, 136, 137, 137, 137, 138, 138,
12882		138, 139, 139, 140, 140, 140, 141, 141,
12883		141, 142, 142, 142, 143, 143, 143, 144,
12884		144, 144, 145, 145, 145, 146, 146, 146,
12885		147, 147, 147, 148, 148, 148, 149, 149,
12886		150, 150, 150, 150, 151, 151, 151, 152,
12887		152, 152, 153, 153, 153, 154, 154, 154,
12888		155, 155, 155, 156, 156, 156, 157, 157,
12889		157, 158, 158, 158, 159, 159, 159, 160
12890	};
12891
12892	if (x == 0)
12893		return (0);
12894	if (x >= 256) {
12895		device_printf(sc->sc_dev,
12896		    "out of bounds of the square-root table (%d)\n", x);
12897		return (16);
12898	}
12899	return (sqrt_table[x - 1] / 10);
12900}
12901
12902static int
12903bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12904{
12905#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12906	int _t;								\
12907	_t = _x - 20;							\
12908	if (_t >= 0) {							\
12909		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12910	} else {							\
12911		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12912	}								\
12913} while (0)
12914#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12915	int _t;								\
12916	_t = _x - 11;							\
12917	if (_t >= 0)							\
12918		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12919	else								\
12920		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12921} while (0)
12922	struct bwn_phy_lp_iq_est ie;
12923	uint16_t v0, v1;
12924	int tmp[2], ret;
12925
12926	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12927	v0 = v1 >> 8;
12928	v1 |= 0xff;
12929
12930	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12931	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12932
12933	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12934	if (ret == 0)
12935		goto done;
12936
12937	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12938		ret = 0;
12939		goto done;
12940	}
12941
12942	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12943	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12944
12945	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12946	v0 = tmp[0] >> 3;
12947	v1 = tmp[1] >> 4;
12948done:
12949	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12950	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12951	return ret;
12952#undef CALC_COEFF
12953#undef CALC_COEFF2
12954}
12955
12956static void
12957bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12958{
12959	static const uint16_t noisescale[] = {
12960		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12961		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12962		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12963		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12964		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12965	};
12966	static const uint16_t crsgainnft[] = {
12967		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12968		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12969		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12970		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12971		0x013d,
12972	};
12973	static const uint16_t filterctl[] = {
12974		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12975		0xff53, 0x0127,
12976	};
12977	static const uint32_t psctl[] = {
12978		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12979		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12980		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12981		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12982		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12983		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12984		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12985		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12986	};
12987	static const uint16_t ofdmcckgain_r0[] = {
12988		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12989		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12990		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12991		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12992		0x755d,
12993	};
12994	static const uint16_t ofdmcckgain_r1[] = {
12995		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12996		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12997		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12998		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12999		0x755d,
13000	};
13001	static const uint16_t gaindelta[] = {
13002		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13003		0x0000,
13004	};
13005	static const uint32_t txpwrctl[] = {
13006		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13007		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13008		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13009		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13010		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13011		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13012		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13013		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13014		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13015		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13016		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13017		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13018		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13019		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13038		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13039		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13040		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13041		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13042		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13043		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13044		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13045		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13046		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13047		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13048		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13049		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13050		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13051		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13052		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13053		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13054		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13055		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13056		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13057		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13058		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13059		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13060		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13061		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13062		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13063		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13064		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13065		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13066		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13067		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13068		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13069		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13070		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13071		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13072		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13073		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13074		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13075		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13076		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13077		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13078		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13079		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13080		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13081		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13082		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13083		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13084		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13085		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13086		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13087		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13088		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13089		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13090		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13091		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13092		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13093		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13094		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13095		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13096		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13097		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13098		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13099		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13100		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13101		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13102		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13103		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13104		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13105		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13106		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13107		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13108		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13109		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13110		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13111		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13112		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13113		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13114		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13115		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13116		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13117		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13118		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13119		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13120		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13121		0x00000702,
13122	};
13123
13124	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13125
13126	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13127	    bwn_tab_sigsq_tbl);
13128	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13129	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13130	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13131	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13132	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13133	    bwn_tab_pllfrac_tbl);
13134	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13135	    bwn_tabl_iqlocal_tbl);
13136	if (mac->mac_phy.rev == 0) {
13137		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13138		    ofdmcckgain_r0);
13139		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13140		    ofdmcckgain_r0);
13141	} else {
13142		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13143		    ofdmcckgain_r1);
13144		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13145		    ofdmcckgain_r1);
13146	}
13147	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13148	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13149}
13150
13151static void
13152bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13153{
13154	struct siba_dev_softc *sd = mac->mac_sd;
13155	struct siba_softc *siba = sd->sd_bus;
13156	int i;
13157	static const uint16_t noisescale[] = {
13158		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13159		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13160		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13161		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13162		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13163		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13164		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13165	};
13166	static const uint32_t filterctl[] = {
13167		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13168		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13169	};
13170	static const uint32_t psctl[] = {
13171		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13172		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13173		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13174		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13175	};
13176	static const uint32_t gainidx[] = {
13177		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13178		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13179		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13180		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13181		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13182		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13183		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13184		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13185		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13186		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13187		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13188		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13189		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13190		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13191		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13192		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13193		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13194		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13195		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13196		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13197		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13198		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13199		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13200		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13201		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13202		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13203		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13204		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13205		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13206		0x0000001a, 0x64ca55ad, 0x0000001a
13207	};
13208	static const uint16_t auxgainidx[] = {
13209		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13210		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13211		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13212		0x0004, 0x0016
13213	};
13214	static const uint16_t swctl[] = {
13215		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13216		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13217		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13218		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13219		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13220		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13221		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13222		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13223	};
13224	static const uint8_t hf[] = {
13225		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13226		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13227	};
13228	static const uint32_t gainval[] = {
13229		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13230		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13231		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13232		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13233		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13234		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13235		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13236		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13237		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13238		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13239		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13240		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13241		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13242		0x000000f1, 0x00000000, 0x00000000
13243	};
13244	static const uint16_t gain[] = {
13245		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13246		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13247		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13248		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13249		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13250		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13251		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13252		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13254		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13255		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13256		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13257	};
13258	static const uint32_t papdeps[] = {
13259		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13260		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13261		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13262		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13263		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13264		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13265		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13266		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13267		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13268		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13269		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13270		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13271		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13272	};
13273	static const uint32_t papdmult[] = {
13274		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13275		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13276		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13277		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13278		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13279		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13280		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13281		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13282		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13283		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13284		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13285		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13286		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13287	};
13288	static const uint32_t gainidx_a0[] = {
13289		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13290		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13291		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13292		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13293		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13294		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13295		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13296		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13297		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13298		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13299		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13300		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13301		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13302	};
13303	static const uint16_t auxgainidx_a0[] = {
13304		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13305		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13306		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13307		0x0002, 0x0014
13308	};
13309	static const uint32_t gainval_a0[] = {
13310		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13311		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13312		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13313		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13314		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13315		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13316		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13317		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13318		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13319		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13320		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13321		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13322		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13323		0x000000f7, 0x00000000, 0x00000000
13324	};
13325	static const uint16_t gain_a0[] = {
13326		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13327		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13328		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13329		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13330		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13331		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13332		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13333		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13334		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13335		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13336		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13337		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13338	};
13339
13340	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13341
13342	for (i = 0; i < 704; i++)
13343		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13344
13345	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13346	    bwn_tab_sigsq_tbl);
13347	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13348	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13349	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13350	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13351	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13352	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13353	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13354	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13355	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13356	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13357	    bwn_tab_pllfrac_tbl);
13358	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13359	    bwn_tabl_iqlocal_tbl);
13360	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13361	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13362
13363	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13364		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13365		    gainidx_a0);
13366		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13367		    auxgainidx_a0);
13368		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13369		    gainval_a0);
13370		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13371	}
13372}
13373
13374static void
13375bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13376{
13377	struct siba_dev_softc *sd = mac->mac_sd;
13378	struct siba_softc *siba = sd->sd_bus;
13379	struct bwn_softc *sc = mac->mac_sc;
13380	struct ifnet *ifp = sc->sc_ifp;
13381	struct ieee80211com *ic = ifp->if_l2com;
13382	static struct bwn_txgain_entry txgain_r2[] = {
13383		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13384		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13385		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13386		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13387		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13388		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13389		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13390		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13391		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13392		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13393		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13394		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13395		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13396		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13397		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13398		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13399		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13400		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13401		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13402		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13403		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13404		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13405		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13406		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13407		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13408		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13409		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13410		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13411		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13412		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13413		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13414		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13415		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13416		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13417		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13418		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13419		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13420		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13421		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13422		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13423		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13424		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13425		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13426		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13427		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13428		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13429		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13430		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13431		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13432		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13433		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13434		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13435		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13436		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13437		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13438		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13439		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13440		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13441		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13442		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13443		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13444		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13445		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13446		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13447	};
13448	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13449		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13450		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13451		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13452		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13453		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13454		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13455		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13456		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13457		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13458		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13459		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13460		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13461		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13462		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13463		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13464		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13465		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13466		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13467		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13468		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13469		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13470		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13471		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13472		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13473		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13474		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13475		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13476		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13477		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13478		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13479		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13480		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13481		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13482		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13483		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13484		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13485		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13486		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13487		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13488		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13489		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13490		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13491		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13492		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13493		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13494		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13495		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13496		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13497		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13498		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13499		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13500		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13501		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13502		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13503		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13504		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13505		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13506		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13507		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13508		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13509		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13510		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13511		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13512		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13513	};
13514	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13515		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13516		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13517		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13518		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13519		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13520		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13521		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13522		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13523		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13524		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13525		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13526		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13527		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13528		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13529		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13530		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13531		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13532		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13533		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13534		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13535		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13536		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13537		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13538		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13539		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13540		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13541		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13542		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13543		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13544		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13545		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13546		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13547		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13548		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13549		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13550		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13551		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13552		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13553		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13554		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13555		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13556		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13557		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13558		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13559		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13560		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13561		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13562		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13563		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13564		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13565		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13566		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13567		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13568		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13569		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13570		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13571		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13572		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13573		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13574		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13575		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13576		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13577		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13578		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13579	};
13580	static struct bwn_txgain_entry txgain_r0[] = {
13581		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13582		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13583		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13584		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13585		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13586		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13587		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13588		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13589		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13590		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13591		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13592		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13593		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13594		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13595		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13596		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13597		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13598		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13599		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13600		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13601		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13602		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13603		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13604		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13605		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13606		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13607		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13608		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13609		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13610		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13611		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13612		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13613		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13614		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13615		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13616		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13617		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13618		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13619		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13620		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13621		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13622		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13623		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13624		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13625		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13626		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13627		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13628		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13629		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13630		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13631		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13632		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13633		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13634		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13635		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13636		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13637		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13638		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13639		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13640		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13641		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13642		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13643		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13644		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13645	};
13646	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13647		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13648		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13649		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13650		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13651		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13652		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13653		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13654		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13655		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13656		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13657		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13658		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13659		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13660		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13661		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13662		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13663		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13664		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13665		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13666		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13667		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13668		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13669		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13670		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13671		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13672		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13673		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13674		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13675		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13676		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13677		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13678		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13679		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13680		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13681		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13682		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13683		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13684		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13685		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13686		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13687		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13688		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13689		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13690		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13691		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13692		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13693		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13694		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13695		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13696		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13697		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13698		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13699		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13700		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13701		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13702		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13703		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13704		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13705		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13706		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13707		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13708		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13709		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13710		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13711	};
13712	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13713		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13714		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13715		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13716		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13717		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13718		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13719		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13720		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13721		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13722		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13723		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13724		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13725		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13726		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13727		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13728		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13729		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13730		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13731		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13732		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13733		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13734		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13735		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13736		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13737		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13738		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13739		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13740		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13741		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13742		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13743		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13744		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13745		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13746		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13747		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13748		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13749		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13750		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13751		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13752		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13753		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13754		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13755		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13756		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13757		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13758		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13759		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13760		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13761		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13762		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13763		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13764		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13765		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13766		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13767		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13768		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13769		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13770		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13771		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13772		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13773		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13774		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13775		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13776		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13777	};
13778	static struct bwn_txgain_entry txgain_r1[] = {
13779		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13780		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13781		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13782		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13783		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13784		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13785		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13786		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13787		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13788		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13789		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13790		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13791		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13792		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13793		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13794		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13795		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13796		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13797		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13798		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13799		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13800		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13801		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13802		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13803		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13804		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13805		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13806		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13807		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13808		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13809		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13810		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13811		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13812		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13813		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13814		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13815		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13816		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13817		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13818		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13819		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13820		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13821		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13822		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13823		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13824		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13825		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13826		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13827		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13828		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13829		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13830		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13831		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13832		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13833		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13834		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13835		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13836		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13837		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13838		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13839		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13840		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13841		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13842		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13843		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13844		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13845		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13846		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13847		{ 7, 11, 6, 0, 71 }
13848	};
13849	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13850		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13851		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13852		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13853		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13854		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13855		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13856		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13857		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13858		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13859		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13860		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13861		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13862		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13863		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13864		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13865		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13866		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13867		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13868		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13869		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13870		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13871		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13872		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13873		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13874		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13875		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13876		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13877		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13878		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13879		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13880		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13881		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13882		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13883		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13884		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13885		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13886		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13887		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13888		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13889		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13890		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13891		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13892		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13893		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13894		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13895		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13896		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13897		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13898		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13899		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13900		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13901		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13902		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13903		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13904		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13905		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13906		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13907		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13908		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13909		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13910		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13911		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13912		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13913		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13914	};
13915	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13916		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13917		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13918		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13919		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13920		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13921		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13922		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13923		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13924		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13925		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13926		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13927		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13928		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13929		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13930		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13931		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13932		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13933		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13934		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13935		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13936		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13937		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13938		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13939		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13940		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13941		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13942		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13943		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13944		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13945		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13946		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13947		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13948		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13949		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13950		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13951		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13952		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13953		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13954		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13955		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13956		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13957		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13958		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13959		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13960		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13961		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13962		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13963		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13964		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13965		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13966		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13967		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13968		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13969		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13970		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13971		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13972		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13973		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13974		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13975		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13976		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13977		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13978		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13979		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13980	};
13981
13982	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13983		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13984			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13985		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13986			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13987			    txgain_2ghz_r2);
13988		else
13989			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13990			    txgain_5ghz_r2);
13991		return;
13992	}
13993
13994	if (mac->mac_phy.rev == 0) {
13995		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13996		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13997			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13998		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13999			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
14000			    txgain_2ghz_r0);
14001		else
14002			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
14003			    txgain_5ghz_r0);
14004		return;
14005	}
14006
14007	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14008	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14009		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14010	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14011		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14012	else
14013		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14014}
14015
14016static void
14017bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14018{
14019	uint32_t offset, type;
14020
14021	type = BWN_TAB_GETTYPE(typeoffset);
14022	offset = BWN_TAB_GETOFFSET(typeoffset);
14023	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14024
14025	switch (type) {
14026	case BWN_TAB_8BIT:
14027		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14028		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14029		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14030		break;
14031	case BWN_TAB_16BIT:
14032		KASSERT(!(value & ~0xffff),
14033		    ("%s:%d: fail", __func__, __LINE__));
14034		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14035		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14036		break;
14037	case BWN_TAB_32BIT:
14038		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14039		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14040		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14041		break;
14042	default:
14043		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14044	}
14045}
14046
14047static int
14048bwn_phy_lp_loopback(struct bwn_mac *mac)
14049{
14050	struct bwn_phy_lp_iq_est ie;
14051	int i, index = -1;
14052	uint32_t tmp;
14053
14054	memset(&ie, 0, sizeof(ie));
14055
14056	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14057	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14058	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14059	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14060	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14061	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14062	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14063	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14064	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14065	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14066	for (i = 0; i < 32; i++) {
14067		bwn_phy_lp_set_rxgain_idx(mac, i);
14068		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14069		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14070			continue;
14071		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14072		if ((tmp > 4000) && (tmp < 10000)) {
14073			index = i;
14074			break;
14075		}
14076	}
14077	bwn_phy_lp_ddfs_turnoff(mac);
14078	return (index);
14079}
14080
14081static void
14082bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14083{
14084
14085	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14086}
14087
14088static void
14089bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14090    int incr1, int incr2, int scale_idx)
14091{
14092
14093	bwn_phy_lp_ddfs_turnoff(mac);
14094	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14095	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14096	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14097	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14098	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14099	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14100	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14101	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14102	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14103	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14104}
14105
14106static uint8_t
14107bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14108    struct bwn_phy_lp_iq_est *ie)
14109{
14110	int i;
14111
14112	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14113	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14114	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14115	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14116	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14117
14118	for (i = 0; i < 500; i++) {
14119		if (!(BWN_PHY_READ(mac,
14120		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14121			break;
14122		DELAY(1000);
14123	}
14124	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14125		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14126		return 0;
14127	}
14128
14129	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14130	ie->ie_iqprod <<= 16;
14131	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14132	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14133	ie->ie_ipwr <<= 16;
14134	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14135	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14136	ie->ie_qpwr <<= 16;
14137	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14138
14139	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14140	return 1;
14141}
14142
14143static uint32_t
14144bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14145{
14146	uint32_t offset, type, value;
14147
14148	type = BWN_TAB_GETTYPE(typeoffset);
14149	offset = BWN_TAB_GETOFFSET(typeoffset);
14150	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14151
14152	switch (type) {
14153	case BWN_TAB_8BIT:
14154		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14155		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14156		break;
14157	case BWN_TAB_16BIT:
14158		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14159		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14160		break;
14161	case BWN_TAB_32BIT:
14162		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14163		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14164		value <<= 16;
14165		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14166		break;
14167	default:
14168		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14169		value = 0;
14170	}
14171
14172	return (value);
14173}
14174
14175static void
14176bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14177{
14178
14179	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14180	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14181}
14182
14183static void
14184bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14185{
14186	uint16_t ctl;
14187
14188	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14189	ctl |= dac << 7;
14190	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14191}
14192
14193static void
14194bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14195{
14196
14197	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14198	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14199}
14200
14201static void
14202bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14203{
14204
14205	if (mac->mac_phy.rev < 2)
14206		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14207	else {
14208		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14209		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14210	}
14211	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14212}
14213
14214static uint16_t
14215bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14216{
14217
14218	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14219}
14220
14221static uint8_t
14222bwn_nbits(int32_t val)
14223{
14224	uint32_t tmp;
14225	uint8_t nbits = 0;
14226
14227	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14228		nbits++;
14229	return (nbits);
14230}
14231
14232static void
14233bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14234    struct bwn_txgain_entry *table)
14235{
14236	int i;
14237
14238	for (i = offset; i < count; i++)
14239		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14240}
14241
14242static void
14243bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14244    struct bwn_txgain_entry data)
14245{
14246
14247	if (mac->mac_phy.rev >= 2)
14248		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14249	else
14250		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14251}
14252
14253static void
14254bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14255    struct bwn_txgain_entry te)
14256{
14257	struct bwn_softc *sc = mac->mac_sc;
14258	struct ifnet *ifp = sc->sc_ifp;
14259	struct ieee80211com *ic = ifp->if_l2com;
14260	uint32_t tmp;
14261
14262	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14263
14264	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14265	if (mac->mac_phy.rev >= 3) {
14266		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14267		    (0x10 << 24) : (0x70 << 24));
14268	} else {
14269		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14270		    (0x14 << 24) : (0x7f << 24));
14271	}
14272	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14273	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14274	    te.te_bbmult << 20 | te.te_dac << 28);
14275}
14276
14277static void
14278bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14279    struct bwn_txgain_entry te)
14280{
14281
14282	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14283
14284	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14285	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14286	    te.te_dac);
14287	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14288}
14289
14290static void
14291bwn_identify(driver_t *driver, device_t parent)
14292{
14293
14294	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14295}
14296
14297static device_method_t bwn_methods[] = {
14298	/* Device interface */
14299	DEVMETHOD(device_identify,	bwn_identify),
14300	DEVMETHOD(device_probe,		bwn_probe),
14301	DEVMETHOD(device_attach,	bwn_attach),
14302	DEVMETHOD(device_detach,	bwn_detach),
14303	DEVMETHOD(device_suspend,	bwn_suspend),
14304	DEVMETHOD(device_resume,	bwn_resume),
14305	{ 0,0 }
14306};
14307static driver_t bwn_driver = {
14308	"bwn",
14309	bwn_methods,
14310	sizeof(struct bwn_softc)
14311};
14312static devclass_t bwn_devclass;
14313DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14314MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14315MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14316MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14317MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14318