if_bwn.c revision 204657
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 204657 2010-03-03 20:06:09Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(struct siba_softc *);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_fix_imcfglobug(struct bwn_mac *);
209static void	bwn_bt_disable(struct bwn_mac *);
210static int	bwn_chip_init(struct bwn_mac *);
211static uint64_t	bwn_hf_read(struct bwn_mac *);
212static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213static void	bwn_set_txretry(struct bwn_mac *, int, int);
214static void	bwn_rate_init(struct bwn_mac *);
215static void	bwn_set_phytxctl(struct bwn_mac *);
216static void	bwn_spu_setdelay(struct bwn_mac *, int);
217static void	bwn_bt_enable(struct bwn_mac *);
218static void	bwn_set_macaddr(struct bwn_mac *);
219static void	bwn_crypt_init(struct bwn_mac *);
220static void	bwn_chip_exit(struct bwn_mac *);
221static int	bwn_fw_fillinfo(struct bwn_mac *);
222static int	bwn_fw_loaducode(struct bwn_mac *);
223static int	bwn_gpio_init(struct bwn_mac *);
224static int	bwn_fw_loadinitvals(struct bwn_mac *);
225static int	bwn_phy_init(struct bwn_mac *);
226static void	bwn_set_txantenna(struct bwn_mac *, int);
227static void	bwn_set_opmode(struct bwn_mac *);
228static void	bwn_gpio_cleanup(struct bwn_mac *);
229static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230static uint8_t	bwn_plcp_getcck(const uint8_t);
231static uint8_t	bwn_plcp_getofdm(const uint8_t);
232static void	bwn_pio_init(struct bwn_mac *);
233static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    int);
236static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237		    struct bwn_pio_rxqueue *, int);
238static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240		    uint16_t);
241static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244static void	bwn_pio_handle_txeof(struct bwn_mac *,
245		    const struct bwn_txstatus *);
246static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249		    uint16_t);
250static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251		    uint32_t);
252static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253		    struct mbuf *);
254static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258		    uint16_t, uint32_t);
259static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264		    uint16_t, struct bwn_pio_txpkt **);
265static void	bwn_dma_init(struct bwn_mac *);
266static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267static int	bwn_dma_mask2type(uint64_t);
268static uint64_t	bwn_dma_mask(struct bwn_mac *);
269static uint16_t	bwn_dma_base(int, int);
270static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272		    int, struct bwn_dmadesc_generic **,
273		    struct bwn_dmadesc_meta **);
274static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276		    int, int);
277static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283		    int, struct bwn_dmadesc_generic **,
284		    struct bwn_dmadesc_meta **);
285static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287		    int, int);
288static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_setup(struct bwn_dma_ring *);
295static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_rx(struct bwn_dma_ring *);
300static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302		    struct bwn_dmadesc_meta *);
303static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304static int	bwn_dma_gettype(struct bwn_mac *);
305static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311		    int);
312static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313		    bus_size_t, int);
314static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315static void	bwn_dma_handle_txeof(struct bwn_mac *,
316		    const struct bwn_txstatus *);
317static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318		    struct mbuf *);
319static int	bwn_dma_getslot(struct bwn_dma_ring *);
320static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321		    uint8_t);
322static int	bwn_dma_attach(struct bwn_mac *);
323static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324		    int, int, int);
325static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326		    const struct bwn_txstatus *, uint16_t, int *);
327static void	bwn_dma_free(struct bwn_mac *);
328static void	bwn_phy_g_init_sub(struct bwn_mac *);
329static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330static void	bwn_phy_init_b5(struct bwn_mac *);
331static void	bwn_phy_init_b6(struct bwn_mac *);
332static void	bwn_phy_init_a(struct bwn_mac *);
333static void	bwn_loopback_calcgain(struct bwn_mac *);
334static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335static void	bwn_lo_g_init(struct bwn_mac *);
336static void	bwn_lo_g_adjust(struct bwn_mac *);
337static void	bwn_lo_get_powervector(struct bwn_mac *);
338static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345		    uint8_t);
346static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349static void	bwn_wa_init(struct bwn_mac *);
350static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354		    uint32_t);
355static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356		    uint16_t);
357static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358static void	bwn_mac_suspend(struct bwn_mac *);
359static void	bwn_mac_enable(struct bwn_mac *);
360static void	bwn_psctl(struct bwn_mac *, uint32_t);
361static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362static void	bwn_nrssi_offset(struct bwn_mac *);
363static void	bwn_nrssi_threshold(struct bwn_mac *);
364static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366		    int16_t);
367static void	bwn_set_original_gains(struct bwn_mac *);
368static void	bwn_hwpctl_early_init(struct bwn_mac *);
369static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373		    const char *, struct bwn_fwfile *);
374static void	bwn_release_firmware(struct bwn_mac *);
375static void	bwn_do_release_fw(struct bwn_fwfile *);
376static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377static int	bwn_fwinitvals_write(struct bwn_mac *,
378		    const struct bwn_fwinitvals *, size_t, size_t);
379static int	bwn_switch_channel(struct bwn_mac *, int);
380static uint16_t	bwn_ant2phy(int);
381static void	bwn_mac_write_bssid(struct bwn_mac *);
382static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383		    const uint8_t *);
384static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385		    const uint8_t *, size_t, const uint8_t *);
386static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387		    const uint8_t *);
388static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389		    const uint8_t *);
390static void	bwn_phy_exit(struct bwn_mac *);
391static void	bwn_core_stop(struct bwn_mac *);
392static int	bwn_switch_band(struct bwn_softc *,
393		    struct ieee80211_channel *);
394static void	bwn_phy_reset(struct bwn_mac *);
395static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396static void	bwn_set_pretbtt(struct bwn_mac *);
397static int	bwn_intr(void *);
398static void	bwn_intrtask(void *, int);
399static void	bwn_restart(struct bwn_mac *, const char *);
400static void	bwn_intr_ucode_debug(struct bwn_mac *);
401static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402static void	bwn_intr_atim_end(struct bwn_mac *);
403static void	bwn_intr_beacon(struct bwn_mac *);
404static void	bwn_intr_pmq(struct bwn_mac *);
405static void	bwn_intr_noise(struct bwn_mac *);
406static void	bwn_intr_txeof(struct bwn_mac *);
407static void	bwn_hwreset(void *, int);
408static void	bwn_handle_fwpanic(struct bwn_mac *);
409static void	bwn_load_beacon0(struct bwn_mac *);
410static void	bwn_load_beacon1(struct bwn_mac *);
411static uint32_t	bwn_jssi_read(struct bwn_mac *);
412static void	bwn_noise_gensample(struct bwn_mac *);
413static void	bwn_handle_txeof(struct bwn_mac *,
414		    const struct bwn_txstatus *);
415static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417static void	bwn_start_locked(struct ifnet *);
418static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419		    struct mbuf *);
420static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421static int	bwn_set_txhdr(struct bwn_mac *,
422		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423		    uint16_t);
424static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425		    const uint8_t);
426static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427static uint8_t	bwn_get_fbrate(uint8_t);
428static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430static void	bwn_phy_lock(struct bwn_mac *);
431static void	bwn_phy_unlock(struct bwn_mac *);
432static void	bwn_rf_lock(struct bwn_mac *);
433static void	bwn_rf_unlock(struct bwn_mac *);
434static void	bwn_txpwr(void *, int);
435static void	bwn_tasks(void *);
436static void	bwn_task_15s(struct bwn_mac *);
437static void	bwn_task_30s(struct bwn_mac *);
438static void	bwn_task_60s(struct bwn_mac *);
439static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440		    uint8_t);
441static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444		    int, int);
445static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448static void	bwn_watchdog(void *);
449static void	bwn_dma_stop(struct bwn_mac *);
450static void	bwn_pio_stop(struct bwn_mac *);
451static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452static void	bwn_led_attach(struct bwn_mac *);
453static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454static void	bwn_led_event(struct bwn_mac *, int);
455static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456static void	bwn_led_blink_next(void *);
457static void	bwn_led_blink_end(void *);
458static void	bwn_rfswitch(void *);
459static void	bwn_rf_turnon(struct bwn_mac *);
460static void	bwn_rf_turnoff(struct bwn_mac *);
461static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462static int	bwn_phy_lp_init(struct bwn_mac *);
463static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466		    uint16_t);
467static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477static void	bwn_phy_lp_calib(struct bwn_mac *);
478static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500		    const void *);
501static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502static struct bwn_txgain
503		bwn_phy_lp_get_txgain(struct bwn_mac *);
504static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518static int	bwn_phy_lp_loopback(struct bwn_mac *);
519static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521		    int);
522static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523		    struct bwn_phy_lp_iq_est *);
524static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530static uint8_t	bwn_nbits(int32_t);
531static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532		    struct bwn_txgain_entry *);
533static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538		    struct bwn_txgain_entry);
539static void	bwn_sysctl_node(struct bwn_softc *);
540
541static struct resource_spec bwn_res_spec_legacy[] = {
542	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
543	{ -1,			0,		0 }
544};
545
546static struct resource_spec bwn_res_spec_msi[] = {
547	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
548	{ -1,			0,		0 }
549};
550
551static const struct bwn_channelinfo bwn_chantable_bg = {
552	.channels = {
553		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
554		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
555		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
556		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
557		{ 2472, 13, 30 }, { 2484, 14, 30 } },
558	.nchannels = 14
559};
560
561static const struct bwn_channelinfo bwn_chantable_a = {
562	.channels = {
563		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
564		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
565		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
566		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
567		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
568		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
569		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
570		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
571		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
572		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
573		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
574		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
575		{ 6080, 216, 30 } },
576	.nchannels = 37
577};
578
579static const struct bwn_channelinfo bwn_chantable_n = {
580	.channels = {
581		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
582		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
583		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
584		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
585		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
586		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
587		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
588		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
589		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
590		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
591		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
592		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
593		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
594		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
595		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
596		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
597		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
598		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
599		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
600		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
601		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
602		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
603		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
604		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
605		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
606		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
607		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
608		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
609		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
610		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
611		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
612		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
613		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
614		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
615		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
616		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
617		{ 6130, 226, 30 }, { 6140, 228, 30 } },
618	.nchannels = 110
619};
620
621static const uint8_t bwn_b2063_chantable_data[33][12] = {
622	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
627	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
628	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
629	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
633	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
634	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
635	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
636	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
638	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
639	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
640	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
641	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
643	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
647	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
654	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
655};
656
657static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
658	{ 1, 2412, bwn_b2063_chantable_data[0] },
659	{ 2, 2417, bwn_b2063_chantable_data[0] },
660	{ 3, 2422, bwn_b2063_chantable_data[0] },
661	{ 4, 2427, bwn_b2063_chantable_data[1] },
662	{ 5, 2432, bwn_b2063_chantable_data[1] },
663	{ 6, 2437, bwn_b2063_chantable_data[1] },
664	{ 7, 2442, bwn_b2063_chantable_data[1] },
665	{ 8, 2447, bwn_b2063_chantable_data[1] },
666	{ 9, 2452, bwn_b2063_chantable_data[2] },
667	{ 10, 2457, bwn_b2063_chantable_data[2] },
668	{ 11, 2462, bwn_b2063_chantable_data[3] },
669	{ 12, 2467, bwn_b2063_chantable_data[3] },
670	{ 13, 2472, bwn_b2063_chantable_data[3] },
671	{ 14, 2484, bwn_b2063_chantable_data[4] },
672	{ 34, 5170, bwn_b2063_chantable_data[5] },
673	{ 36, 5180, bwn_b2063_chantable_data[6] },
674	{ 38, 5190, bwn_b2063_chantable_data[7] },
675	{ 40, 5200, bwn_b2063_chantable_data[8] },
676	{ 42, 5210, bwn_b2063_chantable_data[9] },
677	{ 44, 5220, bwn_b2063_chantable_data[10] },
678	{ 46, 5230, bwn_b2063_chantable_data[11] },
679	{ 48, 5240, bwn_b2063_chantable_data[12] },
680	{ 52, 5260, bwn_b2063_chantable_data[13] },
681	{ 56, 5280, bwn_b2063_chantable_data[14] },
682	{ 60, 5300, bwn_b2063_chantable_data[14] },
683	{ 64, 5320, bwn_b2063_chantable_data[15] },
684	{ 100, 5500, bwn_b2063_chantable_data[16] },
685	{ 104, 5520, bwn_b2063_chantable_data[17] },
686	{ 108, 5540, bwn_b2063_chantable_data[18] },
687	{ 112, 5560, bwn_b2063_chantable_data[19] },
688	{ 116, 5580, bwn_b2063_chantable_data[20] },
689	{ 120, 5600, bwn_b2063_chantable_data[21] },
690	{ 124, 5620, bwn_b2063_chantable_data[21] },
691	{ 128, 5640, bwn_b2063_chantable_data[22] },
692	{ 132, 5660, bwn_b2063_chantable_data[22] },
693	{ 136, 5680, bwn_b2063_chantable_data[22] },
694	{ 140, 5700, bwn_b2063_chantable_data[23] },
695	{ 149, 5745, bwn_b2063_chantable_data[23] },
696	{ 153, 5765, bwn_b2063_chantable_data[23] },
697	{ 157, 5785, bwn_b2063_chantable_data[23] },
698	{ 161, 5805, bwn_b2063_chantable_data[23] },
699	{ 165, 5825, bwn_b2063_chantable_data[23] },
700	{ 184, 4920, bwn_b2063_chantable_data[24] },
701	{ 188, 4940, bwn_b2063_chantable_data[25] },
702	{ 192, 4960, bwn_b2063_chantable_data[26] },
703	{ 196, 4980, bwn_b2063_chantable_data[27] },
704	{ 200, 5000, bwn_b2063_chantable_data[28] },
705	{ 204, 5020, bwn_b2063_chantable_data[29] },
706	{ 208, 5040, bwn_b2063_chantable_data[30] },
707	{ 212, 5060, bwn_b2063_chantable_data[31] },
708	{ 216, 5080, bwn_b2063_chantable_data[32] }
709};
710
711static const uint8_t bwn_b2062_chantable_data[22][12] = {
712	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
713	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
725	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
732	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
733	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
734};
735
736static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
737	{ 1, 2412, bwn_b2062_chantable_data[0] },
738	{ 2, 2417, bwn_b2062_chantable_data[0] },
739	{ 3, 2422, bwn_b2062_chantable_data[0] },
740	{ 4, 2427, bwn_b2062_chantable_data[0] },
741	{ 5, 2432, bwn_b2062_chantable_data[0] },
742	{ 6, 2437, bwn_b2062_chantable_data[0] },
743	{ 7, 2442, bwn_b2062_chantable_data[0] },
744	{ 8, 2447, bwn_b2062_chantable_data[0] },
745	{ 9, 2452, bwn_b2062_chantable_data[0] },
746	{ 10, 2457, bwn_b2062_chantable_data[0] },
747	{ 11, 2462, bwn_b2062_chantable_data[0] },
748	{ 12, 2467, bwn_b2062_chantable_data[0] },
749	{ 13, 2472, bwn_b2062_chantable_data[0] },
750	{ 14, 2484, bwn_b2062_chantable_data[0] },
751	{ 34, 5170, bwn_b2062_chantable_data[1] },
752	{ 38, 5190, bwn_b2062_chantable_data[2] },
753	{ 42, 5210, bwn_b2062_chantable_data[2] },
754	{ 46, 5230, bwn_b2062_chantable_data[3] },
755	{ 36, 5180, bwn_b2062_chantable_data[4] },
756	{ 40, 5200, bwn_b2062_chantable_data[5] },
757	{ 44, 5220, bwn_b2062_chantable_data[6] },
758	{ 48, 5240, bwn_b2062_chantable_data[3] },
759	{ 52, 5260, bwn_b2062_chantable_data[3] },
760	{ 56, 5280, bwn_b2062_chantable_data[3] },
761	{ 60, 5300, bwn_b2062_chantable_data[7] },
762	{ 64, 5320, bwn_b2062_chantable_data[8] },
763	{ 100, 5500, bwn_b2062_chantable_data[9] },
764	{ 104, 5520, bwn_b2062_chantable_data[10] },
765	{ 108, 5540, bwn_b2062_chantable_data[10] },
766	{ 112, 5560, bwn_b2062_chantable_data[10] },
767	{ 116, 5580, bwn_b2062_chantable_data[11] },
768	{ 120, 5600, bwn_b2062_chantable_data[12] },
769	{ 124, 5620, bwn_b2062_chantable_data[12] },
770	{ 128, 5640, bwn_b2062_chantable_data[12] },
771	{ 132, 5660, bwn_b2062_chantable_data[12] },
772	{ 136, 5680, bwn_b2062_chantable_data[12] },
773	{ 140, 5700, bwn_b2062_chantable_data[12] },
774	{ 149, 5745, bwn_b2062_chantable_data[12] },
775	{ 153, 5765, bwn_b2062_chantable_data[12] },
776	{ 157, 5785, bwn_b2062_chantable_data[12] },
777	{ 161, 5805, bwn_b2062_chantable_data[12] },
778	{ 165, 5825, bwn_b2062_chantable_data[12] },
779	{ 184, 4920, bwn_b2062_chantable_data[13] },
780	{ 188, 4940, bwn_b2062_chantable_data[14] },
781	{ 192, 4960, bwn_b2062_chantable_data[15] },
782	{ 196, 4980, bwn_b2062_chantable_data[16] },
783	{ 200, 5000, bwn_b2062_chantable_data[17] },
784	{ 204, 5020, bwn_b2062_chantable_data[18] },
785	{ 208, 5040, bwn_b2062_chantable_data[19] },
786	{ 212, 5060, bwn_b2062_chantable_data[20] },
787	{ 216, 5080, bwn_b2062_chantable_data[21] }
788};
789
790/* for LP PHY */
791static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
792	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
793	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
794	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
795	{ 13, -66, 13 }, { 14, -66, 13 },
796};
797
798/* for LP PHY */
799static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
800	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
801	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
802	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
803	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
804	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
805	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
806	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
807	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
808	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
809	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
810	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
811	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
812	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
813};
814
815static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
816
817static const uint8_t bwn_tab_sigsq_tbl[] = {
818	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
819	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
821	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
822	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
823	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
824};
825
826static const uint8_t bwn_tab_pllfrac_tbl[] = {
827	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
828	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
829};
830
831static const uint16_t bwn_tabl_iqlocal_tbl[] = {
832	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
833	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
836	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
837	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
842	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
844};
845
846static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
847static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
848static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
849static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
850static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
851const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
852
853#define	VENDOR_LED_ACT(vendor)				\
854{							\
855	.vid = PCI_VENDOR_##vendor,			\
856	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
857}
858
859static const struct {
860	uint16_t	vid;
861	uint8_t		led_act[BWN_LED_MAX];
862} bwn_vendor_led_act[] = {
863	VENDOR_LED_ACT(COMPAQ),
864	VENDOR_LED_ACT(ASUSTEK)
865};
866
867static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
868	{ BWN_VENDOR_LED_ACT_DEFAULT };
869
870#undef VENDOR_LED_ACT
871
872static const struct {
873	int		on_dur;
874	int		off_dur;
875} bwn_led_duration[109] = {
876	[0]	= { 400, 100 },
877	[2]	= { 150, 75 },
878	[4]	= { 90, 45 },
879	[11]	= { 66, 34 },
880	[12]	= { 53, 26 },
881	[18]	= { 42, 21 },
882	[22]	= { 35, 17 },
883	[24]	= { 32, 16 },
884	[36]	= { 21, 10 },
885	[48]	= { 16, 8 },
886	[72]	= { 11, 5 },
887	[96]	= { 9, 4 },
888	[108]	= { 7, 3 }
889};
890
891static const uint16_t bwn_wme_shm_offsets[] = {
892	[0] = BWN_WME_BESTEFFORT,
893	[1] = BWN_WME_BACKGROUND,
894	[2] = BWN_WME_VOICE,
895	[3] = BWN_WME_VIDEO,
896};
897
898static const struct siba_devid bwn_devs[] = {
899	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
900	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
901	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
902	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
903	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
904	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
905	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
906	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
907	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
908};
909
910static int
911bwn_probe(device_t dev)
912{
913	struct siba_dev_softc *sd = device_get_ivars(dev);
914	int i;
915
916	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
917		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
918		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
919		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
920			return (BUS_PROBE_DEFAULT);
921	}
922
923	return (ENXIO);
924}
925
926static int
927bwn_attach(device_t dev)
928{
929	struct bwn_mac *mac;
930	struct bwn_softc *sc = device_get_softc(dev);
931	struct siba_dev_softc *sd = device_get_ivars(dev);
932	struct siba_softc *siba = sd->sd_bus;
933	int error, i, msic, reg;
934
935	sc->sc_dev = dev;
936	sc->sc_sd = sd;
937#ifdef BWN_DEBUG
938	sc->sc_debug = bwn_debug;
939#endif
940
941	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
942		error = bwn_attach_pre(sc);
943		if (error != 0)
944			return (error);
945		bwn_sprom_bugfixes(sd->sd_bus);
946		sc->sc_flags |= BWN_FLAG_ATTACHED;
947	}
948
949	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
950		if (siba->siba_pci_did != 0x4313 &&
951		    siba->siba_pci_did != 0x431a &&
952		    siba->siba_pci_did != 0x4321) {
953			device_printf(sc->sc_dev,
954			    "skip 802.11 cores\n");
955			return (ENODEV);
956		}
957	}
958
959	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
960	    M_NOWAIT | M_ZERO);
961	if (mac == NULL)
962		return (ENOMEM);
963	mac->mac_sc = sc;
964	mac->mac_sd = sd;
965	mac->mac_status = BWN_MAC_STATUS_UNINIT;
966	if (bwn_bfp != 0)
967		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
968
969	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
970	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
971	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
972
973	error = bwn_attach_core(mac);
974	if (error)
975		goto fail0;
976	bwn_led_attach(mac);
977
978	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
979	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
980	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
981	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
982	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
983	    mac->mac_phy.rf_rev);
984	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
985		device_printf(sc->sc_dev, "DMA (%d bits)\n",
986		    mac->mac_method.dma.dmatype);
987	else
988		device_printf(sc->sc_dev, "PIO\n");
989
990	/*
991	 * setup PCI resources and interrupt.
992	 */
993	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
994		msic = pci_msi_count(dev);
995		if (bootverbose)
996			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
997	} else
998		msic = 0;
999
1000	mac->mac_intr_spec = bwn_res_spec_legacy;
1001	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1002		if (pci_alloc_msi(dev, &msic) == 0) {
1003			device_printf(sc->sc_dev,
1004			    "Using %d MSI messages\n", msic);
1005			mac->mac_intr_spec = bwn_res_spec_msi;
1006			mac->mac_msi = 1;
1007		}
1008	}
1009
1010	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1011	    mac->mac_res_irq);
1012	if (error) {
1013		device_printf(sc->sc_dev,
1014		    "couldn't allocate IRQ resources (%d)\n", error);
1015		goto fail1;
1016	}
1017
1018	if (mac->mac_msi == 0)
1019		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1020		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1021		    &mac->mac_intrhand[0]);
1022	else {
1023		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1024			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1025			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1026			    &mac->mac_intrhand[i]);
1027			if (error != 0) {
1028				device_printf(sc->sc_dev,
1029				    "couldn't setup interrupt (%d)\n", error);
1030				break;
1031			}
1032		}
1033	}
1034
1035	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1036
1037	/*
1038	 * calls attach-post routine
1039	 */
1040	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1041		bwn_attach_post(sc);
1042
1043	return (0);
1044fail1:
1045	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1046		pci_release_msi(dev);
1047fail0:
1048	free(mac, M_DEVBUF);
1049	return (error);
1050}
1051
1052static int
1053bwn_is_valid_ether_addr(uint8_t *addr)
1054{
1055	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1056
1057	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1058		return (FALSE);
1059
1060	return (TRUE);
1061}
1062
1063static int
1064bwn_attach_post(struct bwn_softc *sc)
1065{
1066	struct ieee80211com *ic;
1067	struct ifnet *ifp = sc->sc_ifp;
1068	struct siba_dev_softc *sd = sc->sc_sd;
1069	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1070
1071	ic = ifp->if_l2com;
1072	ic->ic_ifp = ifp;
1073	/* XXX not right but it's not used anywhere important */
1074	ic->ic_phytype = IEEE80211_T_OFDM;
1075	ic->ic_opmode = IEEE80211_M_STA;
1076	ic->ic_caps =
1077		  IEEE80211_C_STA		/* station mode supported */
1078		| IEEE80211_C_MONITOR		/* monitor mode */
1079		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1080		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1081		| IEEE80211_C_SHSLOT		/* short slot time supported */
1082		| IEEE80211_C_WME		/* WME/WMM supported */
1083		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1084		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1085		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1086		;
1087
1088	/* call MI attach routine. */
1089	ieee80211_ifattach(ic,
1090	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1091	    sprom->mac_80211bg);
1092
1093	ic->ic_headroom = sizeof(struct bwn_txhdr);
1094
1095	/* override default methods */
1096	ic->ic_raw_xmit = bwn_raw_xmit;
1097	ic->ic_newassoc = bwn_newassoc;
1098	ic->ic_updateslot = bwn_updateslot;
1099	ic->ic_update_promisc = bwn_update_promisc;
1100	ic->ic_wme.wme_update = bwn_wme_update;
1101
1102	ic->ic_node_alloc = bwn_node_alloc;
1103	sc->sc_node_cleanup = ic->ic_node_cleanup;
1104	ic->ic_node_cleanup = bwn_node_cleanup;
1105
1106	ic->ic_scan_start = bwn_scan_start;
1107	ic->ic_scan_end = bwn_scan_end;
1108	ic->ic_set_channel = bwn_set_channel;
1109
1110	ic->ic_vap_create = bwn_vap_create;
1111	ic->ic_vap_delete = bwn_vap_delete;
1112
1113	ieee80211_radiotap_attach(ic,
1114	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1115	    BWN_TX_RADIOTAP_PRESENT,
1116	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1117	    BWN_RX_RADIOTAP_PRESENT);
1118
1119	bwn_sysctl_node(sc);
1120
1121	if (bootverbose)
1122		ieee80211_announce(ic);
1123	return (0);
1124}
1125
1126static void
1127bwn_phy_detach(struct bwn_mac *mac)
1128{
1129
1130	if (mac->mac_phy.detach != NULL)
1131		mac->mac_phy.detach(mac);
1132}
1133
1134static int
1135bwn_detach(device_t dev)
1136{
1137	struct bwn_softc *sc = device_get_softc(dev);
1138	struct bwn_mac *mac = sc->sc_curmac;
1139	struct ifnet *ifp = sc->sc_ifp;
1140	struct ieee80211com *ic = ifp->if_l2com;
1141	int i;
1142
1143	sc->sc_flags |= BWN_FLAG_INVALID;
1144
1145	if (device_is_attached(sc->sc_dev)) {
1146		bwn_stop(sc, 1);
1147		bwn_dma_free(mac);
1148		callout_drain(&sc->sc_led_blink_ch);
1149		callout_drain(&sc->sc_rfswitch_ch);
1150		callout_drain(&sc->sc_task_ch);
1151		callout_drain(&sc->sc_watchdog_ch);
1152		bwn_phy_detach(mac);
1153		if (ifp != NULL) {
1154			ieee80211_draintask(ic, &mac->mac_hwreset);
1155			ieee80211_draintask(ic, &mac->mac_txpower);
1156			ieee80211_ifdetach(ic);
1157			if_free(ifp);
1158		}
1159	}
1160	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1161	taskqueue_free(sc->sc_tq);
1162
1163	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1164		if (mac->mac_intrhand[i] != NULL) {
1165			bus_teardown_intr(dev, mac->mac_res_irq[i],
1166			    mac->mac_intrhand[i]);
1167			mac->mac_intrhand[i] = NULL;
1168		}
1169	}
1170	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1171	if (mac->mac_msi != 0)
1172		pci_release_msi(dev);
1173
1174	BWN_LOCK_DESTROY(sc);
1175	return (0);
1176}
1177
1178static int
1179bwn_attach_pre(struct bwn_softc *sc)
1180{
1181	struct ifnet *ifp;
1182	int error = 0;
1183
1184	BWN_LOCK_INIT(sc);
1185	TAILQ_INIT(&sc->sc_maclist);
1186	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1187	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1188	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1189
1190	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1191		taskqueue_thread_enqueue, &sc->sc_tq);
1192	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1193		"%s taskq", device_get_nameunit(sc->sc_dev));
1194
1195	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1196	if (ifp == NULL) {
1197		device_printf(sc->sc_dev, "can not if_alloc()\n");
1198		error = ENOSPC;
1199		goto fail;
1200	}
1201
1202	/* set these up early for if_printf use */
1203	if_initname(ifp, device_get_name(sc->sc_dev),
1204	    device_get_unit(sc->sc_dev));
1205
1206	ifp->if_softc = sc;
1207	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1208	ifp->if_init = bwn_init;
1209	ifp->if_ioctl = bwn_ioctl;
1210	ifp->if_start = bwn_start;
1211	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1212	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1213	IFQ_SET_READY(&ifp->if_snd);
1214
1215	return (0);
1216
1217fail:	BWN_LOCK_DESTROY(sc);
1218	return (error);
1219}
1220
1221static void
1222bwn_sprom_bugfixes(struct siba_softc *siba)
1223{
1224#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1225	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1226	 (siba->siba_pci_did == _device) &&				\
1227	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1228	 (siba->siba_pci_subdid == _subdevice))
1229
1230	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1231	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1232		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1233	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1234	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1235		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1236	if (siba->siba_type == SIBA_TYPE_PCI) {
1237		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1238		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1239		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1240		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1241		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1242		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1243		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1244			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1245	}
1246#undef	BWN_ISDEV
1247}
1248
1249static int
1250bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1251{
1252#define	IS_RUNNING(ifp) \
1253	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1254	struct bwn_softc *sc = ifp->if_softc;
1255	struct ieee80211com *ic = ifp->if_l2com;
1256	struct ifreq *ifr = (struct ifreq *)data;
1257	int error = 0, startall;
1258
1259	switch (cmd) {
1260	case SIOCSIFFLAGS:
1261		startall = 0;
1262		if (IS_RUNNING(ifp)) {
1263			bwn_update_promisc(ifp);
1264		} else if (ifp->if_flags & IFF_UP) {
1265			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1266				bwn_init(sc);
1267				startall = 1;
1268			}
1269		} else
1270			bwn_stop(sc, 1);
1271		if (startall)
1272			ieee80211_start_all(ic);
1273		break;
1274	case SIOCGIFMEDIA:
1275		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1276		break;
1277	case SIOCGIFADDR:
1278		error = ether_ioctl(ifp, cmd, data);
1279		break;
1280	default:
1281		error = EINVAL;
1282		break;
1283	}
1284	return (error);
1285}
1286
1287static void
1288bwn_start(struct ifnet *ifp)
1289{
1290	struct bwn_softc *sc = ifp->if_softc;
1291
1292	BWN_LOCK(sc);
1293	bwn_start_locked(ifp);
1294	BWN_UNLOCK(sc);
1295}
1296
1297static void
1298bwn_start_locked(struct ifnet *ifp)
1299{
1300	struct bwn_softc *sc = ifp->if_softc;
1301	struct bwn_mac *mac = sc->sc_curmac;
1302	struct ieee80211_frame *wh;
1303	struct ieee80211_node *ni;
1304	struct ieee80211_key *k;
1305	struct mbuf *m;
1306
1307	BWN_ASSERT_LOCKED(sc);
1308
1309	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1310	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1311		return;
1312
1313	for (;;) {
1314		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1315		if (m == NULL)
1316			break;
1317
1318		if (bwn_tx_isfull(sc, m))
1319			break;
1320		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1321		if (ni == NULL) {
1322			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1323			m_freem(m);
1324			ifp->if_oerrors++;
1325			continue;
1326		}
1327		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1328		wh = mtod(m, struct ieee80211_frame *);
1329		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1330			k = ieee80211_crypto_encap(ni, m);
1331			if (k == NULL) {
1332				ieee80211_free_node(ni);
1333				m_freem(m);
1334				ifp->if_oerrors++;
1335				continue;
1336			}
1337		}
1338		wh = NULL;	/* Catch any invalid use */
1339
1340		if (bwn_tx_start(sc, ni, m) != 0) {
1341			if (ni != NULL)
1342				ieee80211_free_node(ni);
1343			ifp->if_oerrors++;
1344			continue;
1345		}
1346
1347		sc->sc_watchdog_timer = 5;
1348	}
1349}
1350
1351static int
1352bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1353{
1354	struct bwn_dma_ring *dr;
1355	struct bwn_mac *mac = sc->sc_curmac;
1356	struct bwn_pio_txqueue *tq;
1357	struct ifnet *ifp = sc->sc_ifp;
1358	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1359
1360	BWN_ASSERT_LOCKED(sc);
1361
1362	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1363		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1364		if (dr->dr_stop == 1 ||
1365		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1366			dr->dr_stop = 1;
1367			goto full;
1368		}
1369	} else {
1370		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1371		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1372		    pktlen > (tq->tq_size - tq->tq_used)) {
1373			tq->tq_stop = 1;
1374			goto full;
1375		}
1376	}
1377	return (0);
1378full:
1379	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1380	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1381	return (1);
1382}
1383
1384static int
1385bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1386{
1387	struct bwn_mac *mac = sc->sc_curmac;
1388	int error;
1389
1390	BWN_ASSERT_LOCKED(sc);
1391
1392	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1393		m_freem(m);
1394		return (ENXIO);
1395	}
1396
1397	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1398	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1399	if (error) {
1400		m_freem(m);
1401		return (error);
1402	}
1403	return (0);
1404}
1405
1406static int
1407bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1408{
1409	struct bwn_pio_txpkt *tp;
1410	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1411	struct bwn_softc *sc = mac->mac_sc;
1412	struct bwn_txhdr txhdr;
1413	struct mbuf *m_new;
1414	uint32_t ctl32;
1415	int error;
1416	uint16_t ctl16;
1417
1418	BWN_ASSERT_LOCKED(sc);
1419
1420	/* XXX TODO send packets after DTIM */
1421
1422	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1423	tp = TAILQ_FIRST(&tq->tq_pktlist);
1424	tp->tp_ni = ni;
1425	tp->tp_m = m;
1426
1427	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1428	if (error) {
1429		device_printf(sc->sc_dev, "tx fail\n");
1430		return (error);
1431	}
1432
1433	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1434	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1435	tq->tq_free--;
1436
1437	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1438		/*
1439		 * XXX please removes m_defrag(9)
1440		 */
1441		m_new = m_defrag(m, M_DONTWAIT);
1442		if (m_new == NULL) {
1443			device_printf(sc->sc_dev,
1444			    "%s: can't defrag TX buffer\n",
1445			    __func__);
1446			return (ENOBUFS);
1447		}
1448		if (m_new->m_next != NULL)
1449			device_printf(sc->sc_dev,
1450			    "TODO: fragmented packets for PIO\n");
1451		tp->tp_m = m_new;
1452
1453		/* send HEADER */
1454		ctl32 = bwn_pio_write_multi_4(mac, tq,
1455		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1456			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1457		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458		/* send BODY */
1459		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1460		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1461		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1462		    ctl32 | BWN_PIO8_TXCTL_EOF);
1463	} else {
1464		ctl16 = bwn_pio_write_multi_2(mac, tq,
1465		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1466			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1467		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1468		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1469		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1470		    ctl16 | BWN_PIO_TXCTL_EOF);
1471	}
1472
1473	return (0);
1474}
1475
1476static struct bwn_pio_txqueue *
1477bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1478{
1479
1480	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1481		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482
1483	switch (prio) {
1484	case 0:
1485		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1486	case 1:
1487		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1488	case 2:
1489		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1490	case 3:
1491		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1492	}
1493	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1494	return (NULL);
1495}
1496
1497static int
1498bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1499{
1500#define	BWN_GET_TXHDRCACHE(slot)					\
1501	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1502	struct bwn_dma *dma = &mac->mac_method.dma;
1503	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1504	struct bwn_dmadesc_generic *desc;
1505	struct bwn_dmadesc_meta *mt;
1506	struct bwn_softc *sc = mac->mac_sc;
1507	struct ifnet *ifp = sc->sc_ifp;
1508	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1509	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1510
1511	BWN_ASSERT_LOCKED(sc);
1512	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1513
1514	/* XXX send after DTIM */
1515
1516	slot = bwn_dma_getslot(dr);
1517	dr->getdesc(dr, slot, &desc, &mt);
1518	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1519	    ("%s:%d: fail", __func__, __LINE__));
1520
1521	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1522	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1523	    BWN_DMA_COOKIE(dr, slot));
1524	if (error)
1525		goto fail;
1526	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1527	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1528	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1529	if (error) {
1530		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1531		    __func__, error);
1532		goto fail;
1533	}
1534	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1535	    BUS_DMASYNC_PREWRITE);
1536	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1537	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1538	    BUS_DMASYNC_PREWRITE);
1539
1540	slot = bwn_dma_getslot(dr);
1541	dr->getdesc(dr, slot, &desc, &mt);
1542	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1543	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1544	mt->mt_m = m;
1545	mt->mt_ni = ni;
1546
1547	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1548	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1549	if (error && error != EFBIG) {
1550		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1551		    __func__, error);
1552		goto fail;
1553	}
1554	if (error) {    /* error == EFBIG */
1555		struct mbuf *m_new;
1556
1557		m_new = m_defrag(m, M_DONTWAIT);
1558		if (m_new == NULL) {
1559			if_printf(ifp, "%s: can't defrag TX buffer\n",
1560			    __func__);
1561			error = ENOBUFS;
1562			goto fail;
1563		} else {
1564			m = m_new;
1565		}
1566
1567		mt->mt_m = m;
1568		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1569		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1570		if (error) {
1571			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1572			    __func__, error);
1573			goto fail;
1574		}
1575	}
1576	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1577	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1578	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1579	    BUS_DMASYNC_PREWRITE);
1580
1581	/* XXX send after DTIM */
1582
1583	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1584	return (0);
1585fail:
1586	dr->dr_curslot = backup[0];
1587	dr->dr_usedslot = backup[1];
1588	return (error);
1589#undef BWN_GET_TXHDRCACHE
1590}
1591
1592static void
1593bwn_watchdog(void *arg)
1594{
1595	struct bwn_softc *sc = arg;
1596	struct ifnet *ifp = sc->sc_ifp;
1597
1598	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1599		if_printf(ifp, "device timeout\n");
1600		ifp->if_oerrors++;
1601	}
1602	callout_schedule(&sc->sc_watchdog_ch, hz);
1603}
1604
1605static int
1606bwn_attach_core(struct bwn_mac *mac)
1607{
1608	struct bwn_softc *sc = mac->mac_sc;
1609	struct siba_dev_softc *sd = mac->mac_sd;
1610	struct siba_softc *siba = sd->sd_bus;
1611	int error, have_bg = 0, have_a = 0;
1612	uint32_t high;
1613
1614	KASSERT(sd->sd_id.sd_rev >= 5,
1615	    ("unsupported revision %d", sd->sd_id.sd_rev));
1616
1617	siba_powerup(siba, 0);
1618
1619	high = siba_read_4(sd, SIBA_TGSHIGH);
1620	bwn_reset_core(mac,
1621	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1622	error = bwn_phy_getinfo(mac, high);
1623	if (error)
1624		goto fail;
1625
1626	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1627	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1628	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1629	    siba->siba_pci_did != 0x4324) {
1630		have_a = have_bg = 0;
1631		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1632			have_a = 1;
1633		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1634		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1635		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1636			have_bg = 1;
1637		else
1638			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1639			    mac->mac_phy.type));
1640	}
1641	/* XXX turns off PHY A because it's not supported */
1642	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1643	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1644		have_a = 0;
1645		have_bg = 1;
1646	}
1647
1648	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1649		mac->mac_phy.attach = bwn_phy_g_attach;
1650		mac->mac_phy.detach = bwn_phy_g_detach;
1651		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1652		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1653		mac->mac_phy.init = bwn_phy_g_init;
1654		mac->mac_phy.exit = bwn_phy_g_exit;
1655		mac->mac_phy.phy_read = bwn_phy_g_read;
1656		mac->mac_phy.phy_write = bwn_phy_g_write;
1657		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1658		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1659		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1660		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1661		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1662		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1663		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1664		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1665		mac->mac_phy.set_im = bwn_phy_g_im;
1666		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1667		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1668		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1669		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1670	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1671		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1672		mac->mac_phy.init = bwn_phy_lp_init;
1673		mac->mac_phy.phy_read = bwn_phy_lp_read;
1674		mac->mac_phy.phy_write = bwn_phy_lp_write;
1675		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1676		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1677		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1678		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1679		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1680		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1681		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1682		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1683		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1684	} else {
1685		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1686		    mac->mac_phy.type);
1687		error = ENXIO;
1688		goto fail;
1689	}
1690
1691	mac->mac_phy.gmode = have_bg;
1692	if (mac->mac_phy.attach != NULL) {
1693		error = mac->mac_phy.attach(mac);
1694		if (error) {
1695			device_printf(sc->sc_dev, "failed\n");
1696			goto fail;
1697		}
1698	}
1699
1700	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1701
1702	error = bwn_chiptest(mac);
1703	if (error)
1704		goto fail;
1705	error = bwn_setup_channels(mac, have_bg, have_a);
1706	if (error) {
1707		device_printf(sc->sc_dev, "failed to setup channels\n");
1708		goto fail;
1709	}
1710
1711	if (sc->sc_curmac == NULL)
1712		sc->sc_curmac = mac;
1713
1714	error = bwn_dma_attach(mac);
1715	if (error != 0) {
1716		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1717		goto fail;
1718	}
1719
1720	mac->mac_phy.switch_analog(mac, 0);
1721
1722	siba_dev_down(sd, 0);
1723fail:
1724	siba_powerdown(siba);
1725	return (error);
1726}
1727
1728static void
1729bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1730{
1731	struct siba_dev_softc *sd = mac->mac_sd;
1732	uint32_t low, ctl;
1733
1734	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1735
1736	siba_dev_up(sd, flags);
1737	DELAY(2000);
1738
1739	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1740	    ~BWN_TGSLOW_PHYRESET;
1741	siba_write_4(sd, SIBA_TGSLOW, low);
1742	siba_read_4(sd, SIBA_TGSLOW);
1743	DELAY(1000);
1744	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1745	siba_read_4(sd, SIBA_TGSLOW);
1746	DELAY(1000);
1747
1748	if (mac->mac_phy.switch_analog != NULL)
1749		mac->mac_phy.switch_analog(mac, 1);
1750
1751	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1752	if (flags & BWN_TGSLOW_SUPPORT_G)
1753		ctl |= BWN_MACCTL_GMODE;
1754	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1755}
1756
1757static int
1758bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1759{
1760	struct bwn_phy *phy = &mac->mac_phy;
1761	struct bwn_softc *sc = mac->mac_sc;
1762	struct siba_dev_softc *sd = mac->mac_sd;
1763	struct siba_softc *siba = sd->sd_bus;
1764	uint32_t tmp;
1765
1766	/* PHY */
1767	tmp = BWN_READ_2(mac, BWN_PHYVER);
1768	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1769	phy->rf_on = 1;
1770	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1771	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1772	phy->rev = (tmp & BWN_PHYVER_VERSION);
1773	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1774	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1775		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1776	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1777	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1778	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1779		goto unsupphy;
1780
1781	/* RADIO */
1782	if (siba->siba_chipid == 0x4317) {
1783		if (siba->siba_chiprev == 0)
1784			tmp = 0x3205017f;
1785		else if (siba->siba_chiprev == 1)
1786			tmp = 0x4205017f;
1787		else
1788			tmp = 0x5205017f;
1789	} else {
1790		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1791		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1792		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1793		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1794	}
1795	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1796	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1797	phy->rf_manuf = (tmp & 0x00000fff);
1798	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1799		goto unsupradio;
1800	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1801	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1802	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1803	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1804	    (phy->type == BWN_PHYTYPE_N &&
1805	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1806	    (phy->type == BWN_PHYTYPE_LP &&
1807	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1808		goto unsupradio;
1809
1810	return (0);
1811unsupphy:
1812	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1813	    "analog %#x)\n",
1814	    phy->type, phy->rev, phy->analog);
1815	return (ENXIO);
1816unsupradio:
1817	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1818	    "rev %#x)\n",
1819	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1820	return (ENXIO);
1821}
1822
1823static int
1824bwn_chiptest(struct bwn_mac *mac)
1825{
1826#define	TESTVAL0	0x55aaaa55
1827#define	TESTVAL1	0xaa5555aa
1828	struct bwn_softc *sc = mac->mac_sc;
1829	struct siba_dev_softc *sd = mac->mac_sd;
1830	uint32_t v, backup;
1831
1832	BWN_LOCK(sc);
1833
1834	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1835
1836	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1837	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1838		goto error;
1839	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1840	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1841		goto error;
1842
1843	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1844
1845	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1846		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1847		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1848		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1849			goto error;
1850		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1851			goto error;
1852	}
1853	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1854
1855	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1856	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1857		goto error;
1858
1859	BWN_UNLOCK(sc);
1860	return (0);
1861error:
1862	BWN_UNLOCK(sc);
1863	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1864	return (ENODEV);
1865}
1866
1867#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1868#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1869
1870static int
1871bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1872{
1873	struct bwn_softc *sc = mac->mac_sc;
1874	struct ifnet *ifp = sc->sc_ifp;
1875	struct ieee80211com *ic = ifp->if_l2com;
1876
1877	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1878	ic->ic_nchans = 0;
1879
1880	if (have_bg)
1881		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1882		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1883	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1884		if (have_a)
1885			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886			    &ic->ic_nchans, &bwn_chantable_n,
1887			    IEEE80211_CHAN_HTA);
1888	} else {
1889		if (have_a)
1890			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1891			    &ic->ic_nchans, &bwn_chantable_a,
1892			    IEEE80211_CHAN_A);
1893	}
1894
1895	mac->mac_phy.supports_2ghz = have_bg;
1896	mac->mac_phy.supports_5ghz = have_a;
1897
1898	return (ic->ic_nchans == 0 ? ENXIO : 0);
1899}
1900
1901static uint32_t
1902bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1903{
1904	uint32_t ret;
1905
1906	BWN_ASSERT_LOCKED(mac->mac_sc);
1907
1908	if (way == BWN_SHARED) {
1909		KASSERT((offset & 0x0001) == 0,
1910		    ("%s:%d warn", __func__, __LINE__));
1911		if (offset & 0x0003) {
1912			bwn_shm_ctlword(mac, way, offset >> 2);
1913			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1914			ret <<= 16;
1915			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1916			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1917			goto out;
1918		}
1919		offset >>= 2;
1920	}
1921	bwn_shm_ctlword(mac, way, offset);
1922	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1923out:
1924	return (ret);
1925}
1926
1927static uint16_t
1928bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1929{
1930	uint16_t ret;
1931
1932	BWN_ASSERT_LOCKED(mac->mac_sc);
1933
1934	if (way == BWN_SHARED) {
1935		KASSERT((offset & 0x0001) == 0,
1936		    ("%s:%d warn", __func__, __LINE__));
1937		if (offset & 0x0003) {
1938			bwn_shm_ctlword(mac, way, offset >> 2);
1939			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1940			goto out;
1941		}
1942		offset >>= 2;
1943	}
1944	bwn_shm_ctlword(mac, way, offset);
1945	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1946out:
1947
1948	return (ret);
1949}
1950
1951static void
1952bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1953    uint16_t offset)
1954{
1955	uint32_t control;
1956
1957	control = way;
1958	control <<= 16;
1959	control |= offset;
1960	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1961}
1962
1963static void
1964bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1965    uint32_t value)
1966{
1967	BWN_ASSERT_LOCKED(mac->mac_sc);
1968
1969	if (way == BWN_SHARED) {
1970		KASSERT((offset & 0x0001) == 0,
1971		    ("%s:%d warn", __func__, __LINE__));
1972		if (offset & 0x0003) {
1973			bwn_shm_ctlword(mac, way, offset >> 2);
1974			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1975				    (value >> 16) & 0xffff);
1976			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1977			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1978			return;
1979		}
1980		offset >>= 2;
1981	}
1982	bwn_shm_ctlword(mac, way, offset);
1983	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1984}
1985
1986static void
1987bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1988    uint16_t value)
1989{
1990	BWN_ASSERT_LOCKED(mac->mac_sc);
1991
1992	if (way == BWN_SHARED) {
1993		KASSERT((offset & 0x0001) == 0,
1994		    ("%s:%d warn", __func__, __LINE__));
1995		if (offset & 0x0003) {
1996			bwn_shm_ctlword(mac, way, offset >> 2);
1997			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1998			return;
1999		}
2000		offset >>= 2;
2001	}
2002	bwn_shm_ctlword(mac, way, offset);
2003	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2004}
2005
2006static void
2007bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2008    int txpow)
2009{
2010
2011	c->ic_freq = freq;
2012	c->ic_flags = flags;
2013	c->ic_ieee = ieee;
2014	c->ic_minpower = 0;
2015	c->ic_maxpower = 2 * txpow;
2016	c->ic_maxregpower = txpow;
2017}
2018
2019static void
2020bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2021    const struct bwn_channelinfo *ci, int flags)
2022{
2023	struct ieee80211_channel *c;
2024	int i;
2025
2026	c = &chans[*nchans];
2027
2028	for (i = 0; i < ci->nchannels; i++) {
2029		const struct bwn_channel *hc;
2030
2031		hc = &ci->channels[i];
2032		if (*nchans >= maxchans)
2033			break;
2034		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2035		c++, (*nchans)++;
2036		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2037			/* g channel have a separate b-only entry */
2038			if (*nchans >= maxchans)
2039				break;
2040			c[0] = c[-1];
2041			c[-1].ic_flags = IEEE80211_CHAN_B;
2042			c++, (*nchans)++;
2043		}
2044		if (flags == IEEE80211_CHAN_HTG) {
2045			/* HT g channel have a separate g-only entry */
2046			if (*nchans >= maxchans)
2047				break;
2048			c[-1].ic_flags = IEEE80211_CHAN_G;
2049			c[0] = c[-1];
2050			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2051			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2052			c++, (*nchans)++;
2053		}
2054		if (flags == IEEE80211_CHAN_HTA) {
2055			/* HT a channel have a separate a-only entry */
2056			if (*nchans >= maxchans)
2057				break;
2058			c[-1].ic_flags = IEEE80211_CHAN_A;
2059			c[0] = c[-1];
2060			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2061			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2062			c++, (*nchans)++;
2063		}
2064	}
2065}
2066
2067static int
2068bwn_phy_g_attach(struct bwn_mac *mac)
2069{
2070	struct bwn_softc *sc = mac->mac_sc;
2071	struct bwn_phy *phy = &mac->mac_phy;
2072	struct bwn_phy_g *pg = &phy->phy_g;
2073	struct siba_dev_softc *sd = mac->mac_sd;
2074	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2075	unsigned int i;
2076	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2077	    pab2 = (int16_t)(sprom->pa0b2);
2078	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2079	int8_t bg = (int8_t)sprom->tssi_bg;
2080
2081	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2082		device_printf(sc->sc_dev, "not supported anymore\n");
2083
2084	pg->pg_flags = 0;
2085	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2086	    pab2 == -1) {
2087		pg->pg_idletssi = 52;
2088		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2089		return (0);
2090	}
2091
2092	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2093	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2094	if (pg->pg_tssi2dbm == NULL) {
2095		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2096		return (ENOMEM);
2097	}
2098	for (i = 0; i < 64; i++) {
2099		int32_t m1, m2, f, q, delta;
2100		int8_t j = 0;
2101
2102		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2103		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2104		f = 256;
2105
2106		do {
2107			if (j > 15) {
2108				device_printf(sc->sc_dev,
2109				    "failed to generate tssi2dBm\n");
2110				free(pg->pg_tssi2dbm, M_DEVBUF);
2111				return (ENOMEM);
2112			}
2113			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2114			    f, 2048);
2115			delta = abs(q - f);
2116			f = q;
2117			j++;
2118		} while (delta >= 2);
2119
2120		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2121		    128);
2122	}
2123
2124	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2125	return (0);
2126}
2127
2128static void
2129bwn_phy_g_detach(struct bwn_mac *mac)
2130{
2131	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2132
2133	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2134		free(pg->pg_tssi2dbm, M_DEVBUF);
2135		pg->pg_tssi2dbm = NULL;
2136	}
2137	pg->pg_flags = 0;
2138}
2139
2140static void
2141bwn_phy_g_init_pre(struct bwn_mac *mac)
2142{
2143	struct bwn_phy *phy = &mac->mac_phy;
2144	struct bwn_phy_g *pg = &phy->phy_g;
2145	void *tssi2dbm;
2146	int idletssi;
2147	unsigned int i;
2148
2149	tssi2dbm = pg->pg_tssi2dbm;
2150	idletssi = pg->pg_idletssi;
2151
2152	memset(pg, 0, sizeof(*pg));
2153
2154	pg->pg_tssi2dbm = tssi2dbm;
2155	pg->pg_idletssi = idletssi;
2156
2157	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2158
2159	for (i = 0; i < N(pg->pg_nrssi); i++)
2160		pg->pg_nrssi[i] = -1000;
2161	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2162		pg->pg_nrssi_lt[i] = i;
2163	pg->pg_lofcal = 0xffff;
2164	pg->pg_initval = 0xffff;
2165	pg->pg_immode = BWN_IMMODE_NONE;
2166	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2167	pg->pg_avgtssi = 0xff;
2168
2169	pg->pg_loctl.tx_bias = 0xff;
2170	TAILQ_INIT(&pg->pg_loctl.calib_list);
2171}
2172
2173static int
2174bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2175{
2176	struct bwn_phy *phy = &mac->mac_phy;
2177	struct bwn_phy_g *pg = &phy->phy_g;
2178	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2179	struct siba_softc *bus = mac->mac_sd->sd_bus;
2180	static const struct bwn_rfatt rfatt0[] = {
2181		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2182		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2183		{ 3, 1 }, { 4, 1 }
2184	};
2185	static const struct bwn_rfatt rfatt1[] = {
2186		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2187		{ 14, 1 }
2188	};
2189	static const struct bwn_rfatt rfatt2[] = {
2190		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2191		{ 9, 1 }
2192	};
2193	static const struct bwn_bbatt bbatt_0[] = {
2194		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2195	};
2196
2197	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2198
2199	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2200		pg->pg_bbatt.att = 0;
2201	else
2202		pg->pg_bbatt.att = 2;
2203
2204	/* prepare Radio Attenuation */
2205	pg->pg_rfatt.padmix = 0;
2206
2207	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2208	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2209		if (bus->siba_board_rev < 0x43) {
2210			pg->pg_rfatt.att = 2;
2211			goto done;
2212		} else if (bus->siba_board_rev < 0x51) {
2213			pg->pg_rfatt.att = 3;
2214			goto done;
2215		}
2216	}
2217
2218	if (phy->type == BWN_PHYTYPE_A) {
2219		pg->pg_rfatt.att = 0x60;
2220		goto done;
2221	}
2222
2223	switch (phy->rf_ver) {
2224	case 0x2050:
2225		switch (phy->rf_rev) {
2226		case 0:
2227			pg->pg_rfatt.att = 5;
2228			goto done;
2229		case 1:
2230			if (phy->type == BWN_PHYTYPE_G) {
2231				if (bus->siba_board_vendor ==
2232				    SIBA_BOARDVENDOR_BCM &&
2233				    bus->siba_board_type ==
2234				    SIBA_BOARD_BCM4309G &&
2235				    bus->siba_board_rev >= 30)
2236					pg->pg_rfatt.att = 3;
2237				else if (bus->siba_board_vendor ==
2238				    SIBA_BOARDVENDOR_BCM &&
2239				    bus->siba_board_type == SIBA_BOARD_BU4306)
2240					pg->pg_rfatt.att = 3;
2241				else
2242					pg->pg_rfatt.att = 1;
2243			} else {
2244				if (bus->siba_board_vendor ==
2245				    SIBA_BOARDVENDOR_BCM &&
2246				    bus->siba_board_type ==
2247				    SIBA_BOARD_BCM4309G &&
2248				    bus->siba_board_rev >= 30)
2249					pg->pg_rfatt.att = 7;
2250				else
2251					pg->pg_rfatt.att = 6;
2252			}
2253			goto done;
2254		case 2:
2255			if (phy->type == BWN_PHYTYPE_G) {
2256				if (bus->siba_board_vendor ==
2257				    SIBA_BOARDVENDOR_BCM &&
2258				    bus->siba_board_type ==
2259				    SIBA_BOARD_BCM4309G &&
2260				    bus->siba_board_rev >= 30)
2261					pg->pg_rfatt.att = 3;
2262				else if (bus->siba_board_vendor ==
2263				    SIBA_BOARDVENDOR_BCM &&
2264				    bus->siba_board_type == SIBA_BOARD_BU4306)
2265					pg->pg_rfatt.att = 5;
2266				else if (bus->siba_chipid == 0x4320)
2267					pg->pg_rfatt.att = 4;
2268				else
2269					pg->pg_rfatt.att = 3;
2270			} else
2271				pg->pg_rfatt.att = 6;
2272			goto done;
2273		case 3:
2274			pg->pg_rfatt.att = 5;
2275			goto done;
2276		case 4:
2277		case 5:
2278			pg->pg_rfatt.att = 1;
2279			goto done;
2280		case 6:
2281		case 7:
2282			pg->pg_rfatt.att = 5;
2283			goto done;
2284		case 8:
2285			pg->pg_rfatt.att = 0xa;
2286			pg->pg_rfatt.padmix = 1;
2287			goto done;
2288		case 9:
2289		default:
2290			pg->pg_rfatt.att = 5;
2291			goto done;
2292		}
2293		break;
2294	case 0x2053:
2295		switch (phy->rf_rev) {
2296		case 1:
2297			pg->pg_rfatt.att = 6;
2298			goto done;
2299		}
2300		break;
2301	}
2302	pg->pg_rfatt.att = 5;
2303done:
2304	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2305
2306	if (!bwn_has_hwpctl(mac)) {
2307		lo->rfatt.array = rfatt0;
2308		lo->rfatt.len = N(rfatt0);
2309		lo->rfatt.min = 0;
2310		lo->rfatt.max = 9;
2311		goto genbbatt;
2312	}
2313	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2314		lo->rfatt.array = rfatt1;
2315		lo->rfatt.len = N(rfatt1);
2316		lo->rfatt.min = 0;
2317		lo->rfatt.max = 14;
2318		goto genbbatt;
2319	}
2320	lo->rfatt.array = rfatt2;
2321	lo->rfatt.len = N(rfatt2);
2322	lo->rfatt.min = 0;
2323	lo->rfatt.max = 9;
2324genbbatt:
2325	lo->bbatt.array = bbatt_0;
2326	lo->bbatt.len = N(bbatt_0);
2327	lo->bbatt.min = 0;
2328	lo->bbatt.max = 8;
2329
2330	BWN_READ_4(mac, BWN_MACCTL);
2331	if (phy->rev == 1) {
2332		phy->gmode = 0;
2333		bwn_reset_core(mac, 0);
2334		bwn_phy_g_init_sub(mac);
2335		phy->gmode = 1;
2336		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2337	}
2338	return (0);
2339}
2340
2341static uint16_t
2342bwn_phy_g_txctl(struct bwn_mac *mac)
2343{
2344	struct bwn_phy *phy = &mac->mac_phy;
2345
2346	if (phy->rf_ver != 0x2050)
2347		return (0);
2348	if (phy->rf_rev == 1)
2349		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2350	if (phy->rf_rev < 6)
2351		return (BWN_TXCTL_PA2DB);
2352	if (phy->rf_rev == 8)
2353		return (BWN_TXCTL_TXMIX);
2354	return (0);
2355}
2356
2357static int
2358bwn_phy_g_init(struct bwn_mac *mac)
2359{
2360
2361	bwn_phy_g_init_sub(mac);
2362	return (0);
2363}
2364
2365static void
2366bwn_phy_g_exit(struct bwn_mac *mac)
2367{
2368	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2369	struct bwn_lo_calib *cal, *tmp;
2370
2371	if (lo == NULL)
2372		return;
2373	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2374		TAILQ_REMOVE(&lo->calib_list, cal, list);
2375		free(cal, M_DEVBUF);
2376	}
2377}
2378
2379static uint16_t
2380bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2381{
2382
2383	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2384	return (BWN_READ_2(mac, BWN_PHYDATA));
2385}
2386
2387static void
2388bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2389{
2390
2391	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2392	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2393}
2394
2395static uint16_t
2396bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2397{
2398
2399	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2401	return (BWN_READ_2(mac, BWN_RFDATALO));
2402}
2403
2404static void
2405bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2406{
2407
2408	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2409	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2410	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2411}
2412
2413static int
2414bwn_phy_g_hwpctl(struct bwn_mac *mac)
2415{
2416
2417	return (mac->mac_phy.rev >= 6);
2418}
2419
2420static void
2421bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2422{
2423	struct bwn_phy *phy = &mac->mac_phy;
2424	struct bwn_phy_g *pg = &phy->phy_g;
2425	unsigned int channel;
2426	uint16_t rfover, rfoverval;
2427
2428	if (on) {
2429		if (phy->rf_on)
2430			return;
2431
2432		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2433		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2434		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2435		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2436			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2437			    pg->pg_radioctx_over);
2438			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2439			    pg->pg_radioctx_overval);
2440			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2441		}
2442		channel = phy->chan;
2443		bwn_phy_g_switch_chan(mac, 6, 1);
2444		bwn_phy_g_switch_chan(mac, channel, 0);
2445		return;
2446	}
2447
2448	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2449	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2450	pg->pg_radioctx_over = rfover;
2451	pg->pg_radioctx_overval = rfoverval;
2452	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2453	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2454	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2455}
2456
2457static int
2458bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2459{
2460
2461	if ((newchan < 1) || (newchan > 14))
2462		return (EINVAL);
2463	bwn_phy_g_switch_chan(mac, newchan, 0);
2464
2465	return (0);
2466}
2467
2468static uint32_t
2469bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2470{
2471
2472	return (1);
2473}
2474
2475static void
2476bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2477{
2478	struct bwn_phy *phy = &mac->mac_phy;
2479	uint64_t hf;
2480	int autodiv = 0;
2481	uint16_t tmp;
2482
2483	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2484		autodiv = 1;
2485
2486	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2487	bwn_hf_write(mac, hf);
2488
2489	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2490	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2491	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2492		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2493
2494	if (autodiv) {
2495		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2496		if (antenna == BWN_ANTAUTO1)
2497			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2498		else
2499			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2500		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2501	}
2502	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2503	if (autodiv)
2504		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2505	else
2506		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2507	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2508	if (phy->rev >= 2) {
2509		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2510		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2511		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2512		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2513		    0x15);
2514		if (phy->rev == 2)
2515			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2516		else
2517			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2518			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2519			    8);
2520	}
2521	if (phy->rev >= 6)
2522		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2523
2524	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2525	bwn_hf_write(mac, hf);
2526}
2527
2528static int
2529bwn_phy_g_im(struct bwn_mac *mac, int mode)
2530{
2531	struct bwn_phy *phy = &mac->mac_phy;
2532	struct bwn_phy_g *pg = &phy->phy_g;
2533
2534	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2535	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2536
2537	if (phy->rev == 0 || !phy->gmode)
2538		return (ENODEV);
2539
2540	pg->pg_aci_wlan_automatic = 0;
2541	return (0);
2542}
2543
2544static int
2545bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2546{
2547	struct bwn_phy *phy = &mac->mac_phy;
2548	struct bwn_phy_g *pg = &phy->phy_g;
2549	struct bwn_softc *sc = mac->mac_sc;
2550	struct siba_softc *siba = mac->mac_sd->sd_bus;
2551	unsigned int tssi;
2552	int cck, ofdm;
2553	int power;
2554	int rfatt, bbatt;
2555	unsigned int max;
2556
2557	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2558
2559	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2560	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2561	if (cck < 0 && ofdm < 0) {
2562		if (ignore_tssi == 0)
2563			return (BWN_TXPWR_RES_DONE);
2564		cck = 0;
2565		ofdm = 0;
2566	}
2567	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2568	if (pg->pg_avgtssi != 0xff)
2569		tssi = (tssi + pg->pg_avgtssi) / 2;
2570	pg->pg_avgtssi = tssi;
2571	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2572
2573	max = siba->siba_sprom.maxpwr_bg;
2574	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2575		max -= 3;
2576	if (max >= 120) {
2577		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2578		siba->siba_sprom.maxpwr_bg = max = 80;
2579	}
2580
2581	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2582	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2583	     tssi, 0x00), 0x3f)]);
2584	if (power == 0)
2585		return (BWN_TXPWR_RES_DONE);
2586
2587	rfatt = -((power + 7) / 8);
2588	bbatt = (-(power / 2)) - (4 * rfatt);
2589	if ((rfatt == 0) && (bbatt == 0))
2590		return (BWN_TXPWR_RES_DONE);
2591	pg->pg_bbatt_delta = bbatt;
2592	pg->pg_rfatt_delta = rfatt;
2593	return (BWN_TXPWR_RES_NEED_ADJUST);
2594}
2595
2596static void
2597bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2598{
2599	struct bwn_phy *phy = &mac->mac_phy;
2600	struct bwn_phy_g *pg = &phy->phy_g;
2601	struct bwn_softc *sc = mac->mac_sc;
2602	int rfatt, bbatt;
2603	uint8_t txctl;
2604
2605	bwn_mac_suspend(mac);
2606
2607	BWN_ASSERT_LOCKED(sc);
2608
2609	bbatt = pg->pg_bbatt.att;
2610	bbatt += pg->pg_bbatt_delta;
2611	rfatt = pg->pg_rfatt.att;
2612	rfatt += pg->pg_rfatt_delta;
2613
2614	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2615	txctl = pg->pg_txctl;
2616	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2617		if (rfatt <= 1) {
2618			if (txctl == 0) {
2619				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2620				rfatt += 2;
2621				bbatt += 2;
2622			} else if (mac->mac_sd->sd_bus->siba_sprom.
2623				   bf_lo &
2624				   BWN_BFL_PACTRL) {
2625				bbatt += 4 * (rfatt - 2);
2626				rfatt = 2;
2627			}
2628		} else if (rfatt > 4 && txctl) {
2629			txctl = 0;
2630			if (bbatt < 3) {
2631				rfatt -= 3;
2632				bbatt += 2;
2633			} else {
2634				rfatt -= 2;
2635				bbatt -= 2;
2636			}
2637		}
2638	}
2639	pg->pg_txctl = txctl;
2640	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2641	pg->pg_rfatt.att = rfatt;
2642	pg->pg_bbatt.att = bbatt;
2643
2644	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2645
2646	bwn_phy_lock(mac);
2647	bwn_rf_lock(mac);
2648	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2649	    pg->pg_txctl);
2650	bwn_rf_unlock(mac);
2651	bwn_phy_unlock(mac);
2652
2653	bwn_mac_enable(mac);
2654}
2655
2656static void
2657bwn_phy_g_task_15s(struct bwn_mac *mac)
2658{
2659	struct bwn_phy *phy = &mac->mac_phy;
2660	struct bwn_phy_g *pg = &phy->phy_g;
2661	struct bwn_softc *sc = mac->mac_sc;
2662	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2663	unsigned long expire, now;
2664	struct bwn_lo_calib *cal, *tmp;
2665	uint8_t expired = 0;
2666
2667	bwn_mac_suspend(mac);
2668
2669	if (lo == NULL)
2670		goto fail;
2671
2672	BWN_GETTIME(now);
2673	if (bwn_has_hwpctl(mac)) {
2674		expire = now - BWN_LO_PWRVEC_EXPIRE;
2675		if (time_before(lo->pwr_vec_read_time, expire)) {
2676			bwn_lo_get_powervector(mac);
2677			bwn_phy_g_dc_lookup_init(mac, 0);
2678		}
2679		goto fail;
2680	}
2681
2682	expire = now - BWN_LO_CALIB_EXPIRE;
2683	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2684		if (!time_before(cal->calib_time, expire))
2685			continue;
2686		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2687		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2688			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2689			expired = 1;
2690		}
2691
2692		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2693		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2694		    cal->ctl.i, cal->ctl.q);
2695
2696		TAILQ_REMOVE(&lo->calib_list, cal, list);
2697		free(cal, M_DEVBUF);
2698	}
2699	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2700		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2701		    &pg->pg_rfatt);
2702		if (cal == NULL) {
2703			device_printf(sc->sc_dev,
2704			    "failed to recalibrate LO\n");
2705			goto fail;
2706		}
2707		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2708		bwn_lo_write(mac, &cal->ctl);
2709	}
2710
2711fail:
2712	bwn_mac_enable(mac);
2713}
2714
2715static void
2716bwn_phy_g_task_60s(struct bwn_mac *mac)
2717{
2718	struct bwn_phy *phy = &mac->mac_phy;
2719	uint8_t old = phy->chan;
2720
2721	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2722		return;
2723
2724	bwn_mac_suspend(mac);
2725	bwn_nrssi_slope_11g(mac);
2726	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2727		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2728		bwn_switch_channel(mac, old);
2729	}
2730	bwn_mac_enable(mac);
2731}
2732
2733static void
2734bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2735{
2736
2737	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2738}
2739
2740static int
2741bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2742	const struct ieee80211_bpf_params *params)
2743{
2744	struct ieee80211com *ic = ni->ni_ic;
2745	struct ifnet *ifp = ic->ic_ifp;
2746	struct bwn_softc *sc = ifp->if_softc;
2747	struct bwn_mac *mac = sc->sc_curmac;
2748
2749	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2750	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2751		ieee80211_free_node(ni);
2752		m_freem(m);
2753		return (ENETDOWN);
2754	}
2755
2756	BWN_LOCK(sc);
2757	if (bwn_tx_isfull(sc, m)) {
2758		ieee80211_free_node(ni);
2759		m_freem(m);
2760		ifp->if_oerrors++;
2761		BWN_UNLOCK(sc);
2762		return (ENOBUFS);
2763	}
2764
2765	if (bwn_tx_start(sc, ni, m) != 0) {
2766		if (ni != NULL)
2767			ieee80211_free_node(ni);
2768		ifp->if_oerrors++;
2769	}
2770	sc->sc_watchdog_timer = 5;
2771	BWN_UNLOCK(sc);
2772	return (0);
2773}
2774
2775/*
2776 * Setup driver-specific state for a newly associated node.
2777 * Note that we're called also on a re-associate, the isnew
2778 * param tells us if this is the first time or not.
2779 */
2780static void
2781bwn_newassoc(struct ieee80211_node *ni, int isnew)
2782{
2783	struct ieee80211vap *vap = ni->ni_vap;
2784
2785	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2786	    &BWN_NODE(ni)->bn_amn, ni);
2787}
2788
2789/*
2790 * Callback from the 802.11 layer to update the slot time
2791 * based on the current setting.  We use it to notify the
2792 * firmware of ERP changes and the f/w takes care of things
2793 * like slot time and preamble.
2794 */
2795static void
2796bwn_updateslot(struct ifnet *ifp)
2797{
2798	struct bwn_softc *sc = ifp->if_softc;
2799	struct ieee80211com *ic = ifp->if_l2com;
2800	struct bwn_mac *mac;
2801
2802	BWN_LOCK(sc);
2803	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2804		mac = (struct bwn_mac *)sc->sc_curmac;
2805		bwn_set_slot_time(mac,
2806		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2807	}
2808	BWN_UNLOCK(sc);
2809}
2810
2811/*
2812 * Callback from the 802.11 layer after a promiscuous mode change.
2813 * Note this interface does not check the operating mode as this
2814 * is an internal callback and we are expected to honor the current
2815 * state (e.g. this is used for setting the interface in promiscuous
2816 * mode when operating in hostap mode to do ACS).
2817 */
2818static void
2819bwn_update_promisc(struct ifnet *ifp)
2820{
2821	struct bwn_softc *sc = ifp->if_softc;
2822	struct bwn_mac *mac = sc->sc_curmac;
2823
2824	BWN_LOCK(sc);
2825	mac = sc->sc_curmac;
2826	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827		if (ifp->if_flags & IFF_PROMISC)
2828			sc->sc_filters |= BWN_MACCTL_PROMISC;
2829		else
2830			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2831		bwn_set_opmode(mac);
2832	}
2833	BWN_UNLOCK(sc);
2834}
2835
2836/*
2837 * Callback from the 802.11 layer to update WME parameters.
2838 */
2839static int
2840bwn_wme_update(struct ieee80211com *ic)
2841{
2842	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2843	struct bwn_mac *mac = sc->sc_curmac;
2844	struct wmeParams *wmep;
2845	int i;
2846
2847	BWN_LOCK(sc);
2848	mac = sc->sc_curmac;
2849	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2850		bwn_mac_suspend(mac);
2851		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2852			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2853			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2854		}
2855		bwn_mac_enable(mac);
2856	}
2857	BWN_UNLOCK(sc);
2858	return (0);
2859}
2860
2861static struct ieee80211_node *
2862bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2863{
2864	struct ieee80211com *ic = vap->iv_ic;
2865	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2866	const size_t space = sizeof(struct bwn_node);
2867	struct bwn_node *bn;
2868
2869	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2870	if (bn == NULL) {
2871		/* XXX stat+msg */
2872		return (NULL);
2873	}
2874	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2875	return (&bn->bn_node);
2876}
2877
2878static void
2879bwn_node_cleanup(struct ieee80211_node *ni)
2880{
2881	struct ieee80211com *ic = ni->ni_ic;
2882	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2883
2884	sc->sc_node_cleanup(ni);
2885}
2886
2887static void
2888bwn_scan_start(struct ieee80211com *ic)
2889{
2890	struct ifnet *ifp = ic->ic_ifp;
2891	struct bwn_softc *sc = ifp->if_softc;
2892	struct bwn_mac *mac;
2893
2894	BWN_LOCK(sc);
2895	mac = sc->sc_curmac;
2896	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2897		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2898		bwn_set_opmode(mac);
2899		/* disable CFP update during scan */
2900		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2901	}
2902	BWN_UNLOCK(sc);
2903}
2904
2905static void
2906bwn_scan_end(struct ieee80211com *ic)
2907{
2908	struct ifnet *ifp = ic->ic_ifp;
2909	struct bwn_softc *sc = ifp->if_softc;
2910	struct bwn_mac *mac;
2911
2912	BWN_LOCK(sc);
2913	mac = sc->sc_curmac;
2914	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2915		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2916		bwn_set_opmode(mac);
2917		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2918	}
2919	BWN_UNLOCK(sc);
2920}
2921
2922static void
2923bwn_set_channel(struct ieee80211com *ic)
2924{
2925	struct ifnet *ifp = ic->ic_ifp;
2926	struct bwn_softc *sc = ifp->if_softc;
2927	struct bwn_mac *mac = sc->sc_curmac;
2928	struct bwn_phy *phy = &mac->mac_phy;
2929	int chan, error;
2930
2931	BWN_LOCK(sc);
2932
2933	error = bwn_switch_band(sc, ic->ic_curchan);
2934	if (error)
2935		goto fail;;
2936	bwn_mac_suspend(mac);
2937	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2938	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2939	if (chan != phy->chan)
2940		bwn_switch_channel(mac, chan);
2941
2942	/* TX power level */
2943	if (ic->ic_curchan->ic_maxpower != 0 &&
2944	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2945		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2946		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2947		    BWN_TXPWR_IGNORE_TSSI);
2948	}
2949
2950	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2951	if (phy->set_antenna)
2952		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2953
2954	if (sc->sc_rf_enabled != phy->rf_on) {
2955		if (sc->sc_rf_enabled) {
2956			bwn_rf_turnon(mac);
2957			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2958				device_printf(sc->sc_dev,
2959				    "please turns on the RF switch\n");
2960		} else
2961			bwn_rf_turnoff(mac);
2962	}
2963
2964	bwn_mac_enable(mac);
2965
2966fail:
2967	/*
2968	 * Setup radio tap channel freq and flags
2969	 */
2970	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2971		htole16(ic->ic_curchan->ic_freq);
2972	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2973		htole16(ic->ic_curchan->ic_flags & 0xffff);
2974
2975	BWN_UNLOCK(sc);
2976}
2977
2978static struct ieee80211vap *
2979bwn_vap_create(struct ieee80211com *ic,
2980	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2981	const uint8_t bssid[IEEE80211_ADDR_LEN],
2982	const uint8_t mac0[IEEE80211_ADDR_LEN])
2983{
2984	struct ifnet *ifp = ic->ic_ifp;
2985	struct bwn_softc *sc = ifp->if_softc;
2986	struct ieee80211vap *vap;
2987	struct bwn_vap *bvp;
2988	uint8_t mac[IEEE80211_ADDR_LEN];
2989
2990	IEEE80211_ADDR_COPY(mac, mac0);
2991	switch (opmode) {
2992	case IEEE80211_M_HOSTAP:
2993	case IEEE80211_M_MBSS:
2994	case IEEE80211_M_STA:
2995	case IEEE80211_M_WDS:
2996	case IEEE80211_M_MONITOR:
2997	case IEEE80211_M_IBSS:
2998	case IEEE80211_M_AHDEMO:
2999		break;
3000	default:
3001		return (NULL);
3002	}
3003
3004	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3005
3006	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3007	    M_80211_VAP, M_NOWAIT | M_ZERO);
3008	if (bvp == NULL) {
3009		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3010		return (NULL);
3011	}
3012	vap = &bvp->bv_vap;
3013	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3014	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3015	/* override with driver methods */
3016	bvp->bv_newstate = vap->iv_newstate;
3017	vap->iv_newstate = bwn_newstate;
3018
3019	/* override max aid so sta's cannot assoc when we're out of sta id's */
3020	vap->iv_max_aid = BWN_STAID_MAX;
3021
3022	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3023	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3024	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3025	    500 /*ms*/);
3026
3027	/* complete setup */
3028	ieee80211_vap_attach(vap, ieee80211_media_change,
3029	    ieee80211_media_status);
3030	return (vap);
3031}
3032
3033static void
3034bwn_vap_delete(struct ieee80211vap *vap)
3035{
3036	struct bwn_vap *bvp = BWN_VAP(vap);
3037
3038	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3039	ieee80211_vap_detach(vap);
3040	free(bvp, M_80211_VAP);
3041}
3042
3043static void
3044bwn_init(void *arg)
3045{
3046	struct bwn_softc *sc = arg;
3047	struct ifnet *ifp = sc->sc_ifp;
3048	struct ieee80211com *ic = ifp->if_l2com;
3049	int error = 0;
3050
3051	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3052		__func__, ifp->if_flags);
3053
3054	BWN_LOCK(sc);
3055	error = bwn_init_locked(sc);
3056	BWN_UNLOCK(sc);
3057
3058	if (error == 0)
3059		ieee80211_start_all(ic);	/* start all vap's */
3060}
3061
3062static int
3063bwn_init_locked(struct bwn_softc *sc)
3064{
3065	struct bwn_mac *mac;
3066	struct ifnet *ifp = sc->sc_ifp;
3067	int error;
3068
3069	BWN_ASSERT_LOCKED(sc);
3070
3071	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3072	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3073	sc->sc_filters = 0;
3074	bwn_wme_clear(sc);
3075	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3076	sc->sc_rf_enabled = 1;
3077
3078	mac = sc->sc_curmac;
3079	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3080		error = bwn_core_init(mac);
3081		if (error != 0)
3082			return (error);
3083	}
3084	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3085		bwn_core_start(mac);
3086
3087	bwn_set_opmode(mac);
3088	bwn_set_pretbtt(mac);
3089	bwn_spu_setdelay(mac, 0);
3090	bwn_set_macaddr(mac);
3091
3092	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3093	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3094	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3095
3096	return (0);
3097}
3098
3099static void
3100bwn_stop(struct bwn_softc *sc, int statechg)
3101{
3102
3103	BWN_LOCK(sc);
3104	bwn_stop_locked(sc, statechg);
3105	BWN_UNLOCK(sc);
3106}
3107
3108static void
3109bwn_stop_locked(struct bwn_softc *sc, int statechg)
3110{
3111	struct bwn_mac *mac = sc->sc_curmac;
3112	struct ifnet *ifp = sc->sc_ifp;
3113
3114	BWN_ASSERT_LOCKED(sc);
3115
3116	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3117		/* XXX FIXME opmode not based on VAP */
3118		bwn_set_opmode(mac);
3119		bwn_set_macaddr(mac);
3120	}
3121
3122	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3123		bwn_core_stop(mac);
3124
3125	callout_stop(&sc->sc_led_blink_ch);
3126	sc->sc_led_blinking = 0;
3127
3128	bwn_core_exit(mac);
3129	sc->sc_rf_enabled = 0;
3130
3131	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3132}
3133
3134static void
3135bwn_wme_clear(struct bwn_softc *sc)
3136{
3137#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3138	struct wmeParams *p;
3139	unsigned int i;
3140
3141	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3142	    ("%s:%d: fail", __func__, __LINE__));
3143
3144	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3145		p = &(sc->sc_wmeParams[i]);
3146
3147		switch (bwn_wme_shm_offsets[i]) {
3148		case BWN_WME_VOICE:
3149			p->wmep_txopLimit = 0;
3150			p->wmep_aifsn = 2;
3151			/* XXX FIXME: log2(cwmin) */
3152			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3153			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3154			break;
3155		case BWN_WME_VIDEO:
3156			p->wmep_txopLimit = 0;
3157			p->wmep_aifsn = 2;
3158			/* XXX FIXME: log2(cwmin) */
3159			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3160			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3161			break;
3162		case BWN_WME_BESTEFFORT:
3163			p->wmep_txopLimit = 0;
3164			p->wmep_aifsn = 3;
3165			/* XXX FIXME: log2(cwmin) */
3166			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3167			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3168			break;
3169		case BWN_WME_BACKGROUND:
3170			p->wmep_txopLimit = 0;
3171			p->wmep_aifsn = 7;
3172			/* XXX FIXME: log2(cwmin) */
3173			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3174			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3175			break;
3176		default:
3177			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3178		}
3179	}
3180}
3181
3182static int
3183bwn_core_init(struct bwn_mac *mac)
3184{
3185#ifdef BWN_DEBUG
3186	struct bwn_softc *sc = mac->mac_sc;
3187#endif
3188	struct siba_dev_softc *sd = mac->mac_sd;
3189	struct siba_softc *siba = sd->sd_bus;
3190	struct siba_sprom *sprom = &siba->siba_sprom;
3191	uint64_t hf;
3192	int error;
3193
3194	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3195	    ("%s:%d: fail", __func__, __LINE__));
3196
3197	siba_powerup(siba, 0);
3198	if (!siba_dev_isup(sd))
3199		bwn_reset_core(mac,
3200		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3201
3202	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3203	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3204	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3205	BWN_GETTIME(mac->mac_phy.nexttime);
3206	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3207	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3208	mac->mac_stats.link_noise = -95;
3209	mac->mac_reason_intr = 0;
3210	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3211	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3212#ifdef BWN_DEBUG
3213	if (sc->sc_debug & BWN_DEBUG_XMIT)
3214		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3215#endif
3216	mac->mac_suspended = 1;
3217	mac->mac_task_state = 0;
3218	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3219
3220	mac->mac_phy.init_pre(mac);
3221
3222	siba_pcicore_intr(&siba->siba_pci, sd);
3223
3224	bwn_fix_imcfglobug(mac);
3225	bwn_bt_disable(mac);
3226	if (mac->mac_phy.prepare_hw) {
3227		error = mac->mac_phy.prepare_hw(mac);
3228		if (error)
3229			goto fail0;
3230	}
3231	error = bwn_chip_init(mac);
3232	if (error)
3233		goto fail0;
3234	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3235	    mac->mac_sd->sd_id.sd_rev);
3236	hf = bwn_hf_read(mac);
3237	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3238		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3239		if (sprom->bf_lo & BWN_BFL_PACTRL)
3240			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3241		if (mac->mac_phy.rev == 1)
3242			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3243	}
3244	if (mac->mac_phy.rf_ver == 0x2050) {
3245		if (mac->mac_phy.rf_rev < 6)
3246			hf |= BWN_HF_FORCE_VCO_RECALC;
3247		if (mac->mac_phy.rf_rev == 6)
3248			hf |= BWN_HF_4318_TSSI;
3249	}
3250	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3251		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3252	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3253	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3254		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3255	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3256	bwn_hf_write(mac, hf);
3257
3258	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3259	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3260	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3261	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3262
3263	bwn_rate_init(mac);
3264	bwn_set_phytxctl(mac);
3265
3266	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3267	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3268	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3269
3270	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3271		bwn_pio_init(mac);
3272	else
3273		bwn_dma_init(mac);
3274	if (error)
3275		goto fail1;
3276	bwn_wme_init(mac);
3277	bwn_spu_setdelay(mac, 1);
3278	bwn_bt_enable(mac);
3279
3280	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3281	bwn_set_macaddr(mac);
3282	bwn_crypt_init(mac);
3283
3284	/* XXX LED initializatin */
3285
3286	mac->mac_status = BWN_MAC_STATUS_INITED;
3287
3288	return (error);
3289
3290fail1:
3291	bwn_chip_exit(mac);
3292fail0:
3293	siba_powerdown(siba);
3294	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3295	    ("%s:%d: fail", __func__, __LINE__));
3296	return (error);
3297}
3298
3299static void
3300bwn_core_start(struct bwn_mac *mac)
3301{
3302	struct bwn_softc *sc = mac->mac_sc;
3303	uint32_t tmp;
3304
3305	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3306	    ("%s:%d: fail", __func__, __LINE__));
3307
3308	if (mac->mac_sd->sd_id.sd_rev < 5)
3309		return;
3310
3311	while (1) {
3312		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3313		if (!(tmp & 0x00000001))
3314			break;
3315		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3316	}
3317
3318	bwn_mac_enable(mac);
3319	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3320	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3321
3322	mac->mac_status = BWN_MAC_STATUS_STARTED;
3323}
3324
3325static void
3326bwn_core_exit(struct bwn_mac *mac)
3327{
3328	uint32_t macctl;
3329
3330	BWN_ASSERT_LOCKED(mac->mac_sc);
3331
3332	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3333	    ("%s:%d: fail", __func__, __LINE__));
3334
3335	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3336		return;
3337	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3338
3339	macctl = BWN_READ_4(mac, BWN_MACCTL);
3340	macctl &= ~BWN_MACCTL_MCODE_RUN;
3341	macctl |= BWN_MACCTL_MCODE_JMP0;
3342	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3343
3344	bwn_dma_stop(mac);
3345	bwn_pio_stop(mac);
3346	bwn_chip_exit(mac);
3347	mac->mac_phy.switch_analog(mac, 0);
3348	siba_dev_down(mac->mac_sd, 0);
3349	siba_powerdown(mac->mac_sd->sd_bus);
3350}
3351
3352static void
3353bwn_fix_imcfglobug(struct bwn_mac *mac)
3354{
3355	struct siba_dev_softc *sd = mac->mac_sd;
3356	struct siba_softc *siba = sd->sd_bus;
3357	uint32_t tmp;
3358
3359	if (siba->siba_pci.spc_dev == NULL)
3360		return;
3361	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3362	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3363		return;
3364
3365	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3366	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3367	switch (siba->siba_type) {
3368	case SIBA_TYPE_PCI:
3369	case SIBA_TYPE_PCMCIA:
3370		tmp |= 0x32;
3371		break;
3372	case SIBA_TYPE_SSB:
3373		tmp |= 0x53;
3374		break;
3375	}
3376	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3377}
3378
3379static void
3380bwn_bt_disable(struct bwn_mac *mac)
3381{
3382	struct bwn_softc *sc = mac->mac_sc;
3383
3384	(void)sc;
3385	/* XXX do nothing yet */
3386}
3387
3388static int
3389bwn_chip_init(struct bwn_mac *mac)
3390{
3391	struct bwn_phy *phy = &mac->mac_phy;
3392	uint32_t macctl;
3393	int error;
3394
3395	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3396	if (phy->gmode)
3397		macctl |= BWN_MACCTL_GMODE;
3398	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3399
3400	error = bwn_fw_fillinfo(mac);
3401	if (error)
3402		return (error);
3403	error = bwn_fw_loaducode(mac);
3404	if (error)
3405		return (error);
3406
3407	error = bwn_gpio_init(mac);
3408	if (error)
3409		return (error);
3410
3411	error = bwn_fw_loadinitvals(mac);
3412	if (error) {
3413		bwn_gpio_cleanup(mac);
3414		return (error);
3415	}
3416	phy->switch_analog(mac, 1);
3417	error = bwn_phy_init(mac);
3418	if (error) {
3419		bwn_gpio_cleanup(mac);
3420		return (error);
3421	}
3422	if (phy->set_im)
3423		phy->set_im(mac, BWN_IMMODE_NONE);
3424	if (phy->set_antenna)
3425		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3426	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3427
3428	if (phy->type == BWN_PHYTYPE_B)
3429		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3430	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3431	if (mac->mac_sd->sd_id.sd_rev < 5)
3432		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3433
3434	BWN_WRITE_4(mac, BWN_MACCTL,
3435	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3436	BWN_WRITE_4(mac, BWN_MACCTL,
3437	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3438	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3439
3440	bwn_set_opmode(mac);
3441	if (mac->mac_sd->sd_id.sd_rev < 3) {
3442		BWN_WRITE_2(mac, 0x060e, 0x0000);
3443		BWN_WRITE_2(mac, 0x0610, 0x8000);
3444		BWN_WRITE_2(mac, 0x0604, 0x0000);
3445		BWN_WRITE_2(mac, 0x0606, 0x0200);
3446	} else {
3447		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3448		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3449	}
3450	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3451	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3452	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3453	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3454	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3455	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3456	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3457	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3458	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3459	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3460	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3461	return (error);
3462}
3463
3464/* read hostflags */
3465static uint64_t
3466bwn_hf_read(struct bwn_mac *mac)
3467{
3468	uint64_t ret;
3469
3470	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3471	ret <<= 16;
3472	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3473	ret <<= 16;
3474	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3475	return (ret);
3476}
3477
3478static void
3479bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3480{
3481
3482	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3483	    (value & 0x00000000ffffull));
3484	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3485	    (value & 0x0000ffff0000ull) >> 16);
3486	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3487	    (value & 0xffff00000000ULL) >> 32);
3488}
3489
3490static void
3491bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3492{
3493
3494	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3495	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3496}
3497
3498static void
3499bwn_rate_init(struct bwn_mac *mac)
3500{
3501
3502	switch (mac->mac_phy.type) {
3503	case BWN_PHYTYPE_A:
3504	case BWN_PHYTYPE_G:
3505	case BWN_PHYTYPE_LP:
3506	case BWN_PHYTYPE_N:
3507		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3508		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3509		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3510		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3511		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3512		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3513		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3514		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3515			break;
3516		/* FALLTHROUGH */
3517	case BWN_PHYTYPE_B:
3518		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3519		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3520		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3521		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3522		break;
3523	default:
3524		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3525	}
3526}
3527
3528static void
3529bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3530{
3531	uint16_t offset;
3532
3533	if (ofdm) {
3534		offset = 0x480;
3535		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3536	} else {
3537		offset = 0x4c0;
3538		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3539	}
3540	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3541	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3542}
3543
3544static uint8_t
3545bwn_plcp_getcck(const uint8_t bitrate)
3546{
3547
3548	switch (bitrate) {
3549	case BWN_CCK_RATE_1MB:
3550		return (0x0a);
3551	case BWN_CCK_RATE_2MB:
3552		return (0x14);
3553	case BWN_CCK_RATE_5MB:
3554		return (0x37);
3555	case BWN_CCK_RATE_11MB:
3556		return (0x6e);
3557	}
3558	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3559	return (0);
3560}
3561
3562static uint8_t
3563bwn_plcp_getofdm(const uint8_t bitrate)
3564{
3565
3566	switch (bitrate) {
3567	case BWN_OFDM_RATE_6MB:
3568		return (0xb);
3569	case BWN_OFDM_RATE_9MB:
3570		return (0xf);
3571	case BWN_OFDM_RATE_12MB:
3572		return (0xa);
3573	case BWN_OFDM_RATE_18MB:
3574		return (0xe);
3575	case BWN_OFDM_RATE_24MB:
3576		return (0x9);
3577	case BWN_OFDM_RATE_36MB:
3578		return (0xd);
3579	case BWN_OFDM_RATE_48MB:
3580		return (0x8);
3581	case BWN_OFDM_RATE_54MB:
3582		return (0xc);
3583	}
3584	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3585	return (0);
3586}
3587
3588static void
3589bwn_set_phytxctl(struct bwn_mac *mac)
3590{
3591	uint16_t ctl;
3592
3593	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3594	    BWN_TX_PHY_TXPWR);
3595	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3596	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3597	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3598}
3599
3600static void
3601bwn_pio_init(struct bwn_mac *mac)
3602{
3603	struct bwn_pio *pio = &mac->mac_method.pio;
3604
3605	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3606	    & ~BWN_MACCTL_BIGENDIAN);
3607	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3608
3609	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3610	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3611	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3612	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3613	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3614	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3615}
3616
3617static void
3618bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3619    int index)
3620{
3621	struct bwn_pio_txpkt *tp;
3622	unsigned int i;
3623
3624	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3625	tq->tq_index = index;
3626
3627	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3628	if (mac->mac_sd->sd_id.sd_rev >= 8)
3629		tq->tq_size = 1920;
3630	else {
3631		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3632		tq->tq_size -= 80;
3633	}
3634
3635	TAILQ_INIT(&tq->tq_pktlist);
3636	for (i = 0; i < N(tq->tq_pkts); i++) {
3637		tp = &(tq->tq_pkts[i]);
3638		tp->tp_index = i;
3639		tp->tp_queue = tq;
3640		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3641	}
3642}
3643
3644static uint16_t
3645bwn_pio_idx2base(struct bwn_mac *mac, int index)
3646{
3647	struct bwn_softc *sc = mac->mac_sc;
3648	static const uint16_t bases[] = {
3649		BWN_PIO_BASE0,
3650		BWN_PIO_BASE1,
3651		BWN_PIO_BASE2,
3652		BWN_PIO_BASE3,
3653		BWN_PIO_BASE4,
3654		BWN_PIO_BASE5,
3655		BWN_PIO_BASE6,
3656		BWN_PIO_BASE7,
3657	};
3658	static const uint16_t bases_rev11[] = {
3659		BWN_PIO11_BASE0,
3660		BWN_PIO11_BASE1,
3661		BWN_PIO11_BASE2,
3662		BWN_PIO11_BASE3,
3663		BWN_PIO11_BASE4,
3664		BWN_PIO11_BASE5,
3665	};
3666
3667	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3668		if (index >= N(bases_rev11))
3669			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3670		return (bases_rev11[index]);
3671	}
3672	if (index >= N(bases))
3673		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3674	return (bases[index]);
3675}
3676
3677static void
3678bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3679    int index)
3680{
3681
3682	prq->prq_mac = mac;
3683	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3684	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3685	bwn_dma_rxdirectfifo(mac, index, 1);
3686}
3687
3688static void
3689bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3690{
3691	if (tq == NULL)
3692		return;
3693	bwn_pio_cancel_tx_packets(tq);
3694}
3695
3696static void
3697bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3698{
3699
3700	bwn_destroy_pioqueue_tx(pio);
3701}
3702
3703static uint16_t
3704bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3705    uint16_t offset)
3706{
3707
3708	return (BWN_READ_2(mac, tq->tq_base + offset));
3709}
3710
3711static void
3712bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3713{
3714	uint32_t ctl;
3715	int type;
3716	uint16_t base;
3717
3718	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3719	base = bwn_dma_base(type, idx);
3720	if (type == BWN_DMA_64BIT) {
3721		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3722		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3723		if (enable)
3724			ctl |= BWN_DMA64_RXDIRECTFIFO;
3725		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3726	} else {
3727		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3728		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3729		if (enable)
3730			ctl |= BWN_DMA32_RXDIRECTFIFO;
3731		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3732	}
3733}
3734
3735static uint64_t
3736bwn_dma_mask(struct bwn_mac *mac)
3737{
3738	uint32_t tmp;
3739	uint16_t base;
3740
3741	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3742	if (tmp & SIBA_TGSHIGH_DMA64)
3743		return (BWN_DMA_BIT_MASK(64));
3744	base = bwn_dma_base(0, 0);
3745	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3746	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3747	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3748		return (BWN_DMA_BIT_MASK(32));
3749
3750	return (BWN_DMA_BIT_MASK(30));
3751}
3752
3753static int
3754bwn_dma_mask2type(uint64_t dmamask)
3755{
3756
3757	if (dmamask == BWN_DMA_BIT_MASK(30))
3758		return (BWN_DMA_30BIT);
3759	if (dmamask == BWN_DMA_BIT_MASK(32))
3760		return (BWN_DMA_32BIT);
3761	if (dmamask == BWN_DMA_BIT_MASK(64))
3762		return (BWN_DMA_64BIT);
3763	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3764	return (BWN_DMA_30BIT);
3765}
3766
3767static void
3768bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3769{
3770	struct bwn_pio_txpkt *tp;
3771	unsigned int i;
3772
3773	for (i = 0; i < N(tq->tq_pkts); i++) {
3774		tp = &(tq->tq_pkts[i]);
3775		if (tp->tp_m) {
3776			m_freem(tp->tp_m);
3777			tp->tp_m = NULL;
3778		}
3779	}
3780}
3781
3782static uint16_t
3783bwn_dma_base(int type, int controller_idx)
3784{
3785	static const uint16_t map64[] = {
3786		BWN_DMA64_BASE0,
3787		BWN_DMA64_BASE1,
3788		BWN_DMA64_BASE2,
3789		BWN_DMA64_BASE3,
3790		BWN_DMA64_BASE4,
3791		BWN_DMA64_BASE5,
3792	};
3793	static const uint16_t map32[] = {
3794		BWN_DMA32_BASE0,
3795		BWN_DMA32_BASE1,
3796		BWN_DMA32_BASE2,
3797		BWN_DMA32_BASE3,
3798		BWN_DMA32_BASE4,
3799		BWN_DMA32_BASE5,
3800	};
3801
3802	if (type == BWN_DMA_64BIT) {
3803		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3804		    ("%s:%d: fail", __func__, __LINE__));
3805		return (map64[controller_idx]);
3806	}
3807	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3808	    ("%s:%d: fail", __func__, __LINE__));
3809	return (map32[controller_idx]);
3810}
3811
3812static void
3813bwn_dma_init(struct bwn_mac *mac)
3814{
3815	struct bwn_dma *dma = &mac->mac_method.dma;
3816
3817	/* setup TX DMA channels. */
3818	bwn_dma_setup(dma->wme[WME_AC_BK]);
3819	bwn_dma_setup(dma->wme[WME_AC_BE]);
3820	bwn_dma_setup(dma->wme[WME_AC_VI]);
3821	bwn_dma_setup(dma->wme[WME_AC_VO]);
3822	bwn_dma_setup(dma->mcast);
3823	/* setup RX DMA channel. */
3824	bwn_dma_setup(dma->rx);
3825}
3826
3827static struct bwn_dma_ring *
3828bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3829    int for_tx, int type)
3830{
3831	struct bwn_dma *dma = &mac->mac_method.dma;
3832	struct bwn_dma_ring *dr;
3833	struct bwn_dmadesc_generic *desc;
3834	struct bwn_dmadesc_meta *mt;
3835	struct bwn_softc *sc = mac->mac_sc;
3836	int error, i;
3837
3838	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3839	if (dr == NULL)
3840		goto out;
3841	dr->dr_numslots = BWN_RXRING_SLOTS;
3842	if (for_tx)
3843		dr->dr_numslots = BWN_TXRING_SLOTS;
3844
3845	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3846	    M_DEVBUF, M_NOWAIT | M_ZERO);
3847	if (dr->dr_meta == NULL)
3848		goto fail0;
3849
3850	dr->dr_type = type;
3851	dr->dr_mac = mac;
3852	dr->dr_base = bwn_dma_base(type, controller_index);
3853	dr->dr_index = controller_index;
3854	if (type == BWN_DMA_64BIT) {
3855		dr->getdesc = bwn_dma_64_getdesc;
3856		dr->setdesc = bwn_dma_64_setdesc;
3857		dr->start_transfer = bwn_dma_64_start_transfer;
3858		dr->suspend = bwn_dma_64_suspend;
3859		dr->resume = bwn_dma_64_resume;
3860		dr->get_curslot = bwn_dma_64_get_curslot;
3861		dr->set_curslot = bwn_dma_64_set_curslot;
3862	} else {
3863		dr->getdesc = bwn_dma_32_getdesc;
3864		dr->setdesc = bwn_dma_32_setdesc;
3865		dr->start_transfer = bwn_dma_32_start_transfer;
3866		dr->suspend = bwn_dma_32_suspend;
3867		dr->resume = bwn_dma_32_resume;
3868		dr->get_curslot = bwn_dma_32_get_curslot;
3869		dr->set_curslot = bwn_dma_32_set_curslot;
3870	}
3871	if (for_tx) {
3872		dr->dr_tx = 1;
3873		dr->dr_curslot = -1;
3874	} else {
3875		if (dr->dr_index == 0) {
3876			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3877			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3878		} else
3879			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3880	}
3881
3882	error = bwn_dma_allocringmemory(dr);
3883	if (error)
3884		goto fail2;
3885
3886	if (for_tx) {
3887		/*
3888		 * Assumption: BWN_TXRING_SLOTS can be divided by
3889		 * BWN_TX_SLOTS_PER_FRAME
3890		 */
3891		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3892		    ("%s:%d: fail", __func__, __LINE__));
3893
3894		dr->dr_txhdr_cache =
3895		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3896			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3897		KASSERT(dr->dr_txhdr_cache != NULL,
3898		    ("%s:%d: fail", __func__, __LINE__));
3899
3900		/*
3901		 * Create TX ring DMA stuffs
3902		 */
3903		error = bus_dma_tag_create(dma->parent_dtag,
3904				    BWN_ALIGN, 0,
3905				    BUS_SPACE_MAXADDR,
3906				    BUS_SPACE_MAXADDR,
3907				    NULL, NULL,
3908				    BWN_HDRSIZE(mac),
3909				    1,
3910				    BUS_SPACE_MAXSIZE_32BIT,
3911				    0,
3912				    NULL, NULL,
3913				    &dr->dr_txring_dtag);
3914		if (error) {
3915			device_printf(sc->sc_dev,
3916			    "can't create TX ring DMA tag: TODO frees\n");
3917			goto fail1;
3918		}
3919
3920		for (i = 0; i < dr->dr_numslots; i += 2) {
3921			dr->getdesc(dr, i, &desc, &mt);
3922
3923			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3924			mt->mt_m = NULL;
3925			mt->mt_ni = NULL;
3926			mt->mt_islast = 0;
3927			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3928			    &mt->mt_dmap);
3929			if (error) {
3930				device_printf(sc->sc_dev,
3931				     "can't create RX buf DMA map\n");
3932				goto fail1;
3933			}
3934
3935			dr->getdesc(dr, i + 1, &desc, &mt);
3936
3937			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3938			mt->mt_m = NULL;
3939			mt->mt_ni = NULL;
3940			mt->mt_islast = 1;
3941			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3942			    &mt->mt_dmap);
3943			if (error) {
3944				device_printf(sc->sc_dev,
3945				     "can't create RX buf DMA map\n");
3946				goto fail1;
3947			}
3948		}
3949	} else {
3950		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3951		    &dr->dr_spare_dmap);
3952		if (error) {
3953			device_printf(sc->sc_dev,
3954			    "can't create RX buf DMA map\n");
3955			goto out;		/* XXX wrong! */
3956		}
3957
3958		for (i = 0; i < dr->dr_numslots; i++) {
3959			dr->getdesc(dr, i, &desc, &mt);
3960
3961			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3962			    &mt->mt_dmap);
3963			if (error) {
3964				device_printf(sc->sc_dev,
3965				    "can't create RX buf DMA map\n");
3966				goto out;	/* XXX wrong! */
3967			}
3968			error = bwn_dma_newbuf(dr, desc, mt, 1);
3969			if (error) {
3970				device_printf(sc->sc_dev,
3971				    "failed to allocate RX buf\n");
3972				goto out;	/* XXX wrong! */
3973			}
3974		}
3975
3976		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3977		    BUS_DMASYNC_PREWRITE);
3978
3979		dr->dr_usedslot = dr->dr_numslots;
3980	}
3981
3982      out:
3983	return (dr);
3984
3985fail2:
3986	free(dr->dr_txhdr_cache, M_DEVBUF);
3987fail1:
3988	free(dr->dr_meta, M_DEVBUF);
3989fail0:
3990	free(dr, M_DEVBUF);
3991	return (NULL);
3992}
3993
3994static void
3995bwn_dma_ringfree(struct bwn_dma_ring **dr)
3996{
3997
3998	if (dr == NULL)
3999		return;
4000
4001	bwn_dma_free_descbufs(*dr);
4002	bwn_dma_free_ringmemory(*dr);
4003
4004	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4005	free((*dr)->dr_meta, M_DEVBUF);
4006	free(*dr, M_DEVBUF);
4007
4008	*dr = NULL;
4009}
4010
4011static void
4012bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4013    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4014{
4015	struct bwn_dmadesc32 *desc;
4016
4017	*meta = &(dr->dr_meta[slot]);
4018	desc = dr->dr_ring_descbase;
4019	desc = &(desc[slot]);
4020
4021	*gdesc = (struct bwn_dmadesc_generic *)desc;
4022}
4023
4024static void
4025bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4026    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4027    int start, int end, int irq)
4028{
4029	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4030	uint32_t addr, addrext, ctl;
4031	int slot;
4032
4033	slot = (int)(&(desc->dma.dma32) - descbase);
4034	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4035	    ("%s:%d: fail", __func__, __LINE__));
4036
4037	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4038	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4039	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4040	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4041	if (slot == dr->dr_numslots - 1)
4042		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4043	if (start)
4044		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4045	if (end)
4046		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4047	if (irq)
4048		ctl |= BWN_DMA32_DCTL_IRQ;
4049	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4050	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4051
4052	desc->dma.dma32.control = htole32(ctl);
4053	desc->dma.dma32.address = htole32(addr);
4054}
4055
4056static void
4057bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4058{
4059
4060	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4061	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4062}
4063
4064static void
4065bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4066{
4067
4068	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4069	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4070}
4071
4072static void
4073bwn_dma_32_resume(struct bwn_dma_ring *dr)
4074{
4075
4076	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4077	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4078}
4079
4080static int
4081bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4082{
4083	uint32_t val;
4084
4085	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4086	val &= BWN_DMA32_RXDPTR;
4087
4088	return (val / sizeof(struct bwn_dmadesc32));
4089}
4090
4091static void
4092bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4093{
4094
4095	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4096	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4097}
4098
4099static void
4100bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4101    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4102{
4103	struct bwn_dmadesc64 *desc;
4104
4105	*meta = &(dr->dr_meta[slot]);
4106	desc = dr->dr_ring_descbase;
4107	desc = &(desc[slot]);
4108
4109	*gdesc = (struct bwn_dmadesc_generic *)desc;
4110}
4111
4112static void
4113bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4114    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4115    int start, int end, int irq)
4116{
4117	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4118	int slot;
4119	uint32_t ctl0 = 0, ctl1 = 0;
4120	uint32_t addrlo, addrhi;
4121	uint32_t addrext;
4122
4123	slot = (int)(&(desc->dma.dma64) - descbase);
4124	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4125	    ("%s:%d: fail", __func__, __LINE__));
4126
4127	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4128	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4129	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4130	    30;
4131	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4132	if (slot == dr->dr_numslots - 1)
4133		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4134	if (start)
4135		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4136	if (end)
4137		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4138	if (irq)
4139		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4140	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4141	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4142	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4143
4144	desc->dma.dma64.control0 = htole32(ctl0);
4145	desc->dma.dma64.control1 = htole32(ctl1);
4146	desc->dma.dma64.address_low = htole32(addrlo);
4147	desc->dma.dma64.address_high = htole32(addrhi);
4148}
4149
4150static void
4151bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4152{
4153
4154	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4155	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4156}
4157
4158static void
4159bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4160{
4161
4162	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4163	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4164}
4165
4166static void
4167bwn_dma_64_resume(struct bwn_dma_ring *dr)
4168{
4169
4170	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4171	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4172}
4173
4174static int
4175bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4176{
4177	uint32_t val;
4178
4179	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4180	val &= BWN_DMA64_RXSTATDPTR;
4181
4182	return (val / sizeof(struct bwn_dmadesc64));
4183}
4184
4185static void
4186bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4187{
4188
4189	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4190	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4191}
4192
4193static int
4194bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4195{
4196	struct bwn_mac *mac = dr->dr_mac;
4197	struct bwn_dma *dma = &mac->mac_method.dma;
4198	struct bwn_softc *sc = mac->mac_sc;
4199	int error;
4200
4201	error = bus_dma_tag_create(dma->parent_dtag,
4202			    BWN_ALIGN, 0,
4203			    BUS_SPACE_MAXADDR,
4204			    BUS_SPACE_MAXADDR,
4205			    NULL, NULL,
4206			    BWN_DMA_RINGMEMSIZE,
4207			    1,
4208			    BUS_SPACE_MAXSIZE_32BIT,
4209			    0,
4210			    NULL, NULL,
4211			    &dr->dr_ring_dtag);
4212	if (error) {
4213		device_printf(sc->sc_dev,
4214		    "can't create TX ring DMA tag: TODO frees\n");
4215		return (-1);
4216	}
4217
4218	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4219	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4220	    &dr->dr_ring_dmap);
4221	if (error) {
4222		device_printf(sc->sc_dev,
4223		    "can't allocate DMA mem: TODO frees\n");
4224		return (-1);
4225	}
4226	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4227	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4228	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4229	if (error) {
4230		device_printf(sc->sc_dev,
4231		    "can't load DMA mem: TODO free\n");
4232		return (-1);
4233	}
4234
4235	return (0);
4236}
4237
4238static void
4239bwn_dma_setup(struct bwn_dma_ring *dr)
4240{
4241	uint64_t ring64;
4242	uint32_t addrext, ring32, value;
4243	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4244
4245	if (dr->dr_tx) {
4246		dr->dr_curslot = -1;
4247
4248		if (dr->dr_type == BWN_DMA_64BIT) {
4249			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4250			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4251			    >> 30;
4252			value = BWN_DMA64_TXENABLE;
4253			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4254			    & BWN_DMA64_TXADDREXT_MASK;
4255			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4256			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4257			    (ring64 & 0xffffffff));
4258			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4259			    ((ring64 >> 32) &
4260			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4261		} else {
4262			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4263			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4264			value = BWN_DMA32_TXENABLE;
4265			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4266			    & BWN_DMA32_TXADDREXT_MASK;
4267			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4268			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4269			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4270		}
4271		return;
4272	}
4273
4274	/*
4275	 * set for RX
4276	 */
4277	dr->dr_usedslot = dr->dr_numslots;
4278
4279	if (dr->dr_type == BWN_DMA_64BIT) {
4280		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4281		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4282		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4283		value |= BWN_DMA64_RXENABLE;
4284		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4285		    & BWN_DMA64_RXADDREXT_MASK;
4286		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4287		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4288		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4289		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4290		    | (trans << 1));
4291		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4292		    sizeof(struct bwn_dmadesc64));
4293	} else {
4294		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4295		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4296		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4297		value |= BWN_DMA32_RXENABLE;
4298		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4299		    & BWN_DMA32_RXADDREXT_MASK;
4300		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4301		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4302		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4303		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4304		    sizeof(struct bwn_dmadesc32));
4305	}
4306}
4307
4308static void
4309bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4310{
4311
4312	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4313	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4314	    dr->dr_ring_dmap);
4315}
4316
4317static void
4318bwn_dma_cleanup(struct bwn_dma_ring *dr)
4319{
4320
4321	if (dr->dr_tx) {
4322		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4323		if (dr->dr_type == BWN_DMA_64BIT) {
4324			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4325			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4326		} else
4327			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4328	} else {
4329		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4330		if (dr->dr_type == BWN_DMA_64BIT) {
4331			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4332			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4333		} else
4334			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4335	}
4336}
4337
4338static void
4339bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4340{
4341	struct bwn_dmadesc_generic *desc;
4342	struct bwn_dmadesc_meta *meta;
4343	struct bwn_mac *mac = dr->dr_mac;
4344	struct bwn_dma *dma = &mac->mac_method.dma;
4345	struct bwn_softc *sc = mac->mac_sc;
4346	int i;
4347
4348	if (!dr->dr_usedslot)
4349		return;
4350	for (i = 0; i < dr->dr_numslots; i++) {
4351		dr->getdesc(dr, i, &desc, &meta);
4352
4353		if (meta->mt_m == NULL) {
4354			if (!dr->dr_tx)
4355				device_printf(sc->sc_dev, "%s: not TX?\n",
4356				    __func__);
4357			continue;
4358		}
4359		if (dr->dr_tx) {
4360			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4361				bus_dmamap_unload(dr->dr_txring_dtag,
4362				    meta->mt_dmap);
4363			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4364				bus_dmamap_unload(dma->txbuf_dtag,
4365				    meta->mt_dmap);
4366		} else
4367			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4368		bwn_dma_free_descbuf(dr, meta);
4369	}
4370}
4371
4372static int
4373bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4374    int type)
4375{
4376	struct bwn_softc *sc = mac->mac_sc;
4377	uint32_t value;
4378	int i;
4379	uint16_t offset;
4380
4381	for (i = 0; i < 10; i++) {
4382		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4383		    BWN_DMA32_TXSTATUS;
4384		value = BWN_READ_4(mac, base + offset);
4385		if (type == BWN_DMA_64BIT) {
4386			value &= BWN_DMA64_TXSTAT;
4387			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4388			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4389			    value == BWN_DMA64_TXSTAT_STOPPED)
4390				break;
4391		} else {
4392			value &= BWN_DMA32_TXSTATE;
4393			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4394			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4395			    value == BWN_DMA32_TXSTAT_STOPPED)
4396				break;
4397		}
4398		DELAY(1000);
4399	}
4400	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4401	BWN_WRITE_4(mac, base + offset, 0);
4402	for (i = 0; i < 10; i++) {
4403		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4404						   BWN_DMA32_TXSTATUS;
4405		value = BWN_READ_4(mac, base + offset);
4406		if (type == BWN_DMA_64BIT) {
4407			value &= BWN_DMA64_TXSTAT;
4408			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4409				i = -1;
4410				break;
4411			}
4412		} else {
4413			value &= BWN_DMA32_TXSTATE;
4414			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4415				i = -1;
4416				break;
4417			}
4418		}
4419		DELAY(1000);
4420	}
4421	if (i != -1) {
4422		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4423		return (ENODEV);
4424	}
4425	DELAY(1000);
4426
4427	return (0);
4428}
4429
4430static int
4431bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4432    int type)
4433{
4434	struct bwn_softc *sc = mac->mac_sc;
4435	uint32_t value;
4436	int i;
4437	uint16_t offset;
4438
4439	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4440	BWN_WRITE_4(mac, base + offset, 0);
4441	for (i = 0; i < 10; i++) {
4442		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4443		    BWN_DMA32_RXSTATUS;
4444		value = BWN_READ_4(mac, base + offset);
4445		if (type == BWN_DMA_64BIT) {
4446			value &= BWN_DMA64_RXSTAT;
4447			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4448				i = -1;
4449				break;
4450			}
4451		} else {
4452			value &= BWN_DMA32_RXSTATE;
4453			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4454				i = -1;
4455				break;
4456			}
4457		}
4458		DELAY(1000);
4459	}
4460	if (i != -1) {
4461		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4462		return (ENODEV);
4463	}
4464
4465	return (0);
4466}
4467
4468static void
4469bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4470    struct bwn_dmadesc_meta *meta)
4471{
4472
4473	if (meta->mt_m != NULL) {
4474		m_freem(meta->mt_m);
4475		meta->mt_m = NULL;
4476	}
4477	if (meta->mt_ni != NULL) {
4478		ieee80211_free_node(meta->mt_ni);
4479		meta->mt_ni = NULL;
4480	}
4481}
4482
4483static void
4484bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4485{
4486	struct bwn_rxhdr4 *rxhdr;
4487	unsigned char *frame;
4488
4489	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4490	rxhdr->frame_len = 0;
4491
4492	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4493	    sizeof(struct bwn_plcp6) + 2,
4494	    ("%s:%d: fail", __func__, __LINE__));
4495	frame = mtod(m, char *) + dr->dr_frameoffset;
4496	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4497}
4498
4499static uint8_t
4500bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4501{
4502	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4503
4504	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4505	    == 0xff);
4506}
4507
4508static void
4509bwn_wme_init(struct bwn_mac *mac)
4510{
4511
4512	bwn_wme_load(mac);
4513
4514	/* enable WME support. */
4515	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4516	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4517	    BWN_IFSCTL_USE_EDCF);
4518}
4519
4520static void
4521bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4522{
4523	struct bwn_softc *sc = mac->mac_sc;
4524	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4525	uint16_t delay;	/* microsec */
4526
4527	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4528	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4529		delay = 500;
4530	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4531		delay = max(delay, (uint16_t)2400);
4532
4533	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4534}
4535
4536static void
4537bwn_bt_enable(struct bwn_mac *mac)
4538{
4539	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4540	uint64_t hf;
4541
4542	if (bwn_bluetooth == 0)
4543		return;
4544	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4545		return;
4546	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4547		return;
4548
4549	hf = bwn_hf_read(mac);
4550	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4551		hf |= BWN_HF_BT_COEXISTALT;
4552	else
4553		hf |= BWN_HF_BT_COEXIST;
4554	bwn_hf_write(mac, hf);
4555}
4556
4557static void
4558bwn_set_macaddr(struct bwn_mac *mac)
4559{
4560
4561	bwn_mac_write_bssid(mac);
4562	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4563}
4564
4565static void
4566bwn_clear_keys(struct bwn_mac *mac)
4567{
4568	int i;
4569
4570	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4571		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4572		    ("%s:%d: fail", __func__, __LINE__));
4573
4574		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4575		    NULL, BWN_SEC_KEYSIZE, NULL);
4576		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4577			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4578			    NULL, BWN_SEC_KEYSIZE, NULL);
4579		}
4580		mac->mac_key[i].keyconf = NULL;
4581	}
4582}
4583
4584static void
4585bwn_crypt_init(struct bwn_mac *mac)
4586{
4587
4588	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4589	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4590	    ("%s:%d: fail", __func__, __LINE__));
4591	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4592	mac->mac_ktp *= 2;
4593	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4594		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4595		    mac->mac_max_nr_keys - 8);
4596	}
4597	bwn_clear_keys(mac);
4598}
4599
4600static void
4601bwn_chip_exit(struct bwn_mac *mac)
4602{
4603
4604	bwn_phy_exit(mac);
4605	bwn_gpio_cleanup(mac);
4606}
4607
4608static int
4609bwn_fw_fillinfo(struct bwn_mac *mac)
4610{
4611	int error;
4612
4613	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4614	if (error == 0)
4615		return (0);
4616	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4617	if (error == 0)
4618		return (0);
4619	return (error);
4620}
4621
4622static int
4623bwn_gpio_init(struct bwn_mac *mac)
4624{
4625	struct siba_softc *bus = mac->mac_sd->sd_bus;
4626	struct siba_dev_softc *sd;
4627	uint32_t mask = 0x0000001f, set = 0x0000000f;
4628
4629	BWN_WRITE_4(mac, BWN_MACCTL,
4630	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4631	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4632	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4633
4634	if (bus->siba_chipid == 0x4301) {
4635		mask |= 0x0060;
4636		set |= 0x0060;
4637	}
4638	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4639		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4640		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4641		mask |= 0x0200;
4642		set |= 0x0200;
4643	}
4644	if (mac->mac_sd->sd_id.sd_rev >= 2)
4645		mask |= 0x0010;
4646	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4647	    bus->siba_pci.spc_dev;
4648	if (sd == NULL)
4649		return (0);
4650	siba_write_4(sd, BWN_GPIOCTL,
4651	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4652
4653	return (0);
4654}
4655
4656static int
4657bwn_fw_loadinitvals(struct bwn_mac *mac)
4658{
4659#define	GETFWOFFSET(fwp, offset)				\
4660	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4661	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4662	const struct bwn_fwhdr *hdr;
4663	struct bwn_fw *fw = &mac->mac_fw;
4664	int error;
4665
4666	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4667	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4668	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4669	if (error)
4670		return (error);
4671	if (fw->initvals_band.fw) {
4672		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4673		error = bwn_fwinitvals_write(mac,
4674		    GETFWOFFSET(fw->initvals_band, hdr_len),
4675		    be32toh(hdr->size),
4676		    fw->initvals_band.fw->datasize - hdr_len);
4677	}
4678	return (error);
4679#undef GETFWOFFSET
4680}
4681
4682static int
4683bwn_phy_init(struct bwn_mac *mac)
4684{
4685	struct bwn_softc *sc = mac->mac_sc;
4686	int error;
4687
4688	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4689	mac->mac_phy.rf_onoff(mac, 1);
4690	error = mac->mac_phy.init(mac);
4691	if (error) {
4692		device_printf(sc->sc_dev, "PHY init failed\n");
4693		goto fail0;
4694	}
4695	error = bwn_switch_channel(mac,
4696	    mac->mac_phy.get_default_chan(mac));
4697	if (error) {
4698		device_printf(sc->sc_dev,
4699		    "failed to switch default channel\n");
4700		goto fail1;
4701	}
4702	return (0);
4703fail1:
4704	if (mac->mac_phy.exit)
4705		mac->mac_phy.exit(mac);
4706fail0:
4707	mac->mac_phy.rf_onoff(mac, 0);
4708
4709	return (error);
4710}
4711
4712static void
4713bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4714{
4715	uint16_t ant;
4716	uint16_t tmp;
4717
4718	ant = bwn_ant2phy(antenna);
4719
4720	/* For ACK/CTS */
4721	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4722	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4723	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4724	/* For Probe Resposes */
4725	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4726	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4727	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4728}
4729
4730static void
4731bwn_set_opmode(struct bwn_mac *mac)
4732{
4733	struct bwn_softc *sc = mac->mac_sc;
4734	struct ifnet *ifp = sc->sc_ifp;
4735	struct ieee80211com *ic = ifp->if_l2com;
4736	uint32_t ctl;
4737	uint16_t cfp_pretbtt;
4738
4739	ctl = BWN_READ_4(mac, BWN_MACCTL);
4740	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4741	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4742	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4743	ctl |= BWN_MACCTL_STA;
4744
4745	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4746	    ic->ic_opmode == IEEE80211_M_MBSS)
4747		ctl |= BWN_MACCTL_HOSTAP;
4748	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4749		ctl &= ~BWN_MACCTL_STA;
4750	ctl |= sc->sc_filters;
4751
4752	if (mac->mac_sd->sd_id.sd_rev <= 4)
4753		ctl |= BWN_MACCTL_PROMISC;
4754
4755	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4756
4757	cfp_pretbtt = 2;
4758	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4759		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4760		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4761			cfp_pretbtt = 100;
4762		else
4763			cfp_pretbtt = 50;
4764	}
4765	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4766}
4767
4768static void
4769bwn_gpio_cleanup(struct bwn_mac *mac)
4770{
4771	struct siba_softc *bus = mac->mac_sd->sd_bus;
4772	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4773
4774	pcidev = bus->siba_pci.spc_dev;
4775	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4776	if (!gpiodev)
4777		return;
4778	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4779}
4780
4781static int
4782bwn_dma_gettype(struct bwn_mac *mac)
4783{
4784	uint32_t tmp;
4785	uint16_t base;
4786
4787	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4788	if (tmp & SIBA_TGSHIGH_DMA64)
4789		return (BWN_DMA_64BIT);
4790	base = bwn_dma_base(0, 0);
4791	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4792	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4793	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4794		return (BWN_DMA_32BIT);
4795
4796	return (BWN_DMA_30BIT);
4797}
4798
4799static void
4800bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4801{
4802	if (!error) {
4803		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4804		*((bus_addr_t *)arg) = seg->ds_addr;
4805	}
4806}
4807
4808static void
4809bwn_phy_g_init_sub(struct bwn_mac *mac)
4810{
4811	struct bwn_phy *phy = &mac->mac_phy;
4812	struct bwn_phy_g *pg = &phy->phy_g;
4813	uint16_t i, tmp;
4814
4815	if (phy->rev == 1)
4816		bwn_phy_init_b5(mac);
4817	else
4818		bwn_phy_init_b6(mac);
4819
4820	if (phy->rev >= 2 || phy->gmode)
4821		bwn_phy_init_a(mac);
4822
4823	if (phy->rev >= 2) {
4824		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4825		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4826	}
4827	if (phy->rev == 2) {
4828		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4829		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4830	}
4831	if (phy->rev > 5) {
4832		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4833		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4834	}
4835	if (phy->gmode || phy->rev >= 2) {
4836		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4837		tmp &= BWN_PHYVER_VERSION;
4838		if (tmp == 3 || tmp == 5) {
4839			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4840			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4841		}
4842		if (tmp == 5) {
4843			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4844			    0x1f00);
4845		}
4846	}
4847	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4848		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4849	if (phy->rf_rev == 8) {
4850		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4851		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4852	}
4853	if (BWN_HAS_LOOPBACK(phy))
4854		bwn_loopback_calcgain(mac);
4855
4856	if (phy->rf_rev != 8) {
4857		if (pg->pg_initval == 0xffff)
4858			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4859		else
4860			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4861	}
4862	bwn_lo_g_init(mac);
4863	if (BWN_HAS_TXMAG(phy)) {
4864		BWN_RF_WRITE(mac, 0x52,
4865		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4866		    | pg->pg_loctl.tx_bias |
4867		    pg->pg_loctl.tx_magn);
4868	} else {
4869		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4870	}
4871	if (phy->rev >= 6) {
4872		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4873		    (pg->pg_loctl.tx_bias << 12));
4874	}
4875	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4876		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4877	else
4878		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4879	if (phy->rev < 2)
4880		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4881	else
4882		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4883	if (phy->gmode || phy->rev >= 2) {
4884		bwn_lo_g_adjust(mac);
4885		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4886	}
4887
4888	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4889		for (i = 0; i < 64; i++) {
4890			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4891			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4892			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4893			    -32), 31));
4894		}
4895		bwn_nrssi_threshold(mac);
4896	} else if (phy->gmode || phy->rev >= 2) {
4897		if (pg->pg_nrssi[0] == -1000) {
4898			KASSERT(pg->pg_nrssi[1] == -1000,
4899			    ("%s:%d: fail", __func__, __LINE__));
4900			bwn_nrssi_slope_11g(mac);
4901		} else
4902			bwn_nrssi_threshold(mac);
4903	}
4904	if (phy->rf_rev == 8)
4905		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4906	bwn_phy_hwpctl_init(mac);
4907	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4908	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4909		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4910		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4911	}
4912}
4913
4914static uint8_t
4915bwn_has_hwpctl(struct bwn_mac *mac)
4916{
4917
4918	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4919		return (0);
4920	return (mac->mac_phy.use_hwpctl(mac));
4921}
4922
4923static void
4924bwn_phy_init_b5(struct bwn_mac *mac)
4925{
4926	struct siba_softc *bus = mac->mac_sd->sd_bus;
4927	struct bwn_phy *phy = &mac->mac_phy;
4928	struct bwn_phy_g *pg = &phy->phy_g;
4929	uint16_t offset, value;
4930	uint8_t old_channel;
4931
4932	if (phy->analog == 1)
4933		BWN_RF_SET(mac, 0x007a, 0x0050);
4934	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4935	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4936		value = 0x2120;
4937		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4938			BWN_PHY_WRITE(mac, offset, value);
4939			value += 0x202;
4940		}
4941	}
4942	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4943	if (phy->rf_ver == 0x2050)
4944		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4945
4946	if (phy->gmode || phy->rev >= 2) {
4947		if (phy->rf_ver == 0x2050) {
4948			BWN_RF_SET(mac, 0x007a, 0x0020);
4949			BWN_RF_SET(mac, 0x0051, 0x0004);
4950		}
4951		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4952
4953		BWN_PHY_SET(mac, 0x0802, 0x0100);
4954		BWN_PHY_SET(mac, 0x042b, 0x2000);
4955
4956		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4957
4958		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4959		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4960		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4961	}
4962
4963	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4964		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4965
4966	if (phy->analog == 1) {
4967		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4968		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4969		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4970		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4971		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4972	} else
4973		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4974	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4975	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4976
4977	if (phy->analog == 1)
4978		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4979	else
4980		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4981
4982	if (phy->analog == 0)
4983		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4984
4985	old_channel = phy->chan;
4986	bwn_phy_g_switch_chan(mac, 7, 0);
4987
4988	if (phy->rf_ver != 0x2050) {
4989		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4990		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4991	}
4992
4993	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4994	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4995
4996	if (phy->rf_ver == 0x2050) {
4997		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4998		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4999	}
5000
5001	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5002	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5003	BWN_RF_SET(mac, 0x007a, 0x0007);
5004
5005	bwn_phy_g_switch_chan(mac, old_channel, 0);
5006	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5007	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5008	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5009
5010	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5011	    pg->pg_txctl);
5012
5013	if (phy->rf_ver == 0x2050)
5014		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5015
5016	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5017}
5018
5019static void
5020bwn_loopback_calcgain(struct bwn_mac *mac)
5021{
5022	struct bwn_phy *phy = &mac->mac_phy;
5023	struct bwn_phy_g *pg = &phy->phy_g;
5024	uint16_t backup_phy[16] = { 0 };
5025	uint16_t backup_radio[3];
5026	uint16_t backup_bband;
5027	uint16_t i, j, loop_i_max;
5028	uint16_t trsw_rx;
5029	uint16_t loop1_outer_done, loop1_inner_done;
5030
5031	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5032	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5033	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5034	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5035	if (phy->rev != 1) {
5036		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5037		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5038	}
5039	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5040	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5041	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5042	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5043	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5044	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5045	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5046	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5047	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5048	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5049	backup_bband = pg->pg_bbatt.att;
5050	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5051	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5052	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5053
5054	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5055	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5056	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5057	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5058	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5059	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5060	if (phy->rev != 1) {
5061		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5062		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5063		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5064		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5065	}
5066	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5067	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5068	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5069	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5070
5071	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5072	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5073	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5074
5075	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5076	if (phy->rev != 1) {
5077		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5078		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5079	}
5080	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5081
5082	if (phy->rf_rev == 8)
5083		BWN_RF_WRITE(mac, 0x43, 0x000f);
5084	else {
5085		BWN_RF_WRITE(mac, 0x52, 0);
5086		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5087	}
5088	bwn_phy_g_set_bbatt(mac, 11);
5089
5090	if (phy->rev >= 3)
5091		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5092	else
5093		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5094	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5095
5096	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5097	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5098
5099	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5100	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5101
5102	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5103		if (phy->rev >= 7) {
5104			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5105			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5106		}
5107	}
5108	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5109
5110	j = 0;
5111	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5112	for (i = 0; i < loop_i_max; i++) {
5113		for (j = 0; j < 16; j++) {
5114			BWN_RF_WRITE(mac, 0x43, i);
5115			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5116			    (j << 8));
5117			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5118			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5119			DELAY(20);
5120			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5121				goto done0;
5122		}
5123	}
5124done0:
5125	loop1_outer_done = i;
5126	loop1_inner_done = j;
5127	if (j >= 8) {
5128		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5129		trsw_rx = 0x1b;
5130		for (j = j - 8; j < 16; j++) {
5131			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5132			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5133			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5134			DELAY(20);
5135			trsw_rx -= 3;
5136			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5137				goto done1;
5138		}
5139	} else
5140		trsw_rx = 0x18;
5141done1:
5142
5143	if (phy->rev != 1) {
5144		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5145		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5146	}
5147	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5148	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5149	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5150	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5151	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5152	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5153	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5154	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5155	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5156
5157	bwn_phy_g_set_bbatt(mac, backup_bband);
5158
5159	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5160	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5161	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5162
5163	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5164	DELAY(10);
5165	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5166	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5167	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5168	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5169
5170	pg->pg_max_lb_gain =
5171	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5172	pg->pg_trsw_rx_gain = trsw_rx * 2;
5173}
5174
5175static uint16_t
5176bwn_rf_init_bcm2050(struct bwn_mac *mac)
5177{
5178	struct bwn_phy *phy = &mac->mac_phy;
5179	uint32_t tmp1 = 0, tmp2 = 0;
5180	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5181	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5182	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5183	static const uint8_t rcc_table[] = {
5184		0x02, 0x03, 0x01, 0x0f,
5185		0x06, 0x07, 0x05, 0x0f,
5186		0x0a, 0x0b, 0x09, 0x0f,
5187		0x0e, 0x0f, 0x0d, 0x0f,
5188	};
5189
5190	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5191	    rfoverval = rfover = cck3 = 0;
5192	radio0 = BWN_RF_READ(mac, 0x43);
5193	radio1 = BWN_RF_READ(mac, 0x51);
5194	radio2 = BWN_RF_READ(mac, 0x52);
5195	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5196	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5197	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5198	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5199
5200	if (phy->type == BWN_PHYTYPE_B) {
5201		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5202		reg0 = BWN_READ_2(mac, 0x3ec);
5203
5204		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5205		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5206	} else if (phy->gmode || phy->rev >= 2) {
5207		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5208		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5209		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5210		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5211		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5212		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5213
5214		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5215		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5216		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5217		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5218		if (BWN_HAS_LOOPBACK(phy)) {
5219			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5220			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5221			if (phy->rev >= 3)
5222				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5223			else
5224				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5225			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5226		}
5227
5228		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5229		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5230			BWN_LPD(0, 1, 1)));
5231		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5232		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5233	}
5234	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5235
5236	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5237	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5238	reg1 = BWN_READ_2(mac, 0x3e6);
5239	reg2 = BWN_READ_2(mac, 0x3f4);
5240
5241	if (phy->analog == 0)
5242		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5243	else {
5244		if (phy->analog >= 2)
5245			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5246		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5247		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5248	}
5249
5250	reg = BWN_RF_READ(mac, 0x60);
5251	index = (reg & 0x001e) >> 1;
5252	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5253
5254	if (phy->type == BWN_PHYTYPE_B)
5255		BWN_RF_WRITE(mac, 0x78, 0x26);
5256	if (phy->gmode || phy->rev >= 2) {
5257		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5258		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5259			BWN_LPD(0, 1, 1)));
5260	}
5261	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5262	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5263	if (phy->gmode || phy->rev >= 2) {
5264		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5265		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5266			BWN_LPD(0, 0, 1)));
5267	}
5268	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5269	BWN_RF_SET(mac, 0x51, 0x0004);
5270	if (phy->rf_rev == 8)
5271		BWN_RF_WRITE(mac, 0x43, 0x1f);
5272	else {
5273		BWN_RF_WRITE(mac, 0x52, 0);
5274		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5275	}
5276	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5277
5278	for (i = 0; i < 16; i++) {
5279		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5280		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5281		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5282		if (phy->gmode || phy->rev >= 2) {
5283			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5284			    bwn_rf_2050_rfoverval(mac,
5285				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5286		}
5287		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5288		DELAY(10);
5289		if (phy->gmode || phy->rev >= 2) {
5290			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5291			    bwn_rf_2050_rfoverval(mac,
5292				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5293		}
5294		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5295		DELAY(10);
5296		if (phy->gmode || phy->rev >= 2) {
5297			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5298			    bwn_rf_2050_rfoverval(mac,
5299				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5300		}
5301		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5302		DELAY(20);
5303		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5304		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5305		if (phy->gmode || phy->rev >= 2) {
5306			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5307			    bwn_rf_2050_rfoverval(mac,
5308				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5309		}
5310		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5311	}
5312	DELAY(10);
5313
5314	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5315	tmp1++;
5316	tmp1 >>= 9;
5317
5318	for (i = 0; i < 16; i++) {
5319		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5320		BWN_RF_WRITE(mac, 0x78, radio78);
5321		DELAY(10);
5322		for (j = 0; j < 16; j++) {
5323			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5324			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5325			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5326			if (phy->gmode || phy->rev >= 2) {
5327				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5328				    bwn_rf_2050_rfoverval(mac,
5329					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5330			}
5331			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5332			DELAY(10);
5333			if (phy->gmode || phy->rev >= 2) {
5334				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5335				    bwn_rf_2050_rfoverval(mac,
5336					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5337			}
5338			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5339			DELAY(10);
5340			if (phy->gmode || phy->rev >= 2) {
5341				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5342				    bwn_rf_2050_rfoverval(mac,
5343					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5344			}
5345			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5346			DELAY(10);
5347			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5348			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5349			if (phy->gmode || phy->rev >= 2) {
5350				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5351				    bwn_rf_2050_rfoverval(mac,
5352					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5353			}
5354			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5355		}
5356		tmp2++;
5357		tmp2 >>= 8;
5358		if (tmp1 < tmp2)
5359			break;
5360	}
5361
5362	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5363	BWN_RF_WRITE(mac, 0x51, radio1);
5364	BWN_RF_WRITE(mac, 0x52, radio2);
5365	BWN_RF_WRITE(mac, 0x43, radio0);
5366	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5367	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5368	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5369	BWN_WRITE_2(mac, 0x3e6, reg1);
5370	if (phy->analog != 0)
5371		BWN_WRITE_2(mac, 0x3f4, reg2);
5372	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5373	bwn_spu_workaround(mac, phy->chan);
5374	if (phy->type == BWN_PHYTYPE_B) {
5375		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5376		BWN_WRITE_2(mac, 0x3ec, reg0);
5377	} else if (phy->gmode) {
5378		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5379			    BWN_READ_2(mac, BWN_PHY_RADIO)
5380			    & 0x7fff);
5381		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5382		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5383		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5384		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5385			      analogoverval);
5386		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5387		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5388		if (BWN_HAS_LOOPBACK(phy)) {
5389			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5390			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5391		}
5392	}
5393
5394	return ((i > 15) ? radio78 : rcc);
5395}
5396
5397static void
5398bwn_phy_init_b6(struct bwn_mac *mac)
5399{
5400	struct bwn_phy *phy = &mac->mac_phy;
5401	struct bwn_phy_g *pg = &phy->phy_g;
5402	uint16_t offset, val;
5403	uint8_t old_channel;
5404
5405	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5406	    ("%s:%d: fail", __func__, __LINE__));
5407
5408	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5409	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5410	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5411		BWN_RF_WRITE(mac, 0x51, 0x37);
5412		BWN_RF_WRITE(mac, 0x52, 0x70);
5413		BWN_RF_WRITE(mac, 0x53, 0xb3);
5414		BWN_RF_WRITE(mac, 0x54, 0x9b);
5415		BWN_RF_WRITE(mac, 0x5a, 0x88);
5416		BWN_RF_WRITE(mac, 0x5b, 0x88);
5417		BWN_RF_WRITE(mac, 0x5d, 0x88);
5418		BWN_RF_WRITE(mac, 0x5e, 0x88);
5419		BWN_RF_WRITE(mac, 0x7d, 0x88);
5420		bwn_hf_write(mac,
5421		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5422	}
5423	if (phy->rf_rev == 8) {
5424		BWN_RF_WRITE(mac, 0x51, 0);
5425		BWN_RF_WRITE(mac, 0x52, 0x40);
5426		BWN_RF_WRITE(mac, 0x53, 0xb7);
5427		BWN_RF_WRITE(mac, 0x54, 0x98);
5428		BWN_RF_WRITE(mac, 0x5a, 0x88);
5429		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5430		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5431		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5432			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5433			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5434		} else {
5435			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5436			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5437		}
5438		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5439		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5440		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5441		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5442	}
5443	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5444		BWN_PHY_WRITE(mac, offset, val);
5445		val -= 0x0202;
5446	}
5447	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5448		BWN_PHY_WRITE(mac, offset, val);
5449		val -= 0x0202;
5450	}
5451	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5452		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5453		val += 0x0202;
5454	}
5455	if (phy->type == BWN_PHYTYPE_G) {
5456		BWN_RF_SET(mac, 0x007a, 0x0020);
5457		BWN_RF_SET(mac, 0x0051, 0x0004);
5458		BWN_PHY_SET(mac, 0x0802, 0x0100);
5459		BWN_PHY_SET(mac, 0x042b, 0x2000);
5460		BWN_PHY_WRITE(mac, 0x5b, 0);
5461		BWN_PHY_WRITE(mac, 0x5c, 0);
5462	}
5463
5464	old_channel = phy->chan;
5465	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5466
5467	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5468	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5469	DELAY(40);
5470	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5471		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5472		BWN_RF_WRITE(mac, 0x50, 0x20);
5473	}
5474	if (phy->rf_rev <= 2) {
5475		BWN_RF_WRITE(mac, 0x7c, 0x20);
5476		BWN_RF_WRITE(mac, 0x5a, 0x70);
5477		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5478		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5479	}
5480	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5481
5482	bwn_phy_g_switch_chan(mac, old_channel, 0);
5483
5484	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5485	if (phy->rf_rev >= 6)
5486		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5487	else
5488		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5489	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5490	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5491	    pg->pg_txctl);
5492	if (phy->rf_rev <= 5)
5493		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5494	if (phy->rf_rev <= 2)
5495		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5496
5497	if (phy->analog == 4) {
5498		BWN_WRITE_2(mac, 0x3e4, 9);
5499		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5500	} else
5501		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5502	if (phy->type == BWN_PHYTYPE_B)
5503		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5504	else if (phy->type == BWN_PHYTYPE_G)
5505		BWN_WRITE_2(mac, 0x03e6, 0x0);
5506}
5507
5508static void
5509bwn_phy_init_a(struct bwn_mac *mac)
5510{
5511	struct bwn_phy *phy = &mac->mac_phy;
5512
5513	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5514	    ("%s:%d: fail", __func__, __LINE__));
5515
5516	if (phy->rev >= 6) {
5517		if (phy->type == BWN_PHYTYPE_A)
5518			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5519		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5520			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5521		else
5522			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5523	}
5524
5525	bwn_wa_init(mac);
5526
5527	if (phy->type == BWN_PHYTYPE_G &&
5528	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5529		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5530}
5531
5532static void
5533bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5534{
5535	int i;
5536
5537	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5538		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5539}
5540
5541static void
5542bwn_wa_agc(struct bwn_mac *mac)
5543{
5544	struct bwn_phy *phy = &mac->mac_phy;
5545
5546	if (phy->rev == 1) {
5547		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5548		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5549		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5550		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5551		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5552		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5553		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5554		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5555		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5556	} else {
5557		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5560		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5561	}
5562
5563	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5564	    0x5700);
5565	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5566	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5567	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5568	BWN_RF_SET(mac, 0x7a, 0x0008);
5569	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5570	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5571	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5572	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5573	if (phy->rev == 1)
5574		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5575	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5576	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5577	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5578	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5579	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5580	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5581	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5582	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5583	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5584	if (phy->rev == 1) {
5585		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5586		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5587	} else {
5588		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5589		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5590		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5591		if (phy->rev >= 6) {
5592			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5593			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5594			    (uint16_t)~0xf000, 0x3000);
5595		}
5596	}
5597	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5598	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5599	if (phy->rev == 1) {
5600		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5601		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5602		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5603		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5604		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5605		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5606		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5607		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5608	} else {
5609		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5610		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5611		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5612		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5613	}
5614	if (phy->rev >= 6) {
5615		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5616		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5617	}
5618	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5619}
5620
5621static void
5622bwn_wa_grev1(struct bwn_mac *mac)
5623{
5624	struct bwn_phy *phy = &mac->mac_phy;
5625	int i;
5626	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5627	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5628	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5629
5630	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5631
5632	/* init CRSTHRES and ANTDWELL */
5633	if (phy->rev == 1) {
5634		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5635	} else if (phy->rev == 2) {
5636		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5637		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5638		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5639	} else {
5640		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5641		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5642		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5643		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5644	}
5645	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5646	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5647	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5648
5649	/* XXX support PHY-A??? */
5650	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5651		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5652		    bwn_tab_finefreqg[i]);
5653
5654	/* XXX support PHY-A??? */
5655	if (phy->rev == 1)
5656		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5657			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5658			    bwn_tab_noise_g1[i]);
5659	else
5660		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5661			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5662			    bwn_tab_noise_g2[i]);
5663
5664
5665	for (i = 0; i < N(bwn_tab_rotor); i++)
5666		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5667		    bwn_tab_rotor[i]);
5668
5669	/* XXX support PHY-A??? */
5670	if (phy->rev >= 6) {
5671		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5672		    BWN_PHY_ENCORE_EN)
5673			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5674		else
5675			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5676	} else
5677		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5678
5679	for (i = 0; i < N(bwn_tab_retard); i++)
5680		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5681		    bwn_tab_retard[i]);
5682
5683	if (phy->rev == 1) {
5684		for (i = 0; i < 16; i++)
5685			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5686			    i, 0x0020);
5687	} else {
5688		for (i = 0; i < 32; i++)
5689			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5690	}
5691
5692	bwn_wa_agc(mac);
5693}
5694
5695static void
5696bwn_wa_grev26789(struct bwn_mac *mac)
5697{
5698	struct bwn_phy *phy = &mac->mac_phy;
5699	int i;
5700	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5701	uint16_t ofdmrev;
5702
5703	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5704
5705	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5706
5707	/* init CRSTHRES and ANTDWELL */
5708	if (phy->rev == 1)
5709		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5710	else if (phy->rev == 2) {
5711		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5712		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5713		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5714	} else {
5715		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5716		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5717		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5718		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5719	}
5720
5721	for (i = 0; i < 64; i++)
5722		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5723
5724	/* XXX support PHY-A??? */
5725	if (phy->rev == 1)
5726		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5727			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5728			    bwn_tab_noise_g1[i]);
5729	else
5730		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5731			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5732			    bwn_tab_noise_g2[i]);
5733
5734	/* XXX support PHY-A??? */
5735	if (phy->rev >= 6) {
5736		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5737		    BWN_PHY_ENCORE_EN)
5738			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5739		else
5740			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5741	} else
5742		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5743
5744	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5745		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5746		    bwn_tab_sigmasqr2[i]);
5747
5748	if (phy->rev == 1) {
5749		for (i = 0; i < 16; i++)
5750			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5751			    0x0020);
5752	} else {
5753		for (i = 0; i < 32; i++)
5754			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5755	}
5756
5757	bwn_wa_agc(mac);
5758
5759	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5760	if (ofdmrev > 2) {
5761		if (phy->type == BWN_PHYTYPE_A)
5762			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5763		else
5764			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5765	} else {
5766		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5767		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5768		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5769	}
5770
5771	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5772	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5773}
5774
5775static void
5776bwn_wa_init(struct bwn_mac *mac)
5777{
5778	struct bwn_phy *phy = &mac->mac_phy;
5779	struct siba_softc *bus = mac->mac_sd->sd_bus;
5780
5781	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5782
5783	switch (phy->rev) {
5784	case 1:
5785		bwn_wa_grev1(mac);
5786		break;
5787	case 2:
5788	case 6:
5789	case 7:
5790	case 8:
5791	case 9:
5792		bwn_wa_grev26789(mac);
5793		break;
5794	default:
5795		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5796	}
5797
5798	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5799	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5800	    bus->siba_board_rev != 0x17) {
5801		if (phy->rev < 2) {
5802			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5803			    0x0002);
5804			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5805			    0x0001);
5806		} else {
5807			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5808			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5809			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5810			    (phy->rev >= 7)) {
5811				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5812				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5813				    0x0020, 0x0001);
5814				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5815				    0x0021, 0x0001);
5816				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5817				    0x0022, 0x0001);
5818				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5819				    0x0023, 0x0000);
5820				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5821				    0x0000, 0x0000);
5822				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5823				    0x0003, 0x0002);
5824			}
5825		}
5826	}
5827	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5828		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5829		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5830	}
5831
5832	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5833	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5834}
5835
5836static void
5837bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5838    uint16_t value)
5839{
5840	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5841	uint16_t addr;
5842
5843	addr = table + offset;
5844	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5845	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5846		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5847		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5848	}
5849	pg->pg_ofdmtab_addr = addr;
5850	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5851}
5852
5853static void
5854bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5855    uint32_t value)
5856{
5857	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5858	uint16_t addr;
5859
5860	addr = table + offset;
5861	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5862	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5863		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5864		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5865	}
5866	pg->pg_ofdmtab_addr = addr;
5867
5868	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5869	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5870}
5871
5872static void
5873bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5874    uint16_t value)
5875{
5876
5877	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5878	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5879}
5880
5881static void
5882bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5883{
5884	struct bwn_phy *phy = &mac->mac_phy;
5885	unsigned int i, max_loop;
5886	uint16_t value;
5887	uint32_t buffer[5] = {
5888		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5889	};
5890
5891	if (ofdm) {
5892		max_loop = 0x1e;
5893		buffer[0] = 0x000201cc;
5894	} else {
5895		max_loop = 0xfa;
5896		buffer[0] = 0x000b846e;
5897	}
5898
5899	BWN_ASSERT_LOCKED(mac->mac_sc);
5900
5901	for (i = 0; i < 5; i++)
5902		bwn_ram_write(mac, i * 4, buffer[i]);
5903
5904	BWN_WRITE_2(mac, 0x0568, 0x0000);
5905	BWN_WRITE_2(mac, 0x07c0,
5906	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5907	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5908	BWN_WRITE_2(mac, 0x050c, value);
5909	if (phy->type == BWN_PHYTYPE_LP)
5910		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5911	BWN_WRITE_2(mac, 0x0508, 0x0000);
5912	BWN_WRITE_2(mac, 0x050a, 0x0000);
5913	BWN_WRITE_2(mac, 0x054c, 0x0000);
5914	BWN_WRITE_2(mac, 0x056a, 0x0014);
5915	BWN_WRITE_2(mac, 0x0568, 0x0826);
5916	BWN_WRITE_2(mac, 0x0500, 0x0000);
5917	if (phy->type == BWN_PHYTYPE_LP)
5918		BWN_WRITE_2(mac, 0x0502, 0x0050);
5919	else
5920		BWN_WRITE_2(mac, 0x0502, 0x0030);
5921
5922	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5923		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5924	for (i = 0x00; i < max_loop; i++) {
5925		value = BWN_READ_2(mac, 0x050e);
5926		if (value & 0x0080)
5927			break;
5928		DELAY(10);
5929	}
5930	for (i = 0x00; i < 0x0a; i++) {
5931		value = BWN_READ_2(mac, 0x050e);
5932		if (value & 0x0400)
5933			break;
5934		DELAY(10);
5935	}
5936	for (i = 0x00; i < 0x19; i++) {
5937		value = BWN_READ_2(mac, 0x0690);
5938		if (!(value & 0x0100))
5939			break;
5940		DELAY(10);
5941	}
5942	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5943		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5944}
5945
5946static void
5947bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5948{
5949	uint32_t macctl;
5950
5951	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5952
5953	macctl = BWN_READ_4(mac, BWN_MACCTL);
5954	if (macctl & BWN_MACCTL_BIGENDIAN)
5955		printf("TODO: need swap\n");
5956
5957	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5958	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5959	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5960}
5961
5962static void
5963bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5964{
5965	uint16_t value;
5966
5967	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5968	    ("%s:%d: fail", __func__, __LINE__));
5969
5970	value = (uint8_t) (ctl->q);
5971	value |= ((uint8_t) (ctl->i)) << 8;
5972	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5973}
5974
5975static uint16_t
5976bwn_lo_calcfeed(struct bwn_mac *mac,
5977    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5978{
5979	struct bwn_phy *phy = &mac->mac_phy;
5980	uint16_t rfover;
5981	uint16_t feedthrough;
5982
5983	if (phy->gmode) {
5984		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5985		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5986
5987		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5988		    ("%s:%d: fail", __func__, __LINE__));
5989		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5990		    ("%s:%d: fail", __func__, __LINE__));
5991
5992		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5993
5994		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5995		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
5996		    && phy->rev > 6)
5997			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5998
5999		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6000		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6001		DELAY(10);
6002		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6003		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6004		DELAY(10);
6005		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6006		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6007		DELAY(10);
6008		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6009	} else {
6010		pga |= BWN_PHY_PGACTL_UNKNOWN;
6011		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6012		DELAY(10);
6013		pga |= BWN_PHY_PGACTL_LOWBANDW;
6014		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6015		DELAY(10);
6016		pga |= BWN_PHY_PGACTL_LPF;
6017		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6018	}
6019	DELAY(21);
6020	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6021
6022	return (feedthrough);
6023}
6024
6025static uint16_t
6026bwn_lo_txctl_regtable(struct bwn_mac *mac,
6027    uint16_t *value, uint16_t *pad_mix_gain)
6028{
6029	struct bwn_phy *phy = &mac->mac_phy;
6030	uint16_t reg, v, padmix;
6031
6032	if (phy->type == BWN_PHYTYPE_B) {
6033		v = 0x30;
6034		if (phy->rf_rev <= 5) {
6035			reg = 0x43;
6036			padmix = 0;
6037		} else {
6038			reg = 0x52;
6039			padmix = 5;
6040		}
6041	} else {
6042		if (phy->rev >= 2 && phy->rf_rev == 8) {
6043			reg = 0x43;
6044			v = 0x10;
6045			padmix = 2;
6046		} else {
6047			reg = 0x52;
6048			v = 0x30;
6049			padmix = 5;
6050		}
6051	}
6052	if (value)
6053		*value = v;
6054	if (pad_mix_gain)
6055		*pad_mix_gain = padmix;
6056
6057	return (reg);
6058}
6059
6060static void
6061bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6062{
6063	struct bwn_phy *phy = &mac->mac_phy;
6064	struct bwn_phy_g *pg = &phy->phy_g;
6065	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6066	uint16_t reg, mask;
6067	uint16_t trsw_rx, pga;
6068	uint16_t rf_pctl_reg;
6069
6070	static const uint8_t tx_bias_values[] = {
6071		0x09, 0x08, 0x0a, 0x01, 0x00,
6072		0x02, 0x05, 0x04, 0x06,
6073	};
6074	static const uint8_t tx_magn_values[] = {
6075		0x70, 0x40,
6076	};
6077
6078	if (!BWN_HAS_LOOPBACK(phy)) {
6079		rf_pctl_reg = 6;
6080		trsw_rx = 2;
6081		pga = 0;
6082	} else {
6083		int lb_gain;
6084
6085		trsw_rx = 0;
6086		lb_gain = pg->pg_max_lb_gain / 2;
6087		if (lb_gain > 10) {
6088			rf_pctl_reg = 0;
6089			pga = abs(10 - lb_gain) / 6;
6090			pga = MIN(MAX(pga, 0), 15);
6091		} else {
6092			int cmp_val;
6093			int tmp;
6094
6095			pga = 0;
6096			cmp_val = 0x24;
6097			if ((phy->rev >= 2) &&
6098			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6099				cmp_val = 0x3c;
6100			tmp = lb_gain;
6101			if ((10 - lb_gain) < cmp_val)
6102				tmp = (10 - lb_gain);
6103			if (tmp < 0)
6104				tmp += 6;
6105			else
6106				tmp += 3;
6107			cmp_val /= 4;
6108			tmp /= 4;
6109			if (tmp >= cmp_val)
6110				rf_pctl_reg = cmp_val;
6111			else
6112				rf_pctl_reg = tmp;
6113		}
6114	}
6115	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6116	bwn_phy_g_set_bbatt(mac, 2);
6117
6118	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6119	mask = ~mask;
6120	BWN_RF_MASK(mac, reg, mask);
6121
6122	if (BWN_HAS_TXMAG(phy)) {
6123		int i, j;
6124		int feedthrough;
6125		int min_feedth = 0xffff;
6126		uint8_t tx_magn, tx_bias;
6127
6128		for (i = 0; i < N(tx_magn_values); i++) {
6129			tx_magn = tx_magn_values[i];
6130			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6131			for (j = 0; j < N(tx_bias_values); j++) {
6132				tx_bias = tx_bias_values[j];
6133				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6134				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6135				    trsw_rx);
6136				if (feedthrough < min_feedth) {
6137					lo->tx_bias = tx_bias;
6138					lo->tx_magn = tx_magn;
6139					min_feedth = feedthrough;
6140				}
6141				if (lo->tx_bias == 0)
6142					break;
6143			}
6144			BWN_RF_WRITE(mac, 0x52,
6145					  (BWN_RF_READ(mac, 0x52)
6146					   & 0xff00) | lo->tx_bias | lo->
6147					  tx_magn);
6148		}
6149	} else {
6150		lo->tx_magn = 0;
6151		lo->tx_bias = 0;
6152		BWN_RF_MASK(mac, 0x52, 0xfff0);
6153	}
6154
6155	BWN_GETTIME(lo->txctl_measured_time);
6156}
6157
6158static void
6159bwn_lo_get_powervector(struct bwn_mac *mac)
6160{
6161	struct bwn_phy *phy = &mac->mac_phy;
6162	struct bwn_phy_g *pg = &phy->phy_g;
6163	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6164	int i;
6165	uint64_t tmp;
6166	uint64_t power_vector = 0;
6167
6168	for (i = 0; i < 8; i += 2) {
6169		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6170		power_vector |= (tmp << (i * 8));
6171		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6172	}
6173	if (power_vector)
6174		lo->power_vector = power_vector;
6175
6176	BWN_GETTIME(lo->pwr_vec_read_time);
6177}
6178
6179static void
6180bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6181    int use_trsw_rx)
6182{
6183	struct bwn_phy *phy = &mac->mac_phy;
6184	struct bwn_phy_g *pg = &phy->phy_g;
6185	uint16_t tmp;
6186
6187	if (max_rx_gain < 0)
6188		max_rx_gain = 0;
6189
6190	if (BWN_HAS_LOOPBACK(phy)) {
6191		int trsw_rx = 0;
6192		int trsw_rx_gain;
6193
6194		if (use_trsw_rx) {
6195			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6196			if (max_rx_gain >= trsw_rx_gain) {
6197				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6198				trsw_rx = 0x20;
6199			}
6200		} else
6201			trsw_rx_gain = max_rx_gain;
6202		if (trsw_rx_gain < 9) {
6203			pg->pg_lna_lod_gain = 0;
6204		} else {
6205			pg->pg_lna_lod_gain = 1;
6206			trsw_rx_gain -= 8;
6207		}
6208		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6209		pg->pg_pga_gain = trsw_rx_gain / 3;
6210		if (pg->pg_pga_gain >= 5) {
6211			pg->pg_pga_gain -= 5;
6212			pg->pg_lna_gain = 2;
6213		} else
6214			pg->pg_lna_gain = 0;
6215	} else {
6216		pg->pg_lna_gain = 0;
6217		pg->pg_trsw_rx_gain = 0x20;
6218		if (max_rx_gain >= 0x14) {
6219			pg->pg_lna_lod_gain = 1;
6220			pg->pg_pga_gain = 2;
6221		} else if (max_rx_gain >= 0x12) {
6222			pg->pg_lna_lod_gain = 1;
6223			pg->pg_pga_gain = 1;
6224		} else if (max_rx_gain >= 0xf) {
6225			pg->pg_lna_lod_gain = 1;
6226			pg->pg_pga_gain = 0;
6227		} else {
6228			pg->pg_lna_lod_gain = 0;
6229			pg->pg_pga_gain = 0;
6230		}
6231	}
6232
6233	tmp = BWN_RF_READ(mac, 0x7a);
6234	if (pg->pg_lna_lod_gain == 0)
6235		tmp &= ~0x0008;
6236	else
6237		tmp |= 0x0008;
6238	BWN_RF_WRITE(mac, 0x7a, tmp);
6239}
6240
6241static void
6242bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6243{
6244	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6245	struct bwn_phy *phy = &mac->mac_phy;
6246	struct bwn_phy_g *pg = &phy->phy_g;
6247	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6248	struct timespec ts;
6249	uint16_t tmp;
6250
6251	if (bwn_has_hwpctl(mac)) {
6252		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6253		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6254		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6255		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6256		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6257
6258		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6259		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6260		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6261		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6262	}
6263	if (phy->type == BWN_PHYTYPE_B &&
6264	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6265		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6266		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6267	}
6268	if (phy->rev >= 2) {
6269		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6270		sav->phy_analogoverval =
6271		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6272		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6273		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6274		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6275		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6276		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6277
6278		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6279		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6280		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6281		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6282		if (phy->type == BWN_PHYTYPE_G) {
6283			if ((phy->rev >= 7) &&
6284			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6285				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6286			} else {
6287				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6288			}
6289		} else {
6290			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6291		}
6292		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6293	}
6294	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6295	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6296	sav->rf0 = BWN_RF_READ(mac, 0x43);
6297	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6298	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6299	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6300	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6301	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6302
6303	if (!BWN_HAS_TXMAG(phy)) {
6304		sav->rf2 = BWN_RF_READ(mac, 0x52);
6305		sav->rf2 &= 0x00f0;
6306	}
6307	if (phy->type == BWN_PHYTYPE_B) {
6308		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6309		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6310		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6311		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6312	} else {
6313		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6314			    | 0x8000);
6315	}
6316	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6317		    & 0xf000);
6318
6319	tmp =
6320	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6321	BWN_PHY_WRITE(mac, tmp, 0x007f);
6322
6323	tmp = sav->phy_syncctl;
6324	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6325	tmp = sav->rf1;
6326	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6327
6328	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6329	if (phy->type == BWN_PHYTYPE_G ||
6330	    (phy->type == BWN_PHYTYPE_B &&
6331	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6332		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6333	} else
6334		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6335	if (phy->rev >= 2)
6336		bwn_dummy_transmission(mac, 0, 1);
6337	bwn_phy_g_switch_chan(mac, 6, 0);
6338	BWN_RF_READ(mac, 0x51);
6339	if (phy->type == BWN_PHYTYPE_G)
6340		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6341
6342	nanouptime(&ts);
6343	if (time_before(lo->txctl_measured_time,
6344	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6345		bwn_lo_measure_txctl_values(mac);
6346
6347	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6348		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6349	else {
6350		if (phy->type == BWN_PHYTYPE_B)
6351			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6352		else
6353			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6354	}
6355}
6356
6357static void
6358bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6359{
6360	struct bwn_phy *phy = &mac->mac_phy;
6361	struct bwn_phy_g *pg = &phy->phy_g;
6362	uint16_t tmp;
6363
6364	if (phy->rev >= 2) {
6365		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6366		tmp = (pg->pg_pga_gain << 8);
6367		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6368		DELAY(5);
6369		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6370		DELAY(2);
6371		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6372	} else {
6373		tmp = (pg->pg_pga_gain | 0xefa0);
6374		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6375	}
6376	if (phy->type == BWN_PHYTYPE_G) {
6377		if (phy->rev >= 3)
6378			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6379		else
6380			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6381		if (phy->rev >= 2)
6382			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6383		else
6384			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6385	}
6386	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6387	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6388	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6389	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6390	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6391	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6392	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6393	if (!BWN_HAS_TXMAG(phy)) {
6394		tmp = sav->rf2;
6395		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6396	}
6397	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6398	if (phy->type == BWN_PHYTYPE_B &&
6399	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6400		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6401		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6402	}
6403	if (phy->rev >= 2) {
6404		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6405		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6406			      sav->phy_analogoverval);
6407		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6408		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6409		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6410		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6411		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6412	}
6413	if (bwn_has_hwpctl(mac)) {
6414		tmp = (sav->phy_lomask & 0xbfff);
6415		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6416		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6417		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6418		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6419		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6420	}
6421	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6422}
6423
6424static int
6425bwn_lo_probe_loctl(struct bwn_mac *mac,
6426    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6427{
6428	struct bwn_phy *phy = &mac->mac_phy;
6429	struct bwn_phy_g *pg = &phy->phy_g;
6430	struct bwn_loctl orig, test;
6431	struct bwn_loctl prev = { -100, -100 };
6432	static const struct bwn_loctl modifiers[] = {
6433		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6434		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6435	};
6436	int begin, end, lower = 0, i;
6437	uint16_t feedth;
6438
6439	if (d->curstate == 0) {
6440		begin = 1;
6441		end = 8;
6442	} else if (d->curstate % 2 == 0) {
6443		begin = d->curstate - 1;
6444		end = d->curstate + 1;
6445	} else {
6446		begin = d->curstate - 2;
6447		end = d->curstate + 2;
6448	}
6449	if (begin < 1)
6450		begin += 8;
6451	if (end > 8)
6452		end -= 8;
6453
6454	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6455	i = begin;
6456	d->curstate = i;
6457	while (1) {
6458		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6459		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6460		test.i += modifiers[i - 1].i * d->multipler;
6461		test.q += modifiers[i - 1].q * d->multipler;
6462		if ((test.i != prev.i || test.q != prev.q) &&
6463		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6464			bwn_lo_write(mac, &test);
6465			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6466			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6467			if (feedth < d->feedth) {
6468				memcpy(probe, &test,
6469				    sizeof(struct bwn_loctl));
6470				lower = 1;
6471				d->feedth = feedth;
6472				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6473					break;
6474			}
6475		}
6476		memcpy(&prev, &test, sizeof(prev));
6477		if (i == end)
6478			break;
6479		if (i == 8)
6480			i = 1;
6481		else
6482			i++;
6483		d->curstate = i;
6484	}
6485
6486	return (lower);
6487}
6488
6489static void
6490bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6491{
6492	struct bwn_phy *phy = &mac->mac_phy;
6493	struct bwn_phy_g *pg = &phy->phy_g;
6494	struct bwn_lo_g_sm d;
6495	struct bwn_loctl probe;
6496	int lower, repeat, cnt = 0;
6497	uint16_t feedth;
6498
6499	d.nmeasure = 0;
6500	d.multipler = 1;
6501	if (BWN_HAS_LOOPBACK(phy))
6502		d.multipler = 3;
6503
6504	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6505	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6506
6507	do {
6508		bwn_lo_write(mac, &d.loctl);
6509		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6510		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6511		if (feedth < 0x258) {
6512			if (feedth >= 0x12c)
6513				*rxgain += 6;
6514			else
6515				*rxgain += 3;
6516			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6517			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6518		}
6519		d.feedth = feedth;
6520		d.curstate = 0;
6521		do {
6522			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6523			    ("%s:%d: fail", __func__, __LINE__));
6524			memcpy(&probe, &d.loctl,
6525			       sizeof(struct bwn_loctl));
6526			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6527			if (!lower)
6528				break;
6529			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6530				break;
6531			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6532			d.nmeasure++;
6533		} while (d.nmeasure < 24);
6534		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6535
6536		if (BWN_HAS_LOOPBACK(phy)) {
6537			if (d.feedth > 0x1194)
6538				*rxgain -= 6;
6539			else if (d.feedth < 0x5dc)
6540				*rxgain += 3;
6541			if (cnt == 0) {
6542				if (d.feedth <= 0x5dc) {
6543					d.multipler = 1;
6544					cnt++;
6545				} else
6546					d.multipler = 2;
6547			} else if (cnt == 2)
6548				d.multipler = 1;
6549		}
6550		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6551	} while (++cnt < repeat);
6552}
6553
6554static struct bwn_lo_calib *
6555bwn_lo_calibset(struct bwn_mac *mac,
6556    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6557{
6558	struct bwn_phy *phy = &mac->mac_phy;
6559	struct bwn_phy_g *pg = &phy->phy_g;
6560	struct bwn_loctl loctl = { 0, 0 };
6561	struct bwn_lo_calib *cal;
6562	struct bwn_lo_g_value sval = { 0 };
6563	int rxgain;
6564	uint16_t pad, reg, value;
6565
6566	sval.old_channel = phy->chan;
6567	bwn_mac_suspend(mac);
6568	bwn_lo_save(mac, &sval);
6569
6570	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6571	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6572	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6573
6574	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6575	if (rfatt->padmix)
6576		rxgain -= pad;
6577	if (BWN_HAS_LOOPBACK(phy))
6578		rxgain += pg->pg_max_lb_gain;
6579	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6580	bwn_phy_g_set_bbatt(mac, bbatt->att);
6581	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6582
6583	bwn_lo_restore(mac, &sval);
6584	bwn_mac_enable(mac);
6585
6586	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6587	if (!cal) {
6588		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6589		return (NULL);
6590	}
6591	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6592	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6593	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6594
6595	BWN_GETTIME(cal->calib_time);
6596
6597	return (cal);
6598}
6599
6600static struct bwn_lo_calib *
6601bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6602    const struct bwn_rfatt *rfatt)
6603{
6604	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6605	struct bwn_lo_calib *c;
6606
6607	TAILQ_FOREACH(c, &lo->calib_list, list) {
6608		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6609			continue;
6610		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6611			continue;
6612		return (c);
6613	}
6614
6615	c = bwn_lo_calibset(mac, bbatt, rfatt);
6616	if (!c)
6617		return (NULL);
6618	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6619
6620	return (c);
6621}
6622
6623static void
6624bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6625{
6626	struct bwn_phy *phy = &mac->mac_phy;
6627	struct bwn_phy_g *pg = &phy->phy_g;
6628	struct bwn_softc *sc = mac->mac_sc;
6629	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6630	const struct bwn_rfatt *rfatt;
6631	const struct bwn_bbatt *bbatt;
6632	uint64_t pvector;
6633	int i;
6634	int rf_offset, bb_offset;
6635	uint8_t changed = 0;
6636
6637	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6638	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6639	    ("%s:%d: fail", __func__, __LINE__));
6640
6641	pvector = lo->power_vector;
6642	if (!update && !pvector)
6643		return;
6644
6645	bwn_mac_suspend(mac);
6646
6647	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6648		struct bwn_lo_calib *cal;
6649		int idx;
6650		uint16_t val;
6651
6652		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6653			continue;
6654		bb_offset = i / lo->rfatt.len;
6655		rf_offset = i % lo->rfatt.len;
6656		bbatt = &(lo->bbatt.array[bb_offset]);
6657		rfatt = &(lo->rfatt.array[rf_offset]);
6658
6659		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6660		if (!cal) {
6661			device_printf(sc->sc_dev, "LO: Could not "
6662			    "calibrate DC table entry\n");
6663			continue;
6664		}
6665		val = (uint8_t)(cal->ctl.q);
6666		val |= ((uint8_t)(cal->ctl.i)) << 4;
6667		free(cal, M_DEVBUF);
6668
6669		idx = i / 2;
6670		if (i % 2)
6671			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6672			    | ((val & 0x00ff) << 8);
6673		else
6674			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6675			    | (val & 0x00ff);
6676		changed = 1;
6677	}
6678	if (changed) {
6679		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6680			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6681	}
6682	bwn_mac_enable(mac);
6683}
6684
6685static void
6686bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6687{
6688
6689	if (!rf->padmix)
6690		return;
6691	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6692		rf->att = 4;
6693}
6694
6695static void
6696bwn_lo_g_adjust(struct bwn_mac *mac)
6697{
6698	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6699	struct bwn_lo_calib *cal;
6700	struct bwn_rfatt rf;
6701
6702	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6703	bwn_lo_fixup_rfatt(&rf);
6704
6705	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6706	if (!cal)
6707		return;
6708	bwn_lo_write(mac, &cal->ctl);
6709}
6710
6711static void
6712bwn_lo_g_init(struct bwn_mac *mac)
6713{
6714
6715	if (!bwn_has_hwpctl(mac))
6716		return;
6717
6718	bwn_lo_get_powervector(mac);
6719	bwn_phy_g_dc_lookup_init(mac, 1);
6720}
6721
6722static void
6723bwn_mac_suspend(struct bwn_mac *mac)
6724{
6725	struct bwn_softc *sc = mac->mac_sc;
6726	int i;
6727	uint32_t tmp;
6728
6729	KASSERT(mac->mac_suspended >= 0,
6730	    ("%s:%d: fail", __func__, __LINE__));
6731
6732	if (mac->mac_suspended == 0) {
6733		bwn_psctl(mac, BWN_PS_AWAKE);
6734		BWN_WRITE_4(mac, BWN_MACCTL,
6735			    BWN_READ_4(mac, BWN_MACCTL)
6736			    & ~BWN_MACCTL_ON);
6737		BWN_READ_4(mac, BWN_MACCTL);
6738		for (i = 35; i; i--) {
6739			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6740			if (tmp & BWN_INTR_MAC_SUSPENDED)
6741				goto out;
6742			DELAY(10);
6743		}
6744		for (i = 40; i; i--) {
6745			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6746			if (tmp & BWN_INTR_MAC_SUSPENDED)
6747				goto out;
6748			DELAY(1000);
6749		}
6750		device_printf(sc->sc_dev, "MAC suspend failed\n");
6751	}
6752out:
6753	mac->mac_suspended++;
6754}
6755
6756static void
6757bwn_mac_enable(struct bwn_mac *mac)
6758{
6759	struct bwn_softc *sc = mac->mac_sc;
6760	uint16_t state;
6761
6762	state = bwn_shm_read_2(mac, BWN_SHARED,
6763	    BWN_SHARED_UCODESTAT);
6764	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6765	    state != BWN_SHARED_UCODESTAT_SLEEP)
6766		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6767
6768	mac->mac_suspended--;
6769	KASSERT(mac->mac_suspended >= 0,
6770	    ("%s:%d: fail", __func__, __LINE__));
6771	if (mac->mac_suspended == 0) {
6772		BWN_WRITE_4(mac, BWN_MACCTL,
6773		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6774		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6775		BWN_READ_4(mac, BWN_MACCTL);
6776		BWN_READ_4(mac, BWN_INTR_REASON);
6777		bwn_psctl(mac, 0);
6778	}
6779}
6780
6781static void
6782bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6783{
6784	int i;
6785	uint16_t ucstat;
6786
6787	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6788	    ("%s:%d: fail", __func__, __LINE__));
6789	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6790	    ("%s:%d: fail", __func__, __LINE__));
6791
6792	/* XXX forcibly awake and hwps-off */
6793
6794	BWN_WRITE_4(mac, BWN_MACCTL,
6795	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6796	    ~BWN_MACCTL_HWPS);
6797	BWN_READ_4(mac, BWN_MACCTL);
6798	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6799		for (i = 0; i < 100; i++) {
6800			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6801			    BWN_SHARED_UCODESTAT);
6802			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6803				break;
6804			DELAY(10);
6805		}
6806	}
6807}
6808
6809static int16_t
6810bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6811{
6812
6813	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6814	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6815}
6816
6817static void
6818bwn_nrssi_threshold(struct bwn_mac *mac)
6819{
6820	struct bwn_phy *phy = &mac->mac_phy;
6821	struct bwn_phy_g *pg = &phy->phy_g;
6822	struct siba_softc *siba = mac->mac_sd->sd_bus;
6823	int32_t a, b;
6824	int16_t tmp16;
6825	uint16_t tmpu16;
6826
6827	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6828
6829	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6830		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6831			a = 0x13;
6832			b = 0x12;
6833		} else {
6834			a = 0xe;
6835			b = 0x11;
6836		}
6837
6838		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6839		a += (pg->pg_nrssi[0] << 6);
6840		a += (a < 32) ? 31 : 32;
6841		a = a >> 6;
6842		a = MIN(MAX(a, -31), 31);
6843
6844		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6845		b += (pg->pg_nrssi[0] << 6);
6846		if (b < 32)
6847			b += 31;
6848		else
6849			b += 32;
6850		b = b >> 6;
6851		b = MIN(MAX(b, -31), 31);
6852
6853		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6854		tmpu16 |= ((uint32_t)b & 0x0000003f);
6855		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6856		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6857		return;
6858	}
6859
6860	tmp16 = bwn_nrssi_read(mac, 0x20);
6861	if (tmp16 >= 0x20)
6862		tmp16 -= 0x40;
6863	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6864}
6865
6866static void
6867bwn_nrssi_slope_11g(struct bwn_mac *mac)
6868{
6869#define	SAVE_RF_MAX		3
6870#define	SAVE_PHY_COMM_MAX	4
6871#define	SAVE_PHY3_MAX		8
6872	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6873		{ 0x7a, 0x52, 0x43 };
6874	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6875		{ 0x15, 0x5a, 0x59, 0x58 };
6876	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6877		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6878		0x0801, 0x0060, 0x0014, 0x0478
6879	};
6880	struct bwn_phy *phy = &mac->mac_phy;
6881	struct bwn_phy_g *pg = &phy->phy_g;
6882	int32_t i, tmp32, phy3_idx = 0;
6883	uint16_t delta, tmp;
6884	uint16_t save_rf[SAVE_RF_MAX];
6885	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6886	uint16_t save_phy3[SAVE_PHY3_MAX];
6887	uint16_t ant_div, phy0, chan_ex;
6888	int16_t nrssi0, nrssi1;
6889
6890	KASSERT(phy->type == BWN_PHYTYPE_G,
6891	    ("%s:%d: fail", __func__, __LINE__));
6892
6893	if (phy->rf_rev >= 9)
6894		return;
6895	if (phy->rf_rev == 8)
6896		bwn_nrssi_offset(mac);
6897
6898	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6899	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6900
6901	/*
6902	 * Save RF/PHY registers for later restoration
6903	 */
6904	ant_div = BWN_READ_2(mac, 0x03e2);
6905	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6906	for (i = 0; i < SAVE_RF_MAX; ++i)
6907		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6908	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6909		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6910
6911	phy0 = BWN_READ_2(mac, BWN_PHY0);
6912	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6913	if (phy->rev >= 3) {
6914		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6915			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6916		BWN_PHY_WRITE(mac, 0x002e, 0);
6917		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6918		switch (phy->rev) {
6919		case 4:
6920		case 6:
6921		case 7:
6922			BWN_PHY_SET(mac, 0x0478, 0x0100);
6923			BWN_PHY_SET(mac, 0x0801, 0x0040);
6924			break;
6925		case 3:
6926		case 5:
6927			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6928			break;
6929		}
6930		BWN_PHY_SET(mac, 0x0060, 0x0040);
6931		BWN_PHY_SET(mac, 0x0014, 0x0200);
6932	}
6933	/*
6934	 * Calculate nrssi0
6935	 */
6936	BWN_RF_SET(mac, 0x007a, 0x0070);
6937	bwn_set_all_gains(mac, 0, 8, 0);
6938	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6939	if (phy->rev >= 2) {
6940		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6941		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6942	}
6943	BWN_RF_SET(mac, 0x007a, 0x0080);
6944	DELAY(20);
6945
6946	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6947	if (nrssi0 >= 0x0020)
6948		nrssi0 -= 0x0040;
6949
6950	/*
6951	 * Calculate nrssi1
6952	 */
6953	BWN_RF_MASK(mac, 0x007a, 0x007f);
6954	if (phy->rev >= 2)
6955		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6956
6957	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6958	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6959	BWN_RF_SET(mac, 0x007a, 0x000f);
6960	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6961	if (phy->rev >= 2) {
6962		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6963		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6964	}
6965
6966	bwn_set_all_gains(mac, 3, 0, 1);
6967	if (phy->rf_rev == 8) {
6968		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6969	} else {
6970		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6971		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6972		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6973		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6974	}
6975	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6976	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6977	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6978	DELAY(20);
6979	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6980
6981	/*
6982	 * Install calculated narrow RSSI values
6983	 */
6984	if (nrssi1 >= 0x0020)
6985		nrssi1 -= 0x0040;
6986	if (nrssi0 == nrssi1)
6987		pg->pg_nrssi_slope = 0x00010000;
6988	else
6989		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6990	if (nrssi0 >= -4) {
6991		pg->pg_nrssi[0] = nrssi1;
6992		pg->pg_nrssi[1] = nrssi0;
6993	}
6994
6995	/*
6996	 * Restore saved RF/PHY registers
6997	 */
6998	if (phy->rev >= 3) {
6999		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7000			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7001			    save_phy3[phy3_idx]);
7002		}
7003	}
7004	if (phy->rev >= 2) {
7005		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7006		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7007	}
7008
7009	for (i = 0; i < SAVE_RF_MAX; ++i)
7010		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7011
7012	BWN_WRITE_2(mac, 0x03e2, ant_div);
7013	BWN_WRITE_2(mac, 0x03e6, phy0);
7014	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7015
7016	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7017		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7018
7019	bwn_spu_workaround(mac, phy->chan);
7020	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7021	bwn_set_original_gains(mac);
7022	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7023	if (phy->rev >= 3) {
7024		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7025			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7026			    save_phy3[phy3_idx]);
7027		}
7028	}
7029
7030	delta = 0x1f - pg->pg_nrssi[0];
7031	for (i = 0; i < 64; i++) {
7032		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7033		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7034		pg->pg_nrssi_lt[i] = tmp32;
7035	}
7036
7037	bwn_nrssi_threshold(mac);
7038#undef SAVE_RF_MAX
7039#undef SAVE_PHY_COMM_MAX
7040#undef SAVE_PHY3_MAX
7041}
7042
7043static void
7044bwn_nrssi_offset(struct bwn_mac *mac)
7045{
7046#define	SAVE_RF_MAX		2
7047#define	SAVE_PHY_COMM_MAX	10
7048#define	SAVE_PHY6_MAX		8
7049	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7050		{ 0x7a, 0x43 };
7051	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7052		0x0001, 0x0811, 0x0812, 0x0814,
7053		0x0815, 0x005a, 0x0059, 0x0058,
7054		0x000a, 0x0003
7055	};
7056	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7057		0x002e, 0x002f, 0x080f, 0x0810,
7058		0x0801, 0x0060, 0x0014, 0x0478
7059	};
7060	struct bwn_phy *phy = &mac->mac_phy;
7061	int i, phy6_idx = 0;
7062	uint16_t save_rf[SAVE_RF_MAX];
7063	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7064	uint16_t save_phy6[SAVE_PHY6_MAX];
7065	int16_t nrssi;
7066	uint16_t saved = 0xffff;
7067
7068	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7069		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7070	for (i = 0; i < SAVE_RF_MAX; ++i)
7071		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7072
7073	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7074	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7075	BWN_PHY_SET(mac, 0x0811, 0x000c);
7076	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7077	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7078	if (phy->rev >= 6) {
7079		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7080			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7081
7082		BWN_PHY_WRITE(mac, 0x002e, 0);
7083		BWN_PHY_WRITE(mac, 0x002f, 0);
7084		BWN_PHY_WRITE(mac, 0x080f, 0);
7085		BWN_PHY_WRITE(mac, 0x0810, 0);
7086		BWN_PHY_SET(mac, 0x0478, 0x0100);
7087		BWN_PHY_SET(mac, 0x0801, 0x0040);
7088		BWN_PHY_SET(mac, 0x0060, 0x0040);
7089		BWN_PHY_SET(mac, 0x0014, 0x0200);
7090	}
7091	BWN_RF_SET(mac, 0x007a, 0x0070);
7092	BWN_RF_SET(mac, 0x007a, 0x0080);
7093	DELAY(30);
7094
7095	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7096	if (nrssi >= 0x20)
7097		nrssi -= 0x40;
7098	if (nrssi == 31) {
7099		for (i = 7; i >= 4; i--) {
7100			BWN_RF_WRITE(mac, 0x007b, i);
7101			DELAY(20);
7102			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7103			    0x003f);
7104			if (nrssi >= 0x20)
7105				nrssi -= 0x40;
7106			if (nrssi < 31 && saved == 0xffff)
7107				saved = i;
7108		}
7109		if (saved == 0xffff)
7110			saved = 4;
7111	} else {
7112		BWN_RF_MASK(mac, 0x007a, 0x007f);
7113		if (phy->rev != 1) {
7114			BWN_PHY_SET(mac, 0x0814, 0x0001);
7115			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7116		}
7117		BWN_PHY_SET(mac, 0x0811, 0x000c);
7118		BWN_PHY_SET(mac, 0x0812, 0x000c);
7119		BWN_PHY_SET(mac, 0x0811, 0x0030);
7120		BWN_PHY_SET(mac, 0x0812, 0x0030);
7121		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7122		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7123		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7124		if (phy->rev == 0)
7125			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7126		else
7127			BWN_PHY_SET(mac, 0x000a, 0x2000);
7128		if (phy->rev != 1) {
7129			BWN_PHY_SET(mac, 0x0814, 0x0004);
7130			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7131		}
7132		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7133		BWN_RF_SET(mac, 0x007a, 0x000f);
7134		bwn_set_all_gains(mac, 3, 0, 1);
7135		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7136		DELAY(30);
7137		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7138		if (nrssi >= 0x20)
7139			nrssi -= 0x40;
7140		if (nrssi == -32) {
7141			for (i = 0; i < 4; i++) {
7142				BWN_RF_WRITE(mac, 0x007b, i);
7143				DELAY(20);
7144				nrssi = (int16_t)((BWN_PHY_READ(mac,
7145				    0x047f) >> 8) & 0x003f);
7146				if (nrssi >= 0x20)
7147					nrssi -= 0x40;
7148				if (nrssi > -31 && saved == 0xffff)
7149					saved = i;
7150			}
7151			if (saved == 0xffff)
7152				saved = 3;
7153		} else
7154			saved = 0;
7155	}
7156	BWN_RF_WRITE(mac, 0x007b, saved);
7157
7158	/*
7159	 * Restore saved RF/PHY registers
7160	 */
7161	if (phy->rev >= 6) {
7162		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7163			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7164			    save_phy6[phy6_idx]);
7165		}
7166	}
7167	if (phy->rev != 1) {
7168		for (i = 3; i < 5; i++)
7169			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7170			    save_phy_comm[i]);
7171	}
7172	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7173		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7174
7175	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7176		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7177
7178	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7179	BWN_PHY_SET(mac, 0x0429, 0x8000);
7180	bwn_set_original_gains(mac);
7181	if (phy->rev >= 6) {
7182		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7183			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7184			    save_phy6[phy6_idx]);
7185		}
7186	}
7187
7188	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7189	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7190	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7191}
7192
7193static void
7194bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7195    int16_t third)
7196{
7197	struct bwn_phy *phy = &mac->mac_phy;
7198	uint16_t i;
7199	uint16_t start = 0x08, end = 0x18;
7200	uint16_t tmp;
7201	uint16_t table;
7202
7203	if (phy->rev <= 1) {
7204		start = 0x10;
7205		end = 0x20;
7206	}
7207
7208	table = BWN_OFDMTAB_GAINX;
7209	if (phy->rev <= 1)
7210		table = BWN_OFDMTAB_GAINX_R1;
7211	for (i = 0; i < 4; i++)
7212		bwn_ofdmtab_write_2(mac, table, i, first);
7213
7214	for (i = start; i < end; i++)
7215		bwn_ofdmtab_write_2(mac, table, i, second);
7216
7217	if (third != -1) {
7218		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7219		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7220		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7221		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7222	}
7223	bwn_dummy_transmission(mac, 0, 1);
7224}
7225
7226static void
7227bwn_set_original_gains(struct bwn_mac *mac)
7228{
7229	struct bwn_phy *phy = &mac->mac_phy;
7230	uint16_t i, tmp;
7231	uint16_t table;
7232	uint16_t start = 0x0008, end = 0x0018;
7233
7234	if (phy->rev <= 1) {
7235		start = 0x0010;
7236		end = 0x0020;
7237	}
7238
7239	table = BWN_OFDMTAB_GAINX;
7240	if (phy->rev <= 1)
7241		table = BWN_OFDMTAB_GAINX_R1;
7242	for (i = 0; i < 4; i++) {
7243		tmp = (i & 0xfffc);
7244		tmp |= (i & 0x0001) << 1;
7245		tmp |= (i & 0x0002) >> 1;
7246
7247		bwn_ofdmtab_write_2(mac, table, i, tmp);
7248	}
7249
7250	for (i = start; i < end; i++)
7251		bwn_ofdmtab_write_2(mac, table, i, i - start);
7252
7253	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7254	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7255	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7256	bwn_dummy_transmission(mac, 0, 1);
7257}
7258
7259static void
7260bwn_phy_hwpctl_init(struct bwn_mac *mac)
7261{
7262	struct siba_softc *bus = mac->mac_sd->sd_bus;
7263	struct bwn_phy *phy = &mac->mac_phy;
7264	struct bwn_phy_g *pg = &phy->phy_g;
7265	struct bwn_rfatt old_rfatt, rfatt;
7266	struct bwn_bbatt old_bbatt, bbatt;
7267	uint8_t old_txctl = 0;
7268
7269	KASSERT(phy->type == BWN_PHYTYPE_G,
7270	    ("%s:%d: fail", __func__, __LINE__));
7271
7272	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7273	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7274		return;
7275
7276	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7277
7278	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7279
7280	if (!phy->gmode)
7281		return;
7282	bwn_hwpctl_early_init(mac);
7283	if (pg->pg_curtssi == 0) {
7284		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7285			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7286		} else {
7287			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7288			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7289			old_txctl = pg->pg_txctl;
7290
7291			bbatt.att = 11;
7292			if (phy->rf_rev == 8) {
7293				rfatt.att = 15;
7294				rfatt.padmix = 1;
7295			} else {
7296				rfatt.att = 9;
7297				rfatt.padmix = 0;
7298			}
7299			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7300		}
7301		bwn_dummy_transmission(mac, 0, 1);
7302		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7303		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7304			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7305		else
7306			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7307			    &old_rfatt, old_txctl);
7308	}
7309	bwn_hwpctl_init_gphy(mac);
7310
7311	/* clear TSSI */
7312	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7313	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7314	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7315	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7316}
7317
7318static void
7319bwn_hwpctl_early_init(struct bwn_mac *mac)
7320{
7321	struct bwn_phy *phy = &mac->mac_phy;
7322
7323	if (!bwn_has_hwpctl(mac)) {
7324		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7325		return;
7326	}
7327
7328	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7329	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7330	BWN_PHY_SET(mac, 0x047c, 0x0002);
7331	BWN_PHY_SET(mac, 0x047a, 0xf000);
7332	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7333		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7334		BWN_PHY_SET(mac, 0x005d, 0x8000);
7335		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7336		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7337		BWN_PHY_SET(mac, 0x0036, 0x0400);
7338	} else {
7339		BWN_PHY_SET(mac, 0x0036, 0x0200);
7340		BWN_PHY_SET(mac, 0x0036, 0x0400);
7341		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7342		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7343		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7344		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7345		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7346	}
7347}
7348
7349static void
7350bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7351{
7352	struct bwn_phy *phy = &mac->mac_phy;
7353	struct bwn_phy_g *pg = &phy->phy_g;
7354	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7355	int i;
7356	uint16_t nr_written = 0, tmp, value;
7357	uint8_t rf, bb;
7358
7359	if (!bwn_has_hwpctl(mac)) {
7360		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7361		return;
7362	}
7363
7364	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7365	    (pg->pg_idletssi - pg->pg_curtssi));
7366	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7367	    (pg->pg_idletssi - pg->pg_curtssi));
7368
7369	for (i = 0; i < 32; i++)
7370		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7371	for (i = 32; i < 64; i++)
7372		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7373	for (i = 0; i < 64; i += 2) {
7374		value = (uint16_t) pg->pg_tssi2dbm[i];
7375		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7376		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7377	}
7378
7379	for (rf = 0; rf < lo->rfatt.len; rf++) {
7380		for (bb = 0; bb < lo->bbatt.len; bb++) {
7381			if (nr_written >= 0x40)
7382				return;
7383			tmp = lo->bbatt.array[bb].att;
7384			tmp <<= 8;
7385			if (phy->rf_rev == 8)
7386				tmp |= 0x50;
7387			else
7388				tmp |= 0x40;
7389			tmp |= lo->rfatt.array[rf].att;
7390			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7391			nr_written++;
7392		}
7393	}
7394
7395	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7396	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7397
7398	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7399	BWN_PHY_SET(mac, 0x0478, 0x0800);
7400	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7401	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7402
7403	bwn_phy_g_dc_lookup_init(mac, 1);
7404	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7405}
7406
7407static void
7408bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7409{
7410	struct siba_softc *siba = mac->mac_sd->sd_bus;
7411
7412	if (spu != 0)
7413		bwn_spu_workaround(mac, channel);
7414
7415	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7416
7417	if (channel == 14) {
7418		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7419			bwn_hf_write(mac,
7420			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7421		else
7422			bwn_hf_write(mac,
7423			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7424		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7425		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7426		return;
7427	}
7428
7429	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7430	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7431}
7432
7433static uint16_t
7434bwn_phy_g_chan2freq(uint8_t channel)
7435{
7436	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7437
7438	KASSERT(channel >= 1 && channel <= 14,
7439	    ("%s:%d: fail", __func__, __LINE__));
7440
7441	return (bwn_phy_g_rf_channels[channel - 1]);
7442}
7443
7444static void
7445bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7446    const struct bwn_rfatt *rfatt, uint8_t txctl)
7447{
7448	struct bwn_phy *phy = &mac->mac_phy;
7449	struct bwn_phy_g *pg = &phy->phy_g;
7450	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7451	uint16_t bb, rf;
7452	uint16_t tx_bias, tx_magn;
7453
7454	bb = bbatt->att;
7455	rf = rfatt->att;
7456	tx_bias = lo->tx_bias;
7457	tx_magn = lo->tx_magn;
7458	if (tx_bias == 0xff)
7459		tx_bias = 0;
7460
7461	pg->pg_txctl = txctl;
7462	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7463	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7464	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7465	bwn_phy_g_set_bbatt(mac, bb);
7466	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7467	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7468		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7469	else {
7470		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7471		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7472	}
7473	if (BWN_HAS_TXMAG(phy))
7474		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7475	else
7476		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7477	bwn_lo_g_adjust(mac);
7478}
7479
7480static void
7481bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7482    uint16_t bbatt)
7483{
7484	struct bwn_phy *phy = &mac->mac_phy;
7485
7486	if (phy->analog == 0) {
7487		BWN_WRITE_2(mac, BWN_PHY0,
7488		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7489		return;
7490	}
7491	if (phy->analog > 1) {
7492		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7493		return;
7494	}
7495	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7496}
7497
7498static uint16_t
7499bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7500{
7501	struct bwn_phy *phy = &mac->mac_phy;
7502	struct bwn_phy_g *pg = &phy->phy_g;
7503	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7504	int max_lb_gain;
7505	uint16_t extlna;
7506	uint16_t i;
7507
7508	if (phy->gmode == 0)
7509		return (0);
7510
7511	if (BWN_HAS_LOOPBACK(phy)) {
7512		max_lb_gain = pg->pg_max_lb_gain;
7513		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7514		if (max_lb_gain >= 0x46) {
7515			extlna = 0x3000;
7516			max_lb_gain -= 0x46;
7517		} else if (max_lb_gain >= 0x3a) {
7518			extlna = 0x1000;
7519			max_lb_gain -= 0x3a;
7520		} else if (max_lb_gain >= 0x2e) {
7521			extlna = 0x2000;
7522			max_lb_gain -= 0x2e;
7523		} else {
7524			extlna = 0;
7525			max_lb_gain -= 0x10;
7526		}
7527
7528		for (i = 0; i < 16; i++) {
7529			max_lb_gain -= (i * 6);
7530			if (max_lb_gain < 6)
7531				break;
7532		}
7533
7534		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7535			if (reg == BWN_PHY_RFOVER) {
7536				return (0x1b3);
7537			} else if (reg == BWN_PHY_RFOVERVAL) {
7538				extlna |= (i << 8);
7539				switch (lpd) {
7540				case BWN_LPD(0, 1, 1):
7541					return (0x0f92);
7542				case BWN_LPD(0, 0, 1):
7543				case BWN_LPD(1, 0, 1):
7544					return (0x0092 | extlna);
7545				case BWN_LPD(1, 0, 0):
7546					return (0x0093 | extlna);
7547				}
7548				KASSERT(0 == 1,
7549				    ("%s:%d: fail", __func__, __LINE__));
7550			}
7551			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7552		} else {
7553			if (reg == BWN_PHY_RFOVER)
7554				return (0x9b3);
7555			if (reg == BWN_PHY_RFOVERVAL) {
7556				if (extlna)
7557					extlna |= 0x8000;
7558				extlna |= (i << 8);
7559				switch (lpd) {
7560				case BWN_LPD(0, 1, 1):
7561					return (0x8f92);
7562				case BWN_LPD(0, 0, 1):
7563					return (0x8092 | extlna);
7564				case BWN_LPD(1, 0, 1):
7565					return (0x2092 | extlna);
7566				case BWN_LPD(1, 0, 0):
7567					return (0x2093 | extlna);
7568				}
7569				KASSERT(0 == 1,
7570				    ("%s:%d: fail", __func__, __LINE__));
7571			}
7572			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7573		}
7574		return (0);
7575	}
7576
7577	if ((phy->rev < 7) ||
7578	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7579		if (reg == BWN_PHY_RFOVER) {
7580			return (0x1b3);
7581		} else if (reg == BWN_PHY_RFOVERVAL) {
7582			switch (lpd) {
7583			case BWN_LPD(0, 1, 1):
7584				return (0x0fb2);
7585			case BWN_LPD(0, 0, 1):
7586				return (0x00b2);
7587			case BWN_LPD(1, 0, 1):
7588				return (0x30b2);
7589			case BWN_LPD(1, 0, 0):
7590				return (0x30b3);
7591			}
7592			KASSERT(0 == 1,
7593			    ("%s:%d: fail", __func__, __LINE__));
7594		}
7595		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7596	} else {
7597		if (reg == BWN_PHY_RFOVER) {
7598			return (0x9b3);
7599		} else if (reg == BWN_PHY_RFOVERVAL) {
7600			switch (lpd) {
7601			case BWN_LPD(0, 1, 1):
7602				return (0x8fb2);
7603			case BWN_LPD(0, 0, 1):
7604				return (0x80b2);
7605			case BWN_LPD(1, 0, 1):
7606				return (0x20b2);
7607			case BWN_LPD(1, 0, 0):
7608				return (0x20b3);
7609			}
7610			KASSERT(0 == 1,
7611			    ("%s:%d: fail", __func__, __LINE__));
7612		}
7613		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7614	}
7615	return (0);
7616}
7617
7618static void
7619bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7620{
7621
7622	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7623		return;
7624	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7625	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7626	DELAY(1000);
7627	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7628}
7629
7630static int
7631bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7632{
7633	struct bwn_softc *sc = mac->mac_sc;
7634	struct bwn_fw *fw = &mac->mac_fw;
7635	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7636	const char *filename;
7637	uint32_t high;
7638	int error;
7639
7640	/* microcode */
7641	if (rev >= 5 && rev <= 10)
7642		filename = "ucode5";
7643	else if (rev >= 11 && rev <= 12)
7644		filename = "ucode11";
7645	else if (rev == 13)
7646		filename = "ucode13";
7647	else if (rev == 14)
7648		filename = "ucode14";
7649	else if (rev >= 15)
7650		filename = "ucode15";
7651	else {
7652		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7653		bwn_release_firmware(mac);
7654		return (EOPNOTSUPP);
7655	}
7656	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7657	if (error) {
7658		bwn_release_firmware(mac);
7659		return (error);
7660	}
7661
7662	/* PCM */
7663	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7664	if (rev >= 5 && rev <= 10) {
7665		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7666		if (error == ENOENT)
7667			fw->no_pcmfile = 1;
7668		else if (error) {
7669			bwn_release_firmware(mac);
7670			return (error);
7671		}
7672	} else if (rev < 11) {
7673		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7674		return (EOPNOTSUPP);
7675	}
7676
7677	/* initvals */
7678	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7679	switch (mac->mac_phy.type) {
7680	case BWN_PHYTYPE_A:
7681		if (rev < 5 || rev > 10)
7682			goto fail1;
7683		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7684			filename = "a0g1initvals5";
7685		else
7686			filename = "a0g0initvals5";
7687		break;
7688	case BWN_PHYTYPE_G:
7689		if (rev >= 5 && rev <= 10)
7690			filename = "b0g0initvals5";
7691		else if (rev >= 13)
7692			filename = "b0g0initvals13";
7693		else
7694			goto fail1;
7695		break;
7696	case BWN_PHYTYPE_LP:
7697		if (rev == 13)
7698			filename = "lp0initvals13";
7699		else if (rev == 14)
7700			filename = "lp0initvals14";
7701		else if (rev >= 15)
7702			filename = "lp0initvals15";
7703		else
7704			goto fail1;
7705		break;
7706	case BWN_PHYTYPE_N:
7707		if (rev >= 11 && rev <= 12)
7708			filename = "n0initvals11";
7709		else
7710			goto fail1;
7711		break;
7712	default:
7713		goto fail1;
7714	}
7715	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7716	if (error) {
7717		bwn_release_firmware(mac);
7718		return (error);
7719	}
7720
7721	/* bandswitch initvals */
7722	switch (mac->mac_phy.type) {
7723	case BWN_PHYTYPE_A:
7724		if (rev >= 5 && rev <= 10) {
7725			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7726				filename = "a0g1bsinitvals5";
7727			else
7728				filename = "a0g0bsinitvals5";
7729		} else if (rev >= 11)
7730			filename = NULL;
7731		else
7732			goto fail1;
7733		break;
7734	case BWN_PHYTYPE_G:
7735		if (rev >= 5 && rev <= 10)
7736			filename = "b0g0bsinitvals5";
7737		else if (rev >= 11)
7738			filename = NULL;
7739		else
7740			goto fail1;
7741		break;
7742	case BWN_PHYTYPE_LP:
7743		if (rev == 13)
7744			filename = "lp0bsinitvals13";
7745		else if (rev == 14)
7746			filename = "lp0bsinitvals14";
7747		else if (rev >= 15)
7748			filename = "lp0bsinitvals15";
7749		else
7750			goto fail1;
7751		break;
7752	case BWN_PHYTYPE_N:
7753		if (rev >= 11 && rev <= 12)
7754			filename = "n0bsinitvals11";
7755		else
7756			goto fail1;
7757		break;
7758	default:
7759		goto fail1;
7760	}
7761	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7762	if (error) {
7763		bwn_release_firmware(mac);
7764		return (error);
7765	}
7766	return (0);
7767fail1:
7768	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7769	bwn_release_firmware(mac);
7770	return (EOPNOTSUPP);
7771}
7772
7773static int
7774bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7775    const char *name, struct bwn_fwfile *bfw)
7776{
7777	const struct bwn_fwhdr *hdr;
7778	struct bwn_softc *sc = mac->mac_sc;
7779	const struct firmware *fw;
7780	char namebuf[64];
7781
7782	if (name == NULL) {
7783		bwn_do_release_fw(bfw);
7784		return (0);
7785	}
7786	if (bfw->filename != NULL) {
7787		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7788			return (0);
7789		bwn_do_release_fw(bfw);
7790	}
7791
7792	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7793	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7794	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7795	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7796	fw = firmware_get(namebuf);
7797	if (fw == NULL) {
7798		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7799		    namebuf);
7800		return (ENOENT);
7801	}
7802	if (fw->datasize < sizeof(struct bwn_fwhdr))
7803		goto fail;
7804	hdr = (const struct bwn_fwhdr *)(fw->data);
7805	switch (hdr->type) {
7806	case BWN_FWTYPE_UCODE:
7807	case BWN_FWTYPE_PCM:
7808		if (be32toh(hdr->size) !=
7809		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7810			goto fail;
7811		/* FALLTHROUGH */
7812	case BWN_FWTYPE_IV:
7813		if (hdr->ver != 1)
7814			goto fail;
7815		break;
7816	default:
7817		goto fail;
7818	}
7819	bfw->filename = name;
7820	bfw->fw = fw;
7821	bfw->type = type;
7822	return (0);
7823fail:
7824	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7825	if (fw != NULL)
7826		firmware_put(fw, FIRMWARE_UNLOAD);
7827	return (EPROTO);
7828}
7829
7830static void
7831bwn_release_firmware(struct bwn_mac *mac)
7832{
7833
7834	bwn_do_release_fw(&mac->mac_fw.ucode);
7835	bwn_do_release_fw(&mac->mac_fw.pcm);
7836	bwn_do_release_fw(&mac->mac_fw.initvals);
7837	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7838}
7839
7840static void
7841bwn_do_release_fw(struct bwn_fwfile *bfw)
7842{
7843
7844	if (bfw->fw != NULL)
7845		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7846	bfw->fw = NULL;
7847	bfw->filename = NULL;
7848}
7849
7850static int
7851bwn_fw_loaducode(struct bwn_mac *mac)
7852{
7853#define	GETFWOFFSET(fwp, offset)	\
7854	((const uint32_t *)((const char *)fwp.fw->data + offset))
7855#define	GETFWSIZE(fwp, offset)	\
7856	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7857	struct bwn_softc *sc = mac->mac_sc;
7858	const uint32_t *data;
7859	unsigned int i;
7860	uint32_t ctl;
7861	uint16_t date, fwcaps, time;
7862	int error = 0;
7863
7864	ctl = BWN_READ_4(mac, BWN_MACCTL);
7865	ctl |= BWN_MACCTL_MCODE_JMP0;
7866	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7867	    __LINE__));
7868	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7869	for (i = 0; i < 64; i++)
7870		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7871	for (i = 0; i < 4096; i += 2)
7872		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7873
7874	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7875	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7876	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7877	     i++) {
7878		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7879		DELAY(10);
7880	}
7881
7882	if (mac->mac_fw.pcm.fw) {
7883		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7884		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7885		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7886		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7887		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7888		    sizeof(struct bwn_fwhdr)); i++) {
7889			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7890			DELAY(10);
7891		}
7892	}
7893
7894	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7895	BWN_WRITE_4(mac, BWN_MACCTL,
7896	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7897	    BWN_MACCTL_MCODE_RUN);
7898
7899	for (i = 0; i < 21; i++) {
7900		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7901			break;
7902		if (i >= 20) {
7903			device_printf(sc->sc_dev, "ucode timeout\n");
7904			error = ENXIO;
7905			goto error;
7906		}
7907		DELAY(50000);
7908	}
7909	BWN_READ_4(mac, BWN_INTR_REASON);
7910
7911	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7912	if (mac->mac_fw.rev <= 0x128) {
7913		device_printf(sc->sc_dev, "the firmware is too old\n");
7914		error = EOPNOTSUPP;
7915		goto error;
7916	}
7917	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7918	    BWN_SHARED_UCODE_PATCH);
7919	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7920	mac->mac_fw.opensource = (date == 0xffff);
7921	if (bwn_wme != 0)
7922		mac->mac_flags |= BWN_MAC_FLAG_WME;
7923	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7924
7925	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7926	if (mac->mac_fw.opensource == 0) {
7927		device_printf(sc->sc_dev,
7928		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7929		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7930		if (mac->mac_fw.no_pcmfile)
7931			device_printf(sc->sc_dev,
7932			    "no HW crypto acceleration due to pcm5\n");
7933	} else {
7934		mac->mac_fw.patch = time;
7935		fwcaps = bwn_fwcaps_read(mac);
7936		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7937			device_printf(sc->sc_dev,
7938			    "disabling HW crypto acceleration\n");
7939			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7940		}
7941		if (!(fwcaps & BWN_FWCAPS_WME)) {
7942			device_printf(sc->sc_dev, "disabling WME support\n");
7943			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7944		}
7945	}
7946
7947	if (BWN_ISOLDFMT(mac))
7948		device_printf(sc->sc_dev, "using old firmware image\n");
7949
7950	return (0);
7951
7952error:
7953	BWN_WRITE_4(mac, BWN_MACCTL,
7954	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7955	    BWN_MACCTL_MCODE_JMP0);
7956
7957	return (error);
7958#undef GETFWSIZE
7959#undef GETFWOFFSET
7960}
7961
7962/* OpenFirmware only */
7963static uint16_t
7964bwn_fwcaps_read(struct bwn_mac *mac)
7965{
7966
7967	KASSERT(mac->mac_fw.opensource == 1,
7968	    ("%s:%d: fail", __func__, __LINE__));
7969	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7970}
7971
7972static int
7973bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7974    size_t count, size_t array_size)
7975{
7976#define	GET_NEXTIV16(iv)						\
7977	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7978	    sizeof(uint16_t) + sizeof(uint16_t)))
7979#define	GET_NEXTIV32(iv)						\
7980	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7981	    sizeof(uint16_t) + sizeof(uint32_t)))
7982	struct bwn_softc *sc = mac->mac_sc;
7983	const struct bwn_fwinitvals *iv;
7984	uint16_t offset;
7985	size_t i;
7986	uint8_t bit32;
7987
7988	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7989	    ("%s:%d: fail", __func__, __LINE__));
7990	iv = ivals;
7991	for (i = 0; i < count; i++) {
7992		if (array_size < sizeof(iv->offset_size))
7993			goto fail;
7994		array_size -= sizeof(iv->offset_size);
7995		offset = be16toh(iv->offset_size);
7996		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7997		offset &= BWN_FWINITVALS_OFFSET_MASK;
7998		if (offset >= 0x1000)
7999			goto fail;
8000		if (bit32) {
8001			if (array_size < sizeof(iv->data.d32))
8002				goto fail;
8003			array_size -= sizeof(iv->data.d32);
8004			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8005			iv = GET_NEXTIV32(iv);
8006		} else {
8007
8008			if (array_size < sizeof(iv->data.d16))
8009				goto fail;
8010			array_size -= sizeof(iv->data.d16);
8011			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8012
8013			iv = GET_NEXTIV16(iv);
8014		}
8015	}
8016	if (array_size != 0)
8017		goto fail;
8018	return (0);
8019fail:
8020	device_printf(sc->sc_dev, "initvals: invalid format\n");
8021	return (EPROTO);
8022#undef GET_NEXTIV16
8023#undef GET_NEXTIV32
8024}
8025
8026static int
8027bwn_switch_channel(struct bwn_mac *mac, int chan)
8028{
8029	struct bwn_phy *phy = &(mac->mac_phy);
8030	struct bwn_softc *sc = mac->mac_sc;
8031	struct ifnet *ifp = sc->sc_ifp;
8032	struct ieee80211com *ic = ifp->if_l2com;
8033	uint16_t channelcookie, savedcookie;
8034	int error;
8035
8036	if (chan == 0xffff)
8037		chan = phy->get_default_chan(mac);
8038
8039	channelcookie = chan;
8040	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8041		channelcookie |= 0x100;
8042	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8043	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8044	error = phy->switch_channel(mac, chan);
8045	if (error)
8046		goto fail;
8047
8048	mac->mac_phy.chan = chan;
8049	DELAY(8000);
8050	return (0);
8051fail:
8052	device_printf(sc->sc_dev, "failed to switch channel\n");
8053	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8054	return (error);
8055}
8056
8057static uint16_t
8058bwn_ant2phy(int antenna)
8059{
8060
8061	switch (antenna) {
8062	case BWN_ANT0:
8063		return (BWN_TX_PHY_ANT0);
8064	case BWN_ANT1:
8065		return (BWN_TX_PHY_ANT1);
8066	case BWN_ANT2:
8067		return (BWN_TX_PHY_ANT2);
8068	case BWN_ANT3:
8069		return (BWN_TX_PHY_ANT3);
8070	case BWN_ANTAUTO:
8071		return (BWN_TX_PHY_ANT01AUTO);
8072	}
8073	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8074	return (0);
8075}
8076
8077static void
8078bwn_wme_load(struct bwn_mac *mac)
8079{
8080	struct bwn_softc *sc = mac->mac_sc;
8081	int i;
8082
8083	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8084	    ("%s:%d: fail", __func__, __LINE__));
8085
8086	bwn_mac_suspend(mac);
8087	for (i = 0; i < N(sc->sc_wmeParams); i++)
8088		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8089		    bwn_wme_shm_offsets[i]);
8090	bwn_mac_enable(mac);
8091}
8092
8093static void
8094bwn_wme_loadparams(struct bwn_mac *mac,
8095    const struct wmeParams *p, uint16_t shm_offset)
8096{
8097#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8098	struct bwn_softc *sc = mac->mac_sc;
8099	uint16_t params[BWN_NR_WMEPARAMS];
8100	int slot, tmp;
8101	unsigned int i;
8102
8103	slot = BWN_READ_2(mac, BWN_RNG) &
8104	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8105
8106	memset(&params, 0, sizeof(params));
8107
8108	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8109	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8110	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8111
8112	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8113	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8114	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8115	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8116	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8117	params[BWN_WMEPARAM_BSLOTS] = slot;
8118	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8119
8120	for (i = 0; i < N(params); i++) {
8121		if (i == BWN_WMEPARAM_STATUS) {
8122			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8123			    shm_offset + (i * 2));
8124			tmp |= 0x100;
8125			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8126			    tmp);
8127		} else {
8128			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8129			    params[i]);
8130		}
8131	}
8132}
8133
8134static void
8135bwn_mac_write_bssid(struct bwn_mac *mac)
8136{
8137	struct bwn_softc *sc = mac->mac_sc;
8138	uint32_t tmp;
8139	int i;
8140	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8141
8142	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8143	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8144	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8145	    IEEE80211_ADDR_LEN);
8146
8147	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8148		tmp = (uint32_t) (mac_bssid[i + 0]);
8149		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8150		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8151		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8152		bwn_ram_write(mac, 0x20 + i, tmp);
8153	}
8154}
8155
8156static void
8157bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8158    const uint8_t *macaddr)
8159{
8160	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8161	uint16_t data;
8162
8163	if (!mac)
8164		macaddr = zero;
8165
8166	offset |= 0x0020;
8167	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8168
8169	data = macaddr[0];
8170	data |= macaddr[1] << 8;
8171	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8172	data = macaddr[2];
8173	data |= macaddr[3] << 8;
8174	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8175	data = macaddr[4];
8176	data |= macaddr[5] << 8;
8177	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8178}
8179
8180static void
8181bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8182    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8183{
8184	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8185	uint8_t per_sta_keys_start = 8;
8186
8187	if (BWN_SEC_NEWAPI(mac))
8188		per_sta_keys_start = 4;
8189
8190	KASSERT(index < mac->mac_max_nr_keys,
8191	    ("%s:%d: fail", __func__, __LINE__));
8192	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8193	    ("%s:%d: fail", __func__, __LINE__));
8194
8195	if (index >= per_sta_keys_start)
8196		bwn_key_macwrite(mac, index, NULL);
8197	if (key)
8198		memcpy(buf, key, key_len);
8199	bwn_key_write(mac, index, algorithm, buf);
8200	if (index >= per_sta_keys_start)
8201		bwn_key_macwrite(mac, index, mac_addr);
8202
8203	mac->mac_key[index].algorithm = algorithm;
8204}
8205
8206static void
8207bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8208{
8209	uint32_t addrtmp[2] = { 0, 0 };
8210	uint8_t start = 8;
8211
8212	if (BWN_SEC_NEWAPI(mac))
8213		start = 4;
8214
8215	KASSERT(index >= start,
8216	    ("%s:%d: fail", __func__, __LINE__));
8217	index -= start;
8218
8219	if (addr) {
8220		addrtmp[0] = addr[0];
8221		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8222		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8223		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8224		addrtmp[1] = addr[4];
8225		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8226	}
8227
8228	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8229		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8230		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8231	} else {
8232		if (index >= 8) {
8233			bwn_shm_write_4(mac, BWN_SHARED,
8234			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8235			bwn_shm_write_2(mac, BWN_SHARED,
8236			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8237		}
8238	}
8239}
8240
8241static void
8242bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8243    const uint8_t *key)
8244{
8245	unsigned int i;
8246	uint32_t offset;
8247	uint16_t kidx, value;
8248
8249	kidx = BWN_SEC_KEY2FW(mac, index);
8250	bwn_shm_write_2(mac, BWN_SHARED,
8251	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8252
8253	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8254	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8255		value = key[i];
8256		value |= (uint16_t)(key[i + 1]) << 8;
8257		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8258	}
8259}
8260
8261static void
8262bwn_phy_exit(struct bwn_mac *mac)
8263{
8264
8265	mac->mac_phy.rf_onoff(mac, 0);
8266	if (mac->mac_phy.exit != NULL)
8267		mac->mac_phy.exit(mac);
8268}
8269
8270static void
8271bwn_dma_free(struct bwn_mac *mac)
8272{
8273	struct bwn_dma *dma;
8274
8275	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8276		return;
8277	dma = &mac->mac_method.dma;
8278
8279	bwn_dma_ringfree(&dma->rx);
8280	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8281	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8282	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8283	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8284	bwn_dma_ringfree(&dma->mcast);
8285}
8286
8287static void
8288bwn_core_stop(struct bwn_mac *mac)
8289{
8290	struct bwn_softc *sc = mac->mac_sc;
8291
8292	BWN_ASSERT_LOCKED(sc);
8293
8294	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8295		return;
8296
8297	callout_stop(&sc->sc_rfswitch_ch);
8298	callout_stop(&sc->sc_task_ch);
8299	callout_stop(&sc->sc_watchdog_ch);
8300	sc->sc_watchdog_timer = 0;
8301	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8302	BWN_READ_4(mac, BWN_INTR_MASK);
8303	bwn_mac_suspend(mac);
8304
8305	mac->mac_status = BWN_MAC_STATUS_INITED;
8306}
8307
8308static int
8309bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8310{
8311	struct bwn_mac *up_dev = NULL;
8312	struct bwn_mac *down_dev;
8313	struct bwn_mac *mac;
8314	int err, status;
8315	uint8_t gmode;
8316
8317	BWN_ASSERT_LOCKED(sc);
8318
8319	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8320		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8321		    mac->mac_phy.supports_2ghz) {
8322			up_dev = mac;
8323			gmode = 1;
8324		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8325		    mac->mac_phy.supports_5ghz) {
8326			up_dev = mac;
8327			gmode = 0;
8328		} else {
8329			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8330			return (EINVAL);
8331		}
8332		if (up_dev != NULL)
8333			break;
8334	}
8335	if (up_dev == NULL) {
8336		device_printf(sc->sc_dev, "Could not find a device\n");
8337		return (ENODEV);
8338	}
8339	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8340		return (0);
8341
8342	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8343	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8344
8345	down_dev = sc->sc_curmac;;
8346	status = down_dev->mac_status;
8347	if (status >= BWN_MAC_STATUS_STARTED)
8348		bwn_core_stop(down_dev);
8349	if (status >= BWN_MAC_STATUS_INITED)
8350		bwn_core_exit(down_dev);
8351
8352	if (down_dev != up_dev)
8353		bwn_phy_reset(down_dev);
8354
8355	up_dev->mac_phy.gmode = gmode;
8356	if (status >= BWN_MAC_STATUS_INITED) {
8357		err = bwn_core_init(up_dev);
8358		if (err) {
8359			device_printf(sc->sc_dev,
8360			    "fatal: failed to initialize for %s-GHz\n",
8361			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8362			goto fail;
8363		}
8364	}
8365	if (status >= BWN_MAC_STATUS_STARTED)
8366		bwn_core_start(up_dev);
8367	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8368	sc->sc_curmac = up_dev;
8369
8370	return (0);
8371fail:
8372	sc->sc_curmac = NULL;
8373	return (err);
8374}
8375
8376static void
8377bwn_rf_turnon(struct bwn_mac *mac)
8378{
8379
8380	bwn_mac_suspend(mac);
8381	mac->mac_phy.rf_onoff(mac, 1);
8382	mac->mac_phy.rf_on = 1;
8383	bwn_mac_enable(mac);
8384}
8385
8386static void
8387bwn_rf_turnoff(struct bwn_mac *mac)
8388{
8389
8390	bwn_mac_suspend(mac);
8391	mac->mac_phy.rf_onoff(mac, 0);
8392	mac->mac_phy.rf_on = 0;
8393	bwn_mac_enable(mac);
8394}
8395
8396static void
8397bwn_phy_reset(struct bwn_mac *mac)
8398{
8399	struct siba_dev_softc *sd = mac->mac_sd;
8400
8401	siba_write_4(sd, SIBA_TGSLOW,
8402	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8403	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8404	DELAY(1000);
8405	siba_write_4(sd, SIBA_TGSLOW,
8406	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8407	    BWN_TGSLOW_PHYRESET);
8408	DELAY(1000);
8409}
8410
8411static int
8412bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8413{
8414	struct bwn_vap *bvp = BWN_VAP(vap);
8415	struct ieee80211com *ic= vap->iv_ic;
8416	struct ifnet *ifp = ic->ic_ifp;
8417	enum ieee80211_state ostate = vap->iv_state;
8418	struct bwn_softc *sc = ifp->if_softc;
8419	struct bwn_mac *mac = sc->sc_curmac;
8420	int error;
8421
8422	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8423	    ieee80211_state_name[vap->iv_state],
8424	    ieee80211_state_name[nstate]);
8425
8426	error = bvp->bv_newstate(vap, nstate, arg);
8427	if (error != 0)
8428		return (error);
8429
8430	BWN_LOCK(sc);
8431
8432	bwn_led_newstate(mac, nstate);
8433
8434	/*
8435	 * Clear the BSSID when we stop a STA
8436	 */
8437	if (vap->iv_opmode == IEEE80211_M_STA) {
8438		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8439			/*
8440			 * Clear out the BSSID.  If we reassociate to
8441			 * the same AP, this will reinialize things
8442			 * correctly...
8443			 */
8444			if (ic->ic_opmode == IEEE80211_M_STA &&
8445			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8446				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8447				bwn_set_macaddr(mac);
8448			}
8449		}
8450	}
8451
8452	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8453	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8454		/* XXX nothing to do? */
8455	} else if (nstate == IEEE80211_S_RUN) {
8456		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8457		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8458		bwn_set_opmode(mac);
8459		bwn_set_pretbtt(mac);
8460		bwn_spu_setdelay(mac, 0);
8461		bwn_set_macaddr(mac);
8462	}
8463
8464	BWN_UNLOCK(sc);
8465
8466	return (error);
8467}
8468
8469static void
8470bwn_set_pretbtt(struct bwn_mac *mac)
8471{
8472	struct bwn_softc *sc = mac->mac_sc;
8473	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8474	uint16_t pretbtt;
8475
8476	if (ic->ic_opmode == IEEE80211_M_IBSS)
8477		pretbtt = 2;
8478	else
8479		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8480	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8481	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8482}
8483
8484static int
8485bwn_intr(void *arg)
8486{
8487	struct bwn_mac *mac = arg;
8488	struct bwn_softc *sc = mac->mac_sc;
8489	struct siba_softc *siba = mac->mac_sd->sd_bus;
8490	uint32_t reason;
8491
8492	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8493		return (FILTER_STRAY);
8494
8495	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8496	if (reason == 0xffffffff)	/* shared IRQ */
8497		return (FILTER_STRAY);
8498	reason &= mac->mac_intr_mask;
8499	if (reason == 0)
8500		return (FILTER_HANDLED);
8501
8502	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8503	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8504	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8505	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8506	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8507	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8508	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8509	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8510	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8511	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8512	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8513
8514	/* Disable interrupts. */
8515	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8516
8517	mac->mac_reason_intr = reason;
8518
8519	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8520	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8521
8522	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8523	return (FILTER_HANDLED);
8524}
8525
8526static void
8527bwn_intrtask(void *arg, int npending)
8528{
8529	struct bwn_mac *mac = arg;
8530	struct bwn_softc *sc = mac->mac_sc;
8531	struct ifnet *ifp = sc->sc_ifp;
8532	struct siba_softc *siba = mac->mac_sd->sd_bus;
8533	uint32_t merged = 0;
8534	int i, tx = 0, rx = 0;
8535
8536	BWN_LOCK(sc);
8537	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8538		BWN_UNLOCK(sc);
8539		return;
8540	}
8541
8542	for (i = 0; i < N(mac->mac_reason); i++)
8543		merged |= mac->mac_reason[i];
8544
8545	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8546		device_printf(sc->sc_dev, "MAC trans error\n");
8547
8548	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8549		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8550		mac->mac_phy.txerrors--;
8551		if (mac->mac_phy.txerrors == 0) {
8552			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8553			bwn_restart(mac, "PHY TX errors");
8554		}
8555	}
8556
8557	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8558		if (merged & BWN_DMAINTR_FATALMASK) {
8559			device_printf(sc->sc_dev,
8560			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8561			    mac->mac_reason[0], mac->mac_reason[1],
8562			    mac->mac_reason[2], mac->mac_reason[3],
8563			    mac->mac_reason[4], mac->mac_reason[5]);
8564			bwn_restart(mac, "DMA error");
8565			BWN_UNLOCK(sc);
8566			return;
8567		}
8568		if (merged & BWN_DMAINTR_NONFATALMASK) {
8569			device_printf(sc->sc_dev,
8570			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8571			    mac->mac_reason[0], mac->mac_reason[1],
8572			    mac->mac_reason[2], mac->mac_reason[3],
8573			    mac->mac_reason[4], mac->mac_reason[5]);
8574		}
8575	}
8576
8577	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8578		bwn_intr_ucode_debug(mac);
8579	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8580		bwn_intr_tbtt_indication(mac);
8581	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8582		bwn_intr_atim_end(mac);
8583	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8584		bwn_intr_beacon(mac);
8585	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8586		bwn_intr_pmq(mac);
8587	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8588		bwn_intr_noise(mac);
8589
8590	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8591		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8592			bwn_dma_rx(mac->mac_method.dma.rx);
8593			rx = 1;
8594		}
8595	} else
8596		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8597
8598	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8599	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8600	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8601	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8602	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8603
8604	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8605		bwn_intr_txeof(mac);
8606		tx = 1;
8607	}
8608
8609	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8610
8611	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8612		int evt = BWN_LED_EVENT_NONE;
8613
8614		if (tx && rx) {
8615			if (sc->sc_rx_rate > sc->sc_tx_rate)
8616				evt = BWN_LED_EVENT_RX;
8617			else
8618				evt = BWN_LED_EVENT_TX;
8619		} else if (tx) {
8620			evt = BWN_LED_EVENT_TX;
8621		} else if (rx) {
8622			evt = BWN_LED_EVENT_RX;
8623		} else if (rx == 0) {
8624			evt = BWN_LED_EVENT_POLL;
8625		}
8626
8627		if (evt != BWN_LED_EVENT_NONE)
8628			bwn_led_event(mac, evt);
8629       }
8630
8631	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8632		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8633			bwn_start_locked(ifp);
8634	}
8635
8636	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8637	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8638
8639	BWN_UNLOCK(sc);
8640}
8641
8642static void
8643bwn_restart(struct bwn_mac *mac, const char *msg)
8644{
8645	struct bwn_softc *sc = mac->mac_sc;
8646	struct ifnet *ifp = sc->sc_ifp;
8647	struct ieee80211com *ic = ifp->if_l2com;
8648
8649	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8650		return;
8651
8652	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8653	ieee80211_runtask(ic, &mac->mac_hwreset);
8654}
8655
8656static void
8657bwn_intr_ucode_debug(struct bwn_mac *mac)
8658{
8659	struct bwn_softc *sc = mac->mac_sc;
8660	uint16_t reason;
8661
8662	if (mac->mac_fw.opensource == 0)
8663		return;
8664
8665	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8666	switch (reason) {
8667	case BWN_DEBUGINTR_PANIC:
8668		bwn_handle_fwpanic(mac);
8669		break;
8670	case BWN_DEBUGINTR_DUMP_SHM:
8671		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8672		break;
8673	case BWN_DEBUGINTR_DUMP_REGS:
8674		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8675		break;
8676	case BWN_DEBUGINTR_MARKER:
8677		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8678		break;
8679	default:
8680		device_printf(sc->sc_dev,
8681		    "ucode debug unknown reason: %#x\n", reason);
8682	}
8683
8684	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8685	    BWN_DEBUGINTR_ACK);
8686}
8687
8688static void
8689bwn_intr_tbtt_indication(struct bwn_mac *mac)
8690{
8691	struct bwn_softc *sc = mac->mac_sc;
8692	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8693
8694	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8695		bwn_psctl(mac, 0);
8696	if (ic->ic_opmode == IEEE80211_M_IBSS)
8697		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8698}
8699
8700static void
8701bwn_intr_atim_end(struct bwn_mac *mac)
8702{
8703
8704	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8705		BWN_WRITE_4(mac, BWN_MACCMD,
8706		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8707		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8708	}
8709}
8710
8711static void
8712bwn_intr_beacon(struct bwn_mac *mac)
8713{
8714	struct bwn_softc *sc = mac->mac_sc;
8715	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8716	uint32_t cmd, beacon0, beacon1;
8717
8718	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8719	    ic->ic_opmode == IEEE80211_M_MBSS)
8720		return;
8721
8722	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8723
8724	cmd = BWN_READ_4(mac, BWN_MACCMD);
8725	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8726	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8727
8728	if (beacon0 && beacon1) {
8729		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8730		mac->mac_intr_mask |= BWN_INTR_BEACON;
8731		return;
8732	}
8733
8734	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8735		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8736		bwn_load_beacon0(mac);
8737		bwn_load_beacon1(mac);
8738		cmd = BWN_READ_4(mac, BWN_MACCMD);
8739		cmd |= BWN_MACCMD_BEACON0_VALID;
8740		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8741	} else {
8742		if (!beacon0) {
8743			bwn_load_beacon0(mac);
8744			cmd = BWN_READ_4(mac, BWN_MACCMD);
8745			cmd |= BWN_MACCMD_BEACON0_VALID;
8746			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8747		} else if (!beacon1) {
8748			bwn_load_beacon1(mac);
8749			cmd = BWN_READ_4(mac, BWN_MACCMD);
8750			cmd |= BWN_MACCMD_BEACON1_VALID;
8751			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8752		}
8753	}
8754}
8755
8756static void
8757bwn_intr_pmq(struct bwn_mac *mac)
8758{
8759	uint32_t tmp;
8760
8761	while (1) {
8762		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8763		if (!(tmp & 0x00000008))
8764			break;
8765	}
8766	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8767}
8768
8769static void
8770bwn_intr_noise(struct bwn_mac *mac)
8771{
8772	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8773	uint16_t tmp;
8774	uint8_t noise[4];
8775	uint8_t i, j;
8776	int32_t average;
8777
8778	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8779		return;
8780
8781	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8782	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8783	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8784	    noise[3] == 0x7f)
8785		goto new;
8786
8787	KASSERT(mac->mac_noise.noi_nsamples < 8,
8788	    ("%s:%d: fail", __func__, __LINE__));
8789	i = mac->mac_noise.noi_nsamples;
8790	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8791	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8792	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8793	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8794	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8795	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8796	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8797	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8798	mac->mac_noise.noi_nsamples++;
8799	if (mac->mac_noise.noi_nsamples == 8) {
8800		average = 0;
8801		for (i = 0; i < 8; i++) {
8802			for (j = 0; j < 4; j++)
8803				average += mac->mac_noise.noi_samples[i][j];
8804		}
8805		average = (((average / 32) * 125) + 64) / 128;
8806		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8807		if (tmp >= 8)
8808			average += 2;
8809		else
8810			average -= 25;
8811		average -= (tmp == 8) ? 72 : 48;
8812
8813		mac->mac_stats.link_noise = average;
8814		mac->mac_noise.noi_running = 0;
8815		return;
8816	}
8817new:
8818	bwn_noise_gensample(mac);
8819}
8820
8821static int
8822bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8823{
8824	struct bwn_mac *mac = prq->prq_mac;
8825	struct bwn_softc *sc = mac->mac_sc;
8826	unsigned int i;
8827
8828	BWN_ASSERT_LOCKED(sc);
8829
8830	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8831		return (0);
8832
8833	for (i = 0; i < 5000; i++) {
8834		if (bwn_pio_rxeof(prq) == 0)
8835			break;
8836	}
8837	if (i >= 5000)
8838		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8839	return ((i > 0) ? 1 : 0);
8840}
8841
8842static void
8843bwn_dma_rx(struct bwn_dma_ring *dr)
8844{
8845	int slot, curslot;
8846
8847	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8848	curslot = dr->get_curslot(dr);
8849	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8850	    ("%s:%d: fail", __func__, __LINE__));
8851
8852	slot = dr->dr_curslot;
8853	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8854		bwn_dma_rxeof(dr, &slot);
8855
8856	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8857	    BUS_DMASYNC_PREWRITE);
8858
8859	dr->set_curslot(dr, slot);
8860	dr->dr_curslot = slot;
8861}
8862
8863static void
8864bwn_intr_txeof(struct bwn_mac *mac)
8865{
8866	struct bwn_txstatus stat;
8867	uint32_t stat0, stat1;
8868	uint16_t tmp;
8869
8870	BWN_ASSERT_LOCKED(mac->mac_sc);
8871
8872	while (1) {
8873		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8874		if (!(stat0 & 0x00000001))
8875			break;
8876		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8877
8878		stat.cookie = (stat0 >> 16);
8879		stat.seq = (stat1 & 0x0000ffff);
8880		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8881		tmp = (stat0 & 0x0000ffff);
8882		stat.framecnt = ((tmp & 0xf000) >> 12);
8883		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8884		stat.sreason = ((tmp & 0x001c) >> 2);
8885		stat.pm = (tmp & 0x0080) ? 1 : 0;
8886		stat.im = (tmp & 0x0040) ? 1 : 0;
8887		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8888		stat.ack = (tmp & 0x0002) ? 1 : 0;
8889
8890		bwn_handle_txeof(mac, &stat);
8891	}
8892}
8893
8894static void
8895bwn_hwreset(void *arg, int npending)
8896{
8897	struct bwn_mac *mac = arg;
8898	struct bwn_softc *sc = mac->mac_sc;
8899	int error = 0;
8900	int prev_status;
8901
8902	BWN_LOCK(sc);
8903
8904	prev_status = mac->mac_status;
8905	if (prev_status >= BWN_MAC_STATUS_STARTED)
8906		bwn_core_stop(mac);
8907	if (prev_status >= BWN_MAC_STATUS_INITED)
8908		bwn_core_exit(mac);
8909
8910	if (prev_status >= BWN_MAC_STATUS_INITED) {
8911		error = bwn_core_init(mac);
8912		if (error)
8913			goto out;
8914	}
8915	if (prev_status >= BWN_MAC_STATUS_STARTED)
8916		bwn_core_start(mac);
8917out:
8918	if (error) {
8919		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8920		sc->sc_curmac = NULL;
8921	}
8922	BWN_UNLOCK(sc);
8923}
8924
8925static void
8926bwn_handle_fwpanic(struct bwn_mac *mac)
8927{
8928	struct bwn_softc *sc = mac->mac_sc;
8929	uint16_t reason;
8930
8931	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8932	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8933
8934	if (reason == BWN_FWPANIC_RESTART)
8935		bwn_restart(mac, "ucode panic");
8936}
8937
8938static void
8939bwn_load_beacon0(struct bwn_mac *mac)
8940{
8941
8942	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8943}
8944
8945static void
8946bwn_load_beacon1(struct bwn_mac *mac)
8947{
8948
8949	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8950}
8951
8952static uint32_t
8953bwn_jssi_read(struct bwn_mac *mac)
8954{
8955	uint32_t val = 0;
8956
8957	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8958	val <<= 16;
8959	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8960
8961	return (val);
8962}
8963
8964static void
8965bwn_noise_gensample(struct bwn_mac *mac)
8966{
8967	uint32_t jssi = 0x7f7f7f7f;
8968
8969	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8970	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8971	BWN_WRITE_4(mac, BWN_MACCMD,
8972	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8973}
8974
8975static int
8976bwn_dma_freeslot(struct bwn_dma_ring *dr)
8977{
8978	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8979
8980	return (dr->dr_numslots - dr->dr_usedslot);
8981}
8982
8983static int
8984bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8985{
8986	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8987
8988	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8989	    ("%s:%d: fail", __func__, __LINE__));
8990	if (slot == dr->dr_numslots - 1)
8991		return (0);
8992	return (slot + 1);
8993}
8994
8995static void
8996bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8997{
8998	struct bwn_mac *mac = dr->dr_mac;
8999	struct bwn_softc *sc = mac->mac_sc;
9000	struct bwn_dma *dma = &mac->mac_method.dma;
9001	struct bwn_dmadesc_generic *desc;
9002	struct bwn_dmadesc_meta *meta;
9003	struct bwn_rxhdr4 *rxhdr;
9004	struct ifnet *ifp = sc->sc_ifp;
9005	struct mbuf *m;
9006	uint32_t macstat;
9007	int32_t tmp;
9008	int cnt = 0;
9009	uint16_t len;
9010
9011	dr->getdesc(dr, *slot, &desc, &meta);
9012
9013	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9014	m = meta->mt_m;
9015
9016	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9017		ifp->if_ierrors++;
9018		return;
9019	}
9020
9021	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9022	len = le16toh(rxhdr->frame_len);
9023	if (len <= 0) {
9024		ifp->if_ierrors++;
9025		return;
9026	}
9027	if (bwn_dma_check_redzone(dr, m)) {
9028		device_printf(sc->sc_dev, "redzone error.\n");
9029		bwn_dma_set_redzone(dr, m);
9030		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9031		    BUS_DMASYNC_PREWRITE);
9032		return;
9033	}
9034	if (len > dr->dr_rx_bufsize) {
9035		tmp = len;
9036		while (1) {
9037			dr->getdesc(dr, *slot, &desc, &meta);
9038			bwn_dma_set_redzone(dr, meta->mt_m);
9039			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9040			    BUS_DMASYNC_PREWRITE);
9041			*slot = bwn_dma_nextslot(dr, *slot);
9042			cnt++;
9043			tmp -= dr->dr_rx_bufsize;
9044			if (tmp <= 0)
9045				break;
9046		}
9047		device_printf(sc->sc_dev, "too small buffer "
9048		       "(len %u buffer %u dropped %d)\n",
9049		       len, dr->dr_rx_bufsize, cnt);
9050		return;
9051	}
9052	macstat = le32toh(rxhdr->mac_status);
9053	if (macstat & BWN_RX_MAC_FCSERR) {
9054		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9055			device_printf(sc->sc_dev, "RX drop\n");
9056			return;
9057		}
9058	}
9059
9060	m->m_pkthdr.rcvif = ifp;
9061	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9062	m_adj(m, dr->dr_frameoffset);
9063
9064	bwn_rxeof(dr->dr_mac, m, rxhdr);
9065}
9066
9067static void
9068bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9069{
9070	struct bwn_dma_ring *dr;
9071	struct bwn_dmadesc_generic *desc;
9072	struct bwn_dmadesc_meta *meta;
9073	struct bwn_node *bn;
9074	struct bwn_pio_txqueue *tq;
9075	struct bwn_pio_txpkt *tp = NULL;
9076	struct bwn_softc *sc = mac->mac_sc;
9077	struct bwn_stats *stats = &mac->mac_stats;
9078	struct ieee80211_node *ni;
9079	int slot;
9080
9081	BWN_ASSERT_LOCKED(mac->mac_sc);
9082
9083	if (status->im)
9084		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9085	if (status->ampdu)
9086		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9087	if (status->rtscnt) {
9088		if (status->rtscnt == 0xf)
9089			stats->rtsfail++;
9090		else
9091			stats->rts++;
9092	}
9093
9094	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9095		if (status->ack) {
9096			dr = bwn_dma_parse_cookie(mac, status,
9097			    status->cookie, &slot);
9098			if (dr == NULL) {
9099				device_printf(sc->sc_dev,
9100				    "failed to parse cookie\n");
9101				return;
9102			}
9103			while (1) {
9104				dr->getdesc(dr, slot, &desc, &meta);
9105				if (meta->mt_islast) {
9106					ni = meta->mt_ni;
9107					bn = (struct bwn_node *)ni;
9108					ieee80211_amrr_tx_complete(&bn->bn_amn,
9109					    status->ack, 0);
9110					break;
9111				}
9112				slot = bwn_dma_nextslot(dr, slot);
9113			}
9114		}
9115		bwn_dma_handle_txeof(mac, status);
9116	} else {
9117		if (status->ack) {
9118			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9119			if (tq == NULL) {
9120				device_printf(sc->sc_dev,
9121				    "failed to parse cookie\n");
9122				return;
9123			}
9124			ni = tp->tp_ni;
9125			bn = (struct bwn_node *)ni;
9126			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9127		}
9128		bwn_pio_handle_txeof(mac, status);
9129	}
9130
9131	bwn_phy_txpower_check(mac, 0);
9132}
9133
9134static uint8_t
9135bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9136{
9137	struct bwn_mac *mac = prq->prq_mac;
9138	struct bwn_softc *sc = mac->mac_sc;
9139	struct bwn_rxhdr4 rxhdr;
9140	struct ifnet *ifp = sc->sc_ifp;
9141	struct mbuf *m;
9142	uint32_t ctl32, macstat, v32;
9143	unsigned int i, padding;
9144	uint16_t ctl16, len, v16;
9145	unsigned char *mp;
9146	char *data;
9147
9148	memset(&rxhdr, 0, sizeof(rxhdr));
9149
9150	if (prq->prq_rev >= 8) {
9151		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9152		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9153			return (0);
9154		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9155		    BWN_PIO8_RXCTL_FRAMEREADY);
9156		for (i = 0; i < 10; i++) {
9157			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9158			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9159				goto ready;
9160			DELAY(10);
9161		}
9162	} else {
9163		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9164		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9165			return (0);
9166		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9167		    BWN_PIO_RXCTL_FRAMEREADY);
9168		for (i = 0; i < 10; i++) {
9169			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9170			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9171				goto ready;
9172			DELAY(10);
9173		}
9174	}
9175	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9176	return (1);
9177ready:
9178	if (prq->prq_rev >= 8)
9179		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9180		    prq->prq_base + BWN_PIO8_RXDATA);
9181	else
9182		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9183		    prq->prq_base + BWN_PIO_RXDATA);
9184	len = le16toh(rxhdr.frame_len);
9185	if (len > 0x700) {
9186		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9187		goto error;
9188	}
9189	if (len == 0) {
9190		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9191		goto error;
9192	}
9193
9194	macstat = le32toh(rxhdr.mac_status);
9195	if (macstat & BWN_RX_MAC_FCSERR) {
9196		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9197			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9198			goto error;
9199		}
9200	}
9201
9202	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9203	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9204	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9205	if (m == NULL) {
9206		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9207		goto error;
9208	}
9209	mp = mtod(m, unsigned char *);
9210	if (prq->prq_rev >= 8) {
9211		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9212		    prq->prq_base + BWN_PIO8_RXDATA);
9213		if (len & 3) {
9214			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9215			data = &(mp[len + padding - 1]);
9216			switch (len & 3) {
9217			case 3:
9218				*data = (v32 >> 16);
9219				data--;
9220			case 2:
9221				*data = (v32 >> 8);
9222				data--;
9223			case 1:
9224				*data = v32;
9225			}
9226		}
9227	} else {
9228		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9229		    prq->prq_base + BWN_PIO_RXDATA);
9230		if (len & 1) {
9231			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9232			mp[len + padding - 1] = v16;
9233		}
9234	}
9235
9236	m->m_pkthdr.rcvif = ifp;
9237	m->m_len = m->m_pkthdr.len = len + padding;
9238
9239	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9240
9241	return (1);
9242error:
9243	if (prq->prq_rev >= 8)
9244		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9245		    BWN_PIO8_RXCTL_DATAREADY);
9246	else
9247		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9248	return (1);
9249}
9250
9251static int
9252bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9253    struct bwn_dmadesc_meta *meta, int init)
9254{
9255	struct bwn_mac *mac = dr->dr_mac;
9256	struct bwn_dma *dma = &mac->mac_method.dma;
9257	struct bwn_rxhdr4 *hdr;
9258	bus_dmamap_t map;
9259	bus_addr_t paddr;
9260	struct mbuf *m;
9261	int error;
9262
9263	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9264	if (m == NULL) {
9265		error = ENOBUFS;
9266
9267		/*
9268		 * If the NIC is up and running, we need to:
9269		 * - Clear RX buffer's header.
9270		 * - Restore RX descriptor settings.
9271		 */
9272		if (init)
9273			return (error);
9274		else
9275			goto back;
9276	}
9277	m->m_len = m->m_pkthdr.len = MCLBYTES;
9278
9279	bwn_dma_set_redzone(dr, m);
9280
9281	/*
9282	 * Try to load RX buf into temporary DMA map
9283	 */
9284	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9285	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9286	if (error) {
9287		m_freem(m);
9288
9289		/*
9290		 * See the comment above
9291		 */
9292		if (init)
9293			return (error);
9294		else
9295			goto back;
9296	}
9297
9298	if (!init)
9299		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9300	meta->mt_m = m;
9301	meta->mt_paddr = paddr;
9302
9303	/*
9304	 * Swap RX buf's DMA map with the loaded temporary one
9305	 */
9306	map = meta->mt_dmap;
9307	meta->mt_dmap = dr->dr_spare_dmap;
9308	dr->dr_spare_dmap = map;
9309
9310back:
9311	/*
9312	 * Clear RX buf header
9313	 */
9314	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9315	bzero(hdr, sizeof(*hdr));
9316	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9317	    BUS_DMASYNC_PREWRITE);
9318
9319	/*
9320	 * Setup RX buf descriptor
9321	 */
9322	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9323	    sizeof(*hdr), 0, 0, 0);
9324	return (error);
9325}
9326
9327static void
9328bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9329		 bus_size_t mapsz __unused, int error)
9330{
9331
9332	if (!error) {
9333		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9334		*((bus_addr_t *)arg) = seg->ds_addr;
9335	}
9336}
9337
9338static int
9339bwn_hwrate2ieeerate(int rate)
9340{
9341
9342	switch (rate) {
9343	case BWN_CCK_RATE_1MB:
9344		return (2);
9345	case BWN_CCK_RATE_2MB:
9346		return (4);
9347	case BWN_CCK_RATE_5MB:
9348		return (11);
9349	case BWN_CCK_RATE_11MB:
9350		return (22);
9351	case BWN_OFDM_RATE_6MB:
9352		return (12);
9353	case BWN_OFDM_RATE_9MB:
9354		return (18);
9355	case BWN_OFDM_RATE_12MB:
9356		return (24);
9357	case BWN_OFDM_RATE_18MB:
9358		return (36);
9359	case BWN_OFDM_RATE_24MB:
9360		return (48);
9361	case BWN_OFDM_RATE_36MB:
9362		return (72);
9363	case BWN_OFDM_RATE_48MB:
9364		return (96);
9365	case BWN_OFDM_RATE_54MB:
9366		return (108);
9367	default:
9368		printf("Ooops\n");
9369		return (0);
9370	}
9371}
9372
9373static void
9374bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9375{
9376	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9377	struct bwn_plcp6 *plcp;
9378	struct bwn_softc *sc = mac->mac_sc;
9379	struct ieee80211_frame_min *wh;
9380	struct ieee80211_node *ni;
9381	struct ifnet *ifp = sc->sc_ifp;
9382	struct ieee80211com *ic = ifp->if_l2com;
9383	uint32_t macstat;
9384	int padding, rate, rssi = 0, noise = 0, type;
9385	uint16_t phytype, phystat0, phystat3, chanstat;
9386	unsigned char *mp = mtod(m, unsigned char *);
9387	static int rx_mac_dec_rpt = 0;
9388
9389	BWN_ASSERT_LOCKED(sc);
9390
9391	phystat0 = le16toh(rxhdr->phy_status0);
9392	phystat3 = le16toh(rxhdr->phy_status3);
9393	macstat = le32toh(rxhdr->mac_status);
9394	chanstat = le16toh(rxhdr->channel);
9395	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9396
9397	if (macstat & BWN_RX_MAC_FCSERR)
9398		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9399	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9400		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9401	if (macstat & BWN_RX_MAC_DECERR)
9402		goto drop;
9403
9404	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9405	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9406		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9407		    m->m_pkthdr.len);
9408		goto drop;
9409	}
9410	plcp = (struct bwn_plcp6 *)(mp + padding);
9411	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9412	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9413		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9414		    m->m_pkthdr.len);
9415		goto drop;
9416	}
9417	wh = mtod(m, struct ieee80211_frame_min *);
9418
9419	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9420		device_printf(sc->sc_dev,
9421		    "RX decryption attempted (old %d keyidx %#x)\n",
9422		    BWN_ISOLDFMT(mac),
9423		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9424
9425	/* XXX calculating RSSI & noise & antenna */
9426
9427	if (phystat0 & BWN_RX_PHYST0_OFDM)
9428		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9429		    phytype == BWN_PHYTYPE_A);
9430	else
9431		rate = bwn_plcp_get_cckrate(mac, plcp);
9432	if (rate == -1) {
9433		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9434			goto drop;
9435	}
9436	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9437
9438	/* RX radio tap */
9439	if (ieee80211_radiotap_active(ic))
9440		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9441	m_adj(m, -IEEE80211_CRC_LEN);
9442
9443	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9444	noise = mac->mac_stats.link_noise;
9445
9446	BWN_UNLOCK(sc);
9447
9448	ni = ieee80211_find_rxnode(ic, wh);
9449	if (ni != NULL) {
9450		type = ieee80211_input(ni, m, rssi, noise);
9451		ieee80211_free_node(ni);
9452	} else
9453		type = ieee80211_input_all(ic, m, rssi, noise);
9454
9455	BWN_LOCK(sc);
9456	return;
9457drop:
9458	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9459}
9460
9461static void
9462bwn_dma_handle_txeof(struct bwn_mac *mac,
9463    const struct bwn_txstatus *status)
9464{
9465	struct bwn_dma *dma = &mac->mac_method.dma;
9466	struct bwn_dma_ring *dr;
9467	struct bwn_dmadesc_generic *desc;
9468	struct bwn_dmadesc_meta *meta;
9469	struct bwn_softc *sc = mac->mac_sc;
9470	struct ieee80211_node *ni;
9471	struct ifnet *ifp = sc->sc_ifp;
9472	struct mbuf *m;
9473	int slot;
9474
9475	BWN_ASSERT_LOCKED(sc);
9476
9477	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9478	if (dr == NULL) {
9479		device_printf(sc->sc_dev, "failed to parse cookie\n");
9480		return;
9481	}
9482	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9483
9484	while (1) {
9485		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9486		    ("%s:%d: fail", __func__, __LINE__));
9487		dr->getdesc(dr, slot, &desc, &meta);
9488
9489		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9490			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9491		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9492			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9493
9494		if (meta->mt_islast) {
9495			KASSERT(meta->mt_m != NULL,
9496			    ("%s:%d: fail", __func__, __LINE__));
9497
9498			ni = meta->mt_ni;
9499			m = meta->mt_m;
9500			if (ni != NULL) {
9501				/*
9502				 * Do any tx complete callback. Note this must
9503				 * be done before releasing the node reference.
9504				 */
9505				if (m->m_flags & M_TXCB)
9506					ieee80211_process_callback(ni, m, 0);
9507				ieee80211_free_node(ni);
9508				meta->mt_ni = NULL;
9509			}
9510			m_freem(m);
9511			meta->mt_m = NULL;
9512		} else {
9513			KASSERT(meta->mt_m == NULL,
9514			    ("%s:%d: fail", __func__, __LINE__));
9515		}
9516
9517		dr->dr_usedslot--;
9518		if (meta->mt_islast) {
9519			ifp->if_opackets++;
9520			break;
9521		}
9522		slot = bwn_dma_nextslot(dr, slot);
9523	}
9524	sc->sc_watchdog_timer = 0;
9525	if (dr->dr_stop) {
9526		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9527		    ("%s:%d: fail", __func__, __LINE__));
9528		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9529		dr->dr_stop = 0;
9530	}
9531}
9532
9533static void
9534bwn_pio_handle_txeof(struct bwn_mac *mac,
9535    const struct bwn_txstatus *status)
9536{
9537	struct bwn_pio_txqueue *tq;
9538	struct bwn_pio_txpkt *tp = NULL;
9539	struct bwn_softc *sc = mac->mac_sc;
9540	struct ifnet *ifp = sc->sc_ifp;
9541
9542	BWN_ASSERT_LOCKED(sc);
9543
9544	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9545	if (tq == NULL)
9546		return;
9547
9548	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9549	tq->tq_free++;
9550
9551	if (tp->tp_ni != NULL) {
9552		/*
9553		 * Do any tx complete callback.  Note this must
9554		 * be done before releasing the node reference.
9555		 */
9556		if (tp->tp_m->m_flags & M_TXCB)
9557			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9558		ieee80211_free_node(tp->tp_ni);
9559		tp->tp_ni = NULL;
9560	}
9561	m_freem(tp->tp_m);
9562	tp->tp_m = NULL;
9563	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9564
9565	ifp->if_opackets++;
9566
9567	sc->sc_watchdog_timer = 0;
9568	if (tq->tq_stop) {
9569		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9570		tq->tq_stop = 0;
9571	}
9572}
9573
9574static void
9575bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9576{
9577	struct bwn_softc *sc = mac->mac_sc;
9578	struct bwn_phy *phy = &mac->mac_phy;
9579	struct ifnet *ifp = sc->sc_ifp;
9580	struct ieee80211com *ic = ifp->if_l2com;
9581	struct siba_softc *siba = mac->mac_sd->sd_bus;
9582	unsigned long now;
9583	int result;
9584
9585	BWN_GETTIME(now);
9586
9587	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9588		return;
9589	phy->nexttime = now + 2 * 1000;
9590
9591	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9592	    siba->siba_board_type == SIBA_BOARD_BU4306)
9593		return;
9594
9595	if (phy->recalc_txpwr != NULL) {
9596		result = phy->recalc_txpwr(mac,
9597		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9598		if (result == BWN_TXPWR_RES_DONE)
9599			return;
9600		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9601		    ("%s: fail", __func__));
9602		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9603
9604		ieee80211_runtask(ic, &mac->mac_txpower);
9605	}
9606}
9607
9608static uint16_t
9609bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9610{
9611
9612	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9613}
9614
9615static uint32_t
9616bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9617{
9618
9619	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9620}
9621
9622static void
9623bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9624{
9625
9626	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9627}
9628
9629static void
9630bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9631{
9632
9633	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9634}
9635
9636static int
9637bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9638{
9639
9640	switch (rate) {
9641	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9642	case 12:
9643		return (BWN_OFDM_RATE_6MB);
9644	case 18:
9645		return (BWN_OFDM_RATE_9MB);
9646	case 24:
9647		return (BWN_OFDM_RATE_12MB);
9648	case 36:
9649		return (BWN_OFDM_RATE_18MB);
9650	case 48:
9651		return (BWN_OFDM_RATE_24MB);
9652	case 72:
9653		return (BWN_OFDM_RATE_36MB);
9654	case 96:
9655		return (BWN_OFDM_RATE_48MB);
9656	case 108:
9657		return (BWN_OFDM_RATE_54MB);
9658	/* CCK rates (NB: not IEEE std, device-specific) */
9659	case 2:
9660		return (BWN_CCK_RATE_1MB);
9661	case 4:
9662		return (BWN_CCK_RATE_2MB);
9663	case 11:
9664		return (BWN_CCK_RATE_5MB);
9665	case 22:
9666		return (BWN_CCK_RATE_11MB);
9667	}
9668
9669	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9670	return (BWN_CCK_RATE_1MB);
9671}
9672
9673static int
9674bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9675    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9676{
9677	const struct bwn_phy *phy = &mac->mac_phy;
9678	struct bwn_softc *sc = mac->mac_sc;
9679	struct ieee80211_frame *wh;
9680	struct ieee80211_frame *protwh;
9681	struct ieee80211_frame_cts *cts;
9682	struct ieee80211_frame_rts *rts;
9683	const struct ieee80211_txparam *tp;
9684	struct ieee80211vap *vap = ni->ni_vap;
9685	struct ifnet *ifp = sc->sc_ifp;
9686	struct ieee80211com *ic = ifp->if_l2com;
9687	struct mbuf *mprot;
9688	unsigned int len;
9689	uint32_t macctl = 0;
9690	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9691	uint16_t phyctl = 0;
9692	uint8_t rate, rate_fb;
9693
9694	wh = mtod(m, struct ieee80211_frame *);
9695	memset(txhdr, 0, sizeof(*txhdr));
9696
9697	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9698	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9699	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9700
9701	/*
9702	 * Find TX rate
9703	 */
9704	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9705	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9706		rate = rate_fb = tp->mgmtrate;
9707	else if (ismcast)
9708		rate = rate_fb = tp->mcastrate;
9709	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9710		rate = rate_fb = tp->ucastrate;
9711	else {
9712		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9713		rate = ni->ni_txrate;
9714
9715		if (rix > 0)
9716			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9717			    IEEE80211_RATE_VAL;
9718		else
9719			rate_fb = rate;
9720	}
9721
9722	sc->sc_tx_rate = rate;
9723
9724	rate = bwn_ieeerate2hwrate(sc, rate);
9725	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9726
9727	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9728	    bwn_plcp_getcck(rate);
9729	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9730	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9731
9732	if ((rate_fb == rate) ||
9733	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9734	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9735		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9736	else
9737		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9738		    m->m_pkthdr.len, rate, isshort);
9739
9740	/* XXX TX encryption */
9741	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9742	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9743	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9744	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9745	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9746	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9747
9748	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9749	    BWN_TX_EFT_FB_CCK;
9750	txhdr->chan = phy->chan;
9751	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9752	    BWN_TX_PHY_ENC_CCK;
9753	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9754	     rate == BWN_CCK_RATE_11MB))
9755		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9756
9757	/* XXX TX antenna selection */
9758
9759	switch (bwn_antenna_sanitize(mac, 0)) {
9760	case 0:
9761		phyctl |= BWN_TX_PHY_ANT01AUTO;
9762		break;
9763	case 1:
9764		phyctl |= BWN_TX_PHY_ANT0;
9765		break;
9766	case 2:
9767		phyctl |= BWN_TX_PHY_ANT1;
9768		break;
9769	case 3:
9770		phyctl |= BWN_TX_PHY_ANT2;
9771		break;
9772	case 4:
9773		phyctl |= BWN_TX_PHY_ANT3;
9774		break;
9775	default:
9776		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9777	}
9778
9779	if (!ismcast)
9780		macctl |= BWN_TX_MAC_ACK;
9781
9782	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9783	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9784	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9785		macctl |= BWN_TX_MAC_LONGFRAME;
9786
9787	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9788		/* XXX RTS rate is always 1MB??? */
9789		rts_rate = BWN_CCK_RATE_1MB;
9790		rts_rate_fb = bwn_get_fbrate(rts_rate);
9791
9792		protdur = ieee80211_compute_duration(ic->ic_rt,
9793		    m->m_pkthdr.len, rate, isshort) +
9794		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9795
9796		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9797			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9798			    (txhdr->body.old.rts_frame) :
9799			    (txhdr->body.new.rts_frame));
9800			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9801			    protdur);
9802			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9803			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9804			    mprot->m_pkthdr.len);
9805			m_freem(mprot);
9806			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9807			len = sizeof(struct ieee80211_frame_cts);
9808		} else {
9809			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9810			    (txhdr->body.old.rts_frame) :
9811			    (txhdr->body.new.rts_frame));
9812			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9813			    isshort);
9814			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9815			    wh->i_addr2, protdur);
9816			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9817			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9818			    mprot->m_pkthdr.len);
9819			m_freem(mprot);
9820			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9821			len = sizeof(struct ieee80211_frame_rts);
9822		}
9823		len += IEEE80211_CRC_LEN;
9824		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9825		    &txhdr->body.old.rts_plcp :
9826		    &txhdr->body.new.rts_plcp), len, rts_rate);
9827		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9828		    rts_rate_fb);
9829
9830		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9831		    (&txhdr->body.old.rts_frame) :
9832		    (&txhdr->body.new.rts_frame));
9833		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9834
9835		if (BWN_ISOFDMRATE(rts_rate)) {
9836			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9837			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9838		} else {
9839			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9840			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9841		}
9842		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9843		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9844	}
9845
9846	if (BWN_ISOLDFMT(mac))
9847		txhdr->body.old.cookie = htole16(cookie);
9848	else
9849		txhdr->body.new.cookie = htole16(cookie);
9850
9851	txhdr->macctl = htole32(macctl);
9852	txhdr->phyctl = htole16(phyctl);
9853
9854	/*
9855	 * TX radio tap
9856	 */
9857	if (ieee80211_radiotap_active_vap(vap)) {
9858		sc->sc_tx_th.wt_flags = 0;
9859		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9860			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9861		if (isshort &&
9862		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9863		     rate == BWN_CCK_RATE_11MB))
9864			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9865		sc->sc_tx_th.wt_rate = rate;
9866
9867		ieee80211_radiotap_tx(vap, m);
9868	}
9869
9870	return (0);
9871}
9872
9873static void
9874bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9875    const uint8_t rate)
9876{
9877	uint32_t d, plen;
9878	uint8_t *raw = plcp->o.raw;
9879
9880	if (BWN_ISOFDMRATE(rate)) {
9881		d = bwn_plcp_getofdm(rate);
9882		KASSERT(!(octets & 0xf000),
9883		    ("%s:%d: fail", __func__, __LINE__));
9884		d |= (octets << 5);
9885		plcp->o.data = htole32(d);
9886	} else {
9887		plen = octets * 16 / rate;
9888		if ((octets * 16 % rate) > 0) {
9889			plen++;
9890			if ((rate == BWN_CCK_RATE_11MB)
9891			    && ((octets * 8 % 11) < 4)) {
9892				raw[1] = 0x84;
9893			} else
9894				raw[1] = 0x04;
9895		} else
9896			raw[1] = 0x04;
9897		plcp->o.data |= htole32(plen << 16);
9898		raw[0] = bwn_plcp_getcck(rate);
9899	}
9900}
9901
9902static uint8_t
9903bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9904{
9905	uint8_t mask;
9906
9907	if (n == 0)
9908		return (0);
9909	if (mac->mac_phy.gmode)
9910		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9911	else
9912		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9913	if (!(mask & (1 << (n - 1))))
9914		return (0);
9915	return (n);
9916}
9917
9918static uint8_t
9919bwn_get_fbrate(uint8_t bitrate)
9920{
9921	switch (bitrate) {
9922	case BWN_CCK_RATE_1MB:
9923		return (BWN_CCK_RATE_1MB);
9924	case BWN_CCK_RATE_2MB:
9925		return (BWN_CCK_RATE_1MB);
9926	case BWN_CCK_RATE_5MB:
9927		return (BWN_CCK_RATE_2MB);
9928	case BWN_CCK_RATE_11MB:
9929		return (BWN_CCK_RATE_5MB);
9930	case BWN_OFDM_RATE_6MB:
9931		return (BWN_CCK_RATE_5MB);
9932	case BWN_OFDM_RATE_9MB:
9933		return (BWN_OFDM_RATE_6MB);
9934	case BWN_OFDM_RATE_12MB:
9935		return (BWN_OFDM_RATE_9MB);
9936	case BWN_OFDM_RATE_18MB:
9937		return (BWN_OFDM_RATE_12MB);
9938	case BWN_OFDM_RATE_24MB:
9939		return (BWN_OFDM_RATE_18MB);
9940	case BWN_OFDM_RATE_36MB:
9941		return (BWN_OFDM_RATE_24MB);
9942	case BWN_OFDM_RATE_48MB:
9943		return (BWN_OFDM_RATE_36MB);
9944	case BWN_OFDM_RATE_54MB:
9945		return (BWN_OFDM_RATE_48MB);
9946	}
9947	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9948	return (0);
9949}
9950
9951static uint32_t
9952bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9953    uint32_t ctl, const void *_data, int len)
9954{
9955	uint32_t value = 0;
9956	const uint8_t *data = _data;
9957
9958	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9959	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9960	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9961
9962	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9963	    tq->tq_base + BWN_PIO8_TXDATA);
9964	if (len & 3) {
9965		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9966		    BWN_PIO8_TXCTL_24_31);
9967		data = &(data[len - 1]);
9968		switch (len & 3) {
9969		case 3:
9970			ctl |= BWN_PIO8_TXCTL_16_23;
9971			value |= (uint32_t)(*data) << 16;
9972			data--;
9973		case 2:
9974			ctl |= BWN_PIO8_TXCTL_8_15;
9975			value |= (uint32_t)(*data) << 8;
9976			data--;
9977		case 1:
9978			value |= (uint32_t)(*data);
9979		}
9980		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9981		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9982	}
9983
9984	return (ctl);
9985}
9986
9987static void
9988bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9989    uint16_t offset, uint32_t value)
9990{
9991
9992	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9993}
9994
9995static uint16_t
9996bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9997    uint16_t ctl, const void *_data, int len)
9998{
9999	const uint8_t *data = _data;
10000
10001	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10002	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10003
10004	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10005	    tq->tq_base + BWN_PIO_TXDATA);
10006	if (len & 1) {
10007		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10008		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10009		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10010	}
10011
10012	return (ctl);
10013}
10014
10015static uint16_t
10016bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10017    uint16_t ctl, struct mbuf *m0)
10018{
10019	int i, j = 0;
10020	uint16_t data = 0;
10021	const uint8_t *buf;
10022	struct mbuf *m = m0;
10023
10024	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10025	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10026
10027	for (; m != NULL; m = m->m_next) {
10028		buf = mtod(m, const uint8_t *);
10029		for (i = 0; i < m->m_len; i++) {
10030			if (!((j++) % 2))
10031				data |= buf[i];
10032			else {
10033				data |= (buf[i] << 8);
10034				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10035				data = 0;
10036			}
10037		}
10038	}
10039	if (m0->m_pkthdr.len % 2) {
10040		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10041		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10042		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10043	}
10044
10045	return (ctl);
10046}
10047
10048static void
10049bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10050{
10051
10052	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10053		return;
10054	BWN_WRITE_2(mac, 0x684, 510 + time);
10055	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10056}
10057
10058static struct bwn_dma_ring *
10059bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10060{
10061
10062	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10063		return (mac->mac_method.dma.wme[WME_AC_BE]);
10064
10065	switch (prio) {
10066	case 3:
10067		return (mac->mac_method.dma.wme[WME_AC_VO]);
10068	case 2:
10069		return (mac->mac_method.dma.wme[WME_AC_VI]);
10070	case 0:
10071		return (mac->mac_method.dma.wme[WME_AC_BE]);
10072	case 1:
10073		return (mac->mac_method.dma.wme[WME_AC_BK]);
10074	}
10075	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10076	return (NULL);
10077}
10078
10079static int
10080bwn_dma_getslot(struct bwn_dma_ring *dr)
10081{
10082	int slot;
10083
10084	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10085
10086	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10087	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10088	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10089
10090	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10091	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10092	dr->dr_curslot = slot;
10093	dr->dr_usedslot++;
10094
10095	return (slot);
10096}
10097
10098static int
10099bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10100{
10101	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10102	unsigned int a, b, c, d;
10103	unsigned int avg;
10104	uint32_t tmp;
10105
10106	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10107	a = tmp & 0xff;
10108	b = (tmp >> 8) & 0xff;
10109	c = (tmp >> 16) & 0xff;
10110	d = (tmp >> 24) & 0xff;
10111	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10112	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10113		return (ENOENT);
10114	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10115	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10116	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10117
10118	if (ofdm) {
10119		a = (a + 32) & 0x3f;
10120		b = (b + 32) & 0x3f;
10121		c = (c + 32) & 0x3f;
10122		d = (d + 32) & 0x3f;
10123	}
10124
10125	avg = (a + b + c + d + 2) / 4;
10126	if (ofdm) {
10127		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10128		    & BWN_HF_4DB_CCK_POWERBOOST)
10129			avg = (avg >= 13) ? (avg - 13) : 0;
10130	}
10131	return (avg);
10132}
10133
10134static void
10135bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10136{
10137	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10138	int rfatt = *rfattp;
10139	int bbatt = *bbattp;
10140
10141	while (1) {
10142		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10143			break;
10144		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10145			break;
10146		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10147			break;
10148		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10149			break;
10150		if (bbatt > lo->bbatt.max) {
10151			bbatt -= 4;
10152			rfatt += 1;
10153			continue;
10154		}
10155		if (bbatt < lo->bbatt.min) {
10156			bbatt += 4;
10157			rfatt -= 1;
10158			continue;
10159		}
10160		if (rfatt > lo->rfatt.max) {
10161			rfatt -= 1;
10162			bbatt += 4;
10163			continue;
10164		}
10165		if (rfatt < lo->rfatt.min) {
10166			rfatt += 1;
10167			bbatt -= 4;
10168			continue;
10169		}
10170		break;
10171	}
10172
10173	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10174	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10175}
10176
10177static void
10178bwn_phy_lock(struct bwn_mac *mac)
10179{
10180	struct bwn_softc *sc = mac->mac_sc;
10181	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10182
10183	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10184	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10185
10186	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10187		bwn_psctl(mac, BWN_PS_AWAKE);
10188}
10189
10190static void
10191bwn_phy_unlock(struct bwn_mac *mac)
10192{
10193	struct bwn_softc *sc = mac->mac_sc;
10194	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10195
10196	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10197	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10198
10199	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10200		bwn_psctl(mac, 0);
10201}
10202
10203static void
10204bwn_rf_lock(struct bwn_mac *mac)
10205{
10206
10207	BWN_WRITE_4(mac, BWN_MACCTL,
10208	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10209	BWN_READ_4(mac, BWN_MACCTL);
10210	DELAY(10);
10211}
10212
10213static void
10214bwn_rf_unlock(struct bwn_mac *mac)
10215{
10216
10217	BWN_READ_2(mac, BWN_PHYVER);
10218	BWN_WRITE_4(mac, BWN_MACCTL,
10219	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10220}
10221
10222static struct bwn_pio_txqueue *
10223bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10224    struct bwn_pio_txpkt **pack)
10225{
10226	struct bwn_pio *pio = &mac->mac_method.pio;
10227	struct bwn_pio_txqueue *tq = NULL;
10228	unsigned int index;
10229
10230	switch (cookie & 0xf000) {
10231	case 0x1000:
10232		tq = &pio->wme[WME_AC_BK];
10233		break;
10234	case 0x2000:
10235		tq = &pio->wme[WME_AC_BE];
10236		break;
10237	case 0x3000:
10238		tq = &pio->wme[WME_AC_VI];
10239		break;
10240	case 0x4000:
10241		tq = &pio->wme[WME_AC_VO];
10242		break;
10243	case 0x5000:
10244		tq = &pio->mcast;
10245		break;
10246	}
10247	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10248	if (tq == NULL)
10249		return (NULL);
10250	index = (cookie & 0x0fff);
10251	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10252	if (index >= N(tq->tq_pkts))
10253		return (NULL);
10254	*pack = &tq->tq_pkts[index];
10255	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10256	return (tq);
10257}
10258
10259static void
10260bwn_txpwr(void *arg, int npending)
10261{
10262	struct bwn_mac *mac = arg;
10263	struct bwn_softc *sc = mac->mac_sc;
10264
10265	BWN_LOCK(sc);
10266	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10267	    mac->mac_phy.set_txpwr != NULL)
10268		mac->mac_phy.set_txpwr(mac);
10269	BWN_UNLOCK(sc);
10270}
10271
10272static void
10273bwn_task_15s(struct bwn_mac *mac)
10274{
10275	uint16_t reg;
10276
10277	if (mac->mac_fw.opensource) {
10278		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10279		if (reg) {
10280			bwn_restart(mac, "fw watchdog");
10281			return;
10282		}
10283		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10284	}
10285	if (mac->mac_phy.task_15s)
10286		mac->mac_phy.task_15s(mac);
10287
10288	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10289}
10290
10291static void
10292bwn_task_30s(struct bwn_mac *mac)
10293{
10294
10295	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10296		return;
10297	mac->mac_noise.noi_running = 1;
10298	mac->mac_noise.noi_nsamples = 0;
10299
10300	bwn_noise_gensample(mac);
10301}
10302
10303static void
10304bwn_task_60s(struct bwn_mac *mac)
10305{
10306
10307	if (mac->mac_phy.task_60s)
10308		mac->mac_phy.task_60s(mac);
10309	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10310}
10311
10312static void
10313bwn_tasks(void *arg)
10314{
10315	struct bwn_mac *mac = arg;
10316	struct bwn_softc *sc = mac->mac_sc;
10317
10318	BWN_ASSERT_LOCKED(sc);
10319	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10320		return;
10321
10322	if (mac->mac_task_state % 4 == 0)
10323		bwn_task_60s(mac);
10324	if (mac->mac_task_state % 2 == 0)
10325		bwn_task_30s(mac);
10326	bwn_task_15s(mac);
10327
10328	mac->mac_task_state++;
10329	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10330}
10331
10332static int
10333bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10334{
10335	struct bwn_softc *sc = mac->mac_sc;
10336
10337	KASSERT(a == 0, ("not support APHY\n"));
10338
10339	switch (plcp->o.raw[0] & 0xf) {
10340	case 0xb:
10341		return (BWN_OFDM_RATE_6MB);
10342	case 0xf:
10343		return (BWN_OFDM_RATE_9MB);
10344	case 0xa:
10345		return (BWN_OFDM_RATE_12MB);
10346	case 0xe:
10347		return (BWN_OFDM_RATE_18MB);
10348	case 0x9:
10349		return (BWN_OFDM_RATE_24MB);
10350	case 0xd:
10351		return (BWN_OFDM_RATE_36MB);
10352	case 0x8:
10353		return (BWN_OFDM_RATE_48MB);
10354	case 0xc:
10355		return (BWN_OFDM_RATE_54MB);
10356	}
10357	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10358	    plcp->o.raw[0] & 0xf);
10359	return (-1);
10360}
10361
10362static int
10363bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10364{
10365	struct bwn_softc *sc = mac->mac_sc;
10366
10367	switch (plcp->o.raw[0]) {
10368	case 0x0a:
10369		return (BWN_CCK_RATE_1MB);
10370	case 0x14:
10371		return (BWN_CCK_RATE_2MB);
10372	case 0x37:
10373		return (BWN_CCK_RATE_5MB);
10374	case 0x6e:
10375		return (BWN_CCK_RATE_11MB);
10376	}
10377	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10378	return (-1);
10379}
10380
10381static void
10382bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10383    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10384    int rssi, int noise)
10385{
10386	struct bwn_softc *sc = mac->mac_sc;
10387	const struct ieee80211_frame_min *wh;
10388	uint64_t tsf;
10389	uint16_t low_mactime_now;
10390
10391	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10392		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10393
10394	wh = mtod(m, const struct ieee80211_frame_min *);
10395	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10396		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10397
10398	bwn_tsf_read(mac, &tsf);
10399	low_mactime_now = tsf;
10400	tsf = tsf & ~0xffffULL;
10401	tsf += le16toh(rxhdr->mac_time);
10402	if (low_mactime_now < le16toh(rxhdr->mac_time))
10403		tsf -= 0x10000;
10404
10405	sc->sc_rx_th.wr_tsf = tsf;
10406	sc->sc_rx_th.wr_rate = rate;
10407	sc->sc_rx_th.wr_antsignal = rssi;
10408	sc->sc_rx_th.wr_antnoise = noise;
10409}
10410
10411static void
10412bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10413{
10414	uint32_t low, high;
10415
10416	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10417	    ("%s:%d: fail", __func__, __LINE__));
10418
10419	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10420	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10421	*tsf = high;
10422	*tsf <<= 32;
10423	*tsf |= low;
10424}
10425
10426static int
10427bwn_dma_attach(struct bwn_mac *mac)
10428{
10429	struct bwn_dma *dma = &mac->mac_method.dma;
10430	struct bwn_softc *sc = mac->mac_sc;
10431	struct siba_dev_softc *sd = mac->mac_sd;
10432	struct siba_softc *siba = sd->sd_bus;
10433	bus_addr_t lowaddr = 0;
10434	int error;
10435
10436	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10437		return (0);
10438
10439	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10440
10441	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10442
10443	dma->dmatype = bwn_dma_gettype(mac);
10444	if (dma->dmatype == BWN_DMA_30BIT)
10445		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10446	else if (dma->dmatype == BWN_DMA_32BIT)
10447		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10448	else
10449		lowaddr = BUS_SPACE_MAXADDR;
10450
10451	/*
10452	 * Create top level DMA tag
10453	 */
10454	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10455			       BWN_ALIGN, 0,		/* alignment, bounds */
10456			       lowaddr,			/* lowaddr */
10457			       BUS_SPACE_MAXADDR,	/* highaddr */
10458			       NULL, NULL,		/* filter, filterarg */
10459			       MAXBSIZE,		/* maxsize */
10460			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10461			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10462			       0,			/* flags */
10463			       NULL, NULL,		/* lockfunc, lockarg */
10464			       &dma->parent_dtag);
10465	if (error) {
10466		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10467		return (error);
10468	}
10469
10470	/*
10471	 * Create TX/RX mbuf DMA tag
10472	 */
10473	error = bus_dma_tag_create(dma->parent_dtag,
10474				1,
10475				0,
10476				BUS_SPACE_MAXADDR,
10477				BUS_SPACE_MAXADDR,
10478				NULL, NULL,
10479				MCLBYTES,
10480				1,
10481				BUS_SPACE_MAXSIZE_32BIT,
10482				0,
10483				NULL, NULL,
10484				&dma->rxbuf_dtag);
10485	if (error) {
10486		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10487		goto fail0;
10488	}
10489	error = bus_dma_tag_create(dma->parent_dtag,
10490				1,
10491				0,
10492				BUS_SPACE_MAXADDR,
10493				BUS_SPACE_MAXADDR,
10494				NULL, NULL,
10495				MCLBYTES,
10496				1,
10497				BUS_SPACE_MAXSIZE_32BIT,
10498				0,
10499				NULL, NULL,
10500				&dma->txbuf_dtag);
10501	if (error) {
10502		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10503		goto fail1;
10504	}
10505
10506	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10507	if (!dma->wme[WME_AC_BK])
10508		goto fail2;
10509
10510	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10511	if (!dma->wme[WME_AC_BE])
10512		goto fail3;
10513
10514	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10515	if (!dma->wme[WME_AC_VI])
10516		goto fail4;
10517
10518	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10519	if (!dma->wme[WME_AC_VO])
10520		goto fail5;
10521
10522	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10523	if (!dma->mcast)
10524		goto fail6;
10525	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10526	if (!dma->rx)
10527		goto fail7;
10528
10529	return (error);
10530
10531fail7:	bwn_dma_ringfree(&dma->mcast);
10532fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10533fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10534fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10535fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10536fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10537fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10538fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10539	return (error);
10540}
10541
10542static struct bwn_dma_ring *
10543bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10544    uint16_t cookie, int *slot)
10545{
10546	struct bwn_dma *dma = &mac->mac_method.dma;
10547	struct bwn_dma_ring *dr;
10548	struct bwn_softc *sc = mac->mac_sc;
10549
10550	BWN_ASSERT_LOCKED(mac->mac_sc);
10551
10552	switch (cookie & 0xf000) {
10553	case 0x1000:
10554		dr = dma->wme[WME_AC_BK];
10555		break;
10556	case 0x2000:
10557		dr = dma->wme[WME_AC_BE];
10558		break;
10559	case 0x3000:
10560		dr = dma->wme[WME_AC_VI];
10561		break;
10562	case 0x4000:
10563		dr = dma->wme[WME_AC_VO];
10564		break;
10565	case 0x5000:
10566		dr = dma->mcast;
10567		break;
10568	default:
10569		dr = NULL;
10570		KASSERT(0 == 1,
10571		    ("invalid cookie value %d", cookie & 0xf000));
10572	}
10573	*slot = (cookie & 0x0fff);
10574	if (*slot < 0 || *slot >= dr->dr_numslots) {
10575		/*
10576		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10577		 * that it occurs events which have same H/W sequence numbers.
10578		 * When it's occurred just prints a WARNING msgs and ignores.
10579		 */
10580		KASSERT(status->seq == dma->lastseq,
10581		    ("%s:%d: fail", __func__, __LINE__));
10582		device_printf(sc->sc_dev,
10583		    "out of slot ranges (0 < %d < %d)\n", *slot,
10584		    dr->dr_numslots);
10585		return (NULL);
10586	}
10587	dma->lastseq = status->seq;
10588	return (dr);
10589}
10590
10591static void
10592bwn_dma_stop(struct bwn_mac *mac)
10593{
10594	struct bwn_dma *dma;
10595
10596	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10597		return;
10598	dma = &mac->mac_method.dma;
10599
10600	bwn_dma_ringstop(&dma->rx);
10601	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10602	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10603	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10604	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10605	bwn_dma_ringstop(&dma->mcast);
10606}
10607
10608static void
10609bwn_dma_ringstop(struct bwn_dma_ring **dr)
10610{
10611
10612	if (dr == NULL)
10613		return;
10614
10615	bwn_dma_cleanup(*dr);
10616}
10617
10618static void
10619bwn_pio_stop(struct bwn_mac *mac)
10620{
10621	struct bwn_pio *pio;
10622
10623	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10624		return;
10625	pio = &mac->mac_method.pio;
10626
10627	bwn_destroy_queue_tx(&pio->mcast);
10628	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10629	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10630	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10631	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10632}
10633
10634static void
10635bwn_led_attach(struct bwn_mac *mac)
10636{
10637	struct bwn_softc *sc = mac->mac_sc;
10638	struct siba_softc *siba = mac->mac_sd->sd_bus;
10639	const uint8_t *led_act = NULL;
10640	uint16_t val[BWN_LED_MAX];
10641	int i;
10642
10643	sc->sc_led_idle = (2350 * hz) / 1000;
10644	sc->sc_led_blink = 1;
10645
10646	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10647		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10648			led_act = bwn_vendor_led_act[i].led_act;
10649			break;
10650		}
10651	}
10652	if (led_act == NULL)
10653		led_act = bwn_default_led_act;
10654
10655	val[0] = siba->siba_sprom.gpio0;
10656	val[1] = siba->siba_sprom.gpio1;
10657	val[2] = siba->siba_sprom.gpio2;
10658	val[3] = siba->siba_sprom.gpio3;
10659
10660	for (i = 0; i < BWN_LED_MAX; ++i) {
10661		struct bwn_led *led = &sc->sc_leds[i];
10662
10663		if (val[i] == 0xff) {
10664			led->led_act = led_act[i];
10665		} else {
10666			if (val[i] & BWN_LED_ACT_LOW)
10667				led->led_flags |= BWN_LED_F_ACTLOW;
10668			led->led_act = val[i] & BWN_LED_ACT_MASK;
10669		}
10670		led->led_mask = (1 << i);
10671
10672		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10673		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10674		    led->led_act == BWN_LED_ACT_BLINK) {
10675			led->led_flags |= BWN_LED_F_BLINK;
10676			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10677				led->led_flags |= BWN_LED_F_POLLABLE;
10678			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10679				led->led_flags |= BWN_LED_F_SLOW;
10680
10681			if (sc->sc_blink_led == NULL) {
10682				sc->sc_blink_led = led;
10683				if (led->led_flags & BWN_LED_F_SLOW)
10684					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10685			}
10686		}
10687
10688		DPRINTF(sc, BWN_DEBUG_LED,
10689		    "%dth led, act %d, lowact %d\n", i,
10690		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10691	}
10692	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10693}
10694
10695static __inline uint16_t
10696bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10697{
10698
10699	if (led->led_flags & BWN_LED_F_ACTLOW)
10700		on = !on;
10701	if (on)
10702		val |= led->led_mask;
10703	else
10704		val &= ~led->led_mask;
10705	return val;
10706}
10707
10708static void
10709bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10710{
10711	struct bwn_softc *sc = mac->mac_sc;
10712	struct ifnet *ifp = sc->sc_ifp;
10713	struct ieee80211com *ic = ifp->if_l2com;
10714	uint16_t val;
10715	int i;
10716
10717	if (nstate == IEEE80211_S_INIT) {
10718		callout_stop(&sc->sc_led_blink_ch);
10719		sc->sc_led_blinking = 0;
10720	}
10721
10722	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10723		return;
10724
10725	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10726	for (i = 0; i < BWN_LED_MAX; ++i) {
10727		struct bwn_led *led = &sc->sc_leds[i];
10728		int on;
10729
10730		if (led->led_act == BWN_LED_ACT_UNKN ||
10731		    led->led_act == BWN_LED_ACT_NULL)
10732			continue;
10733
10734		if ((led->led_flags & BWN_LED_F_BLINK) &&
10735		    nstate != IEEE80211_S_INIT)
10736			continue;
10737
10738		switch (led->led_act) {
10739		case BWN_LED_ACT_ON:    /* Always on */
10740			on = 1;
10741			break;
10742		case BWN_LED_ACT_OFF:   /* Always off */
10743		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10744			on = 0;
10745			break;
10746		default:
10747			on = 1;
10748			switch (nstate) {
10749			case IEEE80211_S_INIT:
10750				on = 0;
10751				break;
10752			case IEEE80211_S_RUN:
10753				if (led->led_act == BWN_LED_ACT_11G &&
10754				    ic->ic_curmode != IEEE80211_MODE_11G)
10755					on = 0;
10756				break;
10757			default:
10758				if (led->led_act == BWN_LED_ACT_ASSOC)
10759					on = 0;
10760				break;
10761			}
10762			break;
10763		}
10764
10765		val = bwn_led_onoff(led, val, on);
10766	}
10767	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10768}
10769
10770static void
10771bwn_led_event(struct bwn_mac *mac, int event)
10772{
10773	struct bwn_softc *sc = mac->mac_sc;
10774        struct bwn_led *led = sc->sc_blink_led;
10775        int rate;
10776
10777        if (event == BWN_LED_EVENT_POLL) {
10778                if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10779                        return;
10780                if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10781                        return;
10782        }
10783
10784        sc->sc_led_ticks = ticks;
10785        if (sc->sc_led_blinking)
10786                return;
10787
10788        switch (event) {
10789        case BWN_LED_EVENT_RX:
10790                rate = sc->sc_rx_rate;
10791                break;
10792        case BWN_LED_EVENT_TX:
10793                rate = sc->sc_tx_rate;
10794                break;
10795        case BWN_LED_EVENT_POLL:
10796                rate = 0;
10797                break;
10798        default:
10799                panic("unknown LED event %d\n", event);
10800                break;
10801        }
10802        bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10803            bwn_led_duration[rate].off_dur);
10804}
10805
10806static void
10807bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10808{
10809	struct bwn_softc *sc = mac->mac_sc;
10810        struct bwn_led *led = sc->sc_blink_led;
10811        uint16_t val;
10812
10813        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10814        val = bwn_led_onoff(led, val, 1);
10815        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10816
10817        if (led->led_flags & BWN_LED_F_SLOW) {
10818                BWN_LED_SLOWDOWN(on_dur);
10819                BWN_LED_SLOWDOWN(off_dur);
10820        }
10821
10822        sc->sc_led_blinking = 1;
10823        sc->sc_led_blink_offdur = off_dur;
10824
10825        callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10826}
10827
10828static void
10829bwn_led_blink_next(void *arg)
10830{
10831	struct bwn_mac *mac = arg;
10832        struct bwn_softc *sc = mac->mac_sc;
10833        uint16_t val;
10834
10835        val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10836        val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10837        BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10838
10839        callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10840            bwn_led_blink_end, mac);
10841}
10842
10843static void
10844bwn_led_blink_end(void *arg)
10845{
10846	struct bwn_mac *mac = arg;
10847        struct bwn_softc *sc = mac->mac_sc;
10848
10849        sc->sc_led_blinking = 0;
10850}
10851
10852static int
10853bwn_suspend(device_t dev)
10854{
10855	struct bwn_softc *sc = device_get_softc(dev);
10856
10857	bwn_stop(sc, 1);
10858	return (0);
10859}
10860
10861static int
10862bwn_resume(device_t dev)
10863{
10864	struct bwn_softc *sc = device_get_softc(dev);
10865	struct ifnet *ifp = sc->sc_ifp;
10866
10867	if (ifp->if_flags & IFF_UP)
10868		bwn_init(sc);
10869	return (0);
10870}
10871
10872static void
10873bwn_rfswitch(void *arg)
10874{
10875	struct bwn_softc *sc = arg;
10876	struct bwn_mac *mac = sc->sc_curmac;
10877	int cur = 0, prev = 0;
10878
10879	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10880	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10881
10882	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10883		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10884			& BWN_RF_HWENABLED_HI_MASK))
10885			cur = 1;
10886	} else {
10887		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10888		    & BWN_RF_HWENABLED_LO_MASK)
10889			cur = 1;
10890	}
10891
10892	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10893		prev = 1;
10894
10895	if (cur != prev) {
10896		if (cur)
10897			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10898		else
10899			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10900
10901		device_printf(sc->sc_dev,
10902		    "status of RF switch is changed to %s\n",
10903		    cur ? "ON" : "OFF");
10904		if (cur != mac->mac_phy.rf_on) {
10905			if (cur)
10906				bwn_rf_turnon(mac);
10907			else
10908				bwn_rf_turnoff(mac);
10909		}
10910	}
10911
10912	callout_schedule(&sc->sc_rfswitch_ch, hz);
10913}
10914
10915static void
10916bwn_phy_lp_init_pre(struct bwn_mac *mac)
10917{
10918	struct bwn_phy *phy = &mac->mac_phy;
10919	struct bwn_phy_lp *plp = &phy->phy_lp;
10920
10921	plp->plp_antenna = BWN_ANT_DEFAULT;
10922}
10923
10924static int
10925bwn_phy_lp_init(struct bwn_mac *mac)
10926{
10927	static const struct bwn_stxtable tables[] = {
10928		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10929		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10930		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10931		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10932		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10933		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10934		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10935		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10936		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10937		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10938		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10939		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10940		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10941		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10942		{ 2, 11, 0x40, 0, 0x0f }
10943	};
10944	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10945	struct bwn_softc *sc = mac->mac_sc;
10946	const struct bwn_stxtable *st;
10947	struct ifnet *ifp = sc->sc_ifp;
10948	struct ieee80211com *ic = ifp->if_l2com;
10949	int i, error;
10950	uint16_t tmp;
10951
10952	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10953	bwn_phy_lp_bbinit(mac);
10954
10955	/* initialize RF */
10956	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10957	DELAY(1);
10958	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10959	DELAY(1);
10960
10961	if (mac->mac_phy.rf_ver == 0x2062)
10962		bwn_phy_lp_b2062_init(mac);
10963	else {
10964		bwn_phy_lp_b2063_init(mac);
10965
10966		/* synchronize stx table. */
10967		for (i = 0; i < N(tables); i++) {
10968			st = &tables[i];
10969			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10970			tmp >>= st->st_rfshift;
10971			tmp <<= st->st_physhift;
10972			BWN_PHY_SETMASK(mac,
10973			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10974			    ~(st->st_mask << st->st_physhift), tmp);
10975		}
10976
10977		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10978		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10979	}
10980
10981	/* calibrate RC */
10982	if (mac->mac_phy.rev >= 2)
10983		bwn_phy_lp_rxcal_r2(mac);
10984	else if (!plp->plp_rccap) {
10985		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10986			bwn_phy_lp_rccal_r12(mac);
10987	} else
10988		bwn_phy_lp_set_rccap(mac);
10989
10990	error = bwn_phy_lp_switch_channel(mac, 7);
10991	if (error)
10992		device_printf(sc->sc_dev,
10993		    "failed to change channel 7 (%d)\n", error);
10994	bwn_phy_lp_txpctl_init(mac);
10995	bwn_phy_lp_calib(mac);
10996	return (0);
10997}
10998
10999static uint16_t
11000bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11001{
11002
11003	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11004	return (BWN_READ_2(mac, BWN_PHYDATA));
11005}
11006
11007static void
11008bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11009{
11010
11011	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11012	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11013}
11014
11015static void
11016bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11017    uint16_t set)
11018{
11019
11020	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11021	BWN_WRITE_2(mac, BWN_PHYDATA,
11022	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11023}
11024
11025static uint16_t
11026bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11027{
11028
11029	KASSERT(reg != 1, ("unaccessible register %d", reg));
11030	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11031		reg |= 0x100;
11032	if (mac->mac_phy.rev >= 2)
11033		reg |= 0x200;
11034	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11035	return BWN_READ_2(mac, BWN_RFDATALO);
11036}
11037
11038static void
11039bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11040{
11041
11042	KASSERT(reg != 1, ("unaccessible register %d", reg));
11043	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11044	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11045}
11046
11047static void
11048bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11049{
11050
11051	if (on) {
11052		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11053		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11054		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11055		return;
11056	}
11057
11058	if (mac->mac_phy.rev >= 2) {
11059		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11060		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11061		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11062		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11063		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11064		return;
11065	}
11066
11067	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11068	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11069	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11070	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11071}
11072
11073static int
11074bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11075{
11076	struct bwn_phy *phy = &mac->mac_phy;
11077	struct bwn_phy_lp *plp = &phy->phy_lp;
11078	int error;
11079
11080	if (phy->rf_ver == 0x2063) {
11081		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11082		if (error)
11083			return (error);
11084	} else {
11085		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11086		if (error)
11087			return (error);
11088		bwn_phy_lp_set_anafilter(mac, chan);
11089		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11090	}
11091
11092	plp->plp_chan = chan;
11093	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11094	return (0);
11095}
11096
11097static uint32_t
11098bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11099{
11100	struct bwn_softc *sc = mac->mac_sc;
11101	struct ifnet *ifp = sc->sc_ifp;
11102	struct ieee80211com *ic = ifp->if_l2com;
11103
11104	device_printf(sc->sc_dev, "correct?\n");
11105
11106	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11107}
11108
11109static void
11110bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11111{
11112	struct bwn_phy *phy = &mac->mac_phy;
11113	struct bwn_phy_lp *plp = &phy->phy_lp;
11114
11115	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11116		return;
11117
11118	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11119	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11120	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11121	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11122	plp->plp_antenna = antenna;
11123}
11124
11125static void
11126bwn_phy_lp_task_60s(struct bwn_mac *mac)
11127{
11128
11129	bwn_phy_lp_calib(mac);
11130}
11131
11132static void
11133bwn_phy_lp_readsprom(struct bwn_mac *mac)
11134{
11135	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11136	struct bwn_softc *sc = mac->mac_sc;
11137	struct ifnet *ifp = sc->sc_ifp;
11138	struct ieee80211com *ic = ifp->if_l2com;
11139	struct siba_dev_softc *sd = mac->mac_sd;
11140	struct siba_softc *siba = sd->sd_bus;
11141	struct siba_sprom *sprom = &siba->siba_sprom;
11142
11143	device_printf(sc->sc_dev, "XXX using %dghz\n",
11144	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11145
11146	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11147		plp->plp_txisoband_m = sprom->tri2g;
11148		plp->plp_bxarch = sprom->bxa2g;
11149		plp->plp_rxpwroffset = sprom->rxpo2g;
11150		plp->plp_rssivf = sprom->rssismf2g;
11151		plp->plp_rssivc = sprom->rssismc2g;
11152		plp->plp_rssigs = sprom->rssisav2g;
11153		return;
11154	}
11155
11156	plp->plp_txisoband_l = sprom->tri5gl;
11157	plp->plp_txisoband_m = sprom->tri5g;
11158	plp->plp_txisoband_h = sprom->tri5gh;
11159	plp->plp_bxarch = sprom->bxa5g;
11160	plp->plp_rxpwroffset = sprom->rxpo5g;
11161	plp->plp_rssivf = sprom->rssismf5g;
11162	plp->plp_rssivc = sprom->rssismc5g;
11163	plp->plp_rssigs = sprom->rssisav5g;
11164}
11165
11166static void
11167bwn_phy_lp_bbinit(struct bwn_mac *mac)
11168{
11169
11170	bwn_phy_lp_tblinit(mac);
11171	if (mac->mac_phy.rev >= 2)
11172		bwn_phy_lp_bbinit_r2(mac);
11173	else
11174		bwn_phy_lp_bbinit_r01(mac);
11175}
11176
11177static void
11178bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11179{
11180	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11181	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11182	struct bwn_softc *sc = mac->mac_sc;
11183	struct ifnet *ifp = sc->sc_ifp;
11184	struct ieee80211com *ic = ifp->if_l2com;
11185
11186	bwn_phy_lp_set_txgain(mac,
11187	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11188	bwn_phy_lp_set_bbmult(mac, 150);
11189}
11190
11191static void
11192bwn_phy_lp_calib(struct bwn_mac *mac)
11193{
11194	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11195	struct siba_dev_softc *sd = mac->mac_sd;
11196	struct siba_softc *siba = sd->sd_bus;
11197	struct bwn_softc *sc = mac->mac_sc;
11198	struct ifnet *ifp = sc->sc_ifp;
11199	struct ieee80211com *ic = ifp->if_l2com;
11200	const struct bwn_rxcompco *rc = NULL;
11201	struct bwn_txgain ogain;
11202	int i, omode, oafeovr, orf, obbmult;
11203	uint8_t mode, fc = 0;
11204
11205	if (plp->plp_chanfullcal != plp->plp_chan) {
11206		plp->plp_chanfullcal = plp->plp_chan;
11207		fc = 1;
11208	}
11209
11210	bwn_mac_suspend(mac);
11211
11212	/* BlueTooth Coexistance Override */
11213	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11214	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11215
11216	if (mac->mac_phy.rev >= 2)
11217		bwn_phy_lp_digflt_save(mac);
11218	bwn_phy_lp_get_txpctlmode(mac);
11219	mode = plp->plp_txpctlmode;
11220	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11221	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11222		bwn_phy_lp_bugfix(mac);
11223	if (mac->mac_phy.rev >= 2 && fc == 1) {
11224		bwn_phy_lp_get_txpctlmode(mac);
11225		omode = plp->plp_txpctlmode;
11226		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11227		if (oafeovr)
11228			ogain = bwn_phy_lp_get_txgain(mac);
11229		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11230		obbmult = bwn_phy_lp_get_bbmult(mac);
11231		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11232		if (oafeovr)
11233			bwn_phy_lp_set_txgain(mac, &ogain);
11234		bwn_phy_lp_set_bbmult(mac, obbmult);
11235		bwn_phy_lp_set_txpctlmode(mac, omode);
11236		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11237	}
11238	bwn_phy_lp_set_txpctlmode(mac, mode);
11239	if (mac->mac_phy.rev >= 2)
11240		bwn_phy_lp_digflt_restore(mac);
11241
11242	/* do RX IQ Calculation; assumes that noise is true. */
11243	if (siba->siba_chipid == 0x5354) {
11244		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11245			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11246				rc = &bwn_rxcompco_5354[i];
11247		}
11248	} else if (mac->mac_phy.rev >= 2)
11249		rc = &bwn_rxcompco_r2;
11250	else {
11251		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11252			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11253				rc = &bwn_rxcompco_r12[i];
11254		}
11255	}
11256	if (rc == NULL)
11257		goto fail;
11258
11259	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11260	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11261
11262	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11263
11264	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11265		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11266		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11267	} else {
11268		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11269		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11270	}
11271
11272	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11273	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11274	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11275	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11276	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11277	bwn_phy_lp_set_deaf(mac, 0);
11278	/* XXX no checking return value? */
11279	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11280	bwn_phy_lp_clear_deaf(mac, 0);
11281	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11282	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11283	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11284
11285	/* disable RX GAIN override. */
11286	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11287	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11288	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11289	if (mac->mac_phy.rev >= 2) {
11290		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11291		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11292			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11293			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11294		}
11295	} else {
11296		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11297	}
11298
11299	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11300	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11301fail:
11302	bwn_mac_enable(mac);
11303}
11304
11305static void
11306bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11307{
11308
11309       if (on) {
11310               BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11311	       return;
11312       }
11313
11314       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11315       BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11316}
11317
11318static int
11319bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11320{
11321	struct siba_dev_softc *sd = mac->mac_sd;
11322	struct siba_softc *siba = sd->sd_bus;
11323	static const struct bwn_b206x_chan *bc = NULL;
11324	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11325	    tmp[6];
11326	uint16_t old, scale, tmp16;
11327	int i, div;
11328
11329	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11330		if (bwn_b2063_chantable[i].bc_chan == chan) {
11331			bc = &bwn_b2063_chantable[i];
11332			break;
11333		}
11334	}
11335	if (bc == NULL)
11336		return (EINVAL);
11337
11338	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11339	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11340	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11341	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11342	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11343	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11344	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11345	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11346	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11347	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11348	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11349	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11350
11351	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11352	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11353
11354	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11355	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11356	freqref = freqxtal * 3;
11357	div = (freqxtal <= 26000000 ? 1 : 2);
11358	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11359	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11360		999999) / 1000000) + 1;
11361
11362	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11363	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11364	    0xfff8, timeout >> 2);
11365	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11366	    0xff9f,timeout << 5);
11367	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11368
11369	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11370	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11371	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11372
11373	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11374	    (timeoutref + 1)) - 1;
11375	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11376	    0xf0, count >> 8);
11377	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11378
11379	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11380	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11381	while (tmp[1] >= freqref) {
11382		tmp[0]++;
11383		tmp[1] -= freqref;
11384	}
11385	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11386	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11387	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11388	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11389	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11390
11391	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11392	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11393	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11394	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11395
11396	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11397	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11398
11399	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11400		scale = 1;
11401		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11402	} else {
11403		scale = 0;
11404		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11405	}
11406	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11407	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11408
11409	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11410	    (scale + 1);
11411	if (tmp[5] > 150)
11412		tmp[5] = 0;
11413
11414	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11415	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11416
11417	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11418	if (freqxtal > 26000000)
11419		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11420	else
11421		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11422
11423	if (val[0] == 45)
11424		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11425	else
11426		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11427
11428	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11429	DELAY(1);
11430	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11431
11432	/* VCO Calibration */
11433	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11434	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11435	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11436	DELAY(1);
11437	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11438	DELAY(1);
11439	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11440	DELAY(1);
11441	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11442	DELAY(300);
11443	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11444
11445	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11446	return (0);
11447}
11448
11449static int
11450bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11451{
11452	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11453	struct siba_dev_softc *sd = mac->mac_sd;
11454	struct siba_softc *siba = sd->sd_bus;
11455	const struct bwn_b206x_chan *bc = NULL;
11456	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11457	uint32_t tmp[9];
11458	int i;
11459
11460	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11461		if (bwn_b2062_chantable[i].bc_chan == chan) {
11462			bc = &bwn_b2062_chantable[i];
11463			break;
11464		}
11465	}
11466
11467	if (bc == NULL)
11468		return (EINVAL);
11469
11470	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11471	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11472	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11473	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11474	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11475	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11476	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11477	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11478	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11479	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11480
11481	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11482	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11483	bwn_phy_lp_b2062_reset_pllbias(mac);
11484	tmp[0] = freqxtal / 1000;
11485	tmp[1] = plp->plp_div * 1000;
11486	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11487	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11488		tmp[2] *= 2;
11489	tmp[3] = 48 * tmp[0];
11490	tmp[5] = tmp[2] / tmp[3];
11491	tmp[6] = tmp[2] % tmp[3];
11492	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11493	tmp[4] = tmp[6] * 0x100;
11494	tmp[5] = tmp[4] / tmp[3];
11495	tmp[6] = tmp[4] % tmp[3];
11496	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11497	tmp[4] = tmp[6] * 0x100;
11498	tmp[5] = tmp[4] / tmp[3];
11499	tmp[6] = tmp[4] % tmp[3];
11500	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11501	tmp[4] = tmp[6] * 0x100;
11502	tmp[5] = tmp[4] / tmp[3];
11503	tmp[6] = tmp[4] % tmp[3];
11504	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11505	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11506	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11507	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11508	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11509	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11510
11511	bwn_phy_lp_b2062_vco_calib(mac);
11512	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11513		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11514		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11515		bwn_phy_lp_b2062_reset_pllbias(mac);
11516		bwn_phy_lp_b2062_vco_calib(mac);
11517		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11518			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11519			return (EIO);
11520		}
11521	}
11522	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11523	return (0);
11524}
11525
11526static void
11527bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11528{
11529	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11530	uint16_t tmp = (channel == 14);
11531
11532	if (mac->mac_phy.rev < 2) {
11533		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11534		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11535			bwn_phy_lp_set_rccap(mac);
11536		return;
11537	}
11538
11539	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11540}
11541
11542static void
11543bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11544{
11545	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11546	struct bwn_softc *sc = mac->mac_sc;
11547	struct ifnet *ifp = sc->sc_ifp;
11548	struct ieee80211com *ic = ifp->if_l2com;
11549	uint16_t iso, tmp[3];
11550
11551	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11552
11553	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11554		iso = plp->plp_txisoband_m;
11555	else if (freq <= 5320)
11556		iso = plp->plp_txisoband_l;
11557	else if (freq <= 5700)
11558		iso = plp->plp_txisoband_m;
11559	else
11560		iso = plp->plp_txisoband_h;
11561
11562	tmp[0] = ((iso - 26) / 12) << 12;
11563	tmp[1] = tmp[0] + 0x1000;
11564	tmp[2] = tmp[0] + 0x2000;
11565
11566	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11567	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11568}
11569
11570static void
11571bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11572{
11573	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11574	int i;
11575	static const uint16_t addr[] = {
11576		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11577		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11578		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11579		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11580		BWN_PHY_OFDM(0xcf),
11581	};
11582	static const uint16_t val[] = {
11583		0xde5e, 0xe832, 0xe331, 0x4d26,
11584		0x0026, 0x1420, 0x0020, 0xfe08,
11585		0x0008,
11586	};
11587
11588	for (i = 0; i < N(addr); i++) {
11589		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11590		BWN_PHY_WRITE(mac, addr[i], val[i]);
11591	}
11592}
11593
11594static void
11595bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11596{
11597	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11598	struct bwn_softc *sc = mac->mac_sc;
11599	uint16_t ctl;
11600
11601	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11602	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11603	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11604		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11605		break;
11606	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11607		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11608		break;
11609	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11610		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11611		break;
11612	default:
11613		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11614		device_printf(sc->sc_dev, "unknown command mode\n");
11615		break;
11616	}
11617}
11618
11619static void
11620bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11621{
11622	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11623	uint16_t ctl;
11624	uint8_t old;
11625
11626	bwn_phy_lp_get_txpctlmode(mac);
11627	old = plp->plp_txpctlmode;
11628	if (old == mode)
11629		return;
11630	plp->plp_txpctlmode = mode;
11631
11632	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11633		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11634		    plp->plp_tssiidx);
11635		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11636		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11637
11638		/* disable TX GAIN override */
11639		if (mac->mac_phy.rev < 2)
11640			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11641		else {
11642			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11643			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11644		}
11645		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11646
11647		plp->plp_txpwridx = -1;
11648	}
11649	if (mac->mac_phy.rev >= 2) {
11650		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11651			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11652		else
11653			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11654	}
11655
11656	/* writes TX Power Control mode */
11657	switch (plp->plp_txpctlmode) {
11658	case BWN_PHYLP_TXPCTL_OFF:
11659		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11660		break;
11661	case BWN_PHYLP_TXPCTL_ON_HW:
11662		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11663		break;
11664	case BWN_PHYLP_TXPCTL_ON_SW:
11665		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11666		break;
11667	default:
11668		ctl = 0;
11669		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11670	}
11671	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11672	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11673}
11674
11675static void
11676bwn_phy_lp_bugfix(struct bwn_mac *mac)
11677{
11678	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11679	struct bwn_softc *sc = mac->mac_sc;
11680	const unsigned int size = 256;
11681	struct bwn_txgain tg;
11682	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11683	uint16_t tssinpt, tssiidx, value[2];
11684	uint8_t mode;
11685	int8_t txpwridx;
11686
11687	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11688	    M_NOWAIT | M_ZERO);
11689	if (tabs == NULL) {
11690		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11691		return;
11692	}
11693
11694	bwn_phy_lp_get_txpctlmode(mac);
11695	mode = plp->plp_txpctlmode;
11696	txpwridx = plp->plp_txpwridx;
11697	tssinpt = plp->plp_tssinpt;
11698	tssiidx = plp->plp_tssiidx;
11699
11700	bwn_tab_read_multi(mac,
11701	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11702	    BWN_TAB_4(7, 0x140), size, tabs);
11703
11704	bwn_phy_lp_tblinit(mac);
11705	bwn_phy_lp_bbinit(mac);
11706	bwn_phy_lp_txpctl_init(mac);
11707	bwn_phy_lp_rf_onoff(mac, 1);
11708	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11709
11710	bwn_tab_write_multi(mac,
11711	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11712	    BWN_TAB_4(7, 0x140), size, tabs);
11713
11714	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11715	plp->plp_tssinpt = tssinpt;
11716	plp->plp_tssiidx = tssiidx;
11717	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11718	if (txpwridx != -1) {
11719		/* set TX power by index */
11720		plp->plp_txpwridx = txpwridx;
11721		bwn_phy_lp_get_txpctlmode(mac);
11722		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11723			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11724		if (mac->mac_phy.rev >= 2) {
11725			rxcomp = bwn_tab_read(mac,
11726			    BWN_TAB_4(7, txpwridx + 320));
11727			txgain = bwn_tab_read(mac,
11728			    BWN_TAB_4(7, txpwridx + 192));
11729			tg.tg_pad = (txgain >> 16) & 0xff;
11730			tg.tg_gm = txgain & 0xff;
11731			tg.tg_pga = (txgain >> 8) & 0xff;
11732			tg.tg_dac = (rxcomp >> 28) & 0xff;
11733			bwn_phy_lp_set_txgain(mac, &tg);
11734		} else {
11735			rxcomp = bwn_tab_read(mac,
11736			    BWN_TAB_4(10, txpwridx + 320));
11737			txgain = bwn_tab_read(mac,
11738			    BWN_TAB_4(10, txpwridx + 192));
11739			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11740			    0xf800, (txgain >> 4) & 0x7fff);
11741			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11742			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11743		}
11744		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11745
11746		/* set TX IQCC */
11747		value[0] = (rxcomp >> 10) & 0x3ff;
11748		value[1] = rxcomp & 0x3ff;
11749		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11750
11751		coeff = bwn_tab_read(mac,
11752		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11753		    BWN_TAB_4(10, txpwridx + 448));
11754		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11755		if (mac->mac_phy.rev >= 2) {
11756			rfpwr = bwn_tab_read(mac,
11757			    BWN_TAB_4(7, txpwridx + 576));
11758			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11759			    rfpwr & 0xffff);
11760		}
11761		bwn_phy_lp_set_txgain_override(mac);
11762	}
11763	if (plp->plp_rccap)
11764		bwn_phy_lp_set_rccap(mac);
11765	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11766	bwn_phy_lp_set_txpctlmode(mac, mode);
11767	free(tabs, M_DEVBUF);
11768}
11769
11770static void
11771bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11772{
11773	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11774	int i;
11775	static const uint16_t addr[] = {
11776		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11777		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11778		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11779		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11780		BWN_PHY_OFDM(0xcf),
11781	};
11782
11783	for (i = 0; i < N(addr); i++)
11784		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11785}
11786
11787static void
11788bwn_phy_lp_tblinit(struct bwn_mac *mac)
11789{
11790	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11791
11792	if (mac->mac_phy.rev < 2) {
11793		bwn_phy_lp_tblinit_r01(mac);
11794		bwn_phy_lp_tblinit_txgain(mac);
11795		bwn_phy_lp_set_gaintbl(mac, freq);
11796		return;
11797	}
11798
11799	bwn_phy_lp_tblinit_r2(mac);
11800	bwn_phy_lp_tblinit_txgain(mac);
11801}
11802
11803struct bwn_wpair {
11804	uint16_t		reg;
11805	uint16_t		value;
11806};
11807
11808struct bwn_smpair {
11809	uint16_t		offset;
11810	uint16_t		mask;
11811	uint16_t		set;
11812};
11813
11814static void
11815bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11816{
11817	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11818	struct siba_dev_softc *sd = mac->mac_sd;
11819	struct siba_softc *siba = sd->sd_bus;
11820	struct bwn_softc *sc = mac->mac_sc;
11821	struct ifnet *ifp = sc->sc_ifp;
11822	struct ieee80211com *ic = ifp->if_l2com;
11823	static const struct bwn_wpair v1[] = {
11824		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11825		{ BWN_PHY_AFE_CTL, 0x8800 },
11826		{ BWN_PHY_AFE_CTL_OVR, 0 },
11827		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11828		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11829		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11830		{ BWN_PHY_OFDM(0xf9), 0 },
11831		{ BWN_PHY_TR_LOOKUP_1, 0 }
11832	};
11833	static const struct bwn_smpair v2[] = {
11834		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11835		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11836		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11837		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11838		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11839	};
11840	static const struct bwn_smpair v3[] = {
11841		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11842		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11843		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11844		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11845		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11846		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11847		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11848		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11849		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11850		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11851
11852	};
11853	int i;
11854
11855	for (i = 0; i < N(v1); i++)
11856		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11857	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11858	for (i = 0; i < N(v2); i++)
11859		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11860
11861	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11862	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11863	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11864	if (siba->siba_board_rev >= 0x18) {
11865		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11866		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11867	} else {
11868		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11869	}
11870	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11871	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11872	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11873	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11874	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11875	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11876	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11877	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11878	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11879	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11880	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11881	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11882		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11883		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11884	} else {
11885		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11886		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11887	}
11888	for (i = 0; i < N(v3); i++)
11889		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11890	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11891		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11892		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11893	}
11894
11895	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11896		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11897		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11898		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11899		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11900		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11901		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11902	} else
11903		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11904
11905	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11906	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11907	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11908	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11909	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11910	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11911	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11912	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11913	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11914
11915	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11916		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11917		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11918		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11919	}
11920
11921	bwn_phy_lp_digflt_save(mac);
11922}
11923
11924static void
11925bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11926{
11927	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11928	struct siba_dev_softc *sd = mac->mac_sd;
11929	struct siba_softc *siba = sd->sd_bus;
11930	struct bwn_softc *sc = mac->mac_sc;
11931	struct ifnet *ifp = sc->sc_ifp;
11932	struct ieee80211com *ic = ifp->if_l2com;
11933	static const struct bwn_smpair v1[] = {
11934		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11935		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11936		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11937		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11938		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11939		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11940		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11941	};
11942	static const struct bwn_smpair v2[] = {
11943		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11944		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11945		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11946		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11947		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11948		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11949		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11950		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11951		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11952		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11953		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11954		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11955		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11956		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11957		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11958		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11959	};
11960	static const struct bwn_smpair v3[] = {
11961		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11962		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11963		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11964		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11965		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11966		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11967		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11968		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11969	};
11970	static const struct bwn_smpair v4[] = {
11971		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11972		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11973		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11974		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11975		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11976		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11977		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11978		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11979	};
11980	static const struct bwn_smpair v5[] = {
11981		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11982		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11983		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11984		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11985		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11986		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11987		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11988		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11989	};
11990	int i;
11991	uint16_t tmp, tmp2;
11992
11993	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11994	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11995	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11996	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11997	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11998	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11999	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
12000	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12001	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12002	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12003	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12004	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12005	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12006	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12007	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12008	for (i = 0; i < N(v1); i++)
12009		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12010	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12011	    0xff00, plp->plp_rxpwroffset);
12012	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12013	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12014	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12015		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12016		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12017		if (mac->mac_phy.rev == 0)
12018			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12019			    0xffcf, 0x0010);
12020		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12021	} else {
12022		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12023		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12024		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12025	}
12026	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12027	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12028	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12029		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12030	else
12031		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12032	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12033	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12034	    0xfff9, (plp->plp_bxarch << 1));
12035	if (mac->mac_phy.rev == 1 &&
12036	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12037		for (i = 0; i < N(v2); i++)
12038			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12039			    v2[i].set);
12040	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12041	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12042	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12043		for (i = 0; i < N(v3); i++)
12044			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12045			    v3[i].set);
12046	} else if (mac->mac_phy.rev == 1 ||
12047		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12048		for (i = 0; i < N(v4); i++)
12049			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12050			    v4[i].set);
12051	} else {
12052		for (i = 0; i < N(v5); i++)
12053			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12054			    v5[i].set);
12055	}
12056	if (mac->mac_phy.rev == 1 &&
12057	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12058		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12059		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12060		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12061		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12062	}
12063	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12064	    (siba->siba_chipid == 0x5354) &&
12065	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12066		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12067		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12068		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12069		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12070	}
12071	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12072		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12073		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12074		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12075		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12076		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12077		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12078		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12079		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12080	} else {
12081		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12082		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12083	}
12084	if (mac->mac_phy.rev == 1) {
12085		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12086		tmp2 = (tmp & 0x03e0) >> 5;
12087		tmp2 |= tmp2 << 5;
12088		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12089		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12090		tmp2 = (tmp & 0x1f00) >> 8;
12091		tmp2 |= tmp2 << 5;
12092		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12093		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12094		tmp2 = tmp & 0x00ff;
12095		tmp2 |= tmp << 8;
12096		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12097	}
12098}
12099
12100struct bwn_b2062_freq {
12101	uint16_t		freq;
12102	uint8_t			value[6];
12103};
12104
12105static void
12106bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12107{
12108#define	CALC_CTL7(freq, div)						\
12109	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12110#define	CALC_CTL18(freq, div)						\
12111	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12112#define	CALC_CTL19(freq, div)						\
12113	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12114	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12115	struct siba_dev_softc *sd = mac->mac_sd;
12116	struct siba_softc *siba = sd->sd_bus;
12117	struct bwn_softc *sc = mac->mac_sc;
12118	struct ifnet *ifp = sc->sc_ifp;
12119	struct ieee80211com *ic = ifp->if_l2com;
12120	static const struct bwn_b2062_freq freqdata_tab[] = {
12121		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12122		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12123		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12124		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12125		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12126		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12127	};
12128	static const struct bwn_wpair v1[] = {
12129		{ BWN_B2062_N_TXCTL3, 0 },
12130		{ BWN_B2062_N_TXCTL4, 0 },
12131		{ BWN_B2062_N_TXCTL5, 0 },
12132		{ BWN_B2062_N_TXCTL6, 0 },
12133		{ BWN_B2062_N_PDNCTL0, 0x40 },
12134		{ BWN_B2062_N_PDNCTL0, 0 },
12135		{ BWN_B2062_N_CALIB_TS, 0x10 },
12136		{ BWN_B2062_N_CALIB_TS, 0 }
12137	};
12138	const struct bwn_b2062_freq *f = NULL;
12139	uint32_t xtalfreq, ref;
12140	unsigned int i;
12141
12142	bwn_phy_lp_b2062_tblinit(mac);
12143
12144	for (i = 0; i < N(v1); i++)
12145		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12146	if (mac->mac_phy.rev > 0)
12147		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12148		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12149	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12150		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12151	else
12152		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12153
12154	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12155	    ("%s:%d: fail", __func__, __LINE__));
12156	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12157	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12158
12159	if (xtalfreq <= 30000000) {
12160		plp->plp_div = 1;
12161		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12162	} else {
12163		plp->plp_div = 2;
12164		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12165	}
12166
12167	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12168	    CALC_CTL7(xtalfreq, plp->plp_div));
12169	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12170	    CALC_CTL18(xtalfreq, plp->plp_div));
12171	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12172	    CALC_CTL19(xtalfreq, plp->plp_div));
12173
12174	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12175	ref &= 0xffff;
12176	for (i = 0; i < N(freqdata_tab); i++) {
12177		if (ref < freqdata_tab[i].freq) {
12178			f = &freqdata_tab[i];
12179			break;
12180		}
12181	}
12182	if (f == NULL)
12183		f = &freqdata_tab[N(freqdata_tab) - 1];
12184	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12185	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12186	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12187	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12188	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12189	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12190#undef CALC_CTL7
12191#undef CALC_CTL18
12192#undef CALC_CTL19
12193}
12194
12195static void
12196bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12197{
12198
12199	bwn_phy_lp_b2063_tblinit(mac);
12200	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12201	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12202	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12203	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12204	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12205	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12206	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12207	if (mac->mac_phy.rev == 2) {
12208		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12209		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12210		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12211	} else {
12212		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12213		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12214	}
12215}
12216
12217static void
12218bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12219{
12220	struct siba_dev_softc *sd = mac->mac_sd;
12221	struct siba_softc *siba = sd->sd_bus;
12222	static const struct bwn_wpair v1[] = {
12223		{ BWN_B2063_RX_BB_SP8, 0x0 },
12224		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12225		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12226		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12227		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12228		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12229		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12230		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12231	};
12232	static const struct bwn_wpair v2[] = {
12233		{ BWN_B2063_TX_BB_SP3, 0x0 },
12234		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12235		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12236		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12237		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12238	};
12239	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12240	int i;
12241	uint8_t tmp;
12242
12243	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12244
12245	for (i = 0; i < 2; i++)
12246		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12247	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12248	for (i = 2; i < N(v1); i++)
12249		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12250	for (i = 0; i < 10000; i++) {
12251		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12252			break;
12253		DELAY(1000);
12254	}
12255
12256	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12257		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12258
12259	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12260
12261	for (i = 0; i < N(v2); i++)
12262		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12263	if (freqxtal == 24000000) {
12264		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12265		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12266	} else {
12267		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12268		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12269	}
12270	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12271	for (i = 0; i < 10000; i++) {
12272		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12273			break;
12274		DELAY(1000);
12275	}
12276	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12277		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12278	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12279}
12280
12281static void
12282bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12283{
12284	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12285	struct bwn_softc *sc = mac->mac_sc;
12286	struct bwn_phy_lp_iq_est ie;
12287	struct bwn_txgain tx_gains;
12288	static const uint32_t pwrtbl[21] = {
12289		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12290		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12291		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12292		0x0004c, 0x0002c, 0x0001a,
12293	};
12294	uint32_t npwr, ipwr, sqpwr, tmp;
12295	int loopback, i, j, sum, error;
12296	uint16_t save[7];
12297	uint8_t txo, bbmult, txpctlmode;
12298
12299	error = bwn_phy_lp_switch_channel(mac, 7);
12300	if (error)
12301		device_printf(sc->sc_dev,
12302		    "failed to change channel to 7 (%d)\n", error);
12303	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12304	bbmult = bwn_phy_lp_get_bbmult(mac);
12305	if (txo)
12306		tx_gains = bwn_phy_lp_get_txgain(mac);
12307
12308	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12309	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12310	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12311	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12312	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12313	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12314	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12315
12316	bwn_phy_lp_get_txpctlmode(mac);
12317	txpctlmode = plp->plp_txpctlmode;
12318	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12319
12320	/* disable CRS */
12321	bwn_phy_lp_set_deaf(mac, 1);
12322	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12323	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12324	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12325	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12326	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12327	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12328	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12329	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12330	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12331	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12332	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12333	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12334	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12335	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12336	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12337	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12338	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12339	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12340	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12341	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12342	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12343	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12344	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12345	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12346
12347	loopback = bwn_phy_lp_loopback(mac);
12348	if (loopback == -1)
12349		goto done;
12350	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12351	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12352	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12353	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12354	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12355
12356	tmp = 0;
12357	memset(&ie, 0, sizeof(ie));
12358	for (i = 128; i <= 159; i++) {
12359		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12360		sum = 0;
12361		for (j = 5; j <= 25; j++) {
12362			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12363			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12364				goto done;
12365			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12366			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12367			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12368			    12);
12369			sum += ((ipwr - npwr) * (ipwr - npwr));
12370			if ((i == 128) || (sum < tmp)) {
12371				plp->plp_rccap = i;
12372				tmp = sum;
12373			}
12374		}
12375	}
12376	bwn_phy_lp_ddfs_turnoff(mac);
12377done:
12378	/* restore CRS */
12379	bwn_phy_lp_clear_deaf(mac, 1);
12380	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12381	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12382
12383	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12384	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12385	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12386	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12387	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12388	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12389	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12390
12391	bwn_phy_lp_set_bbmult(mac, bbmult);
12392	if (txo)
12393		bwn_phy_lp_set_txgain(mac, &tx_gains);
12394	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12395	if (plp->plp_rccap)
12396		bwn_phy_lp_set_rccap(mac);
12397}
12398
12399static void
12400bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12401{
12402	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12403	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12404
12405	if (mac->mac_phy.rev == 1)
12406		rc_cap = MIN(rc_cap + 5, 15);
12407
12408	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12409	    MAX(plp->plp_rccap - 4, 0x80));
12410	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12411	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12412	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12413}
12414
12415static uint32_t
12416bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12417{
12418	uint32_t i, q, r;
12419
12420	if (div == 0)
12421		return (0);
12422
12423	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12424		q <<= 1;
12425		if (r << 1 >= div) {
12426			q++;
12427			r = (r << 1) - div;
12428		}
12429	}
12430	if (r << 1 >= div)
12431		q++;
12432	return (q);
12433}
12434
12435static void
12436bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12437{
12438	struct siba_dev_softc *sd = mac->mac_sd;
12439	struct siba_softc *siba = sd->sd_bus;
12440
12441	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12442	DELAY(20);
12443	if (siba->siba_chipid == 0x5354) {
12444		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12445		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12446	} else {
12447		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12448	}
12449	DELAY(5);
12450}
12451
12452static void
12453bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12454{
12455
12456	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12457	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12458	DELAY(200);
12459}
12460
12461static void
12462bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12463{
12464#define	FLAG_A	0x01
12465#define	FLAG_G	0x02
12466	struct bwn_softc *sc = mac->mac_sc;
12467	struct ifnet *ifp = sc->sc_ifp;
12468	struct ieee80211com *ic = ifp->if_l2com;
12469	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12470		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12471		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12472		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12473		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12474		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12475		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12476		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12477		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12478		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12479		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12480		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12481		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12482		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12483		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12484		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12485		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12486		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12487		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12488		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12489		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12490		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12491		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12492		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12493		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12494		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12495		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12496		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12497		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12498		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12499		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12500		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12501		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12502		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12503		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12504		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12505		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12506		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12507		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12508		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12509		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12510		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12511		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12512		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12513		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12514		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12515		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12516		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12517	};
12518	const struct bwn_b206x_rfinit_entry *br;
12519	unsigned int i;
12520
12521	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12522		br = &bwn_b2062_init_tab[i];
12523		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12524			if (br->br_flags & FLAG_G)
12525				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12526		} else {
12527			if (br->br_flags & FLAG_A)
12528				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12529		}
12530	}
12531#undef FLAG_A
12532#undef FLAG_B
12533}
12534
12535static void
12536bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12537{
12538#define	FLAG_A	0x01
12539#define	FLAG_G	0x02
12540	struct bwn_softc *sc = mac->mac_sc;
12541	struct ifnet *ifp = sc->sc_ifp;
12542	struct ieee80211com *ic = ifp->if_l2com;
12543	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12544		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12545		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12546		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12547		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12548		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12549		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12550		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12551		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12552		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12553		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12554		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12555		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12556		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12557		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12558		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12559		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12560		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12561		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12562		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12563		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12564		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12565		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12566		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12567		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12568		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12569		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12570		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12571		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12572		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12573		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12574		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12575		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12576		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12577		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12578		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12579		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12580		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12581		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12582		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12583		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12584		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12585		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12586	};
12587	const struct bwn_b206x_rfinit_entry *br;
12588	unsigned int i;
12589
12590	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12591		br = &bwn_b2063_init_tab[i];
12592		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12593			if (br->br_flags & FLAG_G)
12594				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12595		} else {
12596			if (br->br_flags & FLAG_A)
12597				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12598		}
12599	}
12600#undef FLAG_A
12601#undef FLAG_B
12602}
12603
12604static void
12605bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12606    int count, void *_data)
12607{
12608	unsigned int i;
12609	uint32_t offset, type;
12610	uint8_t *data = _data;
12611
12612	type = BWN_TAB_GETTYPE(typenoffset);
12613	offset = BWN_TAB_GETOFFSET(typenoffset);
12614	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12615
12616	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12617
12618	for (i = 0; i < count; i++) {
12619		switch (type) {
12620		case BWN_TAB_8BIT:
12621			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12622			data++;
12623			break;
12624		case BWN_TAB_16BIT:
12625			*((uint16_t *)data) = BWN_PHY_READ(mac,
12626			    BWN_PHY_TABLEDATALO);
12627			data += 2;
12628			break;
12629		case BWN_TAB_32BIT:
12630			*((uint32_t *)data) = BWN_PHY_READ(mac,
12631			    BWN_PHY_TABLEDATAHI);
12632			*((uint32_t *)data) <<= 16;
12633			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12634			    BWN_PHY_TABLEDATALO);
12635			data += 4;
12636			break;
12637		default:
12638			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12639		}
12640	}
12641}
12642
12643static void
12644bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12645    int count, const void *_data)
12646{
12647	uint32_t offset, type, value;
12648	const uint8_t *data = _data;
12649	unsigned int i;
12650
12651	type = BWN_TAB_GETTYPE(typenoffset);
12652	offset = BWN_TAB_GETOFFSET(typenoffset);
12653	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12654
12655	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12656
12657	for (i = 0; i < count; i++) {
12658		switch (type) {
12659		case BWN_TAB_8BIT:
12660			value = *data;
12661			data++;
12662			KASSERT(!(value & ~0xff),
12663			    ("%s:%d: fail", __func__, __LINE__));
12664			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12665			break;
12666		case BWN_TAB_16BIT:
12667			value = *((const uint16_t *)data);
12668			data += 2;
12669			KASSERT(!(value & ~0xffff),
12670			    ("%s:%d: fail", __func__, __LINE__));
12671			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12672			break;
12673		case BWN_TAB_32BIT:
12674			value = *((const uint32_t *)data);
12675			data += 4;
12676			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12677			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12678			break;
12679		default:
12680			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12681		}
12682	}
12683}
12684
12685static struct bwn_txgain
12686bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12687{
12688	struct bwn_txgain tg;
12689	uint16_t tmp;
12690
12691	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12692	if (mac->mac_phy.rev < 2) {
12693		tmp = BWN_PHY_READ(mac,
12694		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12695		tg.tg_gm = tmp & 0x0007;
12696		tg.tg_pga = (tmp & 0x0078) >> 3;
12697		tg.tg_pad = (tmp & 0x780) >> 7;
12698		return (tg);
12699	}
12700
12701	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12702	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12703	tg.tg_gm = tmp & 0xff;
12704	tg.tg_pga = (tmp >> 8) & 0xff;
12705	return (tg);
12706}
12707
12708static uint8_t
12709bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12710{
12711
12712	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12713}
12714
12715static void
12716bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12717{
12718	uint16_t pa;
12719
12720	if (mac->mac_phy.rev < 2) {
12721		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12722		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12723		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12724		bwn_phy_lp_set_txgain_override(mac);
12725		return;
12726	}
12727
12728	pa = bwn_phy_lp_get_pa_gain(mac);
12729	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12730	    (tg->tg_pga << 8) | tg->tg_gm);
12731	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12732	    tg->tg_pad | (pa << 6));
12733	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12734	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12735	    tg->tg_pad | (pa << 8));
12736	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12737	bwn_phy_lp_set_txgain_override(mac);
12738}
12739
12740static void
12741bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12742{
12743
12744	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12745}
12746
12747static void
12748bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12749{
12750	uint16_t trsw = (tx << 1) | rx;
12751
12752	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12753	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12754}
12755
12756static void
12757bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12758{
12759	struct bwn_softc *sc = mac->mac_sc;
12760	struct ifnet *ifp = sc->sc_ifp;
12761	struct ieee80211com *ic = ifp->if_l2com;
12762	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12763
12764	if (mac->mac_phy.rev < 2) {
12765		trsw = gain & 0x1;
12766		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12767		ext_lna = (gain & 2) >> 1;
12768
12769		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12770		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12771		    0xfbff, ext_lna << 10);
12772		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12773		    0xf7ff, ext_lna << 11);
12774		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12775	} else {
12776		low_gain = gain & 0xffff;
12777		high_gain = (gain >> 16) & 0xf;
12778		ext_lna = (gain >> 21) & 0x1;
12779		trsw = ~(gain >> 20) & 0x1;
12780
12781		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12782		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12783		    0xfdff, ext_lna << 9);
12784		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12785		    0xfbff, ext_lna << 10);
12786		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12787		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12788		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12789			tmp = (gain >> 2) & 0x3;
12790			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12791			    0xe7ff, tmp<<11);
12792			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12793			    tmp << 3);
12794		}
12795	}
12796
12797	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12798	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12799	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12800	if (mac->mac_phy.rev >= 2) {
12801		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12802		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12803			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12804			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12805		}
12806		return;
12807	}
12808	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12809}
12810
12811static void
12812bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12813{
12814	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12815
12816	if (user)
12817		plp->plp_crsusr_off = 1;
12818	else
12819		plp->plp_crssys_off = 1;
12820
12821	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12822}
12823
12824static void
12825bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12826{
12827	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12828	struct bwn_softc *sc = mac->mac_sc;
12829	struct ifnet *ifp = sc->sc_ifp;
12830	struct ieee80211com *ic = ifp->if_l2com;
12831
12832	if (user)
12833		plp->plp_crsusr_off = 0;
12834	else
12835		plp->plp_crssys_off = 0;
12836
12837	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12838		return;
12839
12840	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12841		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12842	else
12843		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12844}
12845
12846static unsigned int
12847bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12848{
12849	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12850	static uint8_t sqrt_table[256] = {
12851		10, 14, 17, 20, 22, 24, 26, 28,
12852		30, 31, 33, 34, 36, 37, 38, 40,
12853		41, 42, 43, 44, 45, 46, 47, 48,
12854		50, 50, 51, 52, 53, 54, 55, 56,
12855		57, 58, 59, 60, 60, 61, 62, 63,
12856		64, 64, 65, 66, 67, 67, 68, 69,
12857		70, 70, 71, 72, 72, 73, 74, 74,
12858		75, 76, 76, 77, 78, 78, 79, 80,
12859		80, 81, 81, 82, 83, 83, 84, 84,
12860		85, 86, 86, 87, 87, 88, 88, 89,
12861		90, 90, 91, 91, 92, 92, 93, 93,
12862		94, 94, 95, 95, 96, 96, 97, 97,
12863		98, 98, 99, 100, 100, 100, 101, 101,
12864		102, 102, 103, 103, 104, 104, 105, 105,
12865		106, 106, 107, 107, 108, 108, 109, 109,
12866		110, 110, 110, 111, 111, 112, 112, 113,
12867		113, 114, 114, 114, 115, 115, 116, 116,
12868		117, 117, 117, 118, 118, 119, 119, 120,
12869		120, 120, 121, 121, 122, 122, 122, 123,
12870		123, 124, 124, 124, 125, 125, 126, 126,
12871		126, 127, 127, 128, 128, 128, 129, 129,
12872		130, 130, 130, 131, 131, 131, 132, 132,
12873		133, 133, 133, 134, 134, 134, 135, 135,
12874		136, 136, 136, 137, 137, 137, 138, 138,
12875		138, 139, 139, 140, 140, 140, 141, 141,
12876		141, 142, 142, 142, 143, 143, 143, 144,
12877		144, 144, 145, 145, 145, 146, 146, 146,
12878		147, 147, 147, 148, 148, 148, 149, 149,
12879		150, 150, 150, 150, 151, 151, 151, 152,
12880		152, 152, 153, 153, 153, 154, 154, 154,
12881		155, 155, 155, 156, 156, 156, 157, 157,
12882		157, 158, 158, 158, 159, 159, 159, 160
12883	};
12884
12885	if (x == 0)
12886		return (0);
12887	if (x >= 256) {
12888		unsigned int tmp;
12889
12890		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12891			/* do nothing */ ;
12892		return (tmp);
12893	}
12894	return (sqrt_table[x - 1] / 10);
12895}
12896
12897static int
12898bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12899{
12900#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12901	int _t;								\
12902	_t = _x - 20;							\
12903	if (_t >= 0) {							\
12904		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12905	} else {							\
12906		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12907	}								\
12908} while (0)
12909#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12910	int _t;								\
12911	_t = _x - 11;							\
12912	if (_t >= 0)							\
12913		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12914	else								\
12915		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12916} while (0)
12917	struct bwn_phy_lp_iq_est ie;
12918	uint16_t v0, v1;
12919	int tmp[2], ret;
12920
12921	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12922	v0 = v1 >> 8;
12923	v1 |= 0xff;
12924
12925	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12926	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12927
12928	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12929	if (ret == 0)
12930		goto done;
12931
12932	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12933		ret = 0;
12934		goto done;
12935	}
12936
12937	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12938	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12939
12940	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12941	v0 = tmp[0] >> 3;
12942	v1 = tmp[1] >> 4;
12943done:
12944	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12945	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12946	return ret;
12947#undef CALC_COEFF
12948#undef CALC_COEFF2
12949}
12950
12951static void
12952bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12953{
12954	static const uint16_t noisescale[] = {
12955		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12956		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12957		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12958		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12959		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12960	};
12961	static const uint16_t crsgainnft[] = {
12962		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12963		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12964		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12965		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12966		0x013d,
12967	};
12968	static const uint16_t filterctl[] = {
12969		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12970		0xff53, 0x0127,
12971	};
12972	static const uint32_t psctl[] = {
12973		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12974		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12975		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12976		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12977		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12978		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12979		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12980		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12981	};
12982	static const uint16_t ofdmcckgain_r0[] = {
12983		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12984		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12985		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12986		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12987		0x755d,
12988	};
12989	static const uint16_t ofdmcckgain_r1[] = {
12990		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12991		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12992		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12993		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12994		0x755d,
12995	};
12996	static const uint16_t gaindelta[] = {
12997		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12998		0x0000,
12999	};
13000	static const uint32_t txpwrctl[] = {
13001		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13002		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13003		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13004		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13005		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13006		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13007		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13008		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13009		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13010		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13011		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13012		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13013		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13014		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13015		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13016		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13017		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13018		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13019		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13038		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13039		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13040		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13041		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13042		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13043		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13044		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13045		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13046		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13047		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13048		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13049		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13050		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13051		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13052		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13053		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13054		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13055		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13056		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13057		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13058		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13059		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13060		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13061		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13062		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13063		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13064		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13065		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13066		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13067		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13068		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13069		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13070		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13071		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13072		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13073		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13074		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13075		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13076		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13077		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13078		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13079		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13080		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13081		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13082		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13083		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13084		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13085		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13086		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13087		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13088		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13089		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13090		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13091		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13092		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13093		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13094		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13095		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13096		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13097		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13098		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13099		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13100		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13101		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13102		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13103		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13104		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13105		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13106		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13107		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13108		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13109		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13110		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13111		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13112		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13113		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13114		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13115		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13116		0x00000702,
13117	};
13118
13119	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13120
13121	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13122	    bwn_tab_sigsq_tbl);
13123	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13124	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13125	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13126	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13127	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13128	    bwn_tab_pllfrac_tbl);
13129	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13130	    bwn_tabl_iqlocal_tbl);
13131	if (mac->mac_phy.rev == 0) {
13132		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13133		    ofdmcckgain_r0);
13134		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13135		    ofdmcckgain_r0);
13136	} else {
13137		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13138		    ofdmcckgain_r1);
13139		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13140		    ofdmcckgain_r1);
13141	}
13142	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13143	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13144}
13145
13146static void
13147bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13148{
13149	struct siba_dev_softc *sd = mac->mac_sd;
13150	struct siba_softc *siba = sd->sd_bus;
13151	int i;
13152	static const uint16_t noisescale[] = {
13153		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13154		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13155		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13156		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13157		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13158		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13159		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13160	};
13161	static const uint32_t filterctl[] = {
13162		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13163		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13164	};
13165	static const uint32_t psctl[] = {
13166		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13167		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13168		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13169		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13170	};
13171	static const uint32_t gainidx[] = {
13172		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13173		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13174		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13175		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13176		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13177		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13178		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13179		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13180		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13181		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13182		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13183		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13184		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13185		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13186		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13187		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13188		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13189		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13190		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13191		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13192		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13193		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13194		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13195		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13196		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13197		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13198		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13199		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13200		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13201		0x0000001a, 0x64ca55ad, 0x0000001a
13202	};
13203	static const uint16_t auxgainidx[] = {
13204		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13205		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13206		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13207		0x0004, 0x0016
13208	};
13209	static const uint16_t swctl[] = {
13210		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13211		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13212		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13213		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13214		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13215		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13216		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13217		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13218	};
13219	static const uint8_t hf[] = {
13220		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13221		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13222	};
13223	static const uint32_t gainval[] = {
13224		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13225		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13226		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13227		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13228		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13230		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13231		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13232		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13233		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13234		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13235		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13236		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13237		0x000000f1, 0x00000000, 0x00000000
13238	};
13239	static const uint16_t gain[] = {
13240		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13241		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13242		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13243		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13244		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13245		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13246		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13250		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13251		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13252	};
13253	static const uint32_t papdeps[] = {
13254		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13255		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13256		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13257		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13258		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13259		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13260		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13261		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13262		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13263		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13264		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13265		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13266		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13267	};
13268	static const uint32_t papdmult[] = {
13269		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13270		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13271		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13272		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13273		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13274		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13275		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13276		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13277		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13278		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13279		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13280		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13281		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13282	};
13283	static const uint32_t gainidx_a0[] = {
13284		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13285		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13286		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13287		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13288		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13289		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13290		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13291		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13292		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13293		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13294		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13295		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13296		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13297	};
13298	static const uint16_t auxgainidx_a0[] = {
13299		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13300		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13301		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13302		0x0002, 0x0014
13303	};
13304	static const uint32_t gainval_a0[] = {
13305		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13306		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13307		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13308		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13309		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13310		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13311		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13312		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13313		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13314		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13315		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13316		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13317		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13318		0x000000f7, 0x00000000, 0x00000000
13319	};
13320	static const uint16_t gain_a0[] = {
13321		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13322		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13323		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13324		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13325		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13326		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13327		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13328		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13329		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13330		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13331		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13332		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13333	};
13334
13335	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13336
13337	for (i = 0; i < 704; i++)
13338		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13339
13340	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13341	    bwn_tab_sigsq_tbl);
13342	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13343	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13344	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13345	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13346	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13347	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13348	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13349	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13350	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13351	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13352	    bwn_tab_pllfrac_tbl);
13353	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13354	    bwn_tabl_iqlocal_tbl);
13355	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13356	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13357
13358	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13359		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13360		    gainidx_a0);
13361		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13362		    auxgainidx_a0);
13363		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13364		    gainval_a0);
13365		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13366	}
13367}
13368
13369static void
13370bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13371{
13372	struct siba_dev_softc *sd = mac->mac_sd;
13373	struct siba_softc *siba = sd->sd_bus;
13374	struct bwn_softc *sc = mac->mac_sc;
13375	struct ifnet *ifp = sc->sc_ifp;
13376	struct ieee80211com *ic = ifp->if_l2com;
13377	static struct bwn_txgain_entry txgain_r2[] = {
13378		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13379		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13380		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13381		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13382		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13383		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13384		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13385		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13386		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13387		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13388		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13389		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13390		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13391		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13392		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13393		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13394		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13395		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13396		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13397		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13398		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13399		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13400		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13401		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13402		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13403		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13404		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13405		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13406		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13407		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13408		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13409		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13410		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13411		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13412		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13413		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13414		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13415		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13416		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13417		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13418		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13419		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13420		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13421		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13422		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13423		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13424		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13425		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13426		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13427		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13428		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13429		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13430		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13431		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13432		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13433		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13434		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13435		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13436		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13437		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13438		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13439		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13440		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13441		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13442	};
13443	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13444		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13445		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13446		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13447		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13448		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13449		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13450		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13451		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13452		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13453		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13454		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13455		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13456		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13457		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13458		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13459		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13460		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13461		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13462		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13463		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13464		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13465		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13466		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13467		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13468		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13469		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13470		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13471		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13472		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13473		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13474		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13475		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13476		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13477		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13478		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13479		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13480		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13481		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13482		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13483		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13484		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13485		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13486		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13487		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13488		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13489		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13490		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13491		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13492		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13493		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13494		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13495		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13496		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13497		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13498		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13499		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13500		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13501		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13502		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13503		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13504		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13505		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13506		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13507		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13508	};
13509	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13510		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13511		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13512		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13513		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13514		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13515		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13516		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13517		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13518		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13519		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13520		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13521		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13522		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13523		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13524		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13525		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13526		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13527		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13528		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13529		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13530		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13531		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13532		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13533		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13534		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13535		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13536		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13537		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13538		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13539		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13540		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13541		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13542		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13543		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13544		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13545		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13546		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13547		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13548		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13549		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13550		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13551		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13552		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13553		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13554		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13555		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13556		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13557		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13558		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13559		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13560		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13561		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13562		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13563		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13564		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13565		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13566		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13567		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13568		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13569		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13570		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13571		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13572		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13573		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13574	};
13575	static struct bwn_txgain_entry txgain_r0[] = {
13576		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13577		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13578		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13579		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13580		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13581		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13582		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13583		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13584		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13585		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13586		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13587		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13588		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13589		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13590		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13591		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13592		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13593		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13594		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13595		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13596		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13597		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13598		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13599		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13600		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13601		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13602		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13603		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13604		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13605		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13606		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13607		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13608		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13609		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13610		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13611		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13612		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13613		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13614		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13615		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13616		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13617		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13618		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13619		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13620		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13621		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13622		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13623		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13624		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13625		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13626		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13627		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13628		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13629		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13630		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13631		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13632		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13633		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13634		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13635		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13636		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13637		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13638		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13639		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13640	};
13641	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13642		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13643		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13644		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13645		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13646		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13647		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13648		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13649		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13650		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13651		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13652		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13653		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13654		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13655		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13656		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13657		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13658		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13659		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13660		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13661		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13662		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13663		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13664		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13665		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13666		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13667		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13668		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13669		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13670		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13671		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13672		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13673		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13674		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13675		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13676		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13677		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13678		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13679		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13680		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13681		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13682		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13683		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13684		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13685		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13686		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13687		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13688		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13689		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13690		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13691		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13692		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13693		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13694		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13695		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13696		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13697		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13698		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13699		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13700		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13701		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13702		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13703		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13704		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13705		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13706	};
13707	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13708		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13709		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13710		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13711		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13712		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13713		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13714		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13715		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13716		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13717		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13718		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13719		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13720		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13721		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13722		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13723		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13724		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13725		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13726		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13727		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13728		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13729		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13730		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13731		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13732		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13733		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13734		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13735		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13736		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13737		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13738		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13739		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13740		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13741		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13742		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13743		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13744		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13745		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13746		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13747		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13748		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13749		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13750		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13751		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13752		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13753		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13754		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13755		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13756		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13757		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13758		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13759		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13760		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13761		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13762		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13763		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13764		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13765		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13766		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13767		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13768		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13769		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13770		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13771		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13772	};
13773	static struct bwn_txgain_entry txgain_r1[] = {
13774		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13775		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13776		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13777		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13778		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13779		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13780		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13781		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13782		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13783		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13784		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13785		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13786		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13787		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13788		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13789		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13790		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13791		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13792		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13793		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13794		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13795		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13796		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13797		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13798		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13799		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13800		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13801		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13802		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13803		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13804		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13805		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13806		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13807		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13808		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13809		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13810		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13811		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13812		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13813		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13814		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13815		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13816		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13817		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13818		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13819		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13820		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13821		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13822		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13823		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13824		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13825		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13826		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13827		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13828		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13829		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13830		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13831		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13832		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13833		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13834		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13835		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13836		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13837		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13838		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13839		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13840		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13841		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13842		{ 7, 11, 6, 0, 71 }
13843	};
13844	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13845		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13846		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13847		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13848		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13849		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13850		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13851		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13852		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13853		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13854		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13855		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13856		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13857		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13858		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13859		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13860		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13861		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13862		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13863		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13864		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13865		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13866		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13867		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13868		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13869		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13870		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13871		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13872		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13873		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13874		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13875		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13876		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13877		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13878		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13879		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13880		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13881		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13882		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13883		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13884		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13885		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13886		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13887		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13888		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13889		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13890		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13891		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13892		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13893		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13894		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13895		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13896		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13897		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13898		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13899		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13900		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13901		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13902		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13903		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13904		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13905		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13906		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13907		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13908		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13909	};
13910	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13911		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13912		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13913		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13914		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13915		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13916		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13917		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13918		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13919		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13920		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13921		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13922		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13923		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13924		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13925		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13926		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13927		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13928		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13929		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13930		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13931		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13932		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13933		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13934		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13935		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13936		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13937		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13938		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13939		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13940		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13941		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13942		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13943		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13944		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13945		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13946		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13947		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13948		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13949		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13950		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13951		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13952		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13953		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13954		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13955		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13956		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13957		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13958		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13959		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13960		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13961		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13962		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13963		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13964		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13965		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13966		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13967		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13968		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13969		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13970		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13971		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13972		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13973		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13974		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13975	};
13976
13977	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13978		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13979			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13980		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13981			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13982			    txgain_2ghz_r2);
13983		else
13984			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13985			    txgain_5ghz_r2);
13986		return;
13987	}
13988
13989	if (mac->mac_phy.rev == 0) {
13990		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13991		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13992			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13993		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13994			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13995			    txgain_2ghz_r0);
13996		else
13997			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13998			    txgain_5ghz_r0);
13999		return;
14000	}
14001
14002	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14003	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14004		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14005	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14006		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14007	else
14008		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14009}
14010
14011static void
14012bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14013{
14014	uint32_t offset, type;
14015
14016	type = BWN_TAB_GETTYPE(typeoffset);
14017	offset = BWN_TAB_GETOFFSET(typeoffset);
14018	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14019
14020	switch (type) {
14021	case BWN_TAB_8BIT:
14022		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14023		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14024		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14025		break;
14026	case BWN_TAB_16BIT:
14027		KASSERT(!(value & ~0xffff),
14028		    ("%s:%d: fail", __func__, __LINE__));
14029		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14030		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14031		break;
14032	case BWN_TAB_32BIT:
14033		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14034		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14035		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14036		break;
14037	default:
14038		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14039	}
14040}
14041
14042static int
14043bwn_phy_lp_loopback(struct bwn_mac *mac)
14044{
14045	struct bwn_phy_lp_iq_est ie;
14046	int i, index = -1;
14047	uint32_t tmp;
14048
14049	memset(&ie, 0, sizeof(ie));
14050
14051	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14052	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14053	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14054	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14055	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14056	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14057	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14058	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14059	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14060	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14061	for (i = 0; i < 32; i++) {
14062		bwn_phy_lp_set_rxgain_idx(mac, i);
14063		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14064		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14065			continue;
14066		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14067		if ((tmp > 4000) && (tmp < 10000)) {
14068			index = i;
14069			break;
14070		}
14071	}
14072	bwn_phy_lp_ddfs_turnoff(mac);
14073	return (index);
14074}
14075
14076static void
14077bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14078{
14079
14080	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14081}
14082
14083static void
14084bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14085    int incr1, int incr2, int scale_idx)
14086{
14087
14088	bwn_phy_lp_ddfs_turnoff(mac);
14089	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14090	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14091	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14092	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14093	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14094	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14095	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14096	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14097	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14098	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14099}
14100
14101static uint8_t
14102bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14103    struct bwn_phy_lp_iq_est *ie)
14104{
14105	int i;
14106
14107	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14108	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14109	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14110	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14111	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14112
14113	for (i = 0; i < 500; i++) {
14114		if (!(BWN_PHY_READ(mac,
14115		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14116			break;
14117		DELAY(1000);
14118	}
14119	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14120		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14121		return 0;
14122	}
14123
14124	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14125	ie->ie_iqprod <<= 16;
14126	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14127	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14128	ie->ie_ipwr <<= 16;
14129	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14130	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14131	ie->ie_qpwr <<= 16;
14132	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14133
14134	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14135	return 1;
14136}
14137
14138static uint32_t
14139bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14140{
14141	uint32_t offset, type, value;
14142
14143	type = BWN_TAB_GETTYPE(typeoffset);
14144	offset = BWN_TAB_GETOFFSET(typeoffset);
14145	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14146
14147	switch (type) {
14148	case BWN_TAB_8BIT:
14149		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14150		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14151		break;
14152	case BWN_TAB_16BIT:
14153		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14154		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14155		break;
14156	case BWN_TAB_32BIT:
14157		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14158		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14159		value <<= 16;
14160		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14161		break;
14162	default:
14163		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14164		value = 0;
14165	}
14166
14167	return (value);
14168}
14169
14170static void
14171bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14172{
14173
14174	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14175	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14176}
14177
14178static void
14179bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14180{
14181	uint16_t ctl;
14182
14183	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14184	ctl |= dac << 7;
14185	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14186}
14187
14188static void
14189bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14190{
14191
14192	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14193	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14194}
14195
14196static void
14197bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14198{
14199
14200	if (mac->mac_phy.rev < 2)
14201		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14202	else {
14203		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14204		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14205	}
14206	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14207}
14208
14209static uint16_t
14210bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14211{
14212
14213	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14214}
14215
14216static uint8_t
14217bwn_nbits(int32_t val)
14218{
14219	uint32_t tmp;
14220	uint8_t nbits = 0;
14221
14222	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14223		nbits++;
14224	return (nbits);
14225}
14226
14227static void
14228bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14229    struct bwn_txgain_entry *table)
14230{
14231	int i;
14232
14233	for (i = offset; i < count; i++)
14234		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14235}
14236
14237static void
14238bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14239    struct bwn_txgain_entry data)
14240{
14241
14242	if (mac->mac_phy.rev >= 2)
14243		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14244	else
14245		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14246}
14247
14248static void
14249bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14250    struct bwn_txgain_entry te)
14251{
14252	struct bwn_softc *sc = mac->mac_sc;
14253	struct ifnet *ifp = sc->sc_ifp;
14254	struct ieee80211com *ic = ifp->if_l2com;
14255	uint32_t tmp;
14256
14257	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14258
14259	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14260	if (mac->mac_phy.rev >= 3) {
14261		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14262		    (0x10 << 24) : (0x70 << 24));
14263	} else {
14264		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14265		    (0x14 << 24) : (0x7f << 24));
14266	}
14267	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14268	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14269	    te.te_bbmult << 20 | te.te_dac << 28);
14270}
14271
14272static void
14273bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14274    struct bwn_txgain_entry te)
14275{
14276
14277	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14278
14279	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14280	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14281	    te.te_dac);
14282	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14283}
14284
14285static void
14286bwn_sysctl_node(struct bwn_softc *sc)
14287{
14288	device_t dev = sc->sc_dev;
14289	struct bwn_mac *mac;
14290	struct bwn_stats *stats;
14291
14292	/* XXX assume that count of MAC is only 1. */
14293
14294	if ((mac = sc->sc_curmac) == NULL)
14295		return;
14296	stats = &mac->mac_stats;
14297
14298	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14299	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14300	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14301	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14302	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14303	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14304	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14305	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14306	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14307
14308#ifdef BWN_DEBUG
14309	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14310	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14311	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14312#endif
14313}
14314
14315static device_method_t bwn_methods[] = {
14316	/* Device interface */
14317	DEVMETHOD(device_probe,		bwn_probe),
14318	DEVMETHOD(device_attach,	bwn_attach),
14319	DEVMETHOD(device_detach,	bwn_detach),
14320	DEVMETHOD(device_suspend,	bwn_suspend),
14321	DEVMETHOD(device_resume,	bwn_resume),
14322	{ 0,0 }
14323};
14324static driver_t bwn_driver = {
14325	"bwn",
14326	bwn_methods,
14327	sizeof(struct bwn_softc)
14328};
14329static devclass_t bwn_devclass;
14330DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14331MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14332MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14333MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14334MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14335