if_bwn.c revision 213719
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 213719 2010-10-12 11:05:32Z joel $");
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_phy.h>
71#include <net80211/ieee80211_ratectl.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(device_t);
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_updateslot(struct ifnet *);
184static void	bwn_update_promisc(struct ifnet *);
185static void	bwn_wme_init(struct bwn_mac *);
186static int	bwn_wme_update(struct ieee80211com *);
187static void	bwn_wme_clear(struct bwn_softc *);
188static void	bwn_wme_load(struct bwn_mac *);
189static void	bwn_wme_loadparams(struct bwn_mac *,
190		    const struct wmeParams *, uint16_t);
191static void	bwn_scan_start(struct ieee80211com *);
192static void	bwn_scan_end(struct ieee80211com *);
193static void	bwn_set_channel(struct ieee80211com *);
194static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
195		    const char [IFNAMSIZ], int, int,
196		    int, const uint8_t [IEEE80211_ADDR_LEN],
197		    const uint8_t [IEEE80211_ADDR_LEN]);
198static void	bwn_vap_delete(struct ieee80211vap *);
199static void	bwn_stop(struct bwn_softc *, int);
200static void	bwn_stop_locked(struct bwn_softc *, int);
201static int	bwn_core_init(struct bwn_mac *);
202static void	bwn_core_start(struct bwn_mac *);
203static void	bwn_core_exit(struct bwn_mac *);
204static void	bwn_bt_disable(struct bwn_mac *);
205static int	bwn_chip_init(struct bwn_mac *);
206static uint64_t	bwn_hf_read(struct bwn_mac *);
207static void	bwn_hf_write(struct bwn_mac *, uint64_t);
208static void	bwn_set_txretry(struct bwn_mac *, int, int);
209static void	bwn_rate_init(struct bwn_mac *);
210static void	bwn_set_phytxctl(struct bwn_mac *);
211static void	bwn_spu_setdelay(struct bwn_mac *, int);
212static void	bwn_bt_enable(struct bwn_mac *);
213static void	bwn_set_macaddr(struct bwn_mac *);
214static void	bwn_crypt_init(struct bwn_mac *);
215static void	bwn_chip_exit(struct bwn_mac *);
216static int	bwn_fw_fillinfo(struct bwn_mac *);
217static int	bwn_fw_loaducode(struct bwn_mac *);
218static int	bwn_gpio_init(struct bwn_mac *);
219static int	bwn_fw_loadinitvals(struct bwn_mac *);
220static int	bwn_phy_init(struct bwn_mac *);
221static void	bwn_set_txantenna(struct bwn_mac *, int);
222static void	bwn_set_opmode(struct bwn_mac *);
223static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
224static uint8_t	bwn_plcp_getcck(const uint8_t);
225static uint8_t	bwn_plcp_getofdm(const uint8_t);
226static void	bwn_pio_init(struct bwn_mac *);
227static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
228static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
229		    int);
230static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
231		    struct bwn_pio_rxqueue *, int);
232static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
233static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
234		    uint16_t);
235static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
236static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
237static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
238static void	bwn_pio_handle_txeof(struct bwn_mac *,
239		    const struct bwn_txstatus *);
240static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
241static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
242static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
243		    uint16_t);
244static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
245		    uint32_t);
246static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
247		    struct mbuf *);
248static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
249static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
250		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
251static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
252		    uint16_t, uint32_t);
253static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
254		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
255static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
257static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
258		    uint16_t, struct bwn_pio_txpkt **);
259static void	bwn_dma_init(struct bwn_mac *);
260static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
261static int	bwn_dma_mask2type(uint64_t);
262static uint64_t	bwn_dma_mask(struct bwn_mac *);
263static uint16_t	bwn_dma_base(int, int);
264static void	bwn_dma_ringfree(struct bwn_dma_ring **);
265static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
266		    int, struct bwn_dmadesc_generic **,
267		    struct bwn_dmadesc_meta **);
268static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
269		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
270		    int, int);
271static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
272static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
273static void	bwn_dma_32_resume(struct bwn_dma_ring *);
274static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
275static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
276static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
277		    int, struct bwn_dmadesc_generic **,
278		    struct bwn_dmadesc_meta **);
279static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
280		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
281		    int, int);
282static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
283static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
284static void	bwn_dma_64_resume(struct bwn_dma_ring *);
285static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
286static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
287static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
288static void	bwn_dma_setup(struct bwn_dma_ring *);
289static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
290static void	bwn_dma_cleanup(struct bwn_dma_ring *);
291static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
292static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
293static void	bwn_dma_rx(struct bwn_dma_ring *);
294static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
295static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
296		    struct bwn_dmadesc_meta *);
297static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
298static int	bwn_dma_gettype(struct bwn_mac *);
299static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
300static int	bwn_dma_freeslot(struct bwn_dma_ring *);
301static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
302static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
303static int	bwn_dma_newbuf(struct bwn_dma_ring *,
304		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
305		    int);
306static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
307		    bus_size_t, int);
308static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
309static void	bwn_dma_handle_txeof(struct bwn_mac *,
310		    const struct bwn_txstatus *);
311static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
312		    struct mbuf *);
313static int	bwn_dma_getslot(struct bwn_dma_ring *);
314static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
315		    uint8_t);
316static int	bwn_dma_attach(struct bwn_mac *);
317static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
318		    int, int, int);
319static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
320		    const struct bwn_txstatus *, uint16_t, int *);
321static void	bwn_dma_free(struct bwn_mac *);
322static void	bwn_phy_g_init_sub(struct bwn_mac *);
323static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
324static void	bwn_phy_init_b5(struct bwn_mac *);
325static void	bwn_phy_init_b6(struct bwn_mac *);
326static void	bwn_phy_init_a(struct bwn_mac *);
327static void	bwn_loopback_calcgain(struct bwn_mac *);
328static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
329static void	bwn_lo_g_init(struct bwn_mac *);
330static void	bwn_lo_g_adjust(struct bwn_mac *);
331static void	bwn_lo_get_powervector(struct bwn_mac *);
332static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
333		    const struct bwn_bbatt *, const struct bwn_rfatt *);
334static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
335static void	bwn_phy_hwpctl_init(struct bwn_mac *);
336static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
337static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
338		    const struct bwn_bbatt *, const struct bwn_rfatt *,
339		    uint8_t);
340static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
341static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
342static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
343static void	bwn_wa_init(struct bwn_mac *);
344static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
345		    uint16_t);
346static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
347static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
348		    uint32_t);
349static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
350		    uint16_t);
351static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
352static void	bwn_mac_suspend(struct bwn_mac *);
353static void	bwn_mac_enable(struct bwn_mac *);
354static void	bwn_psctl(struct bwn_mac *, uint32_t);
355static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
356static void	bwn_nrssi_offset(struct bwn_mac *);
357static void	bwn_nrssi_threshold(struct bwn_mac *);
358static void	bwn_nrssi_slope_11g(struct bwn_mac *);
359static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
360		    int16_t);
361static void	bwn_set_original_gains(struct bwn_mac *);
362static void	bwn_hwpctl_early_init(struct bwn_mac *);
363static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
364static uint16_t	bwn_phy_g_chan2freq(uint8_t);
365static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
366static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
367		    const char *, struct bwn_fwfile *);
368static void	bwn_release_firmware(struct bwn_mac *);
369static void	bwn_do_release_fw(struct bwn_fwfile *);
370static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
371static int	bwn_fwinitvals_write(struct bwn_mac *,
372		    const struct bwn_fwinitvals *, size_t, size_t);
373static int	bwn_switch_channel(struct bwn_mac *, int);
374static uint16_t	bwn_ant2phy(int);
375static void	bwn_mac_write_bssid(struct bwn_mac *);
376static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
377		    const uint8_t *);
378static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
379		    const uint8_t *, size_t, const uint8_t *);
380static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
381		    const uint8_t *);
382static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
383		    const uint8_t *);
384static void	bwn_phy_exit(struct bwn_mac *);
385static void	bwn_core_stop(struct bwn_mac *);
386static int	bwn_switch_band(struct bwn_softc *,
387		    struct ieee80211_channel *);
388static void	bwn_phy_reset(struct bwn_mac *);
389static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
390static void	bwn_set_pretbtt(struct bwn_mac *);
391static int	bwn_intr(void *);
392static void	bwn_intrtask(void *, int);
393static void	bwn_restart(struct bwn_mac *, const char *);
394static void	bwn_intr_ucode_debug(struct bwn_mac *);
395static void	bwn_intr_tbtt_indication(struct bwn_mac *);
396static void	bwn_intr_atim_end(struct bwn_mac *);
397static void	bwn_intr_beacon(struct bwn_mac *);
398static void	bwn_intr_pmq(struct bwn_mac *);
399static void	bwn_intr_noise(struct bwn_mac *);
400static void	bwn_intr_txeof(struct bwn_mac *);
401static void	bwn_hwreset(void *, int);
402static void	bwn_handle_fwpanic(struct bwn_mac *);
403static void	bwn_load_beacon0(struct bwn_mac *);
404static void	bwn_load_beacon1(struct bwn_mac *);
405static uint32_t	bwn_jssi_read(struct bwn_mac *);
406static void	bwn_noise_gensample(struct bwn_mac *);
407static void	bwn_handle_txeof(struct bwn_mac *,
408		    const struct bwn_txstatus *);
409static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
410static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
411static void	bwn_start_locked(struct ifnet *);
412static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
413		    struct mbuf *);
414static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
415static int	bwn_set_txhdr(struct bwn_mac *,
416		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
417		    uint16_t);
418static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
419		    const uint8_t);
420static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
421static uint8_t	bwn_get_fbrate(uint8_t);
422static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
423static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
424static void	bwn_phy_lock(struct bwn_mac *);
425static void	bwn_phy_unlock(struct bwn_mac *);
426static void	bwn_rf_lock(struct bwn_mac *);
427static void	bwn_rf_unlock(struct bwn_mac *);
428static void	bwn_txpwr(void *, int);
429static void	bwn_tasks(void *);
430static void	bwn_task_15s(struct bwn_mac *);
431static void	bwn_task_30s(struct bwn_mac *);
432static void	bwn_task_60s(struct bwn_mac *);
433static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
434		    uint8_t);
435static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
436static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
437		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
438		    int, int);
439static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
440static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
441static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
442static void	bwn_watchdog(void *);
443static void	bwn_dma_stop(struct bwn_mac *);
444static void	bwn_pio_stop(struct bwn_mac *);
445static void	bwn_dma_ringstop(struct bwn_dma_ring **);
446static void	bwn_led_attach(struct bwn_mac *);
447static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
448static void	bwn_led_event(struct bwn_mac *, int);
449static void	bwn_led_blink_start(struct bwn_mac *, int, int);
450static void	bwn_led_blink_next(void *);
451static void	bwn_led_blink_end(void *);
452static void	bwn_rfswitch(void *);
453static void	bwn_rf_turnon(struct bwn_mac *);
454static void	bwn_rf_turnoff(struct bwn_mac *);
455static void	bwn_phy_lp_init_pre(struct bwn_mac *);
456static int	bwn_phy_lp_init(struct bwn_mac *);
457static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
458static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
459static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
460		    uint16_t);
461static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
462static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
463static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
464static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
465static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
466static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
467static void	bwn_phy_lp_task_60s(struct bwn_mac *);
468static void	bwn_phy_lp_readsprom(struct bwn_mac *);
469static void	bwn_phy_lp_bbinit(struct bwn_mac *);
470static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
471static void	bwn_phy_lp_calib(struct bwn_mac *);
472static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
473static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
474static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
475static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
476static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
477static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
478static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
479static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
480static void	bwn_phy_lp_bugfix(struct bwn_mac *);
481static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
482static void	bwn_phy_lp_tblinit(struct bwn_mac *);
483static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
484static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
485static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
486static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
487static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
488static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
489static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
490static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
491static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
492static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
493static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
494		    const void *);
495static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
496static struct bwn_txgain
497		bwn_phy_lp_get_txgain(struct bwn_mac *);
498static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
499static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
500static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
501static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
502static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
503static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
504static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
505static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
506static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
507static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
508static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
509static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
510static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
511static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
512static int	bwn_phy_lp_loopback(struct bwn_mac *);
513static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
514static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
515		    int);
516static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
517		    struct bwn_phy_lp_iq_est *);
518static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
519static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
520static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
521static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
522static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
523static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
524static uint8_t	bwn_nbits(int32_t);
525static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
526		    struct bwn_txgain_entry *);
527static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
528		    struct bwn_txgain_entry);
529static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
530		    struct bwn_txgain_entry);
531static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
532		    struct bwn_txgain_entry);
533static void	bwn_sysctl_node(struct bwn_softc *);
534
535static struct resource_spec bwn_res_spec_legacy[] = {
536	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
537	{ -1,			0,		0 }
538};
539
540static struct resource_spec bwn_res_spec_msi[] = {
541	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
542	{ -1,			0,		0 }
543};
544
545static const struct bwn_channelinfo bwn_chantable_bg = {
546	.channels = {
547		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
548		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
549		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
550		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
551		{ 2472, 13, 30 }, { 2484, 14, 30 } },
552	.nchannels = 14
553};
554
555static const struct bwn_channelinfo bwn_chantable_a = {
556	.channels = {
557		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
558		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
559		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
560		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
561		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
562		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
563		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
564		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
565		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
566		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
567		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
568		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
569		{ 6080, 216, 30 } },
570	.nchannels = 37
571};
572
573static const struct bwn_channelinfo bwn_chantable_n = {
574	.channels = {
575		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
576		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
577		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
578		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
579		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
580		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
581		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
582		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
583		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
584		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
585		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
586		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
587		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
588		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
589		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
590		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
591		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
592		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
593		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
594		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
595		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
596		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
597		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
598		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
599		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
600		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
601		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
602		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
603		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
604		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
605		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
606		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
607		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
608		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
609		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
610		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
611		{ 6130, 226, 30 }, { 6140, 228, 30 } },
612	.nchannels = 110
613};
614
615static const uint8_t bwn_b2063_chantable_data[33][12] = {
616	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
617	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
622	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
623	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
624	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
625	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
626	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
627	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
629	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
630	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
631	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
633	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
634	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
635	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
636	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
638	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
641	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
642	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
644	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
647	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
649};
650
651static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
652	{ 1, 2412, bwn_b2063_chantable_data[0] },
653	{ 2, 2417, bwn_b2063_chantable_data[0] },
654	{ 3, 2422, bwn_b2063_chantable_data[0] },
655	{ 4, 2427, bwn_b2063_chantable_data[1] },
656	{ 5, 2432, bwn_b2063_chantable_data[1] },
657	{ 6, 2437, bwn_b2063_chantable_data[1] },
658	{ 7, 2442, bwn_b2063_chantable_data[1] },
659	{ 8, 2447, bwn_b2063_chantable_data[1] },
660	{ 9, 2452, bwn_b2063_chantable_data[2] },
661	{ 10, 2457, bwn_b2063_chantable_data[2] },
662	{ 11, 2462, bwn_b2063_chantable_data[3] },
663	{ 12, 2467, bwn_b2063_chantable_data[3] },
664	{ 13, 2472, bwn_b2063_chantable_data[3] },
665	{ 14, 2484, bwn_b2063_chantable_data[4] },
666	{ 34, 5170, bwn_b2063_chantable_data[5] },
667	{ 36, 5180, bwn_b2063_chantable_data[6] },
668	{ 38, 5190, bwn_b2063_chantable_data[7] },
669	{ 40, 5200, bwn_b2063_chantable_data[8] },
670	{ 42, 5210, bwn_b2063_chantable_data[9] },
671	{ 44, 5220, bwn_b2063_chantable_data[10] },
672	{ 46, 5230, bwn_b2063_chantable_data[11] },
673	{ 48, 5240, bwn_b2063_chantable_data[12] },
674	{ 52, 5260, bwn_b2063_chantable_data[13] },
675	{ 56, 5280, bwn_b2063_chantable_data[14] },
676	{ 60, 5300, bwn_b2063_chantable_data[14] },
677	{ 64, 5320, bwn_b2063_chantable_data[15] },
678	{ 100, 5500, bwn_b2063_chantable_data[16] },
679	{ 104, 5520, bwn_b2063_chantable_data[17] },
680	{ 108, 5540, bwn_b2063_chantable_data[18] },
681	{ 112, 5560, bwn_b2063_chantable_data[19] },
682	{ 116, 5580, bwn_b2063_chantable_data[20] },
683	{ 120, 5600, bwn_b2063_chantable_data[21] },
684	{ 124, 5620, bwn_b2063_chantable_data[21] },
685	{ 128, 5640, bwn_b2063_chantable_data[22] },
686	{ 132, 5660, bwn_b2063_chantable_data[22] },
687	{ 136, 5680, bwn_b2063_chantable_data[22] },
688	{ 140, 5700, bwn_b2063_chantable_data[23] },
689	{ 149, 5745, bwn_b2063_chantable_data[23] },
690	{ 153, 5765, bwn_b2063_chantable_data[23] },
691	{ 157, 5785, bwn_b2063_chantable_data[23] },
692	{ 161, 5805, bwn_b2063_chantable_data[23] },
693	{ 165, 5825, bwn_b2063_chantable_data[23] },
694	{ 184, 4920, bwn_b2063_chantable_data[24] },
695	{ 188, 4940, bwn_b2063_chantable_data[25] },
696	{ 192, 4960, bwn_b2063_chantable_data[26] },
697	{ 196, 4980, bwn_b2063_chantable_data[27] },
698	{ 200, 5000, bwn_b2063_chantable_data[28] },
699	{ 204, 5020, bwn_b2063_chantable_data[29] },
700	{ 208, 5040, bwn_b2063_chantable_data[30] },
701	{ 212, 5060, bwn_b2063_chantable_data[31] },
702	{ 216, 5080, bwn_b2063_chantable_data[32] }
703};
704
705static const uint8_t bwn_b2062_chantable_data[22][12] = {
706	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
707	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
727	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
728};
729
730static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
731	{ 1, 2412, bwn_b2062_chantable_data[0] },
732	{ 2, 2417, bwn_b2062_chantable_data[0] },
733	{ 3, 2422, bwn_b2062_chantable_data[0] },
734	{ 4, 2427, bwn_b2062_chantable_data[0] },
735	{ 5, 2432, bwn_b2062_chantable_data[0] },
736	{ 6, 2437, bwn_b2062_chantable_data[0] },
737	{ 7, 2442, bwn_b2062_chantable_data[0] },
738	{ 8, 2447, bwn_b2062_chantable_data[0] },
739	{ 9, 2452, bwn_b2062_chantable_data[0] },
740	{ 10, 2457, bwn_b2062_chantable_data[0] },
741	{ 11, 2462, bwn_b2062_chantable_data[0] },
742	{ 12, 2467, bwn_b2062_chantable_data[0] },
743	{ 13, 2472, bwn_b2062_chantable_data[0] },
744	{ 14, 2484, bwn_b2062_chantable_data[0] },
745	{ 34, 5170, bwn_b2062_chantable_data[1] },
746	{ 38, 5190, bwn_b2062_chantable_data[2] },
747	{ 42, 5210, bwn_b2062_chantable_data[2] },
748	{ 46, 5230, bwn_b2062_chantable_data[3] },
749	{ 36, 5180, bwn_b2062_chantable_data[4] },
750	{ 40, 5200, bwn_b2062_chantable_data[5] },
751	{ 44, 5220, bwn_b2062_chantable_data[6] },
752	{ 48, 5240, bwn_b2062_chantable_data[3] },
753	{ 52, 5260, bwn_b2062_chantable_data[3] },
754	{ 56, 5280, bwn_b2062_chantable_data[3] },
755	{ 60, 5300, bwn_b2062_chantable_data[7] },
756	{ 64, 5320, bwn_b2062_chantable_data[8] },
757	{ 100, 5500, bwn_b2062_chantable_data[9] },
758	{ 104, 5520, bwn_b2062_chantable_data[10] },
759	{ 108, 5540, bwn_b2062_chantable_data[10] },
760	{ 112, 5560, bwn_b2062_chantable_data[10] },
761	{ 116, 5580, bwn_b2062_chantable_data[11] },
762	{ 120, 5600, bwn_b2062_chantable_data[12] },
763	{ 124, 5620, bwn_b2062_chantable_data[12] },
764	{ 128, 5640, bwn_b2062_chantable_data[12] },
765	{ 132, 5660, bwn_b2062_chantable_data[12] },
766	{ 136, 5680, bwn_b2062_chantable_data[12] },
767	{ 140, 5700, bwn_b2062_chantable_data[12] },
768	{ 149, 5745, bwn_b2062_chantable_data[12] },
769	{ 153, 5765, bwn_b2062_chantable_data[12] },
770	{ 157, 5785, bwn_b2062_chantable_data[12] },
771	{ 161, 5805, bwn_b2062_chantable_data[12] },
772	{ 165, 5825, bwn_b2062_chantable_data[12] },
773	{ 184, 4920, bwn_b2062_chantable_data[13] },
774	{ 188, 4940, bwn_b2062_chantable_data[14] },
775	{ 192, 4960, bwn_b2062_chantable_data[15] },
776	{ 196, 4980, bwn_b2062_chantable_data[16] },
777	{ 200, 5000, bwn_b2062_chantable_data[17] },
778	{ 204, 5020, bwn_b2062_chantable_data[18] },
779	{ 208, 5040, bwn_b2062_chantable_data[19] },
780	{ 212, 5060, bwn_b2062_chantable_data[20] },
781	{ 216, 5080, bwn_b2062_chantable_data[21] }
782};
783
784/* for LP PHY */
785static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
786	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
787	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
788	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
789	{ 13, -66, 13 }, { 14, -66, 13 },
790};
791
792/* for LP PHY */
793static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
794	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
795	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
796	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
797	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
798	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
799	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
800	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
801	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
802	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
803	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
804	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
805	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
806	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
807};
808
809static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
810
811static const uint8_t bwn_tab_sigsq_tbl[] = {
812	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
813	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
814	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
815	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
816	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
817	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
818};
819
820static const uint8_t bwn_tab_pllfrac_tbl[] = {
821	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
822	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
823};
824
825static const uint16_t bwn_tabl_iqlocal_tbl[] = {
826	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
827	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
828	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
829	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
830	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
831	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
832	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838};
839
840static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
841static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
842static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
843static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
844static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
845const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
846
847#define	VENDOR_LED_ACT(vendor)				\
848{							\
849	.vid = PCI_VENDOR_##vendor,			\
850	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
851}
852
853static const struct {
854	uint16_t	vid;
855	uint8_t		led_act[BWN_LED_MAX];
856} bwn_vendor_led_act[] = {
857	VENDOR_LED_ACT(COMPAQ),
858	VENDOR_LED_ACT(ASUSTEK)
859};
860
861static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
862	{ BWN_VENDOR_LED_ACT_DEFAULT };
863
864#undef VENDOR_LED_ACT
865
866static const struct {
867	int		on_dur;
868	int		off_dur;
869} bwn_led_duration[109] = {
870	[0]	= { 400, 100 },
871	[2]	= { 150, 75 },
872	[4]	= { 90, 45 },
873	[11]	= { 66, 34 },
874	[12]	= { 53, 26 },
875	[18]	= { 42, 21 },
876	[22]	= { 35, 17 },
877	[24]	= { 32, 16 },
878	[36]	= { 21, 10 },
879	[48]	= { 16, 8 },
880	[72]	= { 11, 5 },
881	[96]	= { 9, 4 },
882	[108]	= { 7, 3 }
883};
884
885static const uint16_t bwn_wme_shm_offsets[] = {
886	[0] = BWN_WME_BESTEFFORT,
887	[1] = BWN_WME_BACKGROUND,
888	[2] = BWN_WME_VOICE,
889	[3] = BWN_WME_VIDEO,
890};
891
892static const struct siba_devid bwn_devs[] = {
893	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
894	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
895	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
896	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
897	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
898	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
899	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
900	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
901	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
902};
903
904static int
905bwn_probe(device_t dev)
906{
907	int i;
908
909	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
910		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
911		    siba_get_device(dev) == bwn_devs[i].sd_device &&
912		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
913			return (BUS_PROBE_DEFAULT);
914	}
915
916	return (ENXIO);
917}
918
919static int
920bwn_attach(device_t dev)
921{
922	struct bwn_mac *mac;
923	struct bwn_softc *sc = device_get_softc(dev);
924	int error, i, msic, reg;
925
926	sc->sc_dev = dev;
927#ifdef BWN_DEBUG
928	sc->sc_debug = bwn_debug;
929#endif
930
931	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
932		error = bwn_attach_pre(sc);
933		if (error != 0)
934			return (error);
935		bwn_sprom_bugfixes(dev);
936		sc->sc_flags |= BWN_FLAG_ATTACHED;
937	}
938
939	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
940		if (siba_get_pci_device(dev) != 0x4313 &&
941		    siba_get_pci_device(dev) != 0x431a &&
942		    siba_get_pci_device(dev) != 0x4321) {
943			device_printf(sc->sc_dev,
944			    "skip 802.11 cores\n");
945			return (ENODEV);
946		}
947	}
948
949	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
950	    M_NOWAIT | M_ZERO);
951	if (mac == NULL)
952		return (ENOMEM);
953	mac->mac_sc = sc;
954	mac->mac_status = BWN_MAC_STATUS_UNINIT;
955	if (bwn_bfp != 0)
956		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
957
958	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
959	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
960	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
961
962	error = bwn_attach_core(mac);
963	if (error)
964		goto fail0;
965	bwn_led_attach(mac);
966
967	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
968	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
969	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
970	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
971	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
972	    mac->mac_phy.rf_rev);
973	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
974		device_printf(sc->sc_dev, "DMA (%d bits)\n",
975		    mac->mac_method.dma.dmatype);
976	else
977		device_printf(sc->sc_dev, "PIO\n");
978
979	/*
980	 * setup PCI resources and interrupt.
981	 */
982	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
983		msic = pci_msi_count(dev);
984		if (bootverbose)
985			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
986	} else
987		msic = 0;
988
989	mac->mac_intr_spec = bwn_res_spec_legacy;
990	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
991		if (pci_alloc_msi(dev, &msic) == 0) {
992			device_printf(sc->sc_dev,
993			    "Using %d MSI messages\n", msic);
994			mac->mac_intr_spec = bwn_res_spec_msi;
995			mac->mac_msi = 1;
996		}
997	}
998
999	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1000	    mac->mac_res_irq);
1001	if (error) {
1002		device_printf(sc->sc_dev,
1003		    "couldn't allocate IRQ resources (%d)\n", error);
1004		goto fail1;
1005	}
1006
1007	if (mac->mac_msi == 0)
1008		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1009		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1010		    &mac->mac_intrhand[0]);
1011	else {
1012		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1013			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1014			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1015			    &mac->mac_intrhand[i]);
1016			if (error != 0) {
1017				device_printf(sc->sc_dev,
1018				    "couldn't setup interrupt (%d)\n", error);
1019				break;
1020			}
1021		}
1022	}
1023
1024	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1025
1026	/*
1027	 * calls attach-post routine
1028	 */
1029	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1030		bwn_attach_post(sc);
1031
1032	return (0);
1033fail1:
1034	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1035		pci_release_msi(dev);
1036fail0:
1037	free(mac, M_DEVBUF);
1038	return (error);
1039}
1040
1041static int
1042bwn_is_valid_ether_addr(uint8_t *addr)
1043{
1044	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1045
1046	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1047		return (FALSE);
1048
1049	return (TRUE);
1050}
1051
1052static int
1053bwn_attach_post(struct bwn_softc *sc)
1054{
1055	struct ieee80211com *ic;
1056	struct ifnet *ifp = sc->sc_ifp;
1057
1058	ic = ifp->if_l2com;
1059	ic->ic_ifp = ifp;
1060	/* XXX not right but it's not used anywhere important */
1061	ic->ic_phytype = IEEE80211_T_OFDM;
1062	ic->ic_opmode = IEEE80211_M_STA;
1063	ic->ic_caps =
1064		  IEEE80211_C_STA		/* station mode supported */
1065		| IEEE80211_C_MONITOR		/* monitor mode */
1066		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1067		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1068		| IEEE80211_C_SHSLOT		/* short slot time supported */
1069		| IEEE80211_C_WME		/* WME/WMM supported */
1070		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1071		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1072		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1073		| IEEE80211_C_RATECTL		/* use ratectl */
1074		;
1075
1076	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1077
1078	/* call MI attach routine. */
1079	ieee80211_ifattach(ic,
1080	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1082	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1083
1084	ic->ic_headroom = sizeof(struct bwn_txhdr);
1085
1086	/* override default methods */
1087	ic->ic_raw_xmit = bwn_raw_xmit;
1088	ic->ic_updateslot = bwn_updateslot;
1089	ic->ic_update_promisc = bwn_update_promisc;
1090	ic->ic_wme.wme_update = bwn_wme_update;
1091
1092	ic->ic_scan_start = bwn_scan_start;
1093	ic->ic_scan_end = bwn_scan_end;
1094	ic->ic_set_channel = bwn_set_channel;
1095
1096	ic->ic_vap_create = bwn_vap_create;
1097	ic->ic_vap_delete = bwn_vap_delete;
1098
1099	ieee80211_radiotap_attach(ic,
1100	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101	    BWN_TX_RADIOTAP_PRESENT,
1102	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103	    BWN_RX_RADIOTAP_PRESENT);
1104
1105	bwn_sysctl_node(sc);
1106
1107	if (bootverbose)
1108		ieee80211_announce(ic);
1109	return (0);
1110}
1111
1112static void
1113bwn_phy_detach(struct bwn_mac *mac)
1114{
1115
1116	if (mac->mac_phy.detach != NULL)
1117		mac->mac_phy.detach(mac);
1118}
1119
1120static int
1121bwn_detach(device_t dev)
1122{
1123	struct bwn_softc *sc = device_get_softc(dev);
1124	struct bwn_mac *mac = sc->sc_curmac;
1125	struct ifnet *ifp = sc->sc_ifp;
1126	struct ieee80211com *ic = ifp->if_l2com;
1127	int i;
1128
1129	sc->sc_flags |= BWN_FLAG_INVALID;
1130
1131	if (device_is_attached(sc->sc_dev)) {
1132		bwn_stop(sc, 1);
1133		bwn_dma_free(mac);
1134		callout_drain(&sc->sc_led_blink_ch);
1135		callout_drain(&sc->sc_rfswitch_ch);
1136		callout_drain(&sc->sc_task_ch);
1137		callout_drain(&sc->sc_watchdog_ch);
1138		bwn_phy_detach(mac);
1139		if (ifp != NULL) {
1140			ieee80211_draintask(ic, &mac->mac_hwreset);
1141			ieee80211_draintask(ic, &mac->mac_txpower);
1142			ieee80211_ifdetach(ic);
1143			if_free(ifp);
1144		}
1145	}
1146	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147	taskqueue_free(sc->sc_tq);
1148
1149	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150		if (mac->mac_intrhand[i] != NULL) {
1151			bus_teardown_intr(dev, mac->mac_res_irq[i],
1152			    mac->mac_intrhand[i]);
1153			mac->mac_intrhand[i] = NULL;
1154		}
1155	}
1156	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157	if (mac->mac_msi != 0)
1158		pci_release_msi(dev);
1159
1160	BWN_LOCK_DESTROY(sc);
1161	return (0);
1162}
1163
1164static int
1165bwn_attach_pre(struct bwn_softc *sc)
1166{
1167	struct ifnet *ifp;
1168	int error = 0;
1169
1170	BWN_LOCK_INIT(sc);
1171	TAILQ_INIT(&sc->sc_maclist);
1172	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175
1176	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177		taskqueue_thread_enqueue, &sc->sc_tq);
1178	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179		"%s taskq", device_get_nameunit(sc->sc_dev));
1180
1181	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182	if (ifp == NULL) {
1183		device_printf(sc->sc_dev, "can not if_alloc()\n");
1184		error = ENOSPC;
1185		goto fail;
1186	}
1187
1188	/* set these up early for if_printf use */
1189	if_initname(ifp, device_get_name(sc->sc_dev),
1190	    device_get_unit(sc->sc_dev));
1191
1192	ifp->if_softc = sc;
1193	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194	ifp->if_init = bwn_init;
1195	ifp->if_ioctl = bwn_ioctl;
1196	ifp->if_start = bwn_start;
1197	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199	IFQ_SET_READY(&ifp->if_snd);
1200
1201	return (0);
1202
1203fail:	BWN_LOCK_DESTROY(sc);
1204	return (error);
1205}
1206
1207static void
1208bwn_sprom_bugfixes(device_t dev)
1209{
1210#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1211	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1212	 (siba_get_pci_device(dev) == _device) &&			\
1213	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1214	 (siba_get_pci_subdevice(dev) == _subdevice))
1215
1216	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217	    siba_get_pci_subdevice(dev) == 0x4e &&
1218	    siba_get_pci_revid(dev) > 0x40)
1219		siba_sprom_set_bf_lo(dev,
1220		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223		siba_sprom_set_bf_lo(dev,
1224		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233			siba_sprom_set_bf_lo(dev,
1234			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235	}
1236#undef	BWN_ISDEV
1237}
1238
1239static int
1240bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241{
1242#define	IS_RUNNING(ifp) \
1243	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244	struct bwn_softc *sc = ifp->if_softc;
1245	struct ieee80211com *ic = ifp->if_l2com;
1246	struct ifreq *ifr = (struct ifreq *)data;
1247	int error = 0, startall;
1248
1249	switch (cmd) {
1250	case SIOCSIFFLAGS:
1251		startall = 0;
1252		if (IS_RUNNING(ifp)) {
1253			bwn_update_promisc(ifp);
1254		} else if (ifp->if_flags & IFF_UP) {
1255			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256				bwn_init(sc);
1257				startall = 1;
1258			}
1259		} else
1260			bwn_stop(sc, 1);
1261		if (startall)
1262			ieee80211_start_all(ic);
1263		break;
1264	case SIOCGIFMEDIA:
1265		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266		break;
1267	case SIOCGIFADDR:
1268		error = ether_ioctl(ifp, cmd, data);
1269		break;
1270	default:
1271		error = EINVAL;
1272		break;
1273	}
1274	return (error);
1275}
1276
1277static void
1278bwn_start(struct ifnet *ifp)
1279{
1280	struct bwn_softc *sc = ifp->if_softc;
1281
1282	BWN_LOCK(sc);
1283	bwn_start_locked(ifp);
1284	BWN_UNLOCK(sc);
1285}
1286
1287static void
1288bwn_start_locked(struct ifnet *ifp)
1289{
1290	struct bwn_softc *sc = ifp->if_softc;
1291	struct bwn_mac *mac = sc->sc_curmac;
1292	struct ieee80211_frame *wh;
1293	struct ieee80211_node *ni;
1294	struct ieee80211_key *k;
1295	struct mbuf *m;
1296
1297	BWN_ASSERT_LOCKED(sc);
1298
1299	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1301		return;
1302
1303	for (;;) {
1304		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1305		if (m == NULL)
1306			break;
1307
1308		if (bwn_tx_isfull(sc, m))
1309			break;
1310		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311		if (ni == NULL) {
1312			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313			m_freem(m);
1314			ifp->if_oerrors++;
1315			continue;
1316		}
1317		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318		wh = mtod(m, struct ieee80211_frame *);
1319		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320			k = ieee80211_crypto_encap(ni, m);
1321			if (k == NULL) {
1322				ieee80211_free_node(ni);
1323				m_freem(m);
1324				ifp->if_oerrors++;
1325				continue;
1326			}
1327		}
1328		wh = NULL;	/* Catch any invalid use */
1329
1330		if (bwn_tx_start(sc, ni, m) != 0) {
1331			if (ni != NULL)
1332				ieee80211_free_node(ni);
1333			ifp->if_oerrors++;
1334			continue;
1335		}
1336
1337		sc->sc_watchdog_timer = 5;
1338	}
1339}
1340
1341static int
1342bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343{
1344	struct bwn_dma_ring *dr;
1345	struct bwn_mac *mac = sc->sc_curmac;
1346	struct bwn_pio_txqueue *tq;
1347	struct ifnet *ifp = sc->sc_ifp;
1348	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349
1350	BWN_ASSERT_LOCKED(sc);
1351
1352	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354		if (dr->dr_stop == 1 ||
1355		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356			dr->dr_stop = 1;
1357			goto full;
1358		}
1359	} else {
1360		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362		    pktlen > (tq->tq_size - tq->tq_used)) {
1363			tq->tq_stop = 1;
1364			goto full;
1365		}
1366	}
1367	return (0);
1368full:
1369	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371	return (1);
1372}
1373
1374static int
1375bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376{
1377	struct bwn_mac *mac = sc->sc_curmac;
1378	int error;
1379
1380	BWN_ASSERT_LOCKED(sc);
1381
1382	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383		m_freem(m);
1384		return (ENXIO);
1385	}
1386
1387	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389	if (error) {
1390		m_freem(m);
1391		return (error);
1392	}
1393	return (0);
1394}
1395
1396static int
1397bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398{
1399	struct bwn_pio_txpkt *tp;
1400	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401	struct bwn_softc *sc = mac->mac_sc;
1402	struct bwn_txhdr txhdr;
1403	struct mbuf *m_new;
1404	uint32_t ctl32;
1405	int error;
1406	uint16_t ctl16;
1407
1408	BWN_ASSERT_LOCKED(sc);
1409
1410	/* XXX TODO send packets after DTIM */
1411
1412	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413	tp = TAILQ_FIRST(&tq->tq_pktlist);
1414	tp->tp_ni = ni;
1415	tp->tp_m = m;
1416
1417	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418	if (error) {
1419		device_printf(sc->sc_dev, "tx fail\n");
1420		return (error);
1421	}
1422
1423	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425	tq->tq_free--;
1426
1427	if (siba_get_revid(sc->sc_dev) >= 8) {
1428		/*
1429		 * XXX please removes m_defrag(9)
1430		 */
1431		m_new = m_defrag(m, M_DONTWAIT);
1432		if (m_new == NULL) {
1433			device_printf(sc->sc_dev,
1434			    "%s: can't defrag TX buffer\n",
1435			    __func__);
1436			return (ENOBUFS);
1437		}
1438		if (m_new->m_next != NULL)
1439			device_printf(sc->sc_dev,
1440			    "TODO: fragmented packets for PIO\n");
1441		tp->tp_m = m_new;
1442
1443		/* send HEADER */
1444		ctl32 = bwn_pio_write_multi_4(mac, tq,
1445		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448		/* send BODY */
1449		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1451		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452		    ctl32 | BWN_PIO8_TXCTL_EOF);
1453	} else {
1454		ctl16 = bwn_pio_write_multi_2(mac, tq,
1455		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460		    ctl16 | BWN_PIO_TXCTL_EOF);
1461	}
1462
1463	return (0);
1464}
1465
1466static struct bwn_pio_txqueue *
1467bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468{
1469
1470	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472
1473	switch (prio) {
1474	case 0:
1475		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476	case 1:
1477		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478	case 2:
1479		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480	case 3:
1481		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482	}
1483	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484	return (NULL);
1485}
1486
1487static int
1488bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489{
1490#define	BWN_GET_TXHDRCACHE(slot)					\
1491	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492	struct bwn_dma *dma = &mac->mac_method.dma;
1493	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494	struct bwn_dmadesc_generic *desc;
1495	struct bwn_dmadesc_meta *mt;
1496	struct bwn_softc *sc = mac->mac_sc;
1497	struct ifnet *ifp = sc->sc_ifp;
1498	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500
1501	BWN_ASSERT_LOCKED(sc);
1502	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503
1504	/* XXX send after DTIM */
1505
1506	slot = bwn_dma_getslot(dr);
1507	dr->getdesc(dr, slot, &desc, &mt);
1508	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509	    ("%s:%d: fail", __func__, __LINE__));
1510
1511	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513	    BWN_DMA_COOKIE(dr, slot));
1514	if (error)
1515		goto fail;
1516	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1519	if (error) {
1520		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521		    __func__, error);
1522		goto fail;
1523	}
1524	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525	    BUS_DMASYNC_PREWRITE);
1526	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528	    BUS_DMASYNC_PREWRITE);
1529
1530	slot = bwn_dma_getslot(dr);
1531	dr->getdesc(dr, slot, &desc, &mt);
1532	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534	mt->mt_m = m;
1535	mt->mt_ni = ni;
1536
1537	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539	if (error && error != EFBIG) {
1540		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541		    __func__, error);
1542		goto fail;
1543	}
1544	if (error) {    /* error == EFBIG */
1545		struct mbuf *m_new;
1546
1547		m_new = m_defrag(m, M_DONTWAIT);
1548		if (m_new == NULL) {
1549			if_printf(ifp, "%s: can't defrag TX buffer\n",
1550			    __func__);
1551			error = ENOBUFS;
1552			goto fail;
1553		} else {
1554			m = m_new;
1555		}
1556
1557		mt->mt_m = m;
1558		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560		if (error) {
1561			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562			    __func__, error);
1563			goto fail;
1564		}
1565	}
1566	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569	    BUS_DMASYNC_PREWRITE);
1570
1571	/* XXX send after DTIM */
1572
1573	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574	return (0);
1575fail:
1576	dr->dr_curslot = backup[0];
1577	dr->dr_usedslot = backup[1];
1578	return (error);
1579#undef BWN_GET_TXHDRCACHE
1580}
1581
1582static void
1583bwn_watchdog(void *arg)
1584{
1585	struct bwn_softc *sc = arg;
1586	struct ifnet *ifp = sc->sc_ifp;
1587
1588	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589		if_printf(ifp, "device timeout\n");
1590		ifp->if_oerrors++;
1591	}
1592	callout_schedule(&sc->sc_watchdog_ch, hz);
1593}
1594
1595static int
1596bwn_attach_core(struct bwn_mac *mac)
1597{
1598	struct bwn_softc *sc = mac->mac_sc;
1599	int error, have_bg = 0, have_a = 0;
1600	uint32_t high;
1601
1602	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604
1605	siba_powerup(sc->sc_dev, 0);
1606
1607	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608	bwn_reset_core(mac,
1609	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610	error = bwn_phy_getinfo(mac, high);
1611	if (error)
1612		goto fail;
1613
1614	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619		have_a = have_bg = 0;
1620		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621			have_a = 1;
1622		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1624		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1625			have_bg = 1;
1626		else
1627			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628			    mac->mac_phy.type));
1629	}
1630	/* XXX turns off PHY A because it's not supported */
1631	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1633		have_a = 0;
1634		have_bg = 1;
1635	}
1636
1637	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638		mac->mac_phy.attach = bwn_phy_g_attach;
1639		mac->mac_phy.detach = bwn_phy_g_detach;
1640		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642		mac->mac_phy.init = bwn_phy_g_init;
1643		mac->mac_phy.exit = bwn_phy_g_exit;
1644		mac->mac_phy.phy_read = bwn_phy_g_read;
1645		mac->mac_phy.phy_write = bwn_phy_g_write;
1646		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654		mac->mac_phy.set_im = bwn_phy_g_im;
1655		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661		mac->mac_phy.init = bwn_phy_lp_init;
1662		mac->mac_phy.phy_read = bwn_phy_lp_read;
1663		mac->mac_phy.phy_write = bwn_phy_lp_write;
1664		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673	} else {
1674		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675		    mac->mac_phy.type);
1676		error = ENXIO;
1677		goto fail;
1678	}
1679
1680	mac->mac_phy.gmode = have_bg;
1681	if (mac->mac_phy.attach != NULL) {
1682		error = mac->mac_phy.attach(mac);
1683		if (error) {
1684			device_printf(sc->sc_dev, "failed\n");
1685			goto fail;
1686		}
1687	}
1688
1689	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690
1691	error = bwn_chiptest(mac);
1692	if (error)
1693		goto fail;
1694	error = bwn_setup_channels(mac, have_bg, have_a);
1695	if (error) {
1696		device_printf(sc->sc_dev, "failed to setup channels\n");
1697		goto fail;
1698	}
1699
1700	if (sc->sc_curmac == NULL)
1701		sc->sc_curmac = mac;
1702
1703	error = bwn_dma_attach(mac);
1704	if (error != 0) {
1705		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706		goto fail;
1707	}
1708
1709	mac->mac_phy.switch_analog(mac, 0);
1710
1711	siba_dev_down(sc->sc_dev, 0);
1712fail:
1713	siba_powerdown(sc->sc_dev);
1714	return (error);
1715}
1716
1717static void
1718bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719{
1720	struct bwn_softc *sc = mac->mac_sc;
1721	uint32_t low, ctl;
1722
1723	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724
1725	siba_dev_up(sc->sc_dev, flags);
1726	DELAY(2000);
1727
1728	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729	    ~BWN_TGSLOW_PHYRESET;
1730	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732	DELAY(1000);
1733	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735	DELAY(1000);
1736
1737	if (mac->mac_phy.switch_analog != NULL)
1738		mac->mac_phy.switch_analog(mac, 1);
1739
1740	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741	if (flags & BWN_TGSLOW_SUPPORT_G)
1742		ctl |= BWN_MACCTL_GMODE;
1743	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744}
1745
1746static int
1747bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748{
1749	struct bwn_phy *phy = &mac->mac_phy;
1750	struct bwn_softc *sc = mac->mac_sc;
1751	uint32_t tmp;
1752
1753	/* PHY */
1754	tmp = BWN_READ_2(mac, BWN_PHYVER);
1755	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756	phy->rf_on = 1;
1757	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759	phy->rev = (tmp & BWN_PHYVER_VERSION);
1760	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766		goto unsupphy;
1767
1768	/* RADIO */
1769	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770		if (siba_get_chiprev(sc->sc_dev) == 0)
1771			tmp = 0x3205017f;
1772		else if (siba_get_chiprev(sc->sc_dev) == 1)
1773			tmp = 0x4205017f;
1774		else
1775			tmp = 0x5205017f;
1776	} else {
1777		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781	}
1782	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784	phy->rf_manuf = (tmp & 0x00000fff);
1785	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1786		goto unsupradio;
1787	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791	    (phy->type == BWN_PHYTYPE_N &&
1792	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793	    (phy->type == BWN_PHYTYPE_LP &&
1794	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795		goto unsupradio;
1796
1797	return (0);
1798unsupphy:
1799	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800	    "analog %#x)\n",
1801	    phy->type, phy->rev, phy->analog);
1802	return (ENXIO);
1803unsupradio:
1804	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805	    "rev %#x)\n",
1806	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807	return (ENXIO);
1808}
1809
1810static int
1811bwn_chiptest(struct bwn_mac *mac)
1812{
1813#define	TESTVAL0	0x55aaaa55
1814#define	TESTVAL1	0xaa5555aa
1815	struct bwn_softc *sc = mac->mac_sc;
1816	uint32_t v, backup;
1817
1818	BWN_LOCK(sc);
1819
1820	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821
1822	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824		goto error;
1825	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827		goto error;
1828
1829	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830
1831	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832	    (siba_get_revid(sc->sc_dev) <= 10)) {
1833		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836			goto error;
1837		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838			goto error;
1839	}
1840	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841
1842	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844		goto error;
1845
1846	BWN_UNLOCK(sc);
1847	return (0);
1848error:
1849	BWN_UNLOCK(sc);
1850	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851	return (ENODEV);
1852}
1853
1854#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856
1857static int
1858bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859{
1860	struct bwn_softc *sc = mac->mac_sc;
1861	struct ifnet *ifp = sc->sc_ifp;
1862	struct ieee80211com *ic = ifp->if_l2com;
1863
1864	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865	ic->ic_nchans = 0;
1866
1867	if (have_bg)
1868		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871		if (have_a)
1872			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873			    &ic->ic_nchans, &bwn_chantable_n,
1874			    IEEE80211_CHAN_HTA);
1875	} else {
1876		if (have_a)
1877			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878			    &ic->ic_nchans, &bwn_chantable_a,
1879			    IEEE80211_CHAN_A);
1880	}
1881
1882	mac->mac_phy.supports_2ghz = have_bg;
1883	mac->mac_phy.supports_5ghz = have_a;
1884
1885	return (ic->ic_nchans == 0 ? ENXIO : 0);
1886}
1887
1888static uint32_t
1889bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890{
1891	uint32_t ret;
1892
1893	BWN_ASSERT_LOCKED(mac->mac_sc);
1894
1895	if (way == BWN_SHARED) {
1896		KASSERT((offset & 0x0001) == 0,
1897		    ("%s:%d warn", __func__, __LINE__));
1898		if (offset & 0x0003) {
1899			bwn_shm_ctlword(mac, way, offset >> 2);
1900			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901			ret <<= 16;
1902			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904			goto out;
1905		}
1906		offset >>= 2;
1907	}
1908	bwn_shm_ctlword(mac, way, offset);
1909	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910out:
1911	return (ret);
1912}
1913
1914static uint16_t
1915bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916{
1917	uint16_t ret;
1918
1919	BWN_ASSERT_LOCKED(mac->mac_sc);
1920
1921	if (way == BWN_SHARED) {
1922		KASSERT((offset & 0x0001) == 0,
1923		    ("%s:%d warn", __func__, __LINE__));
1924		if (offset & 0x0003) {
1925			bwn_shm_ctlword(mac, way, offset >> 2);
1926			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927			goto out;
1928		}
1929		offset >>= 2;
1930	}
1931	bwn_shm_ctlword(mac, way, offset);
1932	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933out:
1934
1935	return (ret);
1936}
1937
1938static void
1939bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940    uint16_t offset)
1941{
1942	uint32_t control;
1943
1944	control = way;
1945	control <<= 16;
1946	control |= offset;
1947	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948}
1949
1950static void
1951bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952    uint32_t value)
1953{
1954	BWN_ASSERT_LOCKED(mac->mac_sc);
1955
1956	if (way == BWN_SHARED) {
1957		KASSERT((offset & 0x0001) == 0,
1958		    ("%s:%d warn", __func__, __LINE__));
1959		if (offset & 0x0003) {
1960			bwn_shm_ctlword(mac, way, offset >> 2);
1961			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962				    (value >> 16) & 0xffff);
1963			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965			return;
1966		}
1967		offset >>= 2;
1968	}
1969	bwn_shm_ctlword(mac, way, offset);
1970	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971}
1972
1973static void
1974bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975    uint16_t value)
1976{
1977	BWN_ASSERT_LOCKED(mac->mac_sc);
1978
1979	if (way == BWN_SHARED) {
1980		KASSERT((offset & 0x0001) == 0,
1981		    ("%s:%d warn", __func__, __LINE__));
1982		if (offset & 0x0003) {
1983			bwn_shm_ctlword(mac, way, offset >> 2);
1984			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985			return;
1986		}
1987		offset >>= 2;
1988	}
1989	bwn_shm_ctlword(mac, way, offset);
1990	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991}
1992
1993static void
1994bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995    int txpow)
1996{
1997
1998	c->ic_freq = freq;
1999	c->ic_flags = flags;
2000	c->ic_ieee = ieee;
2001	c->ic_minpower = 0;
2002	c->ic_maxpower = 2 * txpow;
2003	c->ic_maxregpower = txpow;
2004}
2005
2006static void
2007bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008    const struct bwn_channelinfo *ci, int flags)
2009{
2010	struct ieee80211_channel *c;
2011	int i;
2012
2013	c = &chans[*nchans];
2014
2015	for (i = 0; i < ci->nchannels; i++) {
2016		const struct bwn_channel *hc;
2017
2018		hc = &ci->channels[i];
2019		if (*nchans >= maxchans)
2020			break;
2021		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022		c++, (*nchans)++;
2023		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024			/* g channel have a separate b-only entry */
2025			if (*nchans >= maxchans)
2026				break;
2027			c[0] = c[-1];
2028			c[-1].ic_flags = IEEE80211_CHAN_B;
2029			c++, (*nchans)++;
2030		}
2031		if (flags == IEEE80211_CHAN_HTG) {
2032			/* HT g channel have a separate g-only entry */
2033			if (*nchans >= maxchans)
2034				break;
2035			c[-1].ic_flags = IEEE80211_CHAN_G;
2036			c[0] = c[-1];
2037			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2039			c++, (*nchans)++;
2040		}
2041		if (flags == IEEE80211_CHAN_HTA) {
2042			/* HT a channel have a separate a-only entry */
2043			if (*nchans >= maxchans)
2044				break;
2045			c[-1].ic_flags = IEEE80211_CHAN_A;
2046			c[0] = c[-1];
2047			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2049			c++, (*nchans)++;
2050		}
2051	}
2052}
2053
2054static int
2055bwn_phy_g_attach(struct bwn_mac *mac)
2056{
2057	struct bwn_softc *sc = mac->mac_sc;
2058	struct bwn_phy *phy = &mac->mac_phy;
2059	struct bwn_phy_g *pg = &phy->phy_g;
2060	unsigned int i;
2061	int16_t pab0, pab1, pab2;
2062	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063	int8_t bg;
2064
2065	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069
2070	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071		device_printf(sc->sc_dev, "not supported anymore\n");
2072
2073	pg->pg_flags = 0;
2074	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075	    pab2 == -1) {
2076		pg->pg_idletssi = 52;
2077		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078		return (0);
2079	}
2080
2081	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083	if (pg->pg_tssi2dbm == NULL) {
2084		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085		return (ENOMEM);
2086	}
2087	for (i = 0; i < 64; i++) {
2088		int32_t m1, m2, f, q, delta;
2089		int8_t j = 0;
2090
2091		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093		f = 256;
2094
2095		do {
2096			if (j > 15) {
2097				device_printf(sc->sc_dev,
2098				    "failed to generate tssi2dBm\n");
2099				free(pg->pg_tssi2dbm, M_DEVBUF);
2100				return (ENOMEM);
2101			}
2102			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103			    f, 2048);
2104			delta = abs(q - f);
2105			f = q;
2106			j++;
2107		} while (delta >= 2);
2108
2109		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110		    128);
2111	}
2112
2113	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114	return (0);
2115}
2116
2117static void
2118bwn_phy_g_detach(struct bwn_mac *mac)
2119{
2120	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121
2122	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123		free(pg->pg_tssi2dbm, M_DEVBUF);
2124		pg->pg_tssi2dbm = NULL;
2125	}
2126	pg->pg_flags = 0;
2127}
2128
2129static void
2130bwn_phy_g_init_pre(struct bwn_mac *mac)
2131{
2132	struct bwn_phy *phy = &mac->mac_phy;
2133	struct bwn_phy_g *pg = &phy->phy_g;
2134	void *tssi2dbm;
2135	int idletssi;
2136	unsigned int i;
2137
2138	tssi2dbm = pg->pg_tssi2dbm;
2139	idletssi = pg->pg_idletssi;
2140
2141	memset(pg, 0, sizeof(*pg));
2142
2143	pg->pg_tssi2dbm = tssi2dbm;
2144	pg->pg_idletssi = idletssi;
2145
2146	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147
2148	for (i = 0; i < N(pg->pg_nrssi); i++)
2149		pg->pg_nrssi[i] = -1000;
2150	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151		pg->pg_nrssi_lt[i] = i;
2152	pg->pg_lofcal = 0xffff;
2153	pg->pg_initval = 0xffff;
2154	pg->pg_immode = BWN_IMMODE_NONE;
2155	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156	pg->pg_avgtssi = 0xff;
2157
2158	pg->pg_loctl.tx_bias = 0xff;
2159	TAILQ_INIT(&pg->pg_loctl.calib_list);
2160}
2161
2162static int
2163bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164{
2165	struct bwn_phy *phy = &mac->mac_phy;
2166	struct bwn_phy_g *pg = &phy->phy_g;
2167	struct bwn_softc *sc = mac->mac_sc;
2168	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169	static const struct bwn_rfatt rfatt0[] = {
2170		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2171		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172		{ 3, 1 }, { 4, 1 }
2173	};
2174	static const struct bwn_rfatt rfatt1[] = {
2175		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176		{ 14, 1 }
2177	};
2178	static const struct bwn_rfatt rfatt2[] = {
2179		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180		{ 9, 1 }
2181	};
2182	static const struct bwn_bbatt bbatt_0[] = {
2183		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184	};
2185
2186	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187
2188	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189		pg->pg_bbatt.att = 0;
2190	else
2191		pg->pg_bbatt.att = 2;
2192
2193	/* prepare Radio Attenuation */
2194	pg->pg_rfatt.padmix = 0;
2195
2196	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199			pg->pg_rfatt.att = 2;
2200			goto done;
2201		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202			pg->pg_rfatt.att = 3;
2203			goto done;
2204		}
2205	}
2206
2207	if (phy->type == BWN_PHYTYPE_A) {
2208		pg->pg_rfatt.att = 0x60;
2209		goto done;
2210	}
2211
2212	switch (phy->rf_ver) {
2213	case 0x2050:
2214		switch (phy->rf_rev) {
2215		case 0:
2216			pg->pg_rfatt.att = 5;
2217			goto done;
2218		case 1:
2219			if (phy->type == BWN_PHYTYPE_G) {
2220				if (siba_get_pci_subvendor(sc->sc_dev) ==
2221				    SIBA_BOARDVENDOR_BCM &&
2222				    siba_get_pci_subdevice(sc->sc_dev) ==
2223				    SIBA_BOARD_BCM4309G &&
2224				    siba_get_pci_revid(sc->sc_dev) >= 30)
2225					pg->pg_rfatt.att = 3;
2226				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227				    SIBA_BOARDVENDOR_BCM &&
2228				    siba_get_pci_subdevice(sc->sc_dev) ==
2229				    SIBA_BOARD_BU4306)
2230					pg->pg_rfatt.att = 3;
2231				else
2232					pg->pg_rfatt.att = 1;
2233			} else {
2234				if (siba_get_pci_subvendor(sc->sc_dev) ==
2235				    SIBA_BOARDVENDOR_BCM &&
2236				    siba_get_pci_subdevice(sc->sc_dev) ==
2237				    SIBA_BOARD_BCM4309G &&
2238				    siba_get_pci_revid(sc->sc_dev) >= 30)
2239					pg->pg_rfatt.att = 7;
2240				else
2241					pg->pg_rfatt.att = 6;
2242			}
2243			goto done;
2244		case 2:
2245			if (phy->type == BWN_PHYTYPE_G) {
2246				if (siba_get_pci_subvendor(sc->sc_dev) ==
2247				    SIBA_BOARDVENDOR_BCM &&
2248				    siba_get_pci_subdevice(sc->sc_dev) ==
2249				    SIBA_BOARD_BCM4309G &&
2250				    siba_get_pci_revid(sc->sc_dev) >= 30)
2251					pg->pg_rfatt.att = 3;
2252				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253				    SIBA_BOARDVENDOR_BCM &&
2254				    siba_get_pci_subdevice(sc->sc_dev) ==
2255				    SIBA_BOARD_BU4306)
2256					pg->pg_rfatt.att = 5;
2257				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258					pg->pg_rfatt.att = 4;
2259				else
2260					pg->pg_rfatt.att = 3;
2261			} else
2262				pg->pg_rfatt.att = 6;
2263			goto done;
2264		case 3:
2265			pg->pg_rfatt.att = 5;
2266			goto done;
2267		case 4:
2268		case 5:
2269			pg->pg_rfatt.att = 1;
2270			goto done;
2271		case 6:
2272		case 7:
2273			pg->pg_rfatt.att = 5;
2274			goto done;
2275		case 8:
2276			pg->pg_rfatt.att = 0xa;
2277			pg->pg_rfatt.padmix = 1;
2278			goto done;
2279		case 9:
2280		default:
2281			pg->pg_rfatt.att = 5;
2282			goto done;
2283		}
2284		break;
2285	case 0x2053:
2286		switch (phy->rf_rev) {
2287		case 1:
2288			pg->pg_rfatt.att = 6;
2289			goto done;
2290		}
2291		break;
2292	}
2293	pg->pg_rfatt.att = 5;
2294done:
2295	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296
2297	if (!bwn_has_hwpctl(mac)) {
2298		lo->rfatt.array = rfatt0;
2299		lo->rfatt.len = N(rfatt0);
2300		lo->rfatt.min = 0;
2301		lo->rfatt.max = 9;
2302		goto genbbatt;
2303	}
2304	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305		lo->rfatt.array = rfatt1;
2306		lo->rfatt.len = N(rfatt1);
2307		lo->rfatt.min = 0;
2308		lo->rfatt.max = 14;
2309		goto genbbatt;
2310	}
2311	lo->rfatt.array = rfatt2;
2312	lo->rfatt.len = N(rfatt2);
2313	lo->rfatt.min = 0;
2314	lo->rfatt.max = 9;
2315genbbatt:
2316	lo->bbatt.array = bbatt_0;
2317	lo->bbatt.len = N(bbatt_0);
2318	lo->bbatt.min = 0;
2319	lo->bbatt.max = 8;
2320
2321	BWN_READ_4(mac, BWN_MACCTL);
2322	if (phy->rev == 1) {
2323		phy->gmode = 0;
2324		bwn_reset_core(mac, 0);
2325		bwn_phy_g_init_sub(mac);
2326		phy->gmode = 1;
2327		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328	}
2329	return (0);
2330}
2331
2332static uint16_t
2333bwn_phy_g_txctl(struct bwn_mac *mac)
2334{
2335	struct bwn_phy *phy = &mac->mac_phy;
2336
2337	if (phy->rf_ver != 0x2050)
2338		return (0);
2339	if (phy->rf_rev == 1)
2340		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341	if (phy->rf_rev < 6)
2342		return (BWN_TXCTL_PA2DB);
2343	if (phy->rf_rev == 8)
2344		return (BWN_TXCTL_TXMIX);
2345	return (0);
2346}
2347
2348static int
2349bwn_phy_g_init(struct bwn_mac *mac)
2350{
2351
2352	bwn_phy_g_init_sub(mac);
2353	return (0);
2354}
2355
2356static void
2357bwn_phy_g_exit(struct bwn_mac *mac)
2358{
2359	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360	struct bwn_lo_calib *cal, *tmp;
2361
2362	if (lo == NULL)
2363		return;
2364	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365		TAILQ_REMOVE(&lo->calib_list, cal, list);
2366		free(cal, M_DEVBUF);
2367	}
2368}
2369
2370static uint16_t
2371bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372{
2373
2374	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375	return (BWN_READ_2(mac, BWN_PHYDATA));
2376}
2377
2378static void
2379bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380{
2381
2382	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384}
2385
2386static uint16_t
2387bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388{
2389
2390	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392	return (BWN_READ_2(mac, BWN_RFDATALO));
2393}
2394
2395static void
2396bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397{
2398
2399	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402}
2403
2404static int
2405bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406{
2407
2408	return (mac->mac_phy.rev >= 6);
2409}
2410
2411static void
2412bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413{
2414	struct bwn_phy *phy = &mac->mac_phy;
2415	struct bwn_phy_g *pg = &phy->phy_g;
2416	unsigned int channel;
2417	uint16_t rfover, rfoverval;
2418
2419	if (on) {
2420		if (phy->rf_on)
2421			return;
2422
2423		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428			    pg->pg_radioctx_over);
2429			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430			    pg->pg_radioctx_overval);
2431			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432		}
2433		channel = phy->chan;
2434		bwn_phy_g_switch_chan(mac, 6, 1);
2435		bwn_phy_g_switch_chan(mac, channel, 0);
2436		return;
2437	}
2438
2439	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441	pg->pg_radioctx_over = rfover;
2442	pg->pg_radioctx_overval = rfoverval;
2443	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446}
2447
2448static int
2449bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450{
2451
2452	if ((newchan < 1) || (newchan > 14))
2453		return (EINVAL);
2454	bwn_phy_g_switch_chan(mac, newchan, 0);
2455
2456	return (0);
2457}
2458
2459static uint32_t
2460bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461{
2462
2463	return (1);
2464}
2465
2466static void
2467bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468{
2469	struct bwn_phy *phy = &mac->mac_phy;
2470	uint64_t hf;
2471	int autodiv = 0;
2472	uint16_t tmp;
2473
2474	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475		autodiv = 1;
2476
2477	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478	bwn_hf_write(mac, hf);
2479
2480	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2483		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484
2485	if (autodiv) {
2486		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487		if (antenna == BWN_ANTAUTO1)
2488			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489		else
2490			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492	}
2493	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494	if (autodiv)
2495		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496	else
2497		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499	if (phy->rev >= 2) {
2500		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504		    0x15);
2505		if (phy->rev == 2)
2506			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507		else
2508			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510			    8);
2511	}
2512	if (phy->rev >= 6)
2513		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514
2515	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516	bwn_hf_write(mac, hf);
2517}
2518
2519static int
2520bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521{
2522	struct bwn_phy *phy = &mac->mac_phy;
2523	struct bwn_phy_g *pg = &phy->phy_g;
2524
2525	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527
2528	if (phy->rev == 0 || !phy->gmode)
2529		return (ENODEV);
2530
2531	pg->pg_aci_wlan_automatic = 0;
2532	return (0);
2533}
2534
2535static int
2536bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537{
2538	struct bwn_phy *phy = &mac->mac_phy;
2539	struct bwn_phy_g *pg = &phy->phy_g;
2540	struct bwn_softc *sc = mac->mac_sc;
2541	unsigned int tssi;
2542	int cck, ofdm;
2543	int power;
2544	int rfatt, bbatt;
2545	unsigned int max;
2546
2547	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548
2549	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551	if (cck < 0 && ofdm < 0) {
2552		if (ignore_tssi == 0)
2553			return (BWN_TXPWR_RES_DONE);
2554		cck = 0;
2555		ofdm = 0;
2556	}
2557	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558	if (pg->pg_avgtssi != 0xff)
2559		tssi = (tssi + pg->pg_avgtssi) / 2;
2560	pg->pg_avgtssi = tssi;
2561	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562
2563	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565		max -= 3;
2566	if (max >= 120) {
2567		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568		max = 80;
2569		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570	}
2571
2572	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574	     tssi, 0x00), 0x3f)]);
2575	if (power == 0)
2576		return (BWN_TXPWR_RES_DONE);
2577
2578	rfatt = -((power + 7) / 8);
2579	bbatt = (-(power / 2)) - (4 * rfatt);
2580	if ((rfatt == 0) && (bbatt == 0))
2581		return (BWN_TXPWR_RES_DONE);
2582	pg->pg_bbatt_delta = bbatt;
2583	pg->pg_rfatt_delta = rfatt;
2584	return (BWN_TXPWR_RES_NEED_ADJUST);
2585}
2586
2587static void
2588bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589{
2590	struct bwn_phy *phy = &mac->mac_phy;
2591	struct bwn_phy_g *pg = &phy->phy_g;
2592	struct bwn_softc *sc = mac->mac_sc;
2593	int rfatt, bbatt;
2594	uint8_t txctl;
2595
2596	bwn_mac_suspend(mac);
2597
2598	BWN_ASSERT_LOCKED(sc);
2599
2600	bbatt = pg->pg_bbatt.att;
2601	bbatt += pg->pg_bbatt_delta;
2602	rfatt = pg->pg_rfatt.att;
2603	rfatt += pg->pg_rfatt_delta;
2604
2605	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606	txctl = pg->pg_txctl;
2607	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608		if (rfatt <= 1) {
2609			if (txctl == 0) {
2610				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611				rfatt += 2;
2612				bbatt += 2;
2613			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614			    BWN_BFL_PACTRL) {
2615				bbatt += 4 * (rfatt - 2);
2616				rfatt = 2;
2617			}
2618		} else if (rfatt > 4 && txctl) {
2619			txctl = 0;
2620			if (bbatt < 3) {
2621				rfatt -= 3;
2622				bbatt += 2;
2623			} else {
2624				rfatt -= 2;
2625				bbatt -= 2;
2626			}
2627		}
2628	}
2629	pg->pg_txctl = txctl;
2630	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631	pg->pg_rfatt.att = rfatt;
2632	pg->pg_bbatt.att = bbatt;
2633
2634	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635
2636	bwn_phy_lock(mac);
2637	bwn_rf_lock(mac);
2638	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639	    pg->pg_txctl);
2640	bwn_rf_unlock(mac);
2641	bwn_phy_unlock(mac);
2642
2643	bwn_mac_enable(mac);
2644}
2645
2646static void
2647bwn_phy_g_task_15s(struct bwn_mac *mac)
2648{
2649	struct bwn_phy *phy = &mac->mac_phy;
2650	struct bwn_phy_g *pg = &phy->phy_g;
2651	struct bwn_softc *sc = mac->mac_sc;
2652	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653	unsigned long expire, now;
2654	struct bwn_lo_calib *cal, *tmp;
2655	uint8_t expired = 0;
2656
2657	bwn_mac_suspend(mac);
2658
2659	if (lo == NULL)
2660		goto fail;
2661
2662	BWN_GETTIME(now);
2663	if (bwn_has_hwpctl(mac)) {
2664		expire = now - BWN_LO_PWRVEC_EXPIRE;
2665		if (time_before(lo->pwr_vec_read_time, expire)) {
2666			bwn_lo_get_powervector(mac);
2667			bwn_phy_g_dc_lookup_init(mac, 0);
2668		}
2669		goto fail;
2670	}
2671
2672	expire = now - BWN_LO_CALIB_EXPIRE;
2673	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674		if (!time_before(cal->calib_time, expire))
2675			continue;
2676		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679			expired = 1;
2680		}
2681
2682		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684		    cal->ctl.i, cal->ctl.q);
2685
2686		TAILQ_REMOVE(&lo->calib_list, cal, list);
2687		free(cal, M_DEVBUF);
2688	}
2689	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691		    &pg->pg_rfatt);
2692		if (cal == NULL) {
2693			device_printf(sc->sc_dev,
2694			    "failed to recalibrate LO\n");
2695			goto fail;
2696		}
2697		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698		bwn_lo_write(mac, &cal->ctl);
2699	}
2700
2701fail:
2702	bwn_mac_enable(mac);
2703}
2704
2705static void
2706bwn_phy_g_task_60s(struct bwn_mac *mac)
2707{
2708	struct bwn_phy *phy = &mac->mac_phy;
2709	struct bwn_softc *sc = mac->mac_sc;
2710	uint8_t old = phy->chan;
2711
2712	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713		return;
2714
2715	bwn_mac_suspend(mac);
2716	bwn_nrssi_slope_11g(mac);
2717	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719		bwn_switch_channel(mac, old);
2720	}
2721	bwn_mac_enable(mac);
2722}
2723
2724static void
2725bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726{
2727
2728	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729}
2730
2731static int
2732bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733	const struct ieee80211_bpf_params *params)
2734{
2735	struct ieee80211com *ic = ni->ni_ic;
2736	struct ifnet *ifp = ic->ic_ifp;
2737	struct bwn_softc *sc = ifp->if_softc;
2738	struct bwn_mac *mac = sc->sc_curmac;
2739
2740	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742		ieee80211_free_node(ni);
2743		m_freem(m);
2744		return (ENETDOWN);
2745	}
2746
2747	BWN_LOCK(sc);
2748	if (bwn_tx_isfull(sc, m)) {
2749		ieee80211_free_node(ni);
2750		m_freem(m);
2751		ifp->if_oerrors++;
2752		BWN_UNLOCK(sc);
2753		return (ENOBUFS);
2754	}
2755
2756	if (bwn_tx_start(sc, ni, m) != 0) {
2757		if (ni != NULL)
2758			ieee80211_free_node(ni);
2759		ifp->if_oerrors++;
2760	}
2761	sc->sc_watchdog_timer = 5;
2762	BWN_UNLOCK(sc);
2763	return (0);
2764}
2765
2766/*
2767 * Callback from the 802.11 layer to update the slot time
2768 * based on the current setting.  We use it to notify the
2769 * firmware of ERP changes and the f/w takes care of things
2770 * like slot time and preamble.
2771 */
2772static void
2773bwn_updateslot(struct ifnet *ifp)
2774{
2775	struct bwn_softc *sc = ifp->if_softc;
2776	struct ieee80211com *ic = ifp->if_l2com;
2777	struct bwn_mac *mac;
2778
2779	BWN_LOCK(sc);
2780	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781		mac = (struct bwn_mac *)sc->sc_curmac;
2782		bwn_set_slot_time(mac,
2783		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784	}
2785	BWN_UNLOCK(sc);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer after a promiscuous mode change.
2790 * Note this interface does not check the operating mode as this
2791 * is an internal callback and we are expected to honor the current
2792 * state (e.g. this is used for setting the interface in promiscuous
2793 * mode when operating in hostap mode to do ACS).
2794 */
2795static void
2796bwn_update_promisc(struct ifnet *ifp)
2797{
2798	struct bwn_softc *sc = ifp->if_softc;
2799	struct bwn_mac *mac = sc->sc_curmac;
2800
2801	BWN_LOCK(sc);
2802	mac = sc->sc_curmac;
2803	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804		if (ifp->if_flags & IFF_PROMISC)
2805			sc->sc_filters |= BWN_MACCTL_PROMISC;
2806		else
2807			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808		bwn_set_opmode(mac);
2809	}
2810	BWN_UNLOCK(sc);
2811}
2812
2813/*
2814 * Callback from the 802.11 layer to update WME parameters.
2815 */
2816static int
2817bwn_wme_update(struct ieee80211com *ic)
2818{
2819	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820	struct bwn_mac *mac = sc->sc_curmac;
2821	struct wmeParams *wmep;
2822	int i;
2823
2824	BWN_LOCK(sc);
2825	mac = sc->sc_curmac;
2826	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827		bwn_mac_suspend(mac);
2828		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831		}
2832		bwn_mac_enable(mac);
2833	}
2834	BWN_UNLOCK(sc);
2835	return (0);
2836}
2837
2838static void
2839bwn_scan_start(struct ieee80211com *ic)
2840{
2841	struct ifnet *ifp = ic->ic_ifp;
2842	struct bwn_softc *sc = ifp->if_softc;
2843	struct bwn_mac *mac;
2844
2845	BWN_LOCK(sc);
2846	mac = sc->sc_curmac;
2847	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849		bwn_set_opmode(mac);
2850		/* disable CFP update during scan */
2851		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852	}
2853	BWN_UNLOCK(sc);
2854}
2855
2856static void
2857bwn_scan_end(struct ieee80211com *ic)
2858{
2859	struct ifnet *ifp = ic->ic_ifp;
2860	struct bwn_softc *sc = ifp->if_softc;
2861	struct bwn_mac *mac;
2862
2863	BWN_LOCK(sc);
2864	mac = sc->sc_curmac;
2865	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867		bwn_set_opmode(mac);
2868		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869	}
2870	BWN_UNLOCK(sc);
2871}
2872
2873static void
2874bwn_set_channel(struct ieee80211com *ic)
2875{
2876	struct ifnet *ifp = ic->ic_ifp;
2877	struct bwn_softc *sc = ifp->if_softc;
2878	struct bwn_mac *mac = sc->sc_curmac;
2879	struct bwn_phy *phy = &mac->mac_phy;
2880	int chan, error;
2881
2882	BWN_LOCK(sc);
2883
2884	error = bwn_switch_band(sc, ic->ic_curchan);
2885	if (error)
2886		goto fail;;
2887	bwn_mac_suspend(mac);
2888	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890	if (chan != phy->chan)
2891		bwn_switch_channel(mac, chan);
2892
2893	/* TX power level */
2894	if (ic->ic_curchan->ic_maxpower != 0 &&
2895	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2896		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898		    BWN_TXPWR_IGNORE_TSSI);
2899	}
2900
2901	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902	if (phy->set_antenna)
2903		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904
2905	if (sc->sc_rf_enabled != phy->rf_on) {
2906		if (sc->sc_rf_enabled) {
2907			bwn_rf_turnon(mac);
2908			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909				device_printf(sc->sc_dev,
2910				    "please turn on the RF switch\n");
2911		} else
2912			bwn_rf_turnoff(mac);
2913	}
2914
2915	bwn_mac_enable(mac);
2916
2917fail:
2918	/*
2919	 * Setup radio tap channel freq and flags
2920	 */
2921	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922		htole16(ic->ic_curchan->ic_freq);
2923	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924		htole16(ic->ic_curchan->ic_flags & 0xffff);
2925
2926	BWN_UNLOCK(sc);
2927}
2928
2929static struct ieee80211vap *
2930bwn_vap_create(struct ieee80211com *ic,
2931	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2932	const uint8_t bssid[IEEE80211_ADDR_LEN],
2933	const uint8_t mac0[IEEE80211_ADDR_LEN])
2934{
2935	struct ifnet *ifp = ic->ic_ifp;
2936	struct bwn_softc *sc = ifp->if_softc;
2937	struct ieee80211vap *vap;
2938	struct bwn_vap *bvp;
2939	uint8_t mac[IEEE80211_ADDR_LEN];
2940
2941	IEEE80211_ADDR_COPY(mac, mac0);
2942	switch (opmode) {
2943	case IEEE80211_M_HOSTAP:
2944	case IEEE80211_M_MBSS:
2945	case IEEE80211_M_STA:
2946	case IEEE80211_M_WDS:
2947	case IEEE80211_M_MONITOR:
2948	case IEEE80211_M_IBSS:
2949	case IEEE80211_M_AHDEMO:
2950		break;
2951	default:
2952		return (NULL);
2953	}
2954
2955	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956
2957	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958	    M_80211_VAP, M_NOWAIT | M_ZERO);
2959	if (bvp == NULL) {
2960		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961		return (NULL);
2962	}
2963	vap = &bvp->bv_vap;
2964	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966	/* override with driver methods */
2967	bvp->bv_newstate = vap->iv_newstate;
2968	vap->iv_newstate = bwn_newstate;
2969
2970	/* override max aid so sta's cannot assoc when we're out of sta id's */
2971	vap->iv_max_aid = BWN_STAID_MAX;
2972
2973	ieee80211_ratectl_init(vap);
2974
2975	/* complete setup */
2976	ieee80211_vap_attach(vap, ieee80211_media_change,
2977	    ieee80211_media_status);
2978	return (vap);
2979}
2980
2981static void
2982bwn_vap_delete(struct ieee80211vap *vap)
2983{
2984	struct bwn_vap *bvp = BWN_VAP(vap);
2985
2986	ieee80211_ratectl_deinit(vap);
2987	ieee80211_vap_detach(vap);
2988	free(bvp, M_80211_VAP);
2989}
2990
2991static void
2992bwn_init(void *arg)
2993{
2994	struct bwn_softc *sc = arg;
2995	struct ifnet *ifp = sc->sc_ifp;
2996	struct ieee80211com *ic = ifp->if_l2com;
2997	int error = 0;
2998
2999	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000		__func__, ifp->if_flags);
3001
3002	BWN_LOCK(sc);
3003	error = bwn_init_locked(sc);
3004	BWN_UNLOCK(sc);
3005
3006	if (error == 0)
3007		ieee80211_start_all(ic);	/* start all vap's */
3008}
3009
3010static int
3011bwn_init_locked(struct bwn_softc *sc)
3012{
3013	struct bwn_mac *mac;
3014	struct ifnet *ifp = sc->sc_ifp;
3015	int error;
3016
3017	BWN_ASSERT_LOCKED(sc);
3018
3019	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021	sc->sc_filters = 0;
3022	bwn_wme_clear(sc);
3023	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024	sc->sc_rf_enabled = 1;
3025
3026	mac = sc->sc_curmac;
3027	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028		error = bwn_core_init(mac);
3029		if (error != 0)
3030			return (error);
3031	}
3032	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033		bwn_core_start(mac);
3034
3035	bwn_set_opmode(mac);
3036	bwn_set_pretbtt(mac);
3037	bwn_spu_setdelay(mac, 0);
3038	bwn_set_macaddr(mac);
3039
3040	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043
3044	return (0);
3045}
3046
3047static void
3048bwn_stop(struct bwn_softc *sc, int statechg)
3049{
3050
3051	BWN_LOCK(sc);
3052	bwn_stop_locked(sc, statechg);
3053	BWN_UNLOCK(sc);
3054}
3055
3056static void
3057bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058{
3059	struct bwn_mac *mac = sc->sc_curmac;
3060	struct ifnet *ifp = sc->sc_ifp;
3061
3062	BWN_ASSERT_LOCKED(sc);
3063
3064	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065		/* XXX FIXME opmode not based on VAP */
3066		bwn_set_opmode(mac);
3067		bwn_set_macaddr(mac);
3068	}
3069
3070	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071		bwn_core_stop(mac);
3072
3073	callout_stop(&sc->sc_led_blink_ch);
3074	sc->sc_led_blinking = 0;
3075
3076	bwn_core_exit(mac);
3077	sc->sc_rf_enabled = 0;
3078
3079	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080}
3081
3082static void
3083bwn_wme_clear(struct bwn_softc *sc)
3084{
3085#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3086	struct wmeParams *p;
3087	unsigned int i;
3088
3089	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090	    ("%s:%d: fail", __func__, __LINE__));
3091
3092	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093		p = &(sc->sc_wmeParams[i]);
3094
3095		switch (bwn_wme_shm_offsets[i]) {
3096		case BWN_WME_VOICE:
3097			p->wmep_txopLimit = 0;
3098			p->wmep_aifsn = 2;
3099			/* XXX FIXME: log2(cwmin) */
3100			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102			break;
3103		case BWN_WME_VIDEO:
3104			p->wmep_txopLimit = 0;
3105			p->wmep_aifsn = 2;
3106			/* XXX FIXME: log2(cwmin) */
3107			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109			break;
3110		case BWN_WME_BESTEFFORT:
3111			p->wmep_txopLimit = 0;
3112			p->wmep_aifsn = 3;
3113			/* XXX FIXME: log2(cwmin) */
3114			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116			break;
3117		case BWN_WME_BACKGROUND:
3118			p->wmep_txopLimit = 0;
3119			p->wmep_aifsn = 7;
3120			/* XXX FIXME: log2(cwmin) */
3121			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123			break;
3124		default:
3125			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126		}
3127	}
3128}
3129
3130static int
3131bwn_core_init(struct bwn_mac *mac)
3132{
3133	struct bwn_softc *sc = mac->mac_sc;
3134	uint64_t hf;
3135	int error;
3136
3137	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138	    ("%s:%d: fail", __func__, __LINE__));
3139
3140	siba_powerup(sc->sc_dev, 0);
3141	if (!siba_dev_isup(sc->sc_dev))
3142		bwn_reset_core(mac,
3143		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144
3145	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148	BWN_GETTIME(mac->mac_phy.nexttime);
3149	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151	mac->mac_stats.link_noise = -95;
3152	mac->mac_reason_intr = 0;
3153	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155#ifdef BWN_DEBUG
3156	if (sc->sc_debug & BWN_DEBUG_XMIT)
3157		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158#endif
3159	mac->mac_suspended = 1;
3160	mac->mac_task_state = 0;
3161	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162
3163	mac->mac_phy.init_pre(mac);
3164
3165	siba_pcicore_intr(sc->sc_dev);
3166
3167	siba_fix_imcfglobug(sc->sc_dev);
3168	bwn_bt_disable(mac);
3169	if (mac->mac_phy.prepare_hw) {
3170		error = mac->mac_phy.prepare_hw(mac);
3171		if (error)
3172			goto fail0;
3173	}
3174	error = bwn_chip_init(mac);
3175	if (error)
3176		goto fail0;
3177	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178	    siba_get_revid(sc->sc_dev));
3179	hf = bwn_hf_read(mac);
3180	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184		if (mac->mac_phy.rev == 1)
3185			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186	}
3187	if (mac->mac_phy.rf_ver == 0x2050) {
3188		if (mac->mac_phy.rf_rev < 6)
3189			hf |= BWN_HF_FORCE_VCO_RECALC;
3190		if (mac->mac_phy.rf_rev == 6)
3191			hf |= BWN_HF_4318_TSSI;
3192	}
3193	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199	bwn_hf_write(mac, hf);
3200
3201	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205
3206	bwn_rate_init(mac);
3207	bwn_set_phytxctl(mac);
3208
3209	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212
3213	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214		bwn_pio_init(mac);
3215	else
3216		bwn_dma_init(mac);
3217	if (error)
3218		goto fail1;
3219	bwn_wme_init(mac);
3220	bwn_spu_setdelay(mac, 1);
3221	bwn_bt_enable(mac);
3222
3223	siba_powerup(sc->sc_dev,
3224	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3225	bwn_set_macaddr(mac);
3226	bwn_crypt_init(mac);
3227
3228	/* XXX LED initializatin */
3229
3230	mac->mac_status = BWN_MAC_STATUS_INITED;
3231
3232	return (error);
3233
3234fail1:
3235	bwn_chip_exit(mac);
3236fail0:
3237	siba_powerdown(sc->sc_dev);
3238	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3239	    ("%s:%d: fail", __func__, __LINE__));
3240	return (error);
3241}
3242
3243static void
3244bwn_core_start(struct bwn_mac *mac)
3245{
3246	struct bwn_softc *sc = mac->mac_sc;
3247	uint32_t tmp;
3248
3249	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3250	    ("%s:%d: fail", __func__, __LINE__));
3251
3252	if (siba_get_revid(sc->sc_dev) < 5)
3253		return;
3254
3255	while (1) {
3256		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3257		if (!(tmp & 0x00000001))
3258			break;
3259		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3260	}
3261
3262	bwn_mac_enable(mac);
3263	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3264	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3265
3266	mac->mac_status = BWN_MAC_STATUS_STARTED;
3267}
3268
3269static void
3270bwn_core_exit(struct bwn_mac *mac)
3271{
3272	struct bwn_softc *sc = mac->mac_sc;
3273	uint32_t macctl;
3274
3275	BWN_ASSERT_LOCKED(mac->mac_sc);
3276
3277	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3278	    ("%s:%d: fail", __func__, __LINE__));
3279
3280	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3281		return;
3282	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3283
3284	macctl = BWN_READ_4(mac, BWN_MACCTL);
3285	macctl &= ~BWN_MACCTL_MCODE_RUN;
3286	macctl |= BWN_MACCTL_MCODE_JMP0;
3287	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3288
3289	bwn_dma_stop(mac);
3290	bwn_pio_stop(mac);
3291	bwn_chip_exit(mac);
3292	mac->mac_phy.switch_analog(mac, 0);
3293	siba_dev_down(sc->sc_dev, 0);
3294	siba_powerdown(sc->sc_dev);
3295}
3296
3297static void
3298bwn_bt_disable(struct bwn_mac *mac)
3299{
3300	struct bwn_softc *sc = mac->mac_sc;
3301
3302	(void)sc;
3303	/* XXX do nothing yet */
3304}
3305
3306static int
3307bwn_chip_init(struct bwn_mac *mac)
3308{
3309	struct bwn_softc *sc = mac->mac_sc;
3310	struct bwn_phy *phy = &mac->mac_phy;
3311	uint32_t macctl;
3312	int error;
3313
3314	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3315	if (phy->gmode)
3316		macctl |= BWN_MACCTL_GMODE;
3317	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3318
3319	error = bwn_fw_fillinfo(mac);
3320	if (error)
3321		return (error);
3322	error = bwn_fw_loaducode(mac);
3323	if (error)
3324		return (error);
3325
3326	error = bwn_gpio_init(mac);
3327	if (error)
3328		return (error);
3329
3330	error = bwn_fw_loadinitvals(mac);
3331	if (error) {
3332		siba_gpio_set(sc->sc_dev, 0);
3333		return (error);
3334	}
3335	phy->switch_analog(mac, 1);
3336	error = bwn_phy_init(mac);
3337	if (error) {
3338		siba_gpio_set(sc->sc_dev, 0);
3339		return (error);
3340	}
3341	if (phy->set_im)
3342		phy->set_im(mac, BWN_IMMODE_NONE);
3343	if (phy->set_antenna)
3344		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3345	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3346
3347	if (phy->type == BWN_PHYTYPE_B)
3348		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3349	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3350	if (siba_get_revid(sc->sc_dev) < 5)
3351		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3352
3353	BWN_WRITE_4(mac, BWN_MACCTL,
3354	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3355	BWN_WRITE_4(mac, BWN_MACCTL,
3356	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3357	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3358
3359	bwn_set_opmode(mac);
3360	if (siba_get_revid(sc->sc_dev) < 3) {
3361		BWN_WRITE_2(mac, 0x060e, 0x0000);
3362		BWN_WRITE_2(mac, 0x0610, 0x8000);
3363		BWN_WRITE_2(mac, 0x0604, 0x0000);
3364		BWN_WRITE_2(mac, 0x0606, 0x0200);
3365	} else {
3366		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3367		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3368	}
3369	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3370	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3371	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3372	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3373	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3374	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3375	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3376	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3377	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3378	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3379	return (error);
3380}
3381
3382/* read hostflags */
3383static uint64_t
3384bwn_hf_read(struct bwn_mac *mac)
3385{
3386	uint64_t ret;
3387
3388	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3389	ret <<= 16;
3390	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3391	ret <<= 16;
3392	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3393	return (ret);
3394}
3395
3396static void
3397bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3398{
3399
3400	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3401	    (value & 0x00000000ffffull));
3402	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3403	    (value & 0x0000ffff0000ull) >> 16);
3404	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3405	    (value & 0xffff00000000ULL) >> 32);
3406}
3407
3408static void
3409bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3410{
3411
3412	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3413	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3414}
3415
3416static void
3417bwn_rate_init(struct bwn_mac *mac)
3418{
3419
3420	switch (mac->mac_phy.type) {
3421	case BWN_PHYTYPE_A:
3422	case BWN_PHYTYPE_G:
3423	case BWN_PHYTYPE_LP:
3424	case BWN_PHYTYPE_N:
3425		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3427		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3428		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3429		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3430		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3431		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3432		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3433			break;
3434		/* FALLTHROUGH */
3435	case BWN_PHYTYPE_B:
3436		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3437		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3438		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3439		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3440		break;
3441	default:
3442		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3443	}
3444}
3445
3446static void
3447bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3448{
3449	uint16_t offset;
3450
3451	if (ofdm) {
3452		offset = 0x480;
3453		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3454	} else {
3455		offset = 0x4c0;
3456		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3457	}
3458	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3459	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3460}
3461
3462static uint8_t
3463bwn_plcp_getcck(const uint8_t bitrate)
3464{
3465
3466	switch (bitrate) {
3467	case BWN_CCK_RATE_1MB:
3468		return (0x0a);
3469	case BWN_CCK_RATE_2MB:
3470		return (0x14);
3471	case BWN_CCK_RATE_5MB:
3472		return (0x37);
3473	case BWN_CCK_RATE_11MB:
3474		return (0x6e);
3475	}
3476	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3477	return (0);
3478}
3479
3480static uint8_t
3481bwn_plcp_getofdm(const uint8_t bitrate)
3482{
3483
3484	switch (bitrate) {
3485	case BWN_OFDM_RATE_6MB:
3486		return (0xb);
3487	case BWN_OFDM_RATE_9MB:
3488		return (0xf);
3489	case BWN_OFDM_RATE_12MB:
3490		return (0xa);
3491	case BWN_OFDM_RATE_18MB:
3492		return (0xe);
3493	case BWN_OFDM_RATE_24MB:
3494		return (0x9);
3495	case BWN_OFDM_RATE_36MB:
3496		return (0xd);
3497	case BWN_OFDM_RATE_48MB:
3498		return (0x8);
3499	case BWN_OFDM_RATE_54MB:
3500		return (0xc);
3501	}
3502	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3503	return (0);
3504}
3505
3506static void
3507bwn_set_phytxctl(struct bwn_mac *mac)
3508{
3509	uint16_t ctl;
3510
3511	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3512	    BWN_TX_PHY_TXPWR);
3513	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3514	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3515	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3516}
3517
3518static void
3519bwn_pio_init(struct bwn_mac *mac)
3520{
3521	struct bwn_pio *pio = &mac->mac_method.pio;
3522
3523	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3524	    & ~BWN_MACCTL_BIGENDIAN);
3525	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3526
3527	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3528	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3529	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3530	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3531	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3532	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3533}
3534
3535static void
3536bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3537    int index)
3538{
3539	struct bwn_pio_txpkt *tp;
3540	struct bwn_softc *sc = mac->mac_sc;
3541	unsigned int i;
3542
3543	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3544	tq->tq_index = index;
3545
3546	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3547	if (siba_get_revid(sc->sc_dev) >= 8)
3548		tq->tq_size = 1920;
3549	else {
3550		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3551		tq->tq_size -= 80;
3552	}
3553
3554	TAILQ_INIT(&tq->tq_pktlist);
3555	for (i = 0; i < N(tq->tq_pkts); i++) {
3556		tp = &(tq->tq_pkts[i]);
3557		tp->tp_index = i;
3558		tp->tp_queue = tq;
3559		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3560	}
3561}
3562
3563static uint16_t
3564bwn_pio_idx2base(struct bwn_mac *mac, int index)
3565{
3566	struct bwn_softc *sc = mac->mac_sc;
3567	static const uint16_t bases[] = {
3568		BWN_PIO_BASE0,
3569		BWN_PIO_BASE1,
3570		BWN_PIO_BASE2,
3571		BWN_PIO_BASE3,
3572		BWN_PIO_BASE4,
3573		BWN_PIO_BASE5,
3574		BWN_PIO_BASE6,
3575		BWN_PIO_BASE7,
3576	};
3577	static const uint16_t bases_rev11[] = {
3578		BWN_PIO11_BASE0,
3579		BWN_PIO11_BASE1,
3580		BWN_PIO11_BASE2,
3581		BWN_PIO11_BASE3,
3582		BWN_PIO11_BASE4,
3583		BWN_PIO11_BASE5,
3584	};
3585
3586	if (siba_get_revid(sc->sc_dev) >= 11) {
3587		if (index >= N(bases_rev11))
3588			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589		return (bases_rev11[index]);
3590	}
3591	if (index >= N(bases))
3592		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3593	return (bases[index]);
3594}
3595
3596static void
3597bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3598    int index)
3599{
3600	struct bwn_softc *sc = mac->mac_sc;
3601
3602	prq->prq_mac = mac;
3603	prq->prq_rev = siba_get_revid(sc->sc_dev);
3604	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3605	bwn_dma_rxdirectfifo(mac, index, 1);
3606}
3607
3608static void
3609bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3610{
3611	if (tq == NULL)
3612		return;
3613	bwn_pio_cancel_tx_packets(tq);
3614}
3615
3616static void
3617bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3618{
3619
3620	bwn_destroy_pioqueue_tx(pio);
3621}
3622
3623static uint16_t
3624bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3625    uint16_t offset)
3626{
3627
3628	return (BWN_READ_2(mac, tq->tq_base + offset));
3629}
3630
3631static void
3632bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3633{
3634	uint32_t ctl;
3635	int type;
3636	uint16_t base;
3637
3638	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3639	base = bwn_dma_base(type, idx);
3640	if (type == BWN_DMA_64BIT) {
3641		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3642		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3643		if (enable)
3644			ctl |= BWN_DMA64_RXDIRECTFIFO;
3645		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3646	} else {
3647		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3648		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3649		if (enable)
3650			ctl |= BWN_DMA32_RXDIRECTFIFO;
3651		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3652	}
3653}
3654
3655static uint64_t
3656bwn_dma_mask(struct bwn_mac *mac)
3657{
3658	uint32_t tmp;
3659	uint16_t base;
3660
3661	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3662	if (tmp & SIBA_TGSHIGH_DMA64)
3663		return (BWN_DMA_BIT_MASK(64));
3664	base = bwn_dma_base(0, 0);
3665	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3666	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3667	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3668		return (BWN_DMA_BIT_MASK(32));
3669
3670	return (BWN_DMA_BIT_MASK(30));
3671}
3672
3673static int
3674bwn_dma_mask2type(uint64_t dmamask)
3675{
3676
3677	if (dmamask == BWN_DMA_BIT_MASK(30))
3678		return (BWN_DMA_30BIT);
3679	if (dmamask == BWN_DMA_BIT_MASK(32))
3680		return (BWN_DMA_32BIT);
3681	if (dmamask == BWN_DMA_BIT_MASK(64))
3682		return (BWN_DMA_64BIT);
3683	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3684	return (BWN_DMA_30BIT);
3685}
3686
3687static void
3688bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3689{
3690	struct bwn_pio_txpkt *tp;
3691	unsigned int i;
3692
3693	for (i = 0; i < N(tq->tq_pkts); i++) {
3694		tp = &(tq->tq_pkts[i]);
3695		if (tp->tp_m) {
3696			m_freem(tp->tp_m);
3697			tp->tp_m = NULL;
3698		}
3699	}
3700}
3701
3702static uint16_t
3703bwn_dma_base(int type, int controller_idx)
3704{
3705	static const uint16_t map64[] = {
3706		BWN_DMA64_BASE0,
3707		BWN_DMA64_BASE1,
3708		BWN_DMA64_BASE2,
3709		BWN_DMA64_BASE3,
3710		BWN_DMA64_BASE4,
3711		BWN_DMA64_BASE5,
3712	};
3713	static const uint16_t map32[] = {
3714		BWN_DMA32_BASE0,
3715		BWN_DMA32_BASE1,
3716		BWN_DMA32_BASE2,
3717		BWN_DMA32_BASE3,
3718		BWN_DMA32_BASE4,
3719		BWN_DMA32_BASE5,
3720	};
3721
3722	if (type == BWN_DMA_64BIT) {
3723		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3724		    ("%s:%d: fail", __func__, __LINE__));
3725		return (map64[controller_idx]);
3726	}
3727	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3728	    ("%s:%d: fail", __func__, __LINE__));
3729	return (map32[controller_idx]);
3730}
3731
3732static void
3733bwn_dma_init(struct bwn_mac *mac)
3734{
3735	struct bwn_dma *dma = &mac->mac_method.dma;
3736
3737	/* setup TX DMA channels. */
3738	bwn_dma_setup(dma->wme[WME_AC_BK]);
3739	bwn_dma_setup(dma->wme[WME_AC_BE]);
3740	bwn_dma_setup(dma->wme[WME_AC_VI]);
3741	bwn_dma_setup(dma->wme[WME_AC_VO]);
3742	bwn_dma_setup(dma->mcast);
3743	/* setup RX DMA channel. */
3744	bwn_dma_setup(dma->rx);
3745}
3746
3747static struct bwn_dma_ring *
3748bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3749    int for_tx, int type)
3750{
3751	struct bwn_dma *dma = &mac->mac_method.dma;
3752	struct bwn_dma_ring *dr;
3753	struct bwn_dmadesc_generic *desc;
3754	struct bwn_dmadesc_meta *mt;
3755	struct bwn_softc *sc = mac->mac_sc;
3756	int error, i;
3757
3758	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3759	if (dr == NULL)
3760		goto out;
3761	dr->dr_numslots = BWN_RXRING_SLOTS;
3762	if (for_tx)
3763		dr->dr_numslots = BWN_TXRING_SLOTS;
3764
3765	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3766	    M_DEVBUF, M_NOWAIT | M_ZERO);
3767	if (dr->dr_meta == NULL)
3768		goto fail0;
3769
3770	dr->dr_type = type;
3771	dr->dr_mac = mac;
3772	dr->dr_base = bwn_dma_base(type, controller_index);
3773	dr->dr_index = controller_index;
3774	if (type == BWN_DMA_64BIT) {
3775		dr->getdesc = bwn_dma_64_getdesc;
3776		dr->setdesc = bwn_dma_64_setdesc;
3777		dr->start_transfer = bwn_dma_64_start_transfer;
3778		dr->suspend = bwn_dma_64_suspend;
3779		dr->resume = bwn_dma_64_resume;
3780		dr->get_curslot = bwn_dma_64_get_curslot;
3781		dr->set_curslot = bwn_dma_64_set_curslot;
3782	} else {
3783		dr->getdesc = bwn_dma_32_getdesc;
3784		dr->setdesc = bwn_dma_32_setdesc;
3785		dr->start_transfer = bwn_dma_32_start_transfer;
3786		dr->suspend = bwn_dma_32_suspend;
3787		dr->resume = bwn_dma_32_resume;
3788		dr->get_curslot = bwn_dma_32_get_curslot;
3789		dr->set_curslot = bwn_dma_32_set_curslot;
3790	}
3791	if (for_tx) {
3792		dr->dr_tx = 1;
3793		dr->dr_curslot = -1;
3794	} else {
3795		if (dr->dr_index == 0) {
3796			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3797			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3798		} else
3799			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3800	}
3801
3802	error = bwn_dma_allocringmemory(dr);
3803	if (error)
3804		goto fail2;
3805
3806	if (for_tx) {
3807		/*
3808		 * Assumption: BWN_TXRING_SLOTS can be divided by
3809		 * BWN_TX_SLOTS_PER_FRAME
3810		 */
3811		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3812		    ("%s:%d: fail", __func__, __LINE__));
3813
3814		dr->dr_txhdr_cache =
3815		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3816			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3817		KASSERT(dr->dr_txhdr_cache != NULL,
3818		    ("%s:%d: fail", __func__, __LINE__));
3819
3820		/*
3821		 * Create TX ring DMA stuffs
3822		 */
3823		error = bus_dma_tag_create(dma->parent_dtag,
3824				    BWN_ALIGN, 0,
3825				    BUS_SPACE_MAXADDR,
3826				    BUS_SPACE_MAXADDR,
3827				    NULL, NULL,
3828				    BWN_HDRSIZE(mac),
3829				    1,
3830				    BUS_SPACE_MAXSIZE_32BIT,
3831				    0,
3832				    NULL, NULL,
3833				    &dr->dr_txring_dtag);
3834		if (error) {
3835			device_printf(sc->sc_dev,
3836			    "can't create TX ring DMA tag: TODO frees\n");
3837			goto fail1;
3838		}
3839
3840		for (i = 0; i < dr->dr_numslots; i += 2) {
3841			dr->getdesc(dr, i, &desc, &mt);
3842
3843			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3844			mt->mt_m = NULL;
3845			mt->mt_ni = NULL;
3846			mt->mt_islast = 0;
3847			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3848			    &mt->mt_dmap);
3849			if (error) {
3850				device_printf(sc->sc_dev,
3851				     "can't create RX buf DMA map\n");
3852				goto fail1;
3853			}
3854
3855			dr->getdesc(dr, i + 1, &desc, &mt);
3856
3857			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3858			mt->mt_m = NULL;
3859			mt->mt_ni = NULL;
3860			mt->mt_islast = 1;
3861			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3862			    &mt->mt_dmap);
3863			if (error) {
3864				device_printf(sc->sc_dev,
3865				     "can't create RX buf DMA map\n");
3866				goto fail1;
3867			}
3868		}
3869	} else {
3870		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3871		    &dr->dr_spare_dmap);
3872		if (error) {
3873			device_printf(sc->sc_dev,
3874			    "can't create RX buf DMA map\n");
3875			goto out;		/* XXX wrong! */
3876		}
3877
3878		for (i = 0; i < dr->dr_numslots; i++) {
3879			dr->getdesc(dr, i, &desc, &mt);
3880
3881			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3882			    &mt->mt_dmap);
3883			if (error) {
3884				device_printf(sc->sc_dev,
3885				    "can't create RX buf DMA map\n");
3886				goto out;	/* XXX wrong! */
3887			}
3888			error = bwn_dma_newbuf(dr, desc, mt, 1);
3889			if (error) {
3890				device_printf(sc->sc_dev,
3891				    "failed to allocate RX buf\n");
3892				goto out;	/* XXX wrong! */
3893			}
3894		}
3895
3896		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3897		    BUS_DMASYNC_PREWRITE);
3898
3899		dr->dr_usedslot = dr->dr_numslots;
3900	}
3901
3902      out:
3903	return (dr);
3904
3905fail2:
3906	free(dr->dr_txhdr_cache, M_DEVBUF);
3907fail1:
3908	free(dr->dr_meta, M_DEVBUF);
3909fail0:
3910	free(dr, M_DEVBUF);
3911	return (NULL);
3912}
3913
3914static void
3915bwn_dma_ringfree(struct bwn_dma_ring **dr)
3916{
3917
3918	if (dr == NULL)
3919		return;
3920
3921	bwn_dma_free_descbufs(*dr);
3922	bwn_dma_free_ringmemory(*dr);
3923
3924	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3925	free((*dr)->dr_meta, M_DEVBUF);
3926	free(*dr, M_DEVBUF);
3927
3928	*dr = NULL;
3929}
3930
3931static void
3932bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3933    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3934{
3935	struct bwn_dmadesc32 *desc;
3936
3937	*meta = &(dr->dr_meta[slot]);
3938	desc = dr->dr_ring_descbase;
3939	desc = &(desc[slot]);
3940
3941	*gdesc = (struct bwn_dmadesc_generic *)desc;
3942}
3943
3944static void
3945bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3946    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3947    int start, int end, int irq)
3948{
3949	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3950	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3951	uint32_t addr, addrext, ctl;
3952	int slot;
3953
3954	slot = (int)(&(desc->dma.dma32) - descbase);
3955	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3956	    ("%s:%d: fail", __func__, __LINE__));
3957
3958	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3959	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3960	addr |= siba_dma_translation(sc->sc_dev);
3961	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3962	if (slot == dr->dr_numslots - 1)
3963		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3964	if (start)
3965		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3966	if (end)
3967		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3968	if (irq)
3969		ctl |= BWN_DMA32_DCTL_IRQ;
3970	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3971	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3972
3973	desc->dma.dma32.control = htole32(ctl);
3974	desc->dma.dma32.address = htole32(addr);
3975}
3976
3977static void
3978bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3979{
3980
3981	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3982	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3983}
3984
3985static void
3986bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3987{
3988
3989	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3990	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3991}
3992
3993static void
3994bwn_dma_32_resume(struct bwn_dma_ring *dr)
3995{
3996
3997	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3998	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3999}
4000
4001static int
4002bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4003{
4004	uint32_t val;
4005
4006	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4007	val &= BWN_DMA32_RXDPTR;
4008
4009	return (val / sizeof(struct bwn_dmadesc32));
4010}
4011
4012static void
4013bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4014{
4015
4016	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4017	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4018}
4019
4020static void
4021bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4022    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4023{
4024	struct bwn_dmadesc64 *desc;
4025
4026	*meta = &(dr->dr_meta[slot]);
4027	desc = dr->dr_ring_descbase;
4028	desc = &(desc[slot]);
4029
4030	*gdesc = (struct bwn_dmadesc_generic *)desc;
4031}
4032
4033static void
4034bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4035    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4036    int start, int end, int irq)
4037{
4038	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4039	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4040	int slot;
4041	uint32_t ctl0 = 0, ctl1 = 0;
4042	uint32_t addrlo, addrhi;
4043	uint32_t addrext;
4044
4045	slot = (int)(&(desc->dma.dma64) - descbase);
4046	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4047	    ("%s:%d: fail", __func__, __LINE__));
4048
4049	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4050	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4051	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4052	    30;
4053	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4054	if (slot == dr->dr_numslots - 1)
4055		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4056	if (start)
4057		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4058	if (end)
4059		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4060	if (irq)
4061		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4062	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4063	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4064	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4065
4066	desc->dma.dma64.control0 = htole32(ctl0);
4067	desc->dma.dma64.control1 = htole32(ctl1);
4068	desc->dma.dma64.address_low = htole32(addrlo);
4069	desc->dma.dma64.address_high = htole32(addrhi);
4070}
4071
4072static void
4073bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4074{
4075
4076	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4077	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4078}
4079
4080static void
4081bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4082{
4083
4084	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4085	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4086}
4087
4088static void
4089bwn_dma_64_resume(struct bwn_dma_ring *dr)
4090{
4091
4092	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4093	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4094}
4095
4096static int
4097bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4098{
4099	uint32_t val;
4100
4101	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4102	val &= BWN_DMA64_RXSTATDPTR;
4103
4104	return (val / sizeof(struct bwn_dmadesc64));
4105}
4106
4107static void
4108bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4109{
4110
4111	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4112	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4113}
4114
4115static int
4116bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4117{
4118	struct bwn_mac *mac = dr->dr_mac;
4119	struct bwn_dma *dma = &mac->mac_method.dma;
4120	struct bwn_softc *sc = mac->mac_sc;
4121	int error;
4122
4123	error = bus_dma_tag_create(dma->parent_dtag,
4124			    BWN_ALIGN, 0,
4125			    BUS_SPACE_MAXADDR,
4126			    BUS_SPACE_MAXADDR,
4127			    NULL, NULL,
4128			    BWN_DMA_RINGMEMSIZE,
4129			    1,
4130			    BUS_SPACE_MAXSIZE_32BIT,
4131			    0,
4132			    NULL, NULL,
4133			    &dr->dr_ring_dtag);
4134	if (error) {
4135		device_printf(sc->sc_dev,
4136		    "can't create TX ring DMA tag: TODO frees\n");
4137		return (-1);
4138	}
4139
4140	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4141	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4142	    &dr->dr_ring_dmap);
4143	if (error) {
4144		device_printf(sc->sc_dev,
4145		    "can't allocate DMA mem: TODO frees\n");
4146		return (-1);
4147	}
4148	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4149	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4150	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4151	if (error) {
4152		device_printf(sc->sc_dev,
4153		    "can't load DMA mem: TODO free\n");
4154		return (-1);
4155	}
4156
4157	return (0);
4158}
4159
4160static void
4161bwn_dma_setup(struct bwn_dma_ring *dr)
4162{
4163	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4164	uint64_t ring64;
4165	uint32_t addrext, ring32, value;
4166	uint32_t trans = siba_dma_translation(sc->sc_dev);
4167
4168	if (dr->dr_tx) {
4169		dr->dr_curslot = -1;
4170
4171		if (dr->dr_type == BWN_DMA_64BIT) {
4172			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4173			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4174			    >> 30;
4175			value = BWN_DMA64_TXENABLE;
4176			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4177			    & BWN_DMA64_TXADDREXT_MASK;
4178			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4179			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4180			    (ring64 & 0xffffffff));
4181			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4182			    ((ring64 >> 32) &
4183			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4184		} else {
4185			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4186			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4187			value = BWN_DMA32_TXENABLE;
4188			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4189			    & BWN_DMA32_TXADDREXT_MASK;
4190			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4191			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4192			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4193		}
4194		return;
4195	}
4196
4197	/*
4198	 * set for RX
4199	 */
4200	dr->dr_usedslot = dr->dr_numslots;
4201
4202	if (dr->dr_type == BWN_DMA_64BIT) {
4203		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4204		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4205		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4206		value |= BWN_DMA64_RXENABLE;
4207		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4208		    & BWN_DMA64_RXADDREXT_MASK;
4209		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4210		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4211		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4212		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4213		    | (trans << 1));
4214		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4215		    sizeof(struct bwn_dmadesc64));
4216	} else {
4217		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4218		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4219		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4220		value |= BWN_DMA32_RXENABLE;
4221		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4222		    & BWN_DMA32_RXADDREXT_MASK;
4223		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4224		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4225		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4226		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4227		    sizeof(struct bwn_dmadesc32));
4228	}
4229}
4230
4231static void
4232bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4233{
4234
4235	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4236	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4237	    dr->dr_ring_dmap);
4238}
4239
4240static void
4241bwn_dma_cleanup(struct bwn_dma_ring *dr)
4242{
4243
4244	if (dr->dr_tx) {
4245		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4246		if (dr->dr_type == BWN_DMA_64BIT) {
4247			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4248			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4249		} else
4250			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4251	} else {
4252		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4253		if (dr->dr_type == BWN_DMA_64BIT) {
4254			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4255			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4256		} else
4257			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4258	}
4259}
4260
4261static void
4262bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4263{
4264	struct bwn_dmadesc_generic *desc;
4265	struct bwn_dmadesc_meta *meta;
4266	struct bwn_mac *mac = dr->dr_mac;
4267	struct bwn_dma *dma = &mac->mac_method.dma;
4268	struct bwn_softc *sc = mac->mac_sc;
4269	int i;
4270
4271	if (!dr->dr_usedslot)
4272		return;
4273	for (i = 0; i < dr->dr_numslots; i++) {
4274		dr->getdesc(dr, i, &desc, &meta);
4275
4276		if (meta->mt_m == NULL) {
4277			if (!dr->dr_tx)
4278				device_printf(sc->sc_dev, "%s: not TX?\n",
4279				    __func__);
4280			continue;
4281		}
4282		if (dr->dr_tx) {
4283			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4284				bus_dmamap_unload(dr->dr_txring_dtag,
4285				    meta->mt_dmap);
4286			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4287				bus_dmamap_unload(dma->txbuf_dtag,
4288				    meta->mt_dmap);
4289		} else
4290			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4291		bwn_dma_free_descbuf(dr, meta);
4292	}
4293}
4294
4295static int
4296bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4297    int type)
4298{
4299	struct bwn_softc *sc = mac->mac_sc;
4300	uint32_t value;
4301	int i;
4302	uint16_t offset;
4303
4304	for (i = 0; i < 10; i++) {
4305		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4306		    BWN_DMA32_TXSTATUS;
4307		value = BWN_READ_4(mac, base + offset);
4308		if (type == BWN_DMA_64BIT) {
4309			value &= BWN_DMA64_TXSTAT;
4310			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4311			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4312			    value == BWN_DMA64_TXSTAT_STOPPED)
4313				break;
4314		} else {
4315			value &= BWN_DMA32_TXSTATE;
4316			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4317			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4318			    value == BWN_DMA32_TXSTAT_STOPPED)
4319				break;
4320		}
4321		DELAY(1000);
4322	}
4323	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4324	BWN_WRITE_4(mac, base + offset, 0);
4325	for (i = 0; i < 10; i++) {
4326		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4327						   BWN_DMA32_TXSTATUS;
4328		value = BWN_READ_4(mac, base + offset);
4329		if (type == BWN_DMA_64BIT) {
4330			value &= BWN_DMA64_TXSTAT;
4331			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4332				i = -1;
4333				break;
4334			}
4335		} else {
4336			value &= BWN_DMA32_TXSTATE;
4337			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4338				i = -1;
4339				break;
4340			}
4341		}
4342		DELAY(1000);
4343	}
4344	if (i != -1) {
4345		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4346		return (ENODEV);
4347	}
4348	DELAY(1000);
4349
4350	return (0);
4351}
4352
4353static int
4354bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4355    int type)
4356{
4357	struct bwn_softc *sc = mac->mac_sc;
4358	uint32_t value;
4359	int i;
4360	uint16_t offset;
4361
4362	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4363	BWN_WRITE_4(mac, base + offset, 0);
4364	for (i = 0; i < 10; i++) {
4365		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4366		    BWN_DMA32_RXSTATUS;
4367		value = BWN_READ_4(mac, base + offset);
4368		if (type == BWN_DMA_64BIT) {
4369			value &= BWN_DMA64_RXSTAT;
4370			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4371				i = -1;
4372				break;
4373			}
4374		} else {
4375			value &= BWN_DMA32_RXSTATE;
4376			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4377				i = -1;
4378				break;
4379			}
4380		}
4381		DELAY(1000);
4382	}
4383	if (i != -1) {
4384		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4385		return (ENODEV);
4386	}
4387
4388	return (0);
4389}
4390
4391static void
4392bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4393    struct bwn_dmadesc_meta *meta)
4394{
4395
4396	if (meta->mt_m != NULL) {
4397		m_freem(meta->mt_m);
4398		meta->mt_m = NULL;
4399	}
4400	if (meta->mt_ni != NULL) {
4401		ieee80211_free_node(meta->mt_ni);
4402		meta->mt_ni = NULL;
4403	}
4404}
4405
4406static void
4407bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4408{
4409	struct bwn_rxhdr4 *rxhdr;
4410	unsigned char *frame;
4411
4412	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4413	rxhdr->frame_len = 0;
4414
4415	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4416	    sizeof(struct bwn_plcp6) + 2,
4417	    ("%s:%d: fail", __func__, __LINE__));
4418	frame = mtod(m, char *) + dr->dr_frameoffset;
4419	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4420}
4421
4422static uint8_t
4423bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4424{
4425	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4426
4427	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4428	    == 0xff);
4429}
4430
4431static void
4432bwn_wme_init(struct bwn_mac *mac)
4433{
4434
4435	bwn_wme_load(mac);
4436
4437	/* enable WME support. */
4438	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4439	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4440	    BWN_IFSCTL_USE_EDCF);
4441}
4442
4443static void
4444bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4445{
4446	struct bwn_softc *sc = mac->mac_sc;
4447	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4448	uint16_t delay;	/* microsec */
4449
4450	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4451	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4452		delay = 500;
4453	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4454		delay = max(delay, (uint16_t)2400);
4455
4456	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4457}
4458
4459static void
4460bwn_bt_enable(struct bwn_mac *mac)
4461{
4462	struct bwn_softc *sc = mac->mac_sc;
4463	uint64_t hf;
4464
4465	if (bwn_bluetooth == 0)
4466		return;
4467	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4468		return;
4469	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4470		return;
4471
4472	hf = bwn_hf_read(mac);
4473	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4474		hf |= BWN_HF_BT_COEXISTALT;
4475	else
4476		hf |= BWN_HF_BT_COEXIST;
4477	bwn_hf_write(mac, hf);
4478}
4479
4480static void
4481bwn_set_macaddr(struct bwn_mac *mac)
4482{
4483
4484	bwn_mac_write_bssid(mac);
4485	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4486}
4487
4488static void
4489bwn_clear_keys(struct bwn_mac *mac)
4490{
4491	int i;
4492
4493	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4494		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4495		    ("%s:%d: fail", __func__, __LINE__));
4496
4497		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4498		    NULL, BWN_SEC_KEYSIZE, NULL);
4499		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4500			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4501			    NULL, BWN_SEC_KEYSIZE, NULL);
4502		}
4503		mac->mac_key[i].keyconf = NULL;
4504	}
4505}
4506
4507static void
4508bwn_crypt_init(struct bwn_mac *mac)
4509{
4510	struct bwn_softc *sc = mac->mac_sc;
4511
4512	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4513	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4514	    ("%s:%d: fail", __func__, __LINE__));
4515	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4516	mac->mac_ktp *= 2;
4517	if (siba_get_revid(sc->sc_dev) >= 5)
4518		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4519	bwn_clear_keys(mac);
4520}
4521
4522static void
4523bwn_chip_exit(struct bwn_mac *mac)
4524{
4525	struct bwn_softc *sc = mac->mac_sc;
4526
4527	bwn_phy_exit(mac);
4528	siba_gpio_set(sc->sc_dev, 0);
4529}
4530
4531static int
4532bwn_fw_fillinfo(struct bwn_mac *mac)
4533{
4534	int error;
4535
4536	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4537	if (error == 0)
4538		return (0);
4539	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4540	if (error == 0)
4541		return (0);
4542	return (error);
4543}
4544
4545static int
4546bwn_gpio_init(struct bwn_mac *mac)
4547{
4548	struct bwn_softc *sc = mac->mac_sc;
4549	uint32_t mask = 0x1f, set = 0xf, value;
4550
4551	BWN_WRITE_4(mac, BWN_MACCTL,
4552	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4553	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4554	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4555
4556	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4557		mask |= 0x0060;
4558		set |= 0x0060;
4559	}
4560	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4561		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4562		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4563		mask |= 0x0200;
4564		set |= 0x0200;
4565	}
4566	if (siba_get_revid(sc->sc_dev) >= 2)
4567		mask |= 0x0010;
4568
4569	value = siba_gpio_get(sc->sc_dev);
4570	if (value == -1)
4571		return (0);
4572	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4573
4574	return (0);
4575}
4576
4577static int
4578bwn_fw_loadinitvals(struct bwn_mac *mac)
4579{
4580#define	GETFWOFFSET(fwp, offset)				\
4581	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4582	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4583	const struct bwn_fwhdr *hdr;
4584	struct bwn_fw *fw = &mac->mac_fw;
4585	int error;
4586
4587	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4588	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4589	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4590	if (error)
4591		return (error);
4592	if (fw->initvals_band.fw) {
4593		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4594		error = bwn_fwinitvals_write(mac,
4595		    GETFWOFFSET(fw->initvals_band, hdr_len),
4596		    be32toh(hdr->size),
4597		    fw->initvals_band.fw->datasize - hdr_len);
4598	}
4599	return (error);
4600#undef GETFWOFFSET
4601}
4602
4603static int
4604bwn_phy_init(struct bwn_mac *mac)
4605{
4606	struct bwn_softc *sc = mac->mac_sc;
4607	int error;
4608
4609	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4610	mac->mac_phy.rf_onoff(mac, 1);
4611	error = mac->mac_phy.init(mac);
4612	if (error) {
4613		device_printf(sc->sc_dev, "PHY init failed\n");
4614		goto fail0;
4615	}
4616	error = bwn_switch_channel(mac,
4617	    mac->mac_phy.get_default_chan(mac));
4618	if (error) {
4619		device_printf(sc->sc_dev,
4620		    "failed to switch default channel\n");
4621		goto fail1;
4622	}
4623	return (0);
4624fail1:
4625	if (mac->mac_phy.exit)
4626		mac->mac_phy.exit(mac);
4627fail0:
4628	mac->mac_phy.rf_onoff(mac, 0);
4629
4630	return (error);
4631}
4632
4633static void
4634bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4635{
4636	uint16_t ant;
4637	uint16_t tmp;
4638
4639	ant = bwn_ant2phy(antenna);
4640
4641	/* For ACK/CTS */
4642	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4643	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4645	/* For Probe Resposes */
4646	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4647	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4648	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4649}
4650
4651static void
4652bwn_set_opmode(struct bwn_mac *mac)
4653{
4654	struct bwn_softc *sc = mac->mac_sc;
4655	struct ifnet *ifp = sc->sc_ifp;
4656	struct ieee80211com *ic = ifp->if_l2com;
4657	uint32_t ctl;
4658	uint16_t cfp_pretbtt;
4659
4660	ctl = BWN_READ_4(mac, BWN_MACCTL);
4661	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4662	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4663	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4664	ctl |= BWN_MACCTL_STA;
4665
4666	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4667	    ic->ic_opmode == IEEE80211_M_MBSS)
4668		ctl |= BWN_MACCTL_HOSTAP;
4669	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4670		ctl &= ~BWN_MACCTL_STA;
4671	ctl |= sc->sc_filters;
4672
4673	if (siba_get_revid(sc->sc_dev) <= 4)
4674		ctl |= BWN_MACCTL_PROMISC;
4675
4676	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4677
4678	cfp_pretbtt = 2;
4679	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4680		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4681		    siba_get_chiprev(sc->sc_dev) == 3)
4682			cfp_pretbtt = 100;
4683		else
4684			cfp_pretbtt = 50;
4685	}
4686	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4687}
4688
4689static int
4690bwn_dma_gettype(struct bwn_mac *mac)
4691{
4692	uint32_t tmp;
4693	uint16_t base;
4694
4695	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4696	if (tmp & SIBA_TGSHIGH_DMA64)
4697		return (BWN_DMA_64BIT);
4698	base = bwn_dma_base(0, 0);
4699	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4700	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4701	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4702		return (BWN_DMA_32BIT);
4703
4704	return (BWN_DMA_30BIT);
4705}
4706
4707static void
4708bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4709{
4710	if (!error) {
4711		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4712		*((bus_addr_t *)arg) = seg->ds_addr;
4713	}
4714}
4715
4716static void
4717bwn_phy_g_init_sub(struct bwn_mac *mac)
4718{
4719	struct bwn_phy *phy = &mac->mac_phy;
4720	struct bwn_phy_g *pg = &phy->phy_g;
4721	struct bwn_softc *sc = mac->mac_sc;
4722	uint16_t i, tmp;
4723
4724	if (phy->rev == 1)
4725		bwn_phy_init_b5(mac);
4726	else
4727		bwn_phy_init_b6(mac);
4728
4729	if (phy->rev >= 2 || phy->gmode)
4730		bwn_phy_init_a(mac);
4731
4732	if (phy->rev >= 2) {
4733		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4734		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4735	}
4736	if (phy->rev == 2) {
4737		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4738		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739	}
4740	if (phy->rev > 5) {
4741		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4742		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4743	}
4744	if (phy->gmode || phy->rev >= 2) {
4745		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4746		tmp &= BWN_PHYVER_VERSION;
4747		if (tmp == 3 || tmp == 5) {
4748			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4749			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4750		}
4751		if (tmp == 5) {
4752			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4753			    0x1f00);
4754		}
4755	}
4756	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4757		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4758	if (phy->rf_rev == 8) {
4759		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4760		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4761	}
4762	if (BWN_HAS_LOOPBACK(phy))
4763		bwn_loopback_calcgain(mac);
4764
4765	if (phy->rf_rev != 8) {
4766		if (pg->pg_initval == 0xffff)
4767			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4768		else
4769			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4770	}
4771	bwn_lo_g_init(mac);
4772	if (BWN_HAS_TXMAG(phy)) {
4773		BWN_RF_WRITE(mac, 0x52,
4774		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4775		    | pg->pg_loctl.tx_bias |
4776		    pg->pg_loctl.tx_magn);
4777	} else {
4778		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4779	}
4780	if (phy->rev >= 6) {
4781		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4782		    (pg->pg_loctl.tx_bias << 12));
4783	}
4784	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4785		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4786	else
4787		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4788	if (phy->rev < 2)
4789		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4790	else
4791		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4792	if (phy->gmode || phy->rev >= 2) {
4793		bwn_lo_g_adjust(mac);
4794		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4795	}
4796
4797	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4798		for (i = 0; i < 64; i++) {
4799			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4800			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4801			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4802			    -32), 31));
4803		}
4804		bwn_nrssi_threshold(mac);
4805	} else if (phy->gmode || phy->rev >= 2) {
4806		if (pg->pg_nrssi[0] == -1000) {
4807			KASSERT(pg->pg_nrssi[1] == -1000,
4808			    ("%s:%d: fail", __func__, __LINE__));
4809			bwn_nrssi_slope_11g(mac);
4810		} else
4811			bwn_nrssi_threshold(mac);
4812	}
4813	if (phy->rf_rev == 8)
4814		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4815	bwn_phy_hwpctl_init(mac);
4816	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4817	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4818		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4819		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4820	}
4821}
4822
4823static uint8_t
4824bwn_has_hwpctl(struct bwn_mac *mac)
4825{
4826
4827	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4828		return (0);
4829	return (mac->mac_phy.use_hwpctl(mac));
4830}
4831
4832static void
4833bwn_phy_init_b5(struct bwn_mac *mac)
4834{
4835	struct bwn_phy *phy = &mac->mac_phy;
4836	struct bwn_phy_g *pg = &phy->phy_g;
4837	struct bwn_softc *sc = mac->mac_sc;
4838	uint16_t offset, value;
4839	uint8_t old_channel;
4840
4841	if (phy->analog == 1)
4842		BWN_RF_SET(mac, 0x007a, 0x0050);
4843	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4844	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4845		value = 0x2120;
4846		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4847			BWN_PHY_WRITE(mac, offset, value);
4848			value += 0x202;
4849		}
4850	}
4851	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4852	if (phy->rf_ver == 0x2050)
4853		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4854
4855	if (phy->gmode || phy->rev >= 2) {
4856		if (phy->rf_ver == 0x2050) {
4857			BWN_RF_SET(mac, 0x007a, 0x0020);
4858			BWN_RF_SET(mac, 0x0051, 0x0004);
4859		}
4860		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4861
4862		BWN_PHY_SET(mac, 0x0802, 0x0100);
4863		BWN_PHY_SET(mac, 0x042b, 0x2000);
4864
4865		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4866
4867		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4868		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4869		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4870	}
4871
4872	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4873		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4874
4875	if (phy->analog == 1) {
4876		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4877		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4878		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4879		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4880		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4881	} else
4882		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4883	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4884	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4885
4886	if (phy->analog == 1)
4887		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4888	else
4889		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4890
4891	if (phy->analog == 0)
4892		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4893
4894	old_channel = phy->chan;
4895	bwn_phy_g_switch_chan(mac, 7, 0);
4896
4897	if (phy->rf_ver != 0x2050) {
4898		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4899		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4900	}
4901
4902	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4904
4905	if (phy->rf_ver == 0x2050) {
4906		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4907		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4908	}
4909
4910	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4911	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4912	BWN_RF_SET(mac, 0x007a, 0x0007);
4913
4914	bwn_phy_g_switch_chan(mac, old_channel, 0);
4915	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4916	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4917	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4918
4919	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4920	    pg->pg_txctl);
4921
4922	if (phy->rf_ver == 0x2050)
4923		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4924
4925	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4926}
4927
4928static void
4929bwn_loopback_calcgain(struct bwn_mac *mac)
4930{
4931	struct bwn_phy *phy = &mac->mac_phy;
4932	struct bwn_phy_g *pg = &phy->phy_g;
4933	struct bwn_softc *sc = mac->mac_sc;
4934	uint16_t backup_phy[16] = { 0 };
4935	uint16_t backup_radio[3];
4936	uint16_t backup_bband;
4937	uint16_t i, j, loop_i_max;
4938	uint16_t trsw_rx;
4939	uint16_t loop1_outer_done, loop1_inner_done;
4940
4941	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4942	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4943	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4944	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4945	if (phy->rev != 1) {
4946		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4947		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4948	}
4949	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4950	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4951	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4952	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4953	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4954	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4955	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4956	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4957	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4958	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4959	backup_bband = pg->pg_bbatt.att;
4960	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4961	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4962	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4963
4964	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4965	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4966	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4967	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4968	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4969	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4970	if (phy->rev != 1) {
4971		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4972		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4973		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4974		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4975	}
4976	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4977	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4978	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4979	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4980
4981	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4982	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4983	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4984
4985	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4986	if (phy->rev != 1) {
4987		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4988		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4989	}
4990	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4991
4992	if (phy->rf_rev == 8)
4993		BWN_RF_WRITE(mac, 0x43, 0x000f);
4994	else {
4995		BWN_RF_WRITE(mac, 0x52, 0);
4996		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4997	}
4998	bwn_phy_g_set_bbatt(mac, 11);
4999
5000	if (phy->rev >= 3)
5001		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5002	else
5003		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5004	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5005
5006	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5007	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5008
5009	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5010	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5011
5012	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5013		if (phy->rev >= 7) {
5014			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5015			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5016		}
5017	}
5018	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5019
5020	j = 0;
5021	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5022	for (i = 0; i < loop_i_max; i++) {
5023		for (j = 0; j < 16; j++) {
5024			BWN_RF_WRITE(mac, 0x43, i);
5025			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5026			    (j << 8));
5027			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5028			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5029			DELAY(20);
5030			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5031				goto done0;
5032		}
5033	}
5034done0:
5035	loop1_outer_done = i;
5036	loop1_inner_done = j;
5037	if (j >= 8) {
5038		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5039		trsw_rx = 0x1b;
5040		for (j = j - 8; j < 16; j++) {
5041			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5042			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5043			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5044			DELAY(20);
5045			trsw_rx -= 3;
5046			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5047				goto done1;
5048		}
5049	} else
5050		trsw_rx = 0x18;
5051done1:
5052
5053	if (phy->rev != 1) {
5054		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5055		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5056	}
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5061	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5062	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5063	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5064	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5065	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5066
5067	bwn_phy_g_set_bbatt(mac, backup_bband);
5068
5069	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5070	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5071	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5072
5073	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5074	DELAY(10);
5075	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5076	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5077	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5078	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5079
5080	pg->pg_max_lb_gain =
5081	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5082	pg->pg_trsw_rx_gain = trsw_rx * 2;
5083}
5084
5085static uint16_t
5086bwn_rf_init_bcm2050(struct bwn_mac *mac)
5087{
5088	struct bwn_phy *phy = &mac->mac_phy;
5089	uint32_t tmp1 = 0, tmp2 = 0;
5090	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5091	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5092	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5093	static const uint8_t rcc_table[] = {
5094		0x02, 0x03, 0x01, 0x0f,
5095		0x06, 0x07, 0x05, 0x0f,
5096		0x0a, 0x0b, 0x09, 0x0f,
5097		0x0e, 0x0f, 0x0d, 0x0f,
5098	};
5099
5100	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5101	    rfoverval = rfover = cck3 = 0;
5102	radio0 = BWN_RF_READ(mac, 0x43);
5103	radio1 = BWN_RF_READ(mac, 0x51);
5104	radio2 = BWN_RF_READ(mac, 0x52);
5105	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5106	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5107	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5108	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5109
5110	if (phy->type == BWN_PHYTYPE_B) {
5111		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5112		reg0 = BWN_READ_2(mac, 0x3ec);
5113
5114		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5115		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5116	} else if (phy->gmode || phy->rev >= 2) {
5117		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5118		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5119		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5120		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5121		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5122		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5123
5124		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5125		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5126		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5127		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5128		if (BWN_HAS_LOOPBACK(phy)) {
5129			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5130			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5131			if (phy->rev >= 3)
5132				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5133			else
5134				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5135			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5136		}
5137
5138		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5139		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5140			BWN_LPD(0, 1, 1)));
5141		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5142		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5143	}
5144	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5145
5146	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5147	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5148	reg1 = BWN_READ_2(mac, 0x3e6);
5149	reg2 = BWN_READ_2(mac, 0x3f4);
5150
5151	if (phy->analog == 0)
5152		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5153	else {
5154		if (phy->analog >= 2)
5155			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5156		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5157		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5158	}
5159
5160	reg = BWN_RF_READ(mac, 0x60);
5161	index = (reg & 0x001e) >> 1;
5162	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5163
5164	if (phy->type == BWN_PHYTYPE_B)
5165		BWN_RF_WRITE(mac, 0x78, 0x26);
5166	if (phy->gmode || phy->rev >= 2) {
5167		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5168		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5169			BWN_LPD(0, 1, 1)));
5170	}
5171	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5172	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5173	if (phy->gmode || phy->rev >= 2) {
5174		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5175		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5176			BWN_LPD(0, 0, 1)));
5177	}
5178	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5179	BWN_RF_SET(mac, 0x51, 0x0004);
5180	if (phy->rf_rev == 8)
5181		BWN_RF_WRITE(mac, 0x43, 0x1f);
5182	else {
5183		BWN_RF_WRITE(mac, 0x52, 0);
5184		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5185	}
5186	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5187
5188	for (i = 0; i < 16; i++) {
5189		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5190		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5191		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5192		if (phy->gmode || phy->rev >= 2) {
5193			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5194			    bwn_rf_2050_rfoverval(mac,
5195				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5196		}
5197		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5198		DELAY(10);
5199		if (phy->gmode || phy->rev >= 2) {
5200			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5201			    bwn_rf_2050_rfoverval(mac,
5202				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5203		}
5204		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5205		DELAY(10);
5206		if (phy->gmode || phy->rev >= 2) {
5207			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5208			    bwn_rf_2050_rfoverval(mac,
5209				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5210		}
5211		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5212		DELAY(20);
5213		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5214		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5215		if (phy->gmode || phy->rev >= 2) {
5216			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5217			    bwn_rf_2050_rfoverval(mac,
5218				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5219		}
5220		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5221	}
5222	DELAY(10);
5223
5224	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5225	tmp1++;
5226	tmp1 >>= 9;
5227
5228	for (i = 0; i < 16; i++) {
5229		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5230		BWN_RF_WRITE(mac, 0x78, radio78);
5231		DELAY(10);
5232		for (j = 0; j < 16; j++) {
5233			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5234			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5235			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5236			if (phy->gmode || phy->rev >= 2) {
5237				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238				    bwn_rf_2050_rfoverval(mac,
5239					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5240			}
5241			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5242			DELAY(10);
5243			if (phy->gmode || phy->rev >= 2) {
5244				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245				    bwn_rf_2050_rfoverval(mac,
5246					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5247			}
5248			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5249			DELAY(10);
5250			if (phy->gmode || phy->rev >= 2) {
5251				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5252				    bwn_rf_2050_rfoverval(mac,
5253					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5254			}
5255			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5256			DELAY(10);
5257			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5258			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5259			if (phy->gmode || phy->rev >= 2) {
5260				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5261				    bwn_rf_2050_rfoverval(mac,
5262					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5263			}
5264			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5265		}
5266		tmp2++;
5267		tmp2 >>= 8;
5268		if (tmp1 < tmp2)
5269			break;
5270	}
5271
5272	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5273	BWN_RF_WRITE(mac, 0x51, radio1);
5274	BWN_RF_WRITE(mac, 0x52, radio2);
5275	BWN_RF_WRITE(mac, 0x43, radio0);
5276	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5277	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5278	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5279	BWN_WRITE_2(mac, 0x3e6, reg1);
5280	if (phy->analog != 0)
5281		BWN_WRITE_2(mac, 0x3f4, reg2);
5282	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5283	bwn_spu_workaround(mac, phy->chan);
5284	if (phy->type == BWN_PHYTYPE_B) {
5285		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5286		BWN_WRITE_2(mac, 0x3ec, reg0);
5287	} else if (phy->gmode) {
5288		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5289			    BWN_READ_2(mac, BWN_PHY_RADIO)
5290			    & 0x7fff);
5291		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5292		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5293		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5294		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5295			      analogoverval);
5296		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5297		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5298		if (BWN_HAS_LOOPBACK(phy)) {
5299			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5300			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5301		}
5302	}
5303
5304	return ((i > 15) ? radio78 : rcc);
5305}
5306
5307static void
5308bwn_phy_init_b6(struct bwn_mac *mac)
5309{
5310	struct bwn_phy *phy = &mac->mac_phy;
5311	struct bwn_phy_g *pg = &phy->phy_g;
5312	struct bwn_softc *sc = mac->mac_sc;
5313	uint16_t offset, val;
5314	uint8_t old_channel;
5315
5316	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5317	    ("%s:%d: fail", __func__, __LINE__));
5318
5319	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5320	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5321	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5322		BWN_RF_WRITE(mac, 0x51, 0x37);
5323		BWN_RF_WRITE(mac, 0x52, 0x70);
5324		BWN_RF_WRITE(mac, 0x53, 0xb3);
5325		BWN_RF_WRITE(mac, 0x54, 0x9b);
5326		BWN_RF_WRITE(mac, 0x5a, 0x88);
5327		BWN_RF_WRITE(mac, 0x5b, 0x88);
5328		BWN_RF_WRITE(mac, 0x5d, 0x88);
5329		BWN_RF_WRITE(mac, 0x5e, 0x88);
5330		BWN_RF_WRITE(mac, 0x7d, 0x88);
5331		bwn_hf_write(mac,
5332		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5333	}
5334	if (phy->rf_rev == 8) {
5335		BWN_RF_WRITE(mac, 0x51, 0);
5336		BWN_RF_WRITE(mac, 0x52, 0x40);
5337		BWN_RF_WRITE(mac, 0x53, 0xb7);
5338		BWN_RF_WRITE(mac, 0x54, 0x98);
5339		BWN_RF_WRITE(mac, 0x5a, 0x88);
5340		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5341		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5342		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5343			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5344			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5345		} else {
5346			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5347			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5348		}
5349		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5350		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5351		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5352		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5353	}
5354	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5355		BWN_PHY_WRITE(mac, offset, val);
5356		val -= 0x0202;
5357	}
5358	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5359		BWN_PHY_WRITE(mac, offset, val);
5360		val -= 0x0202;
5361	}
5362	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5363		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5364		val += 0x0202;
5365	}
5366	if (phy->type == BWN_PHYTYPE_G) {
5367		BWN_RF_SET(mac, 0x007a, 0x0020);
5368		BWN_RF_SET(mac, 0x0051, 0x0004);
5369		BWN_PHY_SET(mac, 0x0802, 0x0100);
5370		BWN_PHY_SET(mac, 0x042b, 0x2000);
5371		BWN_PHY_WRITE(mac, 0x5b, 0);
5372		BWN_PHY_WRITE(mac, 0x5c, 0);
5373	}
5374
5375	old_channel = phy->chan;
5376	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5377
5378	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5379	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5380	DELAY(40);
5381	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5382		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5383		BWN_RF_WRITE(mac, 0x50, 0x20);
5384	}
5385	if (phy->rf_rev <= 2) {
5386		BWN_RF_WRITE(mac, 0x7c, 0x20);
5387		BWN_RF_WRITE(mac, 0x5a, 0x70);
5388		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5389		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5390	}
5391	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5392
5393	bwn_phy_g_switch_chan(mac, old_channel, 0);
5394
5395	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5396	if (phy->rf_rev >= 6)
5397		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5398	else
5399		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5400	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5401	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5402	    pg->pg_txctl);
5403	if (phy->rf_rev <= 5)
5404		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5405	if (phy->rf_rev <= 2)
5406		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5407
5408	if (phy->analog == 4) {
5409		BWN_WRITE_2(mac, 0x3e4, 9);
5410		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5411	} else
5412		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5413	if (phy->type == BWN_PHYTYPE_B)
5414		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5415	else if (phy->type == BWN_PHYTYPE_G)
5416		BWN_WRITE_2(mac, 0x03e6, 0x0);
5417}
5418
5419static void
5420bwn_phy_init_a(struct bwn_mac *mac)
5421{
5422	struct bwn_phy *phy = &mac->mac_phy;
5423	struct bwn_softc *sc = mac->mac_sc;
5424
5425	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5426	    ("%s:%d: fail", __func__, __LINE__));
5427
5428	if (phy->rev >= 6) {
5429		if (phy->type == BWN_PHYTYPE_A)
5430			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5431		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5432			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5433		else
5434			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5435	}
5436
5437	bwn_wa_init(mac);
5438
5439	if (phy->type == BWN_PHYTYPE_G &&
5440	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5441		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5442}
5443
5444static void
5445bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5446{
5447	int i;
5448
5449	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5450		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5451}
5452
5453static void
5454bwn_wa_agc(struct bwn_mac *mac)
5455{
5456	struct bwn_phy *phy = &mac->mac_phy;
5457
5458	if (phy->rev == 1) {
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5463		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5464		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5465		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5466		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5467		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5468	} else {
5469		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5470		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5471		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5472		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5473	}
5474
5475	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5476	    0x5700);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5478	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5479	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5480	BWN_RF_SET(mac, 0x7a, 0x0008);
5481	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5482	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5483	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5484	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5485	if (phy->rev == 1)
5486		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5491	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5492	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5493	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5494	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5495	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5496	if (phy->rev == 1) {
5497		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5498		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5499	} else {
5500		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5501		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5502		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5503		if (phy->rev >= 6) {
5504			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5505			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5506			    (uint16_t)~0xf000, 0x3000);
5507		}
5508	}
5509	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5510	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5511	if (phy->rev == 1) {
5512		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5513		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5514		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5515		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5520	} else {
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5522		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5523		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5524		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5525	}
5526	if (phy->rev >= 6) {
5527		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5528		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5529	}
5530	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5531}
5532
5533static void
5534bwn_wa_grev1(struct bwn_mac *mac)
5535{
5536	struct bwn_phy *phy = &mac->mac_phy;
5537	int i;
5538	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5539	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5540	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5541
5542	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5543
5544	/* init CRSTHRES and ANTDWELL */
5545	if (phy->rev == 1) {
5546		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5547	} else if (phy->rev == 2) {
5548		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5549		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5550		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5551	} else {
5552		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5553		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5554		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5555		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5556	}
5557	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5558	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5559	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5560
5561	/* XXX support PHY-A??? */
5562	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5563		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5564		    bwn_tab_finefreqg[i]);
5565
5566	/* XXX support PHY-A??? */
5567	if (phy->rev == 1)
5568		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5569			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570			    bwn_tab_noise_g1[i]);
5571	else
5572		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5573			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5574			    bwn_tab_noise_g2[i]);
5575
5576
5577	for (i = 0; i < N(bwn_tab_rotor); i++)
5578		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5579		    bwn_tab_rotor[i]);
5580
5581	/* XXX support PHY-A??? */
5582	if (phy->rev >= 6) {
5583		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5584		    BWN_PHY_ENCORE_EN)
5585			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5586		else
5587			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5588	} else
5589		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5590
5591	for (i = 0; i < N(bwn_tab_retard); i++)
5592		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5593		    bwn_tab_retard[i]);
5594
5595	if (phy->rev == 1) {
5596		for (i = 0; i < 16; i++)
5597			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5598			    i, 0x0020);
5599	} else {
5600		for (i = 0; i < 32; i++)
5601			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5602	}
5603
5604	bwn_wa_agc(mac);
5605}
5606
5607static void
5608bwn_wa_grev26789(struct bwn_mac *mac)
5609{
5610	struct bwn_phy *phy = &mac->mac_phy;
5611	int i;
5612	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5613	uint16_t ofdmrev;
5614
5615	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5616
5617	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5618
5619	/* init CRSTHRES and ANTDWELL */
5620	if (phy->rev == 1)
5621		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5622	else if (phy->rev == 2) {
5623		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5624		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5625		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5626	} else {
5627		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5628		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5629		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5630		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5631	}
5632
5633	for (i = 0; i < 64; i++)
5634		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5635
5636	/* XXX support PHY-A??? */
5637	if (phy->rev == 1)
5638		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5639			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640			    bwn_tab_noise_g1[i]);
5641	else
5642		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5643			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5644			    bwn_tab_noise_g2[i]);
5645
5646	/* XXX support PHY-A??? */
5647	if (phy->rev >= 6) {
5648		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5649		    BWN_PHY_ENCORE_EN)
5650			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5651		else
5652			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5653	} else
5654		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5655
5656	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5657		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5658		    bwn_tab_sigmasqr2[i]);
5659
5660	if (phy->rev == 1) {
5661		for (i = 0; i < 16; i++)
5662			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5663			    0x0020);
5664	} else {
5665		for (i = 0; i < 32; i++)
5666			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5667	}
5668
5669	bwn_wa_agc(mac);
5670
5671	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5672	if (ofdmrev > 2) {
5673		if (phy->type == BWN_PHYTYPE_A)
5674			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5675		else
5676			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5677	} else {
5678		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5679		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5680		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5681	}
5682
5683	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5684	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5685}
5686
5687static void
5688bwn_wa_init(struct bwn_mac *mac)
5689{
5690	struct bwn_phy *phy = &mac->mac_phy;
5691	struct bwn_softc *sc = mac->mac_sc;
5692
5693	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5694
5695	switch (phy->rev) {
5696	case 1:
5697		bwn_wa_grev1(mac);
5698		break;
5699	case 2:
5700	case 6:
5701	case 7:
5702	case 8:
5703	case 9:
5704		bwn_wa_grev26789(mac);
5705		break;
5706	default:
5707		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5708	}
5709
5710	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5711	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5712	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5713		if (phy->rev < 2) {
5714			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5715			    0x0002);
5716			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5717			    0x0001);
5718		} else {
5719			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5720			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5721			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5722			     BWN_BFL_EXTLNA) &&
5723			    (phy->rev >= 7)) {
5724				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5725				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726				    0x0020, 0x0001);
5727				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728				    0x0021, 0x0001);
5729				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730				    0x0022, 0x0001);
5731				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732				    0x0023, 0x0000);
5733				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5734				    0x0000, 0x0000);
5735				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5736				    0x0003, 0x0002);
5737			}
5738		}
5739	}
5740	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5741		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5742		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5743	}
5744
5745	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5746	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5747}
5748
5749static void
5750bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5751    uint16_t value)
5752{
5753	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5754	uint16_t addr;
5755
5756	addr = table + offset;
5757	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5758	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5759		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5760		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5761	}
5762	pg->pg_ofdmtab_addr = addr;
5763	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5764}
5765
5766static void
5767bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5768    uint32_t value)
5769{
5770	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5771	uint16_t addr;
5772
5773	addr = table + offset;
5774	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5775	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5776		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5777		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5778	}
5779	pg->pg_ofdmtab_addr = addr;
5780
5781	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5782	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5783}
5784
5785static void
5786bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5787    uint16_t value)
5788{
5789
5790	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5791	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5792}
5793
5794static void
5795bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5796{
5797	struct bwn_phy *phy = &mac->mac_phy;
5798	struct bwn_softc *sc = mac->mac_sc;
5799	unsigned int i, max_loop;
5800	uint16_t value;
5801	uint32_t buffer[5] = {
5802		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5803	};
5804
5805	if (ofdm) {
5806		max_loop = 0x1e;
5807		buffer[0] = 0x000201cc;
5808	} else {
5809		max_loop = 0xfa;
5810		buffer[0] = 0x000b846e;
5811	}
5812
5813	BWN_ASSERT_LOCKED(mac->mac_sc);
5814
5815	for (i = 0; i < 5; i++)
5816		bwn_ram_write(mac, i * 4, buffer[i]);
5817
5818	BWN_WRITE_2(mac, 0x0568, 0x0000);
5819	BWN_WRITE_2(mac, 0x07c0,
5820	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5821	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5822	BWN_WRITE_2(mac, 0x050c, value);
5823	if (phy->type == BWN_PHYTYPE_LP)
5824		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5825	BWN_WRITE_2(mac, 0x0508, 0x0000);
5826	BWN_WRITE_2(mac, 0x050a, 0x0000);
5827	BWN_WRITE_2(mac, 0x054c, 0x0000);
5828	BWN_WRITE_2(mac, 0x056a, 0x0014);
5829	BWN_WRITE_2(mac, 0x0568, 0x0826);
5830	BWN_WRITE_2(mac, 0x0500, 0x0000);
5831	if (phy->type == BWN_PHYTYPE_LP)
5832		BWN_WRITE_2(mac, 0x0502, 0x0050);
5833	else
5834		BWN_WRITE_2(mac, 0x0502, 0x0030);
5835
5836	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5837		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5838	for (i = 0x00; i < max_loop; i++) {
5839		value = BWN_READ_2(mac, 0x050e);
5840		if (value & 0x0080)
5841			break;
5842		DELAY(10);
5843	}
5844	for (i = 0x00; i < 0x0a; i++) {
5845		value = BWN_READ_2(mac, 0x050e);
5846		if (value & 0x0400)
5847			break;
5848		DELAY(10);
5849	}
5850	for (i = 0x00; i < 0x19; i++) {
5851		value = BWN_READ_2(mac, 0x0690);
5852		if (!(value & 0x0100))
5853			break;
5854		DELAY(10);
5855	}
5856	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5857		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5858}
5859
5860static void
5861bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5862{
5863	uint32_t macctl;
5864
5865	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5866
5867	macctl = BWN_READ_4(mac, BWN_MACCTL);
5868	if (macctl & BWN_MACCTL_BIGENDIAN)
5869		printf("TODO: need swap\n");
5870
5871	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5872	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5873	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5874}
5875
5876static void
5877bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5878{
5879	uint16_t value;
5880
5881	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5882	    ("%s:%d: fail", __func__, __LINE__));
5883
5884	value = (uint8_t) (ctl->q);
5885	value |= ((uint8_t) (ctl->i)) << 8;
5886	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5887}
5888
5889static uint16_t
5890bwn_lo_calcfeed(struct bwn_mac *mac,
5891    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5892{
5893	struct bwn_phy *phy = &mac->mac_phy;
5894	struct bwn_softc *sc = mac->mac_sc;
5895	uint16_t rfover;
5896	uint16_t feedthrough;
5897
5898	if (phy->gmode) {
5899		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5900		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5901
5902		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5903		    ("%s:%d: fail", __func__, __LINE__));
5904		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5905		    ("%s:%d: fail", __func__, __LINE__));
5906
5907		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5908
5909		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5910		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5911		    phy->rev > 6)
5912			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5913
5914		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5915		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5916		DELAY(10);
5917		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5918		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5919		DELAY(10);
5920		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5921		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5922		DELAY(10);
5923		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5924	} else {
5925		pga |= BWN_PHY_PGACTL_UNKNOWN;
5926		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5927		DELAY(10);
5928		pga |= BWN_PHY_PGACTL_LOWBANDW;
5929		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5930		DELAY(10);
5931		pga |= BWN_PHY_PGACTL_LPF;
5932		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5933	}
5934	DELAY(21);
5935	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5936
5937	return (feedthrough);
5938}
5939
5940static uint16_t
5941bwn_lo_txctl_regtable(struct bwn_mac *mac,
5942    uint16_t *value, uint16_t *pad_mix_gain)
5943{
5944	struct bwn_phy *phy = &mac->mac_phy;
5945	uint16_t reg, v, padmix;
5946
5947	if (phy->type == BWN_PHYTYPE_B) {
5948		v = 0x30;
5949		if (phy->rf_rev <= 5) {
5950			reg = 0x43;
5951			padmix = 0;
5952		} else {
5953			reg = 0x52;
5954			padmix = 5;
5955		}
5956	} else {
5957		if (phy->rev >= 2 && phy->rf_rev == 8) {
5958			reg = 0x43;
5959			v = 0x10;
5960			padmix = 2;
5961		} else {
5962			reg = 0x52;
5963			v = 0x30;
5964			padmix = 5;
5965		}
5966	}
5967	if (value)
5968		*value = v;
5969	if (pad_mix_gain)
5970		*pad_mix_gain = padmix;
5971
5972	return (reg);
5973}
5974
5975static void
5976bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5977{
5978	struct bwn_phy *phy = &mac->mac_phy;
5979	struct bwn_phy_g *pg = &phy->phy_g;
5980	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5981	uint16_t reg, mask;
5982	uint16_t trsw_rx, pga;
5983	uint16_t rf_pctl_reg;
5984
5985	static const uint8_t tx_bias_values[] = {
5986		0x09, 0x08, 0x0a, 0x01, 0x00,
5987		0x02, 0x05, 0x04, 0x06,
5988	};
5989	static const uint8_t tx_magn_values[] = {
5990		0x70, 0x40,
5991	};
5992
5993	if (!BWN_HAS_LOOPBACK(phy)) {
5994		rf_pctl_reg = 6;
5995		trsw_rx = 2;
5996		pga = 0;
5997	} else {
5998		int lb_gain;
5999
6000		trsw_rx = 0;
6001		lb_gain = pg->pg_max_lb_gain / 2;
6002		if (lb_gain > 10) {
6003			rf_pctl_reg = 0;
6004			pga = abs(10 - lb_gain) / 6;
6005			pga = MIN(MAX(pga, 0), 15);
6006		} else {
6007			int cmp_val;
6008			int tmp;
6009
6010			pga = 0;
6011			cmp_val = 0x24;
6012			if ((phy->rev >= 2) &&
6013			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6014				cmp_val = 0x3c;
6015			tmp = lb_gain;
6016			if ((10 - lb_gain) < cmp_val)
6017				tmp = (10 - lb_gain);
6018			if (tmp < 0)
6019				tmp += 6;
6020			else
6021				tmp += 3;
6022			cmp_val /= 4;
6023			tmp /= 4;
6024			if (tmp >= cmp_val)
6025				rf_pctl_reg = cmp_val;
6026			else
6027				rf_pctl_reg = tmp;
6028		}
6029	}
6030	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6031	bwn_phy_g_set_bbatt(mac, 2);
6032
6033	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6034	mask = ~mask;
6035	BWN_RF_MASK(mac, reg, mask);
6036
6037	if (BWN_HAS_TXMAG(phy)) {
6038		int i, j;
6039		int feedthrough;
6040		int min_feedth = 0xffff;
6041		uint8_t tx_magn, tx_bias;
6042
6043		for (i = 0; i < N(tx_magn_values); i++) {
6044			tx_magn = tx_magn_values[i];
6045			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6046			for (j = 0; j < N(tx_bias_values); j++) {
6047				tx_bias = tx_bias_values[j];
6048				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6049				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6050				    trsw_rx);
6051				if (feedthrough < min_feedth) {
6052					lo->tx_bias = tx_bias;
6053					lo->tx_magn = tx_magn;
6054					min_feedth = feedthrough;
6055				}
6056				if (lo->tx_bias == 0)
6057					break;
6058			}
6059			BWN_RF_WRITE(mac, 0x52,
6060					  (BWN_RF_READ(mac, 0x52)
6061					   & 0xff00) | lo->tx_bias | lo->
6062					  tx_magn);
6063		}
6064	} else {
6065		lo->tx_magn = 0;
6066		lo->tx_bias = 0;
6067		BWN_RF_MASK(mac, 0x52, 0xfff0);
6068	}
6069
6070	BWN_GETTIME(lo->txctl_measured_time);
6071}
6072
6073static void
6074bwn_lo_get_powervector(struct bwn_mac *mac)
6075{
6076	struct bwn_phy *phy = &mac->mac_phy;
6077	struct bwn_phy_g *pg = &phy->phy_g;
6078	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6079	int i;
6080	uint64_t tmp;
6081	uint64_t power_vector = 0;
6082
6083	for (i = 0; i < 8; i += 2) {
6084		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6085		power_vector |= (tmp << (i * 8));
6086		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6087	}
6088	if (power_vector)
6089		lo->power_vector = power_vector;
6090
6091	BWN_GETTIME(lo->pwr_vec_read_time);
6092}
6093
6094static void
6095bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6096    int use_trsw_rx)
6097{
6098	struct bwn_phy *phy = &mac->mac_phy;
6099	struct bwn_phy_g *pg = &phy->phy_g;
6100	uint16_t tmp;
6101
6102	if (max_rx_gain < 0)
6103		max_rx_gain = 0;
6104
6105	if (BWN_HAS_LOOPBACK(phy)) {
6106		int trsw_rx = 0;
6107		int trsw_rx_gain;
6108
6109		if (use_trsw_rx) {
6110			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6111			if (max_rx_gain >= trsw_rx_gain) {
6112				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6113				trsw_rx = 0x20;
6114			}
6115		} else
6116			trsw_rx_gain = max_rx_gain;
6117		if (trsw_rx_gain < 9) {
6118			pg->pg_lna_lod_gain = 0;
6119		} else {
6120			pg->pg_lna_lod_gain = 1;
6121			trsw_rx_gain -= 8;
6122		}
6123		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6124		pg->pg_pga_gain = trsw_rx_gain / 3;
6125		if (pg->pg_pga_gain >= 5) {
6126			pg->pg_pga_gain -= 5;
6127			pg->pg_lna_gain = 2;
6128		} else
6129			pg->pg_lna_gain = 0;
6130	} else {
6131		pg->pg_lna_gain = 0;
6132		pg->pg_trsw_rx_gain = 0x20;
6133		if (max_rx_gain >= 0x14) {
6134			pg->pg_lna_lod_gain = 1;
6135			pg->pg_pga_gain = 2;
6136		} else if (max_rx_gain >= 0x12) {
6137			pg->pg_lna_lod_gain = 1;
6138			pg->pg_pga_gain = 1;
6139		} else if (max_rx_gain >= 0xf) {
6140			pg->pg_lna_lod_gain = 1;
6141			pg->pg_pga_gain = 0;
6142		} else {
6143			pg->pg_lna_lod_gain = 0;
6144			pg->pg_pga_gain = 0;
6145		}
6146	}
6147
6148	tmp = BWN_RF_READ(mac, 0x7a);
6149	if (pg->pg_lna_lod_gain == 0)
6150		tmp &= ~0x0008;
6151	else
6152		tmp |= 0x0008;
6153	BWN_RF_WRITE(mac, 0x7a, tmp);
6154}
6155
6156static void
6157bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6158{
6159	struct bwn_phy *phy = &mac->mac_phy;
6160	struct bwn_phy_g *pg = &phy->phy_g;
6161	struct bwn_softc *sc = mac->mac_sc;
6162	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6163	struct timespec ts;
6164	uint16_t tmp;
6165
6166	if (bwn_has_hwpctl(mac)) {
6167		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6168		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6169		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6170		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6171		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6172
6173		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6174		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6175		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6176		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6177	}
6178	if (phy->type == BWN_PHYTYPE_B &&
6179	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6180		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6181		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6182	}
6183	if (phy->rev >= 2) {
6184		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6185		sav->phy_analogoverval =
6186		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6187		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6188		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6189		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6190		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6191		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6192
6193		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6194		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6195		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6196		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6197		if (phy->type == BWN_PHYTYPE_G) {
6198			if ((phy->rev >= 7) &&
6199			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6200			     BWN_BFL_EXTLNA)) {
6201				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6202			} else {
6203				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6204			}
6205		} else {
6206			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6207		}
6208		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6209	}
6210	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6211	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6212	sav->rf0 = BWN_RF_READ(mac, 0x43);
6213	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6214	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6215	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6216	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6217	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6218
6219	if (!BWN_HAS_TXMAG(phy)) {
6220		sav->rf2 = BWN_RF_READ(mac, 0x52);
6221		sav->rf2 &= 0x00f0;
6222	}
6223	if (phy->type == BWN_PHYTYPE_B) {
6224		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6225		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6226		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6227		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6228	} else {
6229		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6230			    | 0x8000);
6231	}
6232	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6233		    & 0xf000);
6234
6235	tmp =
6236	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6237	BWN_PHY_WRITE(mac, tmp, 0x007f);
6238
6239	tmp = sav->phy_syncctl;
6240	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6241	tmp = sav->rf1;
6242	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6243
6244	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6245	if (phy->type == BWN_PHYTYPE_G ||
6246	    (phy->type == BWN_PHYTYPE_B &&
6247	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6248		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6249	} else
6250		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6251	if (phy->rev >= 2)
6252		bwn_dummy_transmission(mac, 0, 1);
6253	bwn_phy_g_switch_chan(mac, 6, 0);
6254	BWN_RF_READ(mac, 0x51);
6255	if (phy->type == BWN_PHYTYPE_G)
6256		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6257
6258	nanouptime(&ts);
6259	if (time_before(lo->txctl_measured_time,
6260	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6261		bwn_lo_measure_txctl_values(mac);
6262
6263	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6264		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6265	else {
6266		if (phy->type == BWN_PHYTYPE_B)
6267			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6268		else
6269			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6270	}
6271}
6272
6273static void
6274bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6275{
6276	struct bwn_phy *phy = &mac->mac_phy;
6277	struct bwn_phy_g *pg = &phy->phy_g;
6278	uint16_t tmp;
6279
6280	if (phy->rev >= 2) {
6281		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6282		tmp = (pg->pg_pga_gain << 8);
6283		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6284		DELAY(5);
6285		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6286		DELAY(2);
6287		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6288	} else {
6289		tmp = (pg->pg_pga_gain | 0xefa0);
6290		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6291	}
6292	if (phy->type == BWN_PHYTYPE_G) {
6293		if (phy->rev >= 3)
6294			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6295		else
6296			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6297		if (phy->rev >= 2)
6298			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6299		else
6300			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6301	}
6302	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6303	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6304	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6305	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6306	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6307	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6308	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6309	if (!BWN_HAS_TXMAG(phy)) {
6310		tmp = sav->rf2;
6311		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6312	}
6313	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6314	if (phy->type == BWN_PHYTYPE_B &&
6315	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6316		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6317		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6318	}
6319	if (phy->rev >= 2) {
6320		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6321		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6322			      sav->phy_analogoverval);
6323		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6324		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6325		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6326		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6327		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6328	}
6329	if (bwn_has_hwpctl(mac)) {
6330		tmp = (sav->phy_lomask & 0xbfff);
6331		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6332		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6333		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6334		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6335		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6336	}
6337	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6338}
6339
6340static int
6341bwn_lo_probe_loctl(struct bwn_mac *mac,
6342    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6343{
6344	struct bwn_phy *phy = &mac->mac_phy;
6345	struct bwn_phy_g *pg = &phy->phy_g;
6346	struct bwn_loctl orig, test;
6347	struct bwn_loctl prev = { -100, -100 };
6348	static const struct bwn_loctl modifiers[] = {
6349		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6350		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6351	};
6352	int begin, end, lower = 0, i;
6353	uint16_t feedth;
6354
6355	if (d->curstate == 0) {
6356		begin = 1;
6357		end = 8;
6358	} else if (d->curstate % 2 == 0) {
6359		begin = d->curstate - 1;
6360		end = d->curstate + 1;
6361	} else {
6362		begin = d->curstate - 2;
6363		end = d->curstate + 2;
6364	}
6365	if (begin < 1)
6366		begin += 8;
6367	if (end > 8)
6368		end -= 8;
6369
6370	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6371	i = begin;
6372	d->curstate = i;
6373	while (1) {
6374		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6375		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6376		test.i += modifiers[i - 1].i * d->multipler;
6377		test.q += modifiers[i - 1].q * d->multipler;
6378		if ((test.i != prev.i || test.q != prev.q) &&
6379		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6380			bwn_lo_write(mac, &test);
6381			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6382			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6383			if (feedth < d->feedth) {
6384				memcpy(probe, &test,
6385				    sizeof(struct bwn_loctl));
6386				lower = 1;
6387				d->feedth = feedth;
6388				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6389					break;
6390			}
6391		}
6392		memcpy(&prev, &test, sizeof(prev));
6393		if (i == end)
6394			break;
6395		if (i == 8)
6396			i = 1;
6397		else
6398			i++;
6399		d->curstate = i;
6400	}
6401
6402	return (lower);
6403}
6404
6405static void
6406bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6407{
6408	struct bwn_phy *phy = &mac->mac_phy;
6409	struct bwn_phy_g *pg = &phy->phy_g;
6410	struct bwn_lo_g_sm d;
6411	struct bwn_loctl probe;
6412	int lower, repeat, cnt = 0;
6413	uint16_t feedth;
6414
6415	d.nmeasure = 0;
6416	d.multipler = 1;
6417	if (BWN_HAS_LOOPBACK(phy))
6418		d.multipler = 3;
6419
6420	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6421	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6422
6423	do {
6424		bwn_lo_write(mac, &d.loctl);
6425		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6426		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6427		if (feedth < 0x258) {
6428			if (feedth >= 0x12c)
6429				*rxgain += 6;
6430			else
6431				*rxgain += 3;
6432			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6433			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6434		}
6435		d.feedth = feedth;
6436		d.curstate = 0;
6437		do {
6438			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6439			    ("%s:%d: fail", __func__, __LINE__));
6440			memcpy(&probe, &d.loctl,
6441			       sizeof(struct bwn_loctl));
6442			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6443			if (!lower)
6444				break;
6445			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6446				break;
6447			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6448			d.nmeasure++;
6449		} while (d.nmeasure < 24);
6450		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6451
6452		if (BWN_HAS_LOOPBACK(phy)) {
6453			if (d.feedth > 0x1194)
6454				*rxgain -= 6;
6455			else if (d.feedth < 0x5dc)
6456				*rxgain += 3;
6457			if (cnt == 0) {
6458				if (d.feedth <= 0x5dc) {
6459					d.multipler = 1;
6460					cnt++;
6461				} else
6462					d.multipler = 2;
6463			} else if (cnt == 2)
6464				d.multipler = 1;
6465		}
6466		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6467	} while (++cnt < repeat);
6468}
6469
6470static struct bwn_lo_calib *
6471bwn_lo_calibset(struct bwn_mac *mac,
6472    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6473{
6474	struct bwn_phy *phy = &mac->mac_phy;
6475	struct bwn_phy_g *pg = &phy->phy_g;
6476	struct bwn_loctl loctl = { 0, 0 };
6477	struct bwn_lo_calib *cal;
6478	struct bwn_lo_g_value sval = { 0 };
6479	int rxgain;
6480	uint16_t pad, reg, value;
6481
6482	sval.old_channel = phy->chan;
6483	bwn_mac_suspend(mac);
6484	bwn_lo_save(mac, &sval);
6485
6486	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6487	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6488	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6489
6490	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6491	if (rfatt->padmix)
6492		rxgain -= pad;
6493	if (BWN_HAS_LOOPBACK(phy))
6494		rxgain += pg->pg_max_lb_gain;
6495	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6496	bwn_phy_g_set_bbatt(mac, bbatt->att);
6497	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6498
6499	bwn_lo_restore(mac, &sval);
6500	bwn_mac_enable(mac);
6501
6502	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6503	if (!cal) {
6504		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6505		return (NULL);
6506	}
6507	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6508	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6509	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6510
6511	BWN_GETTIME(cal->calib_time);
6512
6513	return (cal);
6514}
6515
6516static struct bwn_lo_calib *
6517bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6518    const struct bwn_rfatt *rfatt)
6519{
6520	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6521	struct bwn_lo_calib *c;
6522
6523	TAILQ_FOREACH(c, &lo->calib_list, list) {
6524		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6525			continue;
6526		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6527			continue;
6528		return (c);
6529	}
6530
6531	c = bwn_lo_calibset(mac, bbatt, rfatt);
6532	if (!c)
6533		return (NULL);
6534	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6535
6536	return (c);
6537}
6538
6539static void
6540bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6541{
6542	struct bwn_phy *phy = &mac->mac_phy;
6543	struct bwn_phy_g *pg = &phy->phy_g;
6544	struct bwn_softc *sc = mac->mac_sc;
6545	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6546	const struct bwn_rfatt *rfatt;
6547	const struct bwn_bbatt *bbatt;
6548	uint64_t pvector;
6549	int i;
6550	int rf_offset, bb_offset;
6551	uint8_t changed = 0;
6552
6553	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6554	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6555	    ("%s:%d: fail", __func__, __LINE__));
6556
6557	pvector = lo->power_vector;
6558	if (!update && !pvector)
6559		return;
6560
6561	bwn_mac_suspend(mac);
6562
6563	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6564		struct bwn_lo_calib *cal;
6565		int idx;
6566		uint16_t val;
6567
6568		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6569			continue;
6570		bb_offset = i / lo->rfatt.len;
6571		rf_offset = i % lo->rfatt.len;
6572		bbatt = &(lo->bbatt.array[bb_offset]);
6573		rfatt = &(lo->rfatt.array[rf_offset]);
6574
6575		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6576		if (!cal) {
6577			device_printf(sc->sc_dev, "LO: Could not "
6578			    "calibrate DC table entry\n");
6579			continue;
6580		}
6581		val = (uint8_t)(cal->ctl.q);
6582		val |= ((uint8_t)(cal->ctl.i)) << 4;
6583		free(cal, M_DEVBUF);
6584
6585		idx = i / 2;
6586		if (i % 2)
6587			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6588			    | ((val & 0x00ff) << 8);
6589		else
6590			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6591			    | (val & 0x00ff);
6592		changed = 1;
6593	}
6594	if (changed) {
6595		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6596			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6597	}
6598	bwn_mac_enable(mac);
6599}
6600
6601static void
6602bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6603{
6604
6605	if (!rf->padmix)
6606		return;
6607	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6608		rf->att = 4;
6609}
6610
6611static void
6612bwn_lo_g_adjust(struct bwn_mac *mac)
6613{
6614	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6615	struct bwn_lo_calib *cal;
6616	struct bwn_rfatt rf;
6617
6618	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6619	bwn_lo_fixup_rfatt(&rf);
6620
6621	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6622	if (!cal)
6623		return;
6624	bwn_lo_write(mac, &cal->ctl);
6625}
6626
6627static void
6628bwn_lo_g_init(struct bwn_mac *mac)
6629{
6630
6631	if (!bwn_has_hwpctl(mac))
6632		return;
6633
6634	bwn_lo_get_powervector(mac);
6635	bwn_phy_g_dc_lookup_init(mac, 1);
6636}
6637
6638static void
6639bwn_mac_suspend(struct bwn_mac *mac)
6640{
6641	struct bwn_softc *sc = mac->mac_sc;
6642	int i;
6643	uint32_t tmp;
6644
6645	KASSERT(mac->mac_suspended >= 0,
6646	    ("%s:%d: fail", __func__, __LINE__));
6647
6648	if (mac->mac_suspended == 0) {
6649		bwn_psctl(mac, BWN_PS_AWAKE);
6650		BWN_WRITE_4(mac, BWN_MACCTL,
6651			    BWN_READ_4(mac, BWN_MACCTL)
6652			    & ~BWN_MACCTL_ON);
6653		BWN_READ_4(mac, BWN_MACCTL);
6654		for (i = 35; i; i--) {
6655			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6656			if (tmp & BWN_INTR_MAC_SUSPENDED)
6657				goto out;
6658			DELAY(10);
6659		}
6660		for (i = 40; i; i--) {
6661			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6662			if (tmp & BWN_INTR_MAC_SUSPENDED)
6663				goto out;
6664			DELAY(1000);
6665		}
6666		device_printf(sc->sc_dev, "MAC suspend failed\n");
6667	}
6668out:
6669	mac->mac_suspended++;
6670}
6671
6672static void
6673bwn_mac_enable(struct bwn_mac *mac)
6674{
6675	struct bwn_softc *sc = mac->mac_sc;
6676	uint16_t state;
6677
6678	state = bwn_shm_read_2(mac, BWN_SHARED,
6679	    BWN_SHARED_UCODESTAT);
6680	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6681	    state != BWN_SHARED_UCODESTAT_SLEEP)
6682		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6683
6684	mac->mac_suspended--;
6685	KASSERT(mac->mac_suspended >= 0,
6686	    ("%s:%d: fail", __func__, __LINE__));
6687	if (mac->mac_suspended == 0) {
6688		BWN_WRITE_4(mac, BWN_MACCTL,
6689		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6690		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6691		BWN_READ_4(mac, BWN_MACCTL);
6692		BWN_READ_4(mac, BWN_INTR_REASON);
6693		bwn_psctl(mac, 0);
6694	}
6695}
6696
6697static void
6698bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6699{
6700	struct bwn_softc *sc = mac->mac_sc;
6701	int i;
6702	uint16_t ucstat;
6703
6704	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6705	    ("%s:%d: fail", __func__, __LINE__));
6706	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6707	    ("%s:%d: fail", __func__, __LINE__));
6708
6709	/* XXX forcibly awake and hwps-off */
6710
6711	BWN_WRITE_4(mac, BWN_MACCTL,
6712	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6713	    ~BWN_MACCTL_HWPS);
6714	BWN_READ_4(mac, BWN_MACCTL);
6715	if (siba_get_revid(sc->sc_dev) >= 5) {
6716		for (i = 0; i < 100; i++) {
6717			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6718			    BWN_SHARED_UCODESTAT);
6719			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6720				break;
6721			DELAY(10);
6722		}
6723	}
6724}
6725
6726static int16_t
6727bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6728{
6729
6730	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6731	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6732}
6733
6734static void
6735bwn_nrssi_threshold(struct bwn_mac *mac)
6736{
6737	struct bwn_phy *phy = &mac->mac_phy;
6738	struct bwn_phy_g *pg = &phy->phy_g;
6739	struct bwn_softc *sc = mac->mac_sc;
6740	int32_t a, b;
6741	int16_t tmp16;
6742	uint16_t tmpu16;
6743
6744	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6745
6746	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6747		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6748			a = 0x13;
6749			b = 0x12;
6750		} else {
6751			a = 0xe;
6752			b = 0x11;
6753		}
6754
6755		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6756		a += (pg->pg_nrssi[0] << 6);
6757		a += (a < 32) ? 31 : 32;
6758		a = a >> 6;
6759		a = MIN(MAX(a, -31), 31);
6760
6761		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6762		b += (pg->pg_nrssi[0] << 6);
6763		if (b < 32)
6764			b += 31;
6765		else
6766			b += 32;
6767		b = b >> 6;
6768		b = MIN(MAX(b, -31), 31);
6769
6770		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6771		tmpu16 |= ((uint32_t)b & 0x0000003f);
6772		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6773		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6774		return;
6775	}
6776
6777	tmp16 = bwn_nrssi_read(mac, 0x20);
6778	if (tmp16 >= 0x20)
6779		tmp16 -= 0x40;
6780	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6781}
6782
6783static void
6784bwn_nrssi_slope_11g(struct bwn_mac *mac)
6785{
6786#define	SAVE_RF_MAX		3
6787#define	SAVE_PHY_COMM_MAX	4
6788#define	SAVE_PHY3_MAX		8
6789	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6790		{ 0x7a, 0x52, 0x43 };
6791	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6792		{ 0x15, 0x5a, 0x59, 0x58 };
6793	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6794		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6795		0x0801, 0x0060, 0x0014, 0x0478
6796	};
6797	struct bwn_phy *phy = &mac->mac_phy;
6798	struct bwn_phy_g *pg = &phy->phy_g;
6799	int32_t i, tmp32, phy3_idx = 0;
6800	uint16_t delta, tmp;
6801	uint16_t save_rf[SAVE_RF_MAX];
6802	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6803	uint16_t save_phy3[SAVE_PHY3_MAX];
6804	uint16_t ant_div, phy0, chan_ex;
6805	int16_t nrssi0, nrssi1;
6806
6807	KASSERT(phy->type == BWN_PHYTYPE_G,
6808	    ("%s:%d: fail", __func__, __LINE__));
6809
6810	if (phy->rf_rev >= 9)
6811		return;
6812	if (phy->rf_rev == 8)
6813		bwn_nrssi_offset(mac);
6814
6815	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6816	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6817
6818	/*
6819	 * Save RF/PHY registers for later restoration
6820	 */
6821	ant_div = BWN_READ_2(mac, 0x03e2);
6822	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6823	for (i = 0; i < SAVE_RF_MAX; ++i)
6824		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6825	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6826		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6827
6828	phy0 = BWN_READ_2(mac, BWN_PHY0);
6829	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6830	if (phy->rev >= 3) {
6831		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6832			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6833		BWN_PHY_WRITE(mac, 0x002e, 0);
6834		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6835		switch (phy->rev) {
6836		case 4:
6837		case 6:
6838		case 7:
6839			BWN_PHY_SET(mac, 0x0478, 0x0100);
6840			BWN_PHY_SET(mac, 0x0801, 0x0040);
6841			break;
6842		case 3:
6843		case 5:
6844			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6845			break;
6846		}
6847		BWN_PHY_SET(mac, 0x0060, 0x0040);
6848		BWN_PHY_SET(mac, 0x0014, 0x0200);
6849	}
6850	/*
6851	 * Calculate nrssi0
6852	 */
6853	BWN_RF_SET(mac, 0x007a, 0x0070);
6854	bwn_set_all_gains(mac, 0, 8, 0);
6855	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6856	if (phy->rev >= 2) {
6857		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6858		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6859	}
6860	BWN_RF_SET(mac, 0x007a, 0x0080);
6861	DELAY(20);
6862
6863	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6864	if (nrssi0 >= 0x0020)
6865		nrssi0 -= 0x0040;
6866
6867	/*
6868	 * Calculate nrssi1
6869	 */
6870	BWN_RF_MASK(mac, 0x007a, 0x007f);
6871	if (phy->rev >= 2)
6872		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6873
6874	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6875	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6876	BWN_RF_SET(mac, 0x007a, 0x000f);
6877	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6878	if (phy->rev >= 2) {
6879		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6880		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6881	}
6882
6883	bwn_set_all_gains(mac, 3, 0, 1);
6884	if (phy->rf_rev == 8) {
6885		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6886	} else {
6887		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6888		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6889		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6890		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6891	}
6892	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6893	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6894	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6895	DELAY(20);
6896	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6897
6898	/*
6899	 * Install calculated narrow RSSI values
6900	 */
6901	if (nrssi1 >= 0x0020)
6902		nrssi1 -= 0x0040;
6903	if (nrssi0 == nrssi1)
6904		pg->pg_nrssi_slope = 0x00010000;
6905	else
6906		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6907	if (nrssi0 >= -4) {
6908		pg->pg_nrssi[0] = nrssi1;
6909		pg->pg_nrssi[1] = nrssi0;
6910	}
6911
6912	/*
6913	 * Restore saved RF/PHY registers
6914	 */
6915	if (phy->rev >= 3) {
6916		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6917			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6918			    save_phy3[phy3_idx]);
6919		}
6920	}
6921	if (phy->rev >= 2) {
6922		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6923		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6924	}
6925
6926	for (i = 0; i < SAVE_RF_MAX; ++i)
6927		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6928
6929	BWN_WRITE_2(mac, 0x03e2, ant_div);
6930	BWN_WRITE_2(mac, 0x03e6, phy0);
6931	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6932
6933	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6934		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6935
6936	bwn_spu_workaround(mac, phy->chan);
6937	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6938	bwn_set_original_gains(mac);
6939	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6940	if (phy->rev >= 3) {
6941		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6942			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6943			    save_phy3[phy3_idx]);
6944		}
6945	}
6946
6947	delta = 0x1f - pg->pg_nrssi[0];
6948	for (i = 0; i < 64; i++) {
6949		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6950		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6951		pg->pg_nrssi_lt[i] = tmp32;
6952	}
6953
6954	bwn_nrssi_threshold(mac);
6955#undef SAVE_RF_MAX
6956#undef SAVE_PHY_COMM_MAX
6957#undef SAVE_PHY3_MAX
6958}
6959
6960static void
6961bwn_nrssi_offset(struct bwn_mac *mac)
6962{
6963#define	SAVE_RF_MAX		2
6964#define	SAVE_PHY_COMM_MAX	10
6965#define	SAVE_PHY6_MAX		8
6966	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6967		{ 0x7a, 0x43 };
6968	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6969		0x0001, 0x0811, 0x0812, 0x0814,
6970		0x0815, 0x005a, 0x0059, 0x0058,
6971		0x000a, 0x0003
6972	};
6973	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6974		0x002e, 0x002f, 0x080f, 0x0810,
6975		0x0801, 0x0060, 0x0014, 0x0478
6976	};
6977	struct bwn_phy *phy = &mac->mac_phy;
6978	int i, phy6_idx = 0;
6979	uint16_t save_rf[SAVE_RF_MAX];
6980	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6981	uint16_t save_phy6[SAVE_PHY6_MAX];
6982	int16_t nrssi;
6983	uint16_t saved = 0xffff;
6984
6985	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6986		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6987	for (i = 0; i < SAVE_RF_MAX; ++i)
6988		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6989
6990	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6991	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6992	BWN_PHY_SET(mac, 0x0811, 0x000c);
6993	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6994	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6995	if (phy->rev >= 6) {
6996		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6997			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6998
6999		BWN_PHY_WRITE(mac, 0x002e, 0);
7000		BWN_PHY_WRITE(mac, 0x002f, 0);
7001		BWN_PHY_WRITE(mac, 0x080f, 0);
7002		BWN_PHY_WRITE(mac, 0x0810, 0);
7003		BWN_PHY_SET(mac, 0x0478, 0x0100);
7004		BWN_PHY_SET(mac, 0x0801, 0x0040);
7005		BWN_PHY_SET(mac, 0x0060, 0x0040);
7006		BWN_PHY_SET(mac, 0x0014, 0x0200);
7007	}
7008	BWN_RF_SET(mac, 0x007a, 0x0070);
7009	BWN_RF_SET(mac, 0x007a, 0x0080);
7010	DELAY(30);
7011
7012	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7013	if (nrssi >= 0x20)
7014		nrssi -= 0x40;
7015	if (nrssi == 31) {
7016		for (i = 7; i >= 4; i--) {
7017			BWN_RF_WRITE(mac, 0x007b, i);
7018			DELAY(20);
7019			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7020			    0x003f);
7021			if (nrssi >= 0x20)
7022				nrssi -= 0x40;
7023			if (nrssi < 31 && saved == 0xffff)
7024				saved = i;
7025		}
7026		if (saved == 0xffff)
7027			saved = 4;
7028	} else {
7029		BWN_RF_MASK(mac, 0x007a, 0x007f);
7030		if (phy->rev != 1) {
7031			BWN_PHY_SET(mac, 0x0814, 0x0001);
7032			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7033		}
7034		BWN_PHY_SET(mac, 0x0811, 0x000c);
7035		BWN_PHY_SET(mac, 0x0812, 0x000c);
7036		BWN_PHY_SET(mac, 0x0811, 0x0030);
7037		BWN_PHY_SET(mac, 0x0812, 0x0030);
7038		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7039		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7040		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7041		if (phy->rev == 0)
7042			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7043		else
7044			BWN_PHY_SET(mac, 0x000a, 0x2000);
7045		if (phy->rev != 1) {
7046			BWN_PHY_SET(mac, 0x0814, 0x0004);
7047			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7048		}
7049		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7050		BWN_RF_SET(mac, 0x007a, 0x000f);
7051		bwn_set_all_gains(mac, 3, 0, 1);
7052		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7053		DELAY(30);
7054		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7055		if (nrssi >= 0x20)
7056			nrssi -= 0x40;
7057		if (nrssi == -32) {
7058			for (i = 0; i < 4; i++) {
7059				BWN_RF_WRITE(mac, 0x007b, i);
7060				DELAY(20);
7061				nrssi = (int16_t)((BWN_PHY_READ(mac,
7062				    0x047f) >> 8) & 0x003f);
7063				if (nrssi >= 0x20)
7064					nrssi -= 0x40;
7065				if (nrssi > -31 && saved == 0xffff)
7066					saved = i;
7067			}
7068			if (saved == 0xffff)
7069				saved = 3;
7070		} else
7071			saved = 0;
7072	}
7073	BWN_RF_WRITE(mac, 0x007b, saved);
7074
7075	/*
7076	 * Restore saved RF/PHY registers
7077	 */
7078	if (phy->rev >= 6) {
7079		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7080			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7081			    save_phy6[phy6_idx]);
7082		}
7083	}
7084	if (phy->rev != 1) {
7085		for (i = 3; i < 5; i++)
7086			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7087			    save_phy_comm[i]);
7088	}
7089	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7090		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7091
7092	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7093		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7094
7095	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7096	BWN_PHY_SET(mac, 0x0429, 0x8000);
7097	bwn_set_original_gains(mac);
7098	if (phy->rev >= 6) {
7099		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7100			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7101			    save_phy6[phy6_idx]);
7102		}
7103	}
7104
7105	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7106	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7107	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7108}
7109
7110static void
7111bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7112    int16_t third)
7113{
7114	struct bwn_phy *phy = &mac->mac_phy;
7115	uint16_t i;
7116	uint16_t start = 0x08, end = 0x18;
7117	uint16_t tmp;
7118	uint16_t table;
7119
7120	if (phy->rev <= 1) {
7121		start = 0x10;
7122		end = 0x20;
7123	}
7124
7125	table = BWN_OFDMTAB_GAINX;
7126	if (phy->rev <= 1)
7127		table = BWN_OFDMTAB_GAINX_R1;
7128	for (i = 0; i < 4; i++)
7129		bwn_ofdmtab_write_2(mac, table, i, first);
7130
7131	for (i = start; i < end; i++)
7132		bwn_ofdmtab_write_2(mac, table, i, second);
7133
7134	if (third != -1) {
7135		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7136		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7137		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7138		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7139	}
7140	bwn_dummy_transmission(mac, 0, 1);
7141}
7142
7143static void
7144bwn_set_original_gains(struct bwn_mac *mac)
7145{
7146	struct bwn_phy *phy = &mac->mac_phy;
7147	uint16_t i, tmp;
7148	uint16_t table;
7149	uint16_t start = 0x0008, end = 0x0018;
7150
7151	if (phy->rev <= 1) {
7152		start = 0x0010;
7153		end = 0x0020;
7154	}
7155
7156	table = BWN_OFDMTAB_GAINX;
7157	if (phy->rev <= 1)
7158		table = BWN_OFDMTAB_GAINX_R1;
7159	for (i = 0; i < 4; i++) {
7160		tmp = (i & 0xfffc);
7161		tmp |= (i & 0x0001) << 1;
7162		tmp |= (i & 0x0002) >> 1;
7163
7164		bwn_ofdmtab_write_2(mac, table, i, tmp);
7165	}
7166
7167	for (i = start; i < end; i++)
7168		bwn_ofdmtab_write_2(mac, table, i, i - start);
7169
7170	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7171	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7172	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7173	bwn_dummy_transmission(mac, 0, 1);
7174}
7175
7176static void
7177bwn_phy_hwpctl_init(struct bwn_mac *mac)
7178{
7179	struct bwn_phy *phy = &mac->mac_phy;
7180	struct bwn_phy_g *pg = &phy->phy_g;
7181	struct bwn_rfatt old_rfatt, rfatt;
7182	struct bwn_bbatt old_bbatt, bbatt;
7183	struct bwn_softc *sc = mac->mac_sc;
7184	uint8_t old_txctl = 0;
7185
7186	KASSERT(phy->type == BWN_PHYTYPE_G,
7187	    ("%s:%d: fail", __func__, __LINE__));
7188
7189	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7190	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7191		return;
7192
7193	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7194
7195	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7196
7197	if (!phy->gmode)
7198		return;
7199	bwn_hwpctl_early_init(mac);
7200	if (pg->pg_curtssi == 0) {
7201		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7202			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7203		} else {
7204			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7205			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7206			old_txctl = pg->pg_txctl;
7207
7208			bbatt.att = 11;
7209			if (phy->rf_rev == 8) {
7210				rfatt.att = 15;
7211				rfatt.padmix = 1;
7212			} else {
7213				rfatt.att = 9;
7214				rfatt.padmix = 0;
7215			}
7216			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7217		}
7218		bwn_dummy_transmission(mac, 0, 1);
7219		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7220		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7221			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7222		else
7223			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7224			    &old_rfatt, old_txctl);
7225	}
7226	bwn_hwpctl_init_gphy(mac);
7227
7228	/* clear TSSI */
7229	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7230	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7231	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7232	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7233}
7234
7235static void
7236bwn_hwpctl_early_init(struct bwn_mac *mac)
7237{
7238	struct bwn_phy *phy = &mac->mac_phy;
7239
7240	if (!bwn_has_hwpctl(mac)) {
7241		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7242		return;
7243	}
7244
7245	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7246	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7247	BWN_PHY_SET(mac, 0x047c, 0x0002);
7248	BWN_PHY_SET(mac, 0x047a, 0xf000);
7249	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7250		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7251		BWN_PHY_SET(mac, 0x005d, 0x8000);
7252		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7253		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7254		BWN_PHY_SET(mac, 0x0036, 0x0400);
7255	} else {
7256		BWN_PHY_SET(mac, 0x0036, 0x0200);
7257		BWN_PHY_SET(mac, 0x0036, 0x0400);
7258		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7259		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7260		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7261		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7262		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7263	}
7264}
7265
7266static void
7267bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7268{
7269	struct bwn_phy *phy = &mac->mac_phy;
7270	struct bwn_phy_g *pg = &phy->phy_g;
7271	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7272	int i;
7273	uint16_t nr_written = 0, tmp, value;
7274	uint8_t rf, bb;
7275
7276	if (!bwn_has_hwpctl(mac)) {
7277		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7278		return;
7279	}
7280
7281	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7282	    (pg->pg_idletssi - pg->pg_curtssi));
7283	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7284	    (pg->pg_idletssi - pg->pg_curtssi));
7285
7286	for (i = 0; i < 32; i++)
7287		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7288	for (i = 32; i < 64; i++)
7289		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7290	for (i = 0; i < 64; i += 2) {
7291		value = (uint16_t) pg->pg_tssi2dbm[i];
7292		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7293		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7294	}
7295
7296	for (rf = 0; rf < lo->rfatt.len; rf++) {
7297		for (bb = 0; bb < lo->bbatt.len; bb++) {
7298			if (nr_written >= 0x40)
7299				return;
7300			tmp = lo->bbatt.array[bb].att;
7301			tmp <<= 8;
7302			if (phy->rf_rev == 8)
7303				tmp |= 0x50;
7304			else
7305				tmp |= 0x40;
7306			tmp |= lo->rfatt.array[rf].att;
7307			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7308			nr_written++;
7309		}
7310	}
7311
7312	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7313	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7314
7315	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7316	BWN_PHY_SET(mac, 0x0478, 0x0800);
7317	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7318	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7319
7320	bwn_phy_g_dc_lookup_init(mac, 1);
7321	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7322}
7323
7324static void
7325bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7326{
7327	struct bwn_softc *sc = mac->mac_sc;
7328
7329	if (spu != 0)
7330		bwn_spu_workaround(mac, channel);
7331
7332	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7333
7334	if (channel == 14) {
7335		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7336			bwn_hf_write(mac,
7337			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7338		else
7339			bwn_hf_write(mac,
7340			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7341		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7342		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7343		return;
7344	}
7345
7346	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7347	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7348}
7349
7350static uint16_t
7351bwn_phy_g_chan2freq(uint8_t channel)
7352{
7353	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7354
7355	KASSERT(channel >= 1 && channel <= 14,
7356	    ("%s:%d: fail", __func__, __LINE__));
7357
7358	return (bwn_phy_g_rf_channels[channel - 1]);
7359}
7360
7361static void
7362bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7363    const struct bwn_rfatt *rfatt, uint8_t txctl)
7364{
7365	struct bwn_phy *phy = &mac->mac_phy;
7366	struct bwn_phy_g *pg = &phy->phy_g;
7367	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7368	uint16_t bb, rf;
7369	uint16_t tx_bias, tx_magn;
7370
7371	bb = bbatt->att;
7372	rf = rfatt->att;
7373	tx_bias = lo->tx_bias;
7374	tx_magn = lo->tx_magn;
7375	if (tx_bias == 0xff)
7376		tx_bias = 0;
7377
7378	pg->pg_txctl = txctl;
7379	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7380	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7381	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7382	bwn_phy_g_set_bbatt(mac, bb);
7383	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7384	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7385		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7386	else {
7387		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7388		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7389	}
7390	if (BWN_HAS_TXMAG(phy))
7391		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7392	else
7393		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7394	bwn_lo_g_adjust(mac);
7395}
7396
7397static void
7398bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7399    uint16_t bbatt)
7400{
7401	struct bwn_phy *phy = &mac->mac_phy;
7402
7403	if (phy->analog == 0) {
7404		BWN_WRITE_2(mac, BWN_PHY0,
7405		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7406		return;
7407	}
7408	if (phy->analog > 1) {
7409		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7410		return;
7411	}
7412	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7413}
7414
7415static uint16_t
7416bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7417{
7418	struct bwn_phy *phy = &mac->mac_phy;
7419	struct bwn_phy_g *pg = &phy->phy_g;
7420	struct bwn_softc *sc = mac->mac_sc;
7421	int max_lb_gain;
7422	uint16_t extlna;
7423	uint16_t i;
7424
7425	if (phy->gmode == 0)
7426		return (0);
7427
7428	if (BWN_HAS_LOOPBACK(phy)) {
7429		max_lb_gain = pg->pg_max_lb_gain;
7430		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7431		if (max_lb_gain >= 0x46) {
7432			extlna = 0x3000;
7433			max_lb_gain -= 0x46;
7434		} else if (max_lb_gain >= 0x3a) {
7435			extlna = 0x1000;
7436			max_lb_gain -= 0x3a;
7437		} else if (max_lb_gain >= 0x2e) {
7438			extlna = 0x2000;
7439			max_lb_gain -= 0x2e;
7440		} else {
7441			extlna = 0;
7442			max_lb_gain -= 0x10;
7443		}
7444
7445		for (i = 0; i < 16; i++) {
7446			max_lb_gain -= (i * 6);
7447			if (max_lb_gain < 6)
7448				break;
7449		}
7450
7451		if ((phy->rev < 7) ||
7452		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7453			if (reg == BWN_PHY_RFOVER) {
7454				return (0x1b3);
7455			} else if (reg == BWN_PHY_RFOVERVAL) {
7456				extlna |= (i << 8);
7457				switch (lpd) {
7458				case BWN_LPD(0, 1, 1):
7459					return (0x0f92);
7460				case BWN_LPD(0, 0, 1):
7461				case BWN_LPD(1, 0, 1):
7462					return (0x0092 | extlna);
7463				case BWN_LPD(1, 0, 0):
7464					return (0x0093 | extlna);
7465				}
7466				KASSERT(0 == 1,
7467				    ("%s:%d: fail", __func__, __LINE__));
7468			}
7469			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7470		} else {
7471			if (reg == BWN_PHY_RFOVER)
7472				return (0x9b3);
7473			if (reg == BWN_PHY_RFOVERVAL) {
7474				if (extlna)
7475					extlna |= 0x8000;
7476				extlna |= (i << 8);
7477				switch (lpd) {
7478				case BWN_LPD(0, 1, 1):
7479					return (0x8f92);
7480				case BWN_LPD(0, 0, 1):
7481					return (0x8092 | extlna);
7482				case BWN_LPD(1, 0, 1):
7483					return (0x2092 | extlna);
7484				case BWN_LPD(1, 0, 0):
7485					return (0x2093 | extlna);
7486				}
7487				KASSERT(0 == 1,
7488				    ("%s:%d: fail", __func__, __LINE__));
7489			}
7490			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7491		}
7492		return (0);
7493	}
7494
7495	if ((phy->rev < 7) ||
7496	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7497		if (reg == BWN_PHY_RFOVER) {
7498			return (0x1b3);
7499		} else if (reg == BWN_PHY_RFOVERVAL) {
7500			switch (lpd) {
7501			case BWN_LPD(0, 1, 1):
7502				return (0x0fb2);
7503			case BWN_LPD(0, 0, 1):
7504				return (0x00b2);
7505			case BWN_LPD(1, 0, 1):
7506				return (0x30b2);
7507			case BWN_LPD(1, 0, 0):
7508				return (0x30b3);
7509			}
7510			KASSERT(0 == 1,
7511			    ("%s:%d: fail", __func__, __LINE__));
7512		}
7513		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7514	} else {
7515		if (reg == BWN_PHY_RFOVER) {
7516			return (0x9b3);
7517		} else if (reg == BWN_PHY_RFOVERVAL) {
7518			switch (lpd) {
7519			case BWN_LPD(0, 1, 1):
7520				return (0x8fb2);
7521			case BWN_LPD(0, 0, 1):
7522				return (0x80b2);
7523			case BWN_LPD(1, 0, 1):
7524				return (0x20b2);
7525			case BWN_LPD(1, 0, 0):
7526				return (0x20b3);
7527			}
7528			KASSERT(0 == 1,
7529			    ("%s:%d: fail", __func__, __LINE__));
7530		}
7531		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7532	}
7533	return (0);
7534}
7535
7536static void
7537bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7538{
7539
7540	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7541		return;
7542	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7543	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7544	DELAY(1000);
7545	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7546}
7547
7548static int
7549bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7550{
7551	struct bwn_softc *sc = mac->mac_sc;
7552	struct bwn_fw *fw = &mac->mac_fw;
7553	const uint8_t rev = siba_get_revid(sc->sc_dev);
7554	const char *filename;
7555	uint32_t high;
7556	int error;
7557
7558	/* microcode */
7559	if (rev >= 5 && rev <= 10)
7560		filename = "ucode5";
7561	else if (rev >= 11 && rev <= 12)
7562		filename = "ucode11";
7563	else if (rev == 13)
7564		filename = "ucode13";
7565	else if (rev == 14)
7566		filename = "ucode14";
7567	else if (rev >= 15)
7568		filename = "ucode15";
7569	else {
7570		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7571		bwn_release_firmware(mac);
7572		return (EOPNOTSUPP);
7573	}
7574	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7575	if (error) {
7576		bwn_release_firmware(mac);
7577		return (error);
7578	}
7579
7580	/* PCM */
7581	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7582	if (rev >= 5 && rev <= 10) {
7583		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7584		if (error == ENOENT)
7585			fw->no_pcmfile = 1;
7586		else if (error) {
7587			bwn_release_firmware(mac);
7588			return (error);
7589		}
7590	} else if (rev < 11) {
7591		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7592		return (EOPNOTSUPP);
7593	}
7594
7595	/* initvals */
7596	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7597	switch (mac->mac_phy.type) {
7598	case BWN_PHYTYPE_A:
7599		if (rev < 5 || rev > 10)
7600			goto fail1;
7601		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7602			filename = "a0g1initvals5";
7603		else
7604			filename = "a0g0initvals5";
7605		break;
7606	case BWN_PHYTYPE_G:
7607		if (rev >= 5 && rev <= 10)
7608			filename = "b0g0initvals5";
7609		else if (rev >= 13)
7610			filename = "b0g0initvals13";
7611		else
7612			goto fail1;
7613		break;
7614	case BWN_PHYTYPE_LP:
7615		if (rev == 13)
7616			filename = "lp0initvals13";
7617		else if (rev == 14)
7618			filename = "lp0initvals14";
7619		else if (rev >= 15)
7620			filename = "lp0initvals15";
7621		else
7622			goto fail1;
7623		break;
7624	case BWN_PHYTYPE_N:
7625		if (rev >= 11 && rev <= 12)
7626			filename = "n0initvals11";
7627		else
7628			goto fail1;
7629		break;
7630	default:
7631		goto fail1;
7632	}
7633	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7634	if (error) {
7635		bwn_release_firmware(mac);
7636		return (error);
7637	}
7638
7639	/* bandswitch initvals */
7640	switch (mac->mac_phy.type) {
7641	case BWN_PHYTYPE_A:
7642		if (rev >= 5 && rev <= 10) {
7643			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7644				filename = "a0g1bsinitvals5";
7645			else
7646				filename = "a0g0bsinitvals5";
7647		} else if (rev >= 11)
7648			filename = NULL;
7649		else
7650			goto fail1;
7651		break;
7652	case BWN_PHYTYPE_G:
7653		if (rev >= 5 && rev <= 10)
7654			filename = "b0g0bsinitvals5";
7655		else if (rev >= 11)
7656			filename = NULL;
7657		else
7658			goto fail1;
7659		break;
7660	case BWN_PHYTYPE_LP:
7661		if (rev == 13)
7662			filename = "lp0bsinitvals13";
7663		else if (rev == 14)
7664			filename = "lp0bsinitvals14";
7665		else if (rev >= 15)
7666			filename = "lp0bsinitvals15";
7667		else
7668			goto fail1;
7669		break;
7670	case BWN_PHYTYPE_N:
7671		if (rev >= 11 && rev <= 12)
7672			filename = "n0bsinitvals11";
7673		else
7674			goto fail1;
7675		break;
7676	default:
7677		goto fail1;
7678	}
7679	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7680	if (error) {
7681		bwn_release_firmware(mac);
7682		return (error);
7683	}
7684	return (0);
7685fail1:
7686	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7687	bwn_release_firmware(mac);
7688	return (EOPNOTSUPP);
7689}
7690
7691static int
7692bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7693    const char *name, struct bwn_fwfile *bfw)
7694{
7695	const struct bwn_fwhdr *hdr;
7696	struct bwn_softc *sc = mac->mac_sc;
7697	const struct firmware *fw;
7698	char namebuf[64];
7699
7700	if (name == NULL) {
7701		bwn_do_release_fw(bfw);
7702		return (0);
7703	}
7704	if (bfw->filename != NULL) {
7705		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7706			return (0);
7707		bwn_do_release_fw(bfw);
7708	}
7709
7710	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7711	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7712	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7713	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7714	fw = firmware_get(namebuf);
7715	if (fw == NULL) {
7716		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7717		    namebuf);
7718		return (ENOENT);
7719	}
7720	if (fw->datasize < sizeof(struct bwn_fwhdr))
7721		goto fail;
7722	hdr = (const struct bwn_fwhdr *)(fw->data);
7723	switch (hdr->type) {
7724	case BWN_FWTYPE_UCODE:
7725	case BWN_FWTYPE_PCM:
7726		if (be32toh(hdr->size) !=
7727		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7728			goto fail;
7729		/* FALLTHROUGH */
7730	case BWN_FWTYPE_IV:
7731		if (hdr->ver != 1)
7732			goto fail;
7733		break;
7734	default:
7735		goto fail;
7736	}
7737	bfw->filename = name;
7738	bfw->fw = fw;
7739	bfw->type = type;
7740	return (0);
7741fail:
7742	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7743	if (fw != NULL)
7744		firmware_put(fw, FIRMWARE_UNLOAD);
7745	return (EPROTO);
7746}
7747
7748static void
7749bwn_release_firmware(struct bwn_mac *mac)
7750{
7751
7752	bwn_do_release_fw(&mac->mac_fw.ucode);
7753	bwn_do_release_fw(&mac->mac_fw.pcm);
7754	bwn_do_release_fw(&mac->mac_fw.initvals);
7755	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7756}
7757
7758static void
7759bwn_do_release_fw(struct bwn_fwfile *bfw)
7760{
7761
7762	if (bfw->fw != NULL)
7763		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7764	bfw->fw = NULL;
7765	bfw->filename = NULL;
7766}
7767
7768static int
7769bwn_fw_loaducode(struct bwn_mac *mac)
7770{
7771#define	GETFWOFFSET(fwp, offset)	\
7772	((const uint32_t *)((const char *)fwp.fw->data + offset))
7773#define	GETFWSIZE(fwp, offset)	\
7774	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7775	struct bwn_softc *sc = mac->mac_sc;
7776	const uint32_t *data;
7777	unsigned int i;
7778	uint32_t ctl;
7779	uint16_t date, fwcaps, time;
7780	int error = 0;
7781
7782	ctl = BWN_READ_4(mac, BWN_MACCTL);
7783	ctl |= BWN_MACCTL_MCODE_JMP0;
7784	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7785	    __LINE__));
7786	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7787	for (i = 0; i < 64; i++)
7788		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7789	for (i = 0; i < 4096; i += 2)
7790		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7791
7792	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7793	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7794	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7795	     i++) {
7796		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7797		DELAY(10);
7798	}
7799
7800	if (mac->mac_fw.pcm.fw) {
7801		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7802		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7803		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7804		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7805		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7806		    sizeof(struct bwn_fwhdr)); i++) {
7807			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7808			DELAY(10);
7809		}
7810	}
7811
7812	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7813	BWN_WRITE_4(mac, BWN_MACCTL,
7814	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7815	    BWN_MACCTL_MCODE_RUN);
7816
7817	for (i = 0; i < 21; i++) {
7818		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7819			break;
7820		if (i >= 20) {
7821			device_printf(sc->sc_dev, "ucode timeout\n");
7822			error = ENXIO;
7823			goto error;
7824		}
7825		DELAY(50000);
7826	}
7827	BWN_READ_4(mac, BWN_INTR_REASON);
7828
7829	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7830	if (mac->mac_fw.rev <= 0x128) {
7831		device_printf(sc->sc_dev, "the firmware is too old\n");
7832		error = EOPNOTSUPP;
7833		goto error;
7834	}
7835	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7836	    BWN_SHARED_UCODE_PATCH);
7837	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7838	mac->mac_fw.opensource = (date == 0xffff);
7839	if (bwn_wme != 0)
7840		mac->mac_flags |= BWN_MAC_FLAG_WME;
7841	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7842
7843	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7844	if (mac->mac_fw.opensource == 0) {
7845		device_printf(sc->sc_dev,
7846		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7847		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7848		if (mac->mac_fw.no_pcmfile)
7849			device_printf(sc->sc_dev,
7850			    "no HW crypto acceleration due to pcm5\n");
7851	} else {
7852		mac->mac_fw.patch = time;
7853		fwcaps = bwn_fwcaps_read(mac);
7854		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7855			device_printf(sc->sc_dev,
7856			    "disabling HW crypto acceleration\n");
7857			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7858		}
7859		if (!(fwcaps & BWN_FWCAPS_WME)) {
7860			device_printf(sc->sc_dev, "disabling WME support\n");
7861			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7862		}
7863	}
7864
7865	if (BWN_ISOLDFMT(mac))
7866		device_printf(sc->sc_dev, "using old firmware image\n");
7867
7868	return (0);
7869
7870error:
7871	BWN_WRITE_4(mac, BWN_MACCTL,
7872	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7873	    BWN_MACCTL_MCODE_JMP0);
7874
7875	return (error);
7876#undef GETFWSIZE
7877#undef GETFWOFFSET
7878}
7879
7880/* OpenFirmware only */
7881static uint16_t
7882bwn_fwcaps_read(struct bwn_mac *mac)
7883{
7884
7885	KASSERT(mac->mac_fw.opensource == 1,
7886	    ("%s:%d: fail", __func__, __LINE__));
7887	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7888}
7889
7890static int
7891bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7892    size_t count, size_t array_size)
7893{
7894#define	GET_NEXTIV16(iv)						\
7895	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7896	    sizeof(uint16_t) + sizeof(uint16_t)))
7897#define	GET_NEXTIV32(iv)						\
7898	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7899	    sizeof(uint16_t) + sizeof(uint32_t)))
7900	struct bwn_softc *sc = mac->mac_sc;
7901	const struct bwn_fwinitvals *iv;
7902	uint16_t offset;
7903	size_t i;
7904	uint8_t bit32;
7905
7906	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7907	    ("%s:%d: fail", __func__, __LINE__));
7908	iv = ivals;
7909	for (i = 0; i < count; i++) {
7910		if (array_size < sizeof(iv->offset_size))
7911			goto fail;
7912		array_size -= sizeof(iv->offset_size);
7913		offset = be16toh(iv->offset_size);
7914		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7915		offset &= BWN_FWINITVALS_OFFSET_MASK;
7916		if (offset >= 0x1000)
7917			goto fail;
7918		if (bit32) {
7919			if (array_size < sizeof(iv->data.d32))
7920				goto fail;
7921			array_size -= sizeof(iv->data.d32);
7922			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7923			iv = GET_NEXTIV32(iv);
7924		} else {
7925
7926			if (array_size < sizeof(iv->data.d16))
7927				goto fail;
7928			array_size -= sizeof(iv->data.d16);
7929			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7930
7931			iv = GET_NEXTIV16(iv);
7932		}
7933	}
7934	if (array_size != 0)
7935		goto fail;
7936	return (0);
7937fail:
7938	device_printf(sc->sc_dev, "initvals: invalid format\n");
7939	return (EPROTO);
7940#undef GET_NEXTIV16
7941#undef GET_NEXTIV32
7942}
7943
7944static int
7945bwn_switch_channel(struct bwn_mac *mac, int chan)
7946{
7947	struct bwn_phy *phy = &(mac->mac_phy);
7948	struct bwn_softc *sc = mac->mac_sc;
7949	struct ifnet *ifp = sc->sc_ifp;
7950	struct ieee80211com *ic = ifp->if_l2com;
7951	uint16_t channelcookie, savedcookie;
7952	int error;
7953
7954	if (chan == 0xffff)
7955		chan = phy->get_default_chan(mac);
7956
7957	channelcookie = chan;
7958	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7959		channelcookie |= 0x100;
7960	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7961	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7962	error = phy->switch_channel(mac, chan);
7963	if (error)
7964		goto fail;
7965
7966	mac->mac_phy.chan = chan;
7967	DELAY(8000);
7968	return (0);
7969fail:
7970	device_printf(sc->sc_dev, "failed to switch channel\n");
7971	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7972	return (error);
7973}
7974
7975static uint16_t
7976bwn_ant2phy(int antenna)
7977{
7978
7979	switch (antenna) {
7980	case BWN_ANT0:
7981		return (BWN_TX_PHY_ANT0);
7982	case BWN_ANT1:
7983		return (BWN_TX_PHY_ANT1);
7984	case BWN_ANT2:
7985		return (BWN_TX_PHY_ANT2);
7986	case BWN_ANT3:
7987		return (BWN_TX_PHY_ANT3);
7988	case BWN_ANTAUTO:
7989		return (BWN_TX_PHY_ANT01AUTO);
7990	}
7991	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7992	return (0);
7993}
7994
7995static void
7996bwn_wme_load(struct bwn_mac *mac)
7997{
7998	struct bwn_softc *sc = mac->mac_sc;
7999	int i;
8000
8001	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8002	    ("%s:%d: fail", __func__, __LINE__));
8003
8004	bwn_mac_suspend(mac);
8005	for (i = 0; i < N(sc->sc_wmeParams); i++)
8006		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8007		    bwn_wme_shm_offsets[i]);
8008	bwn_mac_enable(mac);
8009}
8010
8011static void
8012bwn_wme_loadparams(struct bwn_mac *mac,
8013    const struct wmeParams *p, uint16_t shm_offset)
8014{
8015#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8016	struct bwn_softc *sc = mac->mac_sc;
8017	uint16_t params[BWN_NR_WMEPARAMS];
8018	int slot, tmp;
8019	unsigned int i;
8020
8021	slot = BWN_READ_2(mac, BWN_RNG) &
8022	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8023
8024	memset(&params, 0, sizeof(params));
8025
8026	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8027	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8028	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8029
8030	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8031	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8032	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8033	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8034	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8035	params[BWN_WMEPARAM_BSLOTS] = slot;
8036	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8037
8038	for (i = 0; i < N(params); i++) {
8039		if (i == BWN_WMEPARAM_STATUS) {
8040			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8041			    shm_offset + (i * 2));
8042			tmp |= 0x100;
8043			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8044			    tmp);
8045		} else {
8046			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8047			    params[i]);
8048		}
8049	}
8050}
8051
8052static void
8053bwn_mac_write_bssid(struct bwn_mac *mac)
8054{
8055	struct bwn_softc *sc = mac->mac_sc;
8056	uint32_t tmp;
8057	int i;
8058	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8059
8060	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8061	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8062	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8063	    IEEE80211_ADDR_LEN);
8064
8065	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8066		tmp = (uint32_t) (mac_bssid[i + 0]);
8067		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8068		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8069		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8070		bwn_ram_write(mac, 0x20 + i, tmp);
8071	}
8072}
8073
8074static void
8075bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8076    const uint8_t *macaddr)
8077{
8078	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8079	uint16_t data;
8080
8081	if (!mac)
8082		macaddr = zero;
8083
8084	offset |= 0x0020;
8085	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8086
8087	data = macaddr[0];
8088	data |= macaddr[1] << 8;
8089	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8090	data = macaddr[2];
8091	data |= macaddr[3] << 8;
8092	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8093	data = macaddr[4];
8094	data |= macaddr[5] << 8;
8095	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8096}
8097
8098static void
8099bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8100    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8101{
8102	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8103	uint8_t per_sta_keys_start = 8;
8104
8105	if (BWN_SEC_NEWAPI(mac))
8106		per_sta_keys_start = 4;
8107
8108	KASSERT(index < mac->mac_max_nr_keys,
8109	    ("%s:%d: fail", __func__, __LINE__));
8110	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8111	    ("%s:%d: fail", __func__, __LINE__));
8112
8113	if (index >= per_sta_keys_start)
8114		bwn_key_macwrite(mac, index, NULL);
8115	if (key)
8116		memcpy(buf, key, key_len);
8117	bwn_key_write(mac, index, algorithm, buf);
8118	if (index >= per_sta_keys_start)
8119		bwn_key_macwrite(mac, index, mac_addr);
8120
8121	mac->mac_key[index].algorithm = algorithm;
8122}
8123
8124static void
8125bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8126{
8127	struct bwn_softc *sc = mac->mac_sc;
8128	uint32_t addrtmp[2] = { 0, 0 };
8129	uint8_t start = 8;
8130
8131	if (BWN_SEC_NEWAPI(mac))
8132		start = 4;
8133
8134	KASSERT(index >= start,
8135	    ("%s:%d: fail", __func__, __LINE__));
8136	index -= start;
8137
8138	if (addr) {
8139		addrtmp[0] = addr[0];
8140		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8141		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8142		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8143		addrtmp[1] = addr[4];
8144		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8145	}
8146
8147	if (siba_get_revid(sc->sc_dev) >= 5) {
8148		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8149		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8150	} else {
8151		if (index >= 8) {
8152			bwn_shm_write_4(mac, BWN_SHARED,
8153			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8154			bwn_shm_write_2(mac, BWN_SHARED,
8155			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8156		}
8157	}
8158}
8159
8160static void
8161bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8162    const uint8_t *key)
8163{
8164	unsigned int i;
8165	uint32_t offset;
8166	uint16_t kidx, value;
8167
8168	kidx = BWN_SEC_KEY2FW(mac, index);
8169	bwn_shm_write_2(mac, BWN_SHARED,
8170	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8171
8172	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8173	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8174		value = key[i];
8175		value |= (uint16_t)(key[i + 1]) << 8;
8176		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8177	}
8178}
8179
8180static void
8181bwn_phy_exit(struct bwn_mac *mac)
8182{
8183
8184	mac->mac_phy.rf_onoff(mac, 0);
8185	if (mac->mac_phy.exit != NULL)
8186		mac->mac_phy.exit(mac);
8187}
8188
8189static void
8190bwn_dma_free(struct bwn_mac *mac)
8191{
8192	struct bwn_dma *dma;
8193
8194	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8195		return;
8196	dma = &mac->mac_method.dma;
8197
8198	bwn_dma_ringfree(&dma->rx);
8199	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8200	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8201	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8202	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8203	bwn_dma_ringfree(&dma->mcast);
8204}
8205
8206static void
8207bwn_core_stop(struct bwn_mac *mac)
8208{
8209	struct bwn_softc *sc = mac->mac_sc;
8210
8211	BWN_ASSERT_LOCKED(sc);
8212
8213	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8214		return;
8215
8216	callout_stop(&sc->sc_rfswitch_ch);
8217	callout_stop(&sc->sc_task_ch);
8218	callout_stop(&sc->sc_watchdog_ch);
8219	sc->sc_watchdog_timer = 0;
8220	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8221	BWN_READ_4(mac, BWN_INTR_MASK);
8222	bwn_mac_suspend(mac);
8223
8224	mac->mac_status = BWN_MAC_STATUS_INITED;
8225}
8226
8227static int
8228bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8229{
8230	struct bwn_mac *up_dev = NULL;
8231	struct bwn_mac *down_dev;
8232	struct bwn_mac *mac;
8233	int err, status;
8234	uint8_t gmode;
8235
8236	BWN_ASSERT_LOCKED(sc);
8237
8238	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8239		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8240		    mac->mac_phy.supports_2ghz) {
8241			up_dev = mac;
8242			gmode = 1;
8243		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8244		    mac->mac_phy.supports_5ghz) {
8245			up_dev = mac;
8246			gmode = 0;
8247		} else {
8248			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8249			return (EINVAL);
8250		}
8251		if (up_dev != NULL)
8252			break;
8253	}
8254	if (up_dev == NULL) {
8255		device_printf(sc->sc_dev, "Could not find a device\n");
8256		return (ENODEV);
8257	}
8258	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8259		return (0);
8260
8261	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8262	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8263
8264	down_dev = sc->sc_curmac;;
8265	status = down_dev->mac_status;
8266	if (status >= BWN_MAC_STATUS_STARTED)
8267		bwn_core_stop(down_dev);
8268	if (status >= BWN_MAC_STATUS_INITED)
8269		bwn_core_exit(down_dev);
8270
8271	if (down_dev != up_dev)
8272		bwn_phy_reset(down_dev);
8273
8274	up_dev->mac_phy.gmode = gmode;
8275	if (status >= BWN_MAC_STATUS_INITED) {
8276		err = bwn_core_init(up_dev);
8277		if (err) {
8278			device_printf(sc->sc_dev,
8279			    "fatal: failed to initialize for %s-GHz\n",
8280			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8281			goto fail;
8282		}
8283	}
8284	if (status >= BWN_MAC_STATUS_STARTED)
8285		bwn_core_start(up_dev);
8286	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8287	sc->sc_curmac = up_dev;
8288
8289	return (0);
8290fail:
8291	sc->sc_curmac = NULL;
8292	return (err);
8293}
8294
8295static void
8296bwn_rf_turnon(struct bwn_mac *mac)
8297{
8298
8299	bwn_mac_suspend(mac);
8300	mac->mac_phy.rf_onoff(mac, 1);
8301	mac->mac_phy.rf_on = 1;
8302	bwn_mac_enable(mac);
8303}
8304
8305static void
8306bwn_rf_turnoff(struct bwn_mac *mac)
8307{
8308
8309	bwn_mac_suspend(mac);
8310	mac->mac_phy.rf_onoff(mac, 0);
8311	mac->mac_phy.rf_on = 0;
8312	bwn_mac_enable(mac);
8313}
8314
8315static void
8316bwn_phy_reset(struct bwn_mac *mac)
8317{
8318	struct bwn_softc *sc = mac->mac_sc;
8319
8320	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8322	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8323	DELAY(1000);
8324	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8325	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8326	    BWN_TGSLOW_PHYRESET);
8327	DELAY(1000);
8328}
8329
8330static int
8331bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8332{
8333	const struct ieee80211_txparam *tp;
8334	struct bwn_vap *bvp = BWN_VAP(vap);
8335	struct ieee80211com *ic= vap->iv_ic;
8336	struct ifnet *ifp = ic->ic_ifp;
8337	enum ieee80211_state ostate = vap->iv_state;
8338	struct bwn_softc *sc = ifp->if_softc;
8339	struct bwn_mac *mac = sc->sc_curmac;
8340	int error;
8341
8342	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8343	    ieee80211_state_name[vap->iv_state],
8344	    ieee80211_state_name[nstate]);
8345
8346	error = bvp->bv_newstate(vap, nstate, arg);
8347	if (error != 0)
8348		return (error);
8349
8350	BWN_LOCK(sc);
8351
8352	bwn_led_newstate(mac, nstate);
8353
8354	/*
8355	 * Clear the BSSID when we stop a STA
8356	 */
8357	if (vap->iv_opmode == IEEE80211_M_STA) {
8358		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8359			/*
8360			 * Clear out the BSSID.  If we reassociate to
8361			 * the same AP, this will reinialize things
8362			 * correctly...
8363			 */
8364			if (ic->ic_opmode == IEEE80211_M_STA &&
8365			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8366				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8367				bwn_set_macaddr(mac);
8368			}
8369		}
8370	}
8371
8372	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8373	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8374		/* XXX nothing to do? */
8375	} else if (nstate == IEEE80211_S_RUN) {
8376		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8377		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8378		bwn_set_opmode(mac);
8379		bwn_set_pretbtt(mac);
8380		bwn_spu_setdelay(mac, 0);
8381		bwn_set_macaddr(mac);
8382
8383		/* Initializes ratectl for a node. */
8384		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
8385		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
8386			ieee80211_ratectl_node_init(vap->iv_bss);
8387	}
8388
8389	BWN_UNLOCK(sc);
8390
8391	return (error);
8392}
8393
8394static void
8395bwn_set_pretbtt(struct bwn_mac *mac)
8396{
8397	struct bwn_softc *sc = mac->mac_sc;
8398	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8399	uint16_t pretbtt;
8400
8401	if (ic->ic_opmode == IEEE80211_M_IBSS)
8402		pretbtt = 2;
8403	else
8404		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8405	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8406	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8407}
8408
8409static int
8410bwn_intr(void *arg)
8411{
8412	struct bwn_mac *mac = arg;
8413	struct bwn_softc *sc = mac->mac_sc;
8414	uint32_t reason;
8415
8416	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8417	    (sc->sc_flags & BWN_FLAG_INVALID))
8418		return (FILTER_STRAY);
8419
8420	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8421	if (reason == 0xffffffff)	/* shared IRQ */
8422		return (FILTER_STRAY);
8423	reason &= mac->mac_intr_mask;
8424	if (reason == 0)
8425		return (FILTER_HANDLED);
8426
8427	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8428	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8429	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8430	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8431	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8432	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8433	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8434	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8435	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8436	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8437	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8438
8439	/* Disable interrupts. */
8440	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8441
8442	mac->mac_reason_intr = reason;
8443
8444	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8445	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8446
8447	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8448	return (FILTER_HANDLED);
8449}
8450
8451static void
8452bwn_intrtask(void *arg, int npending)
8453{
8454	struct bwn_mac *mac = arg;
8455	struct bwn_softc *sc = mac->mac_sc;
8456	struct ifnet *ifp = sc->sc_ifp;
8457	uint32_t merged = 0;
8458	int i, tx = 0, rx = 0;
8459
8460	BWN_LOCK(sc);
8461	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8462	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8463		BWN_UNLOCK(sc);
8464		return;
8465	}
8466
8467	for (i = 0; i < N(mac->mac_reason); i++)
8468		merged |= mac->mac_reason[i];
8469
8470	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8471		device_printf(sc->sc_dev, "MAC trans error\n");
8472
8473	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8474		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8475		mac->mac_phy.txerrors--;
8476		if (mac->mac_phy.txerrors == 0) {
8477			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8478			bwn_restart(mac, "PHY TX errors");
8479		}
8480	}
8481
8482	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8483		if (merged & BWN_DMAINTR_FATALMASK) {
8484			device_printf(sc->sc_dev,
8485			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8486			    mac->mac_reason[0], mac->mac_reason[1],
8487			    mac->mac_reason[2], mac->mac_reason[3],
8488			    mac->mac_reason[4], mac->mac_reason[5]);
8489			bwn_restart(mac, "DMA error");
8490			BWN_UNLOCK(sc);
8491			return;
8492		}
8493		if (merged & BWN_DMAINTR_NONFATALMASK) {
8494			device_printf(sc->sc_dev,
8495			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8496			    mac->mac_reason[0], mac->mac_reason[1],
8497			    mac->mac_reason[2], mac->mac_reason[3],
8498			    mac->mac_reason[4], mac->mac_reason[5]);
8499		}
8500	}
8501
8502	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8503		bwn_intr_ucode_debug(mac);
8504	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8505		bwn_intr_tbtt_indication(mac);
8506	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8507		bwn_intr_atim_end(mac);
8508	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8509		bwn_intr_beacon(mac);
8510	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8511		bwn_intr_pmq(mac);
8512	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8513		bwn_intr_noise(mac);
8514
8515	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8516		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8517			bwn_dma_rx(mac->mac_method.dma.rx);
8518			rx = 1;
8519		}
8520	} else
8521		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8522
8523	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8524	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8525	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8526	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8527	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8528
8529	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8530		bwn_intr_txeof(mac);
8531		tx = 1;
8532	}
8533
8534	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8535
8536	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8537		int evt = BWN_LED_EVENT_NONE;
8538
8539		if (tx && rx) {
8540			if (sc->sc_rx_rate > sc->sc_tx_rate)
8541				evt = BWN_LED_EVENT_RX;
8542			else
8543				evt = BWN_LED_EVENT_TX;
8544		} else if (tx) {
8545			evt = BWN_LED_EVENT_TX;
8546		} else if (rx) {
8547			evt = BWN_LED_EVENT_RX;
8548		} else if (rx == 0) {
8549			evt = BWN_LED_EVENT_POLL;
8550		}
8551
8552		if (evt != BWN_LED_EVENT_NONE)
8553			bwn_led_event(mac, evt);
8554       }
8555
8556	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8557		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8558			bwn_start_locked(ifp);
8559	}
8560
8561	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8562	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8563
8564	BWN_UNLOCK(sc);
8565}
8566
8567static void
8568bwn_restart(struct bwn_mac *mac, const char *msg)
8569{
8570	struct bwn_softc *sc = mac->mac_sc;
8571	struct ifnet *ifp = sc->sc_ifp;
8572	struct ieee80211com *ic = ifp->if_l2com;
8573
8574	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8575		return;
8576
8577	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8578	ieee80211_runtask(ic, &mac->mac_hwreset);
8579}
8580
8581static void
8582bwn_intr_ucode_debug(struct bwn_mac *mac)
8583{
8584	struct bwn_softc *sc = mac->mac_sc;
8585	uint16_t reason;
8586
8587	if (mac->mac_fw.opensource == 0)
8588		return;
8589
8590	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8591	switch (reason) {
8592	case BWN_DEBUGINTR_PANIC:
8593		bwn_handle_fwpanic(mac);
8594		break;
8595	case BWN_DEBUGINTR_DUMP_SHM:
8596		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8597		break;
8598	case BWN_DEBUGINTR_DUMP_REGS:
8599		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8600		break;
8601	case BWN_DEBUGINTR_MARKER:
8602		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8603		break;
8604	default:
8605		device_printf(sc->sc_dev,
8606		    "ucode debug unknown reason: %#x\n", reason);
8607	}
8608
8609	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8610	    BWN_DEBUGINTR_ACK);
8611}
8612
8613static void
8614bwn_intr_tbtt_indication(struct bwn_mac *mac)
8615{
8616	struct bwn_softc *sc = mac->mac_sc;
8617	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8618
8619	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8620		bwn_psctl(mac, 0);
8621	if (ic->ic_opmode == IEEE80211_M_IBSS)
8622		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8623}
8624
8625static void
8626bwn_intr_atim_end(struct bwn_mac *mac)
8627{
8628
8629	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8630		BWN_WRITE_4(mac, BWN_MACCMD,
8631		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8632		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8633	}
8634}
8635
8636static void
8637bwn_intr_beacon(struct bwn_mac *mac)
8638{
8639	struct bwn_softc *sc = mac->mac_sc;
8640	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8641	uint32_t cmd, beacon0, beacon1;
8642
8643	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8644	    ic->ic_opmode == IEEE80211_M_MBSS)
8645		return;
8646
8647	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8648
8649	cmd = BWN_READ_4(mac, BWN_MACCMD);
8650	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8651	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8652
8653	if (beacon0 && beacon1) {
8654		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8655		mac->mac_intr_mask |= BWN_INTR_BEACON;
8656		return;
8657	}
8658
8659	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8660		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8661		bwn_load_beacon0(mac);
8662		bwn_load_beacon1(mac);
8663		cmd = BWN_READ_4(mac, BWN_MACCMD);
8664		cmd |= BWN_MACCMD_BEACON0_VALID;
8665		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8666	} else {
8667		if (!beacon0) {
8668			bwn_load_beacon0(mac);
8669			cmd = BWN_READ_4(mac, BWN_MACCMD);
8670			cmd |= BWN_MACCMD_BEACON0_VALID;
8671			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8672		} else if (!beacon1) {
8673			bwn_load_beacon1(mac);
8674			cmd = BWN_READ_4(mac, BWN_MACCMD);
8675			cmd |= BWN_MACCMD_BEACON1_VALID;
8676			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8677		}
8678	}
8679}
8680
8681static void
8682bwn_intr_pmq(struct bwn_mac *mac)
8683{
8684	uint32_t tmp;
8685
8686	while (1) {
8687		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8688		if (!(tmp & 0x00000008))
8689			break;
8690	}
8691	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8692}
8693
8694static void
8695bwn_intr_noise(struct bwn_mac *mac)
8696{
8697	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8698	uint16_t tmp;
8699	uint8_t noise[4];
8700	uint8_t i, j;
8701	int32_t average;
8702
8703	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8704		return;
8705
8706	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8707	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8708	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8709	    noise[3] == 0x7f)
8710		goto new;
8711
8712	KASSERT(mac->mac_noise.noi_nsamples < 8,
8713	    ("%s:%d: fail", __func__, __LINE__));
8714	i = mac->mac_noise.noi_nsamples;
8715	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8716	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8717	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8718	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8719	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8720	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8721	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8722	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8723	mac->mac_noise.noi_nsamples++;
8724	if (mac->mac_noise.noi_nsamples == 8) {
8725		average = 0;
8726		for (i = 0; i < 8; i++) {
8727			for (j = 0; j < 4; j++)
8728				average += mac->mac_noise.noi_samples[i][j];
8729		}
8730		average = (((average / 32) * 125) + 64) / 128;
8731		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8732		if (tmp >= 8)
8733			average += 2;
8734		else
8735			average -= 25;
8736		average -= (tmp == 8) ? 72 : 48;
8737
8738		mac->mac_stats.link_noise = average;
8739		mac->mac_noise.noi_running = 0;
8740		return;
8741	}
8742new:
8743	bwn_noise_gensample(mac);
8744}
8745
8746static int
8747bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8748{
8749	struct bwn_mac *mac = prq->prq_mac;
8750	struct bwn_softc *sc = mac->mac_sc;
8751	unsigned int i;
8752
8753	BWN_ASSERT_LOCKED(sc);
8754
8755	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8756		return (0);
8757
8758	for (i = 0; i < 5000; i++) {
8759		if (bwn_pio_rxeof(prq) == 0)
8760			break;
8761	}
8762	if (i >= 5000)
8763		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8764	return ((i > 0) ? 1 : 0);
8765}
8766
8767static void
8768bwn_dma_rx(struct bwn_dma_ring *dr)
8769{
8770	int slot, curslot;
8771
8772	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8773	curslot = dr->get_curslot(dr);
8774	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8775	    ("%s:%d: fail", __func__, __LINE__));
8776
8777	slot = dr->dr_curslot;
8778	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8779		bwn_dma_rxeof(dr, &slot);
8780
8781	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8782	    BUS_DMASYNC_PREWRITE);
8783
8784	dr->set_curslot(dr, slot);
8785	dr->dr_curslot = slot;
8786}
8787
8788static void
8789bwn_intr_txeof(struct bwn_mac *mac)
8790{
8791	struct bwn_txstatus stat;
8792	uint32_t stat0, stat1;
8793	uint16_t tmp;
8794
8795	BWN_ASSERT_LOCKED(mac->mac_sc);
8796
8797	while (1) {
8798		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8799		if (!(stat0 & 0x00000001))
8800			break;
8801		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8802
8803		stat.cookie = (stat0 >> 16);
8804		stat.seq = (stat1 & 0x0000ffff);
8805		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8806		tmp = (stat0 & 0x0000ffff);
8807		stat.framecnt = ((tmp & 0xf000) >> 12);
8808		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8809		stat.sreason = ((tmp & 0x001c) >> 2);
8810		stat.pm = (tmp & 0x0080) ? 1 : 0;
8811		stat.im = (tmp & 0x0040) ? 1 : 0;
8812		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8813		stat.ack = (tmp & 0x0002) ? 1 : 0;
8814
8815		bwn_handle_txeof(mac, &stat);
8816	}
8817}
8818
8819static void
8820bwn_hwreset(void *arg, int npending)
8821{
8822	struct bwn_mac *mac = arg;
8823	struct bwn_softc *sc = mac->mac_sc;
8824	int error = 0;
8825	int prev_status;
8826
8827	BWN_LOCK(sc);
8828
8829	prev_status = mac->mac_status;
8830	if (prev_status >= BWN_MAC_STATUS_STARTED)
8831		bwn_core_stop(mac);
8832	if (prev_status >= BWN_MAC_STATUS_INITED)
8833		bwn_core_exit(mac);
8834
8835	if (prev_status >= BWN_MAC_STATUS_INITED) {
8836		error = bwn_core_init(mac);
8837		if (error)
8838			goto out;
8839	}
8840	if (prev_status >= BWN_MAC_STATUS_STARTED)
8841		bwn_core_start(mac);
8842out:
8843	if (error) {
8844		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8845		sc->sc_curmac = NULL;
8846	}
8847	BWN_UNLOCK(sc);
8848}
8849
8850static void
8851bwn_handle_fwpanic(struct bwn_mac *mac)
8852{
8853	struct bwn_softc *sc = mac->mac_sc;
8854	uint16_t reason;
8855
8856	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8857	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8858
8859	if (reason == BWN_FWPANIC_RESTART)
8860		bwn_restart(mac, "ucode panic");
8861}
8862
8863static void
8864bwn_load_beacon0(struct bwn_mac *mac)
8865{
8866
8867	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8868}
8869
8870static void
8871bwn_load_beacon1(struct bwn_mac *mac)
8872{
8873
8874	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8875}
8876
8877static uint32_t
8878bwn_jssi_read(struct bwn_mac *mac)
8879{
8880	uint32_t val = 0;
8881
8882	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8883	val <<= 16;
8884	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8885
8886	return (val);
8887}
8888
8889static void
8890bwn_noise_gensample(struct bwn_mac *mac)
8891{
8892	uint32_t jssi = 0x7f7f7f7f;
8893
8894	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8895	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8896	BWN_WRITE_4(mac, BWN_MACCMD,
8897	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8898}
8899
8900static int
8901bwn_dma_freeslot(struct bwn_dma_ring *dr)
8902{
8903	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8904
8905	return (dr->dr_numslots - dr->dr_usedslot);
8906}
8907
8908static int
8909bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8910{
8911	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8912
8913	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8914	    ("%s:%d: fail", __func__, __LINE__));
8915	if (slot == dr->dr_numslots - 1)
8916		return (0);
8917	return (slot + 1);
8918}
8919
8920static void
8921bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8922{
8923	struct bwn_mac *mac = dr->dr_mac;
8924	struct bwn_softc *sc = mac->mac_sc;
8925	struct bwn_dma *dma = &mac->mac_method.dma;
8926	struct bwn_dmadesc_generic *desc;
8927	struct bwn_dmadesc_meta *meta;
8928	struct bwn_rxhdr4 *rxhdr;
8929	struct ifnet *ifp = sc->sc_ifp;
8930	struct mbuf *m;
8931	uint32_t macstat;
8932	int32_t tmp;
8933	int cnt = 0;
8934	uint16_t len;
8935
8936	dr->getdesc(dr, *slot, &desc, &meta);
8937
8938	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8939	m = meta->mt_m;
8940
8941	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8942		ifp->if_ierrors++;
8943		return;
8944	}
8945
8946	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8947	len = le16toh(rxhdr->frame_len);
8948	if (len <= 0) {
8949		ifp->if_ierrors++;
8950		return;
8951	}
8952	if (bwn_dma_check_redzone(dr, m)) {
8953		device_printf(sc->sc_dev, "redzone error.\n");
8954		bwn_dma_set_redzone(dr, m);
8955		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8956		    BUS_DMASYNC_PREWRITE);
8957		return;
8958	}
8959	if (len > dr->dr_rx_bufsize) {
8960		tmp = len;
8961		while (1) {
8962			dr->getdesc(dr, *slot, &desc, &meta);
8963			bwn_dma_set_redzone(dr, meta->mt_m);
8964			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8965			    BUS_DMASYNC_PREWRITE);
8966			*slot = bwn_dma_nextslot(dr, *slot);
8967			cnt++;
8968			tmp -= dr->dr_rx_bufsize;
8969			if (tmp <= 0)
8970				break;
8971		}
8972		device_printf(sc->sc_dev, "too small buffer "
8973		       "(len %u buffer %u dropped %d)\n",
8974		       len, dr->dr_rx_bufsize, cnt);
8975		return;
8976	}
8977	macstat = le32toh(rxhdr->mac_status);
8978	if (macstat & BWN_RX_MAC_FCSERR) {
8979		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8980			device_printf(sc->sc_dev, "RX drop\n");
8981			return;
8982		}
8983	}
8984
8985	m->m_pkthdr.rcvif = ifp;
8986	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8987	m_adj(m, dr->dr_frameoffset);
8988
8989	bwn_rxeof(dr->dr_mac, m, rxhdr);
8990}
8991
8992static void
8993bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8994{
8995	struct bwn_dma_ring *dr;
8996	struct bwn_dmadesc_generic *desc;
8997	struct bwn_dmadesc_meta *meta;
8998	struct bwn_pio_txqueue *tq;
8999	struct bwn_pio_txpkt *tp = NULL;
9000	struct bwn_softc *sc = mac->mac_sc;
9001	struct bwn_stats *stats = &mac->mac_stats;
9002	struct ieee80211_node *ni;
9003	struct ieee80211vap *vap;
9004	int retrycnt = 0, slot;
9005
9006	BWN_ASSERT_LOCKED(mac->mac_sc);
9007
9008	if (status->im)
9009		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9010	if (status->ampdu)
9011		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9012	if (status->rtscnt) {
9013		if (status->rtscnt == 0xf)
9014			stats->rtsfail++;
9015		else
9016			stats->rts++;
9017	}
9018
9019	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9020		if (status->ack) {
9021			dr = bwn_dma_parse_cookie(mac, status,
9022			    status->cookie, &slot);
9023			if (dr == NULL) {
9024				device_printf(sc->sc_dev,
9025				    "failed to parse cookie\n");
9026				return;
9027			}
9028			while (1) {
9029				dr->getdesc(dr, slot, &desc, &meta);
9030				if (meta->mt_islast) {
9031					ni = meta->mt_ni;
9032					vap = ni->ni_vap;
9033					ieee80211_ratectl_tx_complete(vap, ni,
9034					    status->ack ?
9035					      IEEE80211_RATECTL_TX_SUCCESS :
9036					      IEEE80211_RATECTL_TX_FAILURE,
9037					    &retrycnt, 0);
9038					break;
9039				}
9040				slot = bwn_dma_nextslot(dr, slot);
9041			}
9042		}
9043		bwn_dma_handle_txeof(mac, status);
9044	} else {
9045		if (status->ack) {
9046			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9047			if (tq == NULL) {
9048				device_printf(sc->sc_dev,
9049				    "failed to parse cookie\n");
9050				return;
9051			}
9052			ni = tp->tp_ni;
9053			vap = ni->ni_vap;
9054			ieee80211_ratectl_tx_complete(vap, ni,
9055			    status->ack ?
9056			      IEEE80211_RATECTL_TX_SUCCESS :
9057			      IEEE80211_RATECTL_TX_FAILURE,
9058			    &retrycnt, 0);
9059		}
9060		bwn_pio_handle_txeof(mac, status);
9061	}
9062
9063	bwn_phy_txpower_check(mac, 0);
9064}
9065
9066static uint8_t
9067bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9068{
9069	struct bwn_mac *mac = prq->prq_mac;
9070	struct bwn_softc *sc = mac->mac_sc;
9071	struct bwn_rxhdr4 rxhdr;
9072	struct ifnet *ifp = sc->sc_ifp;
9073	struct mbuf *m;
9074	uint32_t ctl32, macstat, v32;
9075	unsigned int i, padding;
9076	uint16_t ctl16, len, totlen, v16;
9077	unsigned char *mp;
9078	char *data;
9079
9080	memset(&rxhdr, 0, sizeof(rxhdr));
9081
9082	if (prq->prq_rev >= 8) {
9083		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9084		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9085			return (0);
9086		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9087		    BWN_PIO8_RXCTL_FRAMEREADY);
9088		for (i = 0; i < 10; i++) {
9089			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9090			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9091				goto ready;
9092			DELAY(10);
9093		}
9094	} else {
9095		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9096		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9097			return (0);
9098		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9099		    BWN_PIO_RXCTL_FRAMEREADY);
9100		for (i = 0; i < 10; i++) {
9101			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9102			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9103				goto ready;
9104			DELAY(10);
9105		}
9106	}
9107	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9108	return (1);
9109ready:
9110	if (prq->prq_rev >= 8)
9111		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9112		    prq->prq_base + BWN_PIO8_RXDATA);
9113	else
9114		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9115		    prq->prq_base + BWN_PIO_RXDATA);
9116	len = le16toh(rxhdr.frame_len);
9117	if (len > 0x700) {
9118		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9119		goto error;
9120	}
9121	if (len == 0) {
9122		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9123		goto error;
9124	}
9125
9126	macstat = le32toh(rxhdr.mac_status);
9127	if (macstat & BWN_RX_MAC_FCSERR) {
9128		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9129			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9130			goto error;
9131		}
9132	}
9133
9134	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9135	totlen = len + padding;
9136	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9137	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9138	if (m == NULL) {
9139		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9140		goto error;
9141	}
9142	mp = mtod(m, unsigned char *);
9143	if (prq->prq_rev >= 8) {
9144		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9145		    prq->prq_base + BWN_PIO8_RXDATA);
9146		if (totlen & 3) {
9147			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9148			data = &(mp[totlen - 1]);
9149			switch (totlen & 3) {
9150			case 3:
9151				*data = (v32 >> 16);
9152				data--;
9153			case 2:
9154				*data = (v32 >> 8);
9155				data--;
9156			case 1:
9157				*data = v32;
9158			}
9159		}
9160	} else {
9161		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9162		    prq->prq_base + BWN_PIO_RXDATA);
9163		if (totlen & 1) {
9164			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9165			mp[totlen - 1] = v16;
9166		}
9167	}
9168
9169	m->m_pkthdr.rcvif = ifp;
9170	m->m_len = m->m_pkthdr.len = totlen;
9171
9172	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9173
9174	return (1);
9175error:
9176	if (prq->prq_rev >= 8)
9177		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9178		    BWN_PIO8_RXCTL_DATAREADY);
9179	else
9180		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9181	return (1);
9182}
9183
9184static int
9185bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9186    struct bwn_dmadesc_meta *meta, int init)
9187{
9188	struct bwn_mac *mac = dr->dr_mac;
9189	struct bwn_dma *dma = &mac->mac_method.dma;
9190	struct bwn_rxhdr4 *hdr;
9191	bus_dmamap_t map;
9192	bus_addr_t paddr;
9193	struct mbuf *m;
9194	int error;
9195
9196	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9197	if (m == NULL) {
9198		error = ENOBUFS;
9199
9200		/*
9201		 * If the NIC is up and running, we need to:
9202		 * - Clear RX buffer's header.
9203		 * - Restore RX descriptor settings.
9204		 */
9205		if (init)
9206			return (error);
9207		else
9208			goto back;
9209	}
9210	m->m_len = m->m_pkthdr.len = MCLBYTES;
9211
9212	bwn_dma_set_redzone(dr, m);
9213
9214	/*
9215	 * Try to load RX buf into temporary DMA map
9216	 */
9217	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9218	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9219	if (error) {
9220		m_freem(m);
9221
9222		/*
9223		 * See the comment above
9224		 */
9225		if (init)
9226			return (error);
9227		else
9228			goto back;
9229	}
9230
9231	if (!init)
9232		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9233	meta->mt_m = m;
9234	meta->mt_paddr = paddr;
9235
9236	/*
9237	 * Swap RX buf's DMA map with the loaded temporary one
9238	 */
9239	map = meta->mt_dmap;
9240	meta->mt_dmap = dr->dr_spare_dmap;
9241	dr->dr_spare_dmap = map;
9242
9243back:
9244	/*
9245	 * Clear RX buf header
9246	 */
9247	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9248	bzero(hdr, sizeof(*hdr));
9249	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9250	    BUS_DMASYNC_PREWRITE);
9251
9252	/*
9253	 * Setup RX buf descriptor
9254	 */
9255	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9256	    sizeof(*hdr), 0, 0, 0);
9257	return (error);
9258}
9259
9260static void
9261bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9262		 bus_size_t mapsz __unused, int error)
9263{
9264
9265	if (!error) {
9266		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9267		*((bus_addr_t *)arg) = seg->ds_addr;
9268	}
9269}
9270
9271static int
9272bwn_hwrate2ieeerate(int rate)
9273{
9274
9275	switch (rate) {
9276	case BWN_CCK_RATE_1MB:
9277		return (2);
9278	case BWN_CCK_RATE_2MB:
9279		return (4);
9280	case BWN_CCK_RATE_5MB:
9281		return (11);
9282	case BWN_CCK_RATE_11MB:
9283		return (22);
9284	case BWN_OFDM_RATE_6MB:
9285		return (12);
9286	case BWN_OFDM_RATE_9MB:
9287		return (18);
9288	case BWN_OFDM_RATE_12MB:
9289		return (24);
9290	case BWN_OFDM_RATE_18MB:
9291		return (36);
9292	case BWN_OFDM_RATE_24MB:
9293		return (48);
9294	case BWN_OFDM_RATE_36MB:
9295		return (72);
9296	case BWN_OFDM_RATE_48MB:
9297		return (96);
9298	case BWN_OFDM_RATE_54MB:
9299		return (108);
9300	default:
9301		printf("Ooops\n");
9302		return (0);
9303	}
9304}
9305
9306static void
9307bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9308{
9309	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9310	struct bwn_plcp6 *plcp;
9311	struct bwn_softc *sc = mac->mac_sc;
9312	struct ieee80211_frame_min *wh;
9313	struct ieee80211_node *ni;
9314	struct ifnet *ifp = sc->sc_ifp;
9315	struct ieee80211com *ic = ifp->if_l2com;
9316	uint32_t macstat;
9317	int padding, rate, rssi = 0, noise = 0, type;
9318	uint16_t phytype, phystat0, phystat3, chanstat;
9319	unsigned char *mp = mtod(m, unsigned char *);
9320	static int rx_mac_dec_rpt = 0;
9321
9322	BWN_ASSERT_LOCKED(sc);
9323
9324	phystat0 = le16toh(rxhdr->phy_status0);
9325	phystat3 = le16toh(rxhdr->phy_status3);
9326	macstat = le32toh(rxhdr->mac_status);
9327	chanstat = le16toh(rxhdr->channel);
9328	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9329
9330	if (macstat & BWN_RX_MAC_FCSERR)
9331		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9332	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9333		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9334	if (macstat & BWN_RX_MAC_DECERR)
9335		goto drop;
9336
9337	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9338	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9339		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9340		    m->m_pkthdr.len);
9341		goto drop;
9342	}
9343	plcp = (struct bwn_plcp6 *)(mp + padding);
9344	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9345	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9346		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9347		    m->m_pkthdr.len);
9348		goto drop;
9349	}
9350	wh = mtod(m, struct ieee80211_frame_min *);
9351
9352	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9353		device_printf(sc->sc_dev,
9354		    "RX decryption attempted (old %d keyidx %#x)\n",
9355		    BWN_ISOLDFMT(mac),
9356		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9357
9358	/* XXX calculating RSSI & noise & antenna */
9359
9360	if (phystat0 & BWN_RX_PHYST0_OFDM)
9361		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9362		    phytype == BWN_PHYTYPE_A);
9363	else
9364		rate = bwn_plcp_get_cckrate(mac, plcp);
9365	if (rate == -1) {
9366		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9367			goto drop;
9368	}
9369	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9370
9371	/* RX radio tap */
9372	if (ieee80211_radiotap_active(ic))
9373		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9374	m_adj(m, -IEEE80211_CRC_LEN);
9375
9376	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9377	noise = mac->mac_stats.link_noise;
9378
9379	ifp->if_ipackets++;
9380
9381	BWN_UNLOCK(sc);
9382
9383	ni = ieee80211_find_rxnode(ic, wh);
9384	if (ni != NULL) {
9385		type = ieee80211_input(ni, m, rssi, noise);
9386		ieee80211_free_node(ni);
9387	} else
9388		type = ieee80211_input_all(ic, m, rssi, noise);
9389
9390	BWN_LOCK(sc);
9391	return;
9392drop:
9393	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9394}
9395
9396static void
9397bwn_dma_handle_txeof(struct bwn_mac *mac,
9398    const struct bwn_txstatus *status)
9399{
9400	struct bwn_dma *dma = &mac->mac_method.dma;
9401	struct bwn_dma_ring *dr;
9402	struct bwn_dmadesc_generic *desc;
9403	struct bwn_dmadesc_meta *meta;
9404	struct bwn_softc *sc = mac->mac_sc;
9405	struct ieee80211_node *ni;
9406	struct ifnet *ifp = sc->sc_ifp;
9407	struct mbuf *m;
9408	int slot;
9409
9410	BWN_ASSERT_LOCKED(sc);
9411
9412	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9413	if (dr == NULL) {
9414		device_printf(sc->sc_dev, "failed to parse cookie\n");
9415		return;
9416	}
9417	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9418
9419	while (1) {
9420		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9421		    ("%s:%d: fail", __func__, __LINE__));
9422		dr->getdesc(dr, slot, &desc, &meta);
9423
9424		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9425			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9426		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9427			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9428
9429		if (meta->mt_islast) {
9430			KASSERT(meta->mt_m != NULL,
9431			    ("%s:%d: fail", __func__, __LINE__));
9432
9433			ni = meta->mt_ni;
9434			m = meta->mt_m;
9435			if (ni != NULL) {
9436				/*
9437				 * Do any tx complete callback. Note this must
9438				 * be done before releasing the node reference.
9439				 */
9440				if (m->m_flags & M_TXCB)
9441					ieee80211_process_callback(ni, m, 0);
9442				ieee80211_free_node(ni);
9443				meta->mt_ni = NULL;
9444			}
9445			m_freem(m);
9446			meta->mt_m = NULL;
9447		} else {
9448			KASSERT(meta->mt_m == NULL,
9449			    ("%s:%d: fail", __func__, __LINE__));
9450		}
9451
9452		dr->dr_usedslot--;
9453		if (meta->mt_islast) {
9454			ifp->if_opackets++;
9455			break;
9456		}
9457		slot = bwn_dma_nextslot(dr, slot);
9458	}
9459	sc->sc_watchdog_timer = 0;
9460	if (dr->dr_stop) {
9461		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9462		    ("%s:%d: fail", __func__, __LINE__));
9463		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9464		dr->dr_stop = 0;
9465	}
9466}
9467
9468static void
9469bwn_pio_handle_txeof(struct bwn_mac *mac,
9470    const struct bwn_txstatus *status)
9471{
9472	struct bwn_pio_txqueue *tq;
9473	struct bwn_pio_txpkt *tp = NULL;
9474	struct bwn_softc *sc = mac->mac_sc;
9475	struct ifnet *ifp = sc->sc_ifp;
9476
9477	BWN_ASSERT_LOCKED(sc);
9478
9479	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9480	if (tq == NULL)
9481		return;
9482
9483	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9484	tq->tq_free++;
9485
9486	if (tp->tp_ni != NULL) {
9487		/*
9488		 * Do any tx complete callback.  Note this must
9489		 * be done before releasing the node reference.
9490		 */
9491		if (tp->tp_m->m_flags & M_TXCB)
9492			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9493		ieee80211_free_node(tp->tp_ni);
9494		tp->tp_ni = NULL;
9495	}
9496	m_freem(tp->tp_m);
9497	tp->tp_m = NULL;
9498	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9499
9500	ifp->if_opackets++;
9501
9502	sc->sc_watchdog_timer = 0;
9503	if (tq->tq_stop) {
9504		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9505		tq->tq_stop = 0;
9506	}
9507}
9508
9509static void
9510bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9511{
9512	struct bwn_softc *sc = mac->mac_sc;
9513	struct bwn_phy *phy = &mac->mac_phy;
9514	struct ifnet *ifp = sc->sc_ifp;
9515	struct ieee80211com *ic = ifp->if_l2com;
9516	unsigned long now;
9517	int result;
9518
9519	BWN_GETTIME(now);
9520
9521	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9522		return;
9523	phy->nexttime = now + 2 * 1000;
9524
9525	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9526	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9527		return;
9528
9529	if (phy->recalc_txpwr != NULL) {
9530		result = phy->recalc_txpwr(mac,
9531		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9532		if (result == BWN_TXPWR_RES_DONE)
9533			return;
9534		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9535		    ("%s: fail", __func__));
9536		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9537
9538		ieee80211_runtask(ic, &mac->mac_txpower);
9539	}
9540}
9541
9542static uint16_t
9543bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9544{
9545
9546	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9547}
9548
9549static uint32_t
9550bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9551{
9552
9553	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9554}
9555
9556static void
9557bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9558{
9559
9560	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9561}
9562
9563static void
9564bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9565{
9566
9567	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9568}
9569
9570static int
9571bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9572{
9573
9574	switch (rate) {
9575	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9576	case 12:
9577		return (BWN_OFDM_RATE_6MB);
9578	case 18:
9579		return (BWN_OFDM_RATE_9MB);
9580	case 24:
9581		return (BWN_OFDM_RATE_12MB);
9582	case 36:
9583		return (BWN_OFDM_RATE_18MB);
9584	case 48:
9585		return (BWN_OFDM_RATE_24MB);
9586	case 72:
9587		return (BWN_OFDM_RATE_36MB);
9588	case 96:
9589		return (BWN_OFDM_RATE_48MB);
9590	case 108:
9591		return (BWN_OFDM_RATE_54MB);
9592	/* CCK rates (NB: not IEEE std, device-specific) */
9593	case 2:
9594		return (BWN_CCK_RATE_1MB);
9595	case 4:
9596		return (BWN_CCK_RATE_2MB);
9597	case 11:
9598		return (BWN_CCK_RATE_5MB);
9599	case 22:
9600		return (BWN_CCK_RATE_11MB);
9601	}
9602
9603	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9604	return (BWN_CCK_RATE_1MB);
9605}
9606
9607static int
9608bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9609    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9610{
9611	const struct bwn_phy *phy = &mac->mac_phy;
9612	struct bwn_softc *sc = mac->mac_sc;
9613	struct ieee80211_frame *wh;
9614	struct ieee80211_frame *protwh;
9615	struct ieee80211_frame_cts *cts;
9616	struct ieee80211_frame_rts *rts;
9617	const struct ieee80211_txparam *tp;
9618	struct ieee80211vap *vap = ni->ni_vap;
9619	struct ifnet *ifp = sc->sc_ifp;
9620	struct ieee80211com *ic = ifp->if_l2com;
9621	struct mbuf *mprot;
9622	unsigned int len;
9623	uint32_t macctl = 0;
9624	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9625	uint16_t phyctl = 0;
9626	uint8_t rate, rate_fb;
9627
9628	wh = mtod(m, struct ieee80211_frame *);
9629	memset(txhdr, 0, sizeof(*txhdr));
9630
9631	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9632	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9633	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9634
9635	/*
9636	 * Find TX rate
9637	 */
9638	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9639	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9640		rate = rate_fb = tp->mgmtrate;
9641	else if (ismcast)
9642		rate = rate_fb = tp->mcastrate;
9643	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9644		rate = rate_fb = tp->ucastrate;
9645	else {
9646		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9647		rate = ni->ni_txrate;
9648
9649		if (rix > 0)
9650			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9651			    IEEE80211_RATE_VAL;
9652		else
9653			rate_fb = rate;
9654	}
9655
9656	sc->sc_tx_rate = rate;
9657
9658	rate = bwn_ieeerate2hwrate(sc, rate);
9659	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9660
9661	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9662	    bwn_plcp_getcck(rate);
9663	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9664	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9665
9666	if ((rate_fb == rate) ||
9667	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9668	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9669		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9670	else
9671		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9672		    m->m_pkthdr.len, rate, isshort);
9673
9674	/* XXX TX encryption */
9675	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9676	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9677	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9678	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9679	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9680	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9681
9682	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9683	    BWN_TX_EFT_FB_CCK;
9684	txhdr->chan = phy->chan;
9685	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9686	    BWN_TX_PHY_ENC_CCK;
9687	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9688	     rate == BWN_CCK_RATE_11MB))
9689		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9690
9691	/* XXX TX antenna selection */
9692
9693	switch (bwn_antenna_sanitize(mac, 0)) {
9694	case 0:
9695		phyctl |= BWN_TX_PHY_ANT01AUTO;
9696		break;
9697	case 1:
9698		phyctl |= BWN_TX_PHY_ANT0;
9699		break;
9700	case 2:
9701		phyctl |= BWN_TX_PHY_ANT1;
9702		break;
9703	case 3:
9704		phyctl |= BWN_TX_PHY_ANT2;
9705		break;
9706	case 4:
9707		phyctl |= BWN_TX_PHY_ANT3;
9708		break;
9709	default:
9710		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9711	}
9712
9713	if (!ismcast)
9714		macctl |= BWN_TX_MAC_ACK;
9715
9716	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9717	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9718	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9719		macctl |= BWN_TX_MAC_LONGFRAME;
9720
9721	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9722		/* XXX RTS rate is always 1MB??? */
9723		rts_rate = BWN_CCK_RATE_1MB;
9724		rts_rate_fb = bwn_get_fbrate(rts_rate);
9725
9726		protdur = ieee80211_compute_duration(ic->ic_rt,
9727		    m->m_pkthdr.len, rate, isshort) +
9728		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9729
9730		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9731			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9732			    (txhdr->body.old.rts_frame) :
9733			    (txhdr->body.new.rts_frame));
9734			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9735			    protdur);
9736			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9737			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9738			    mprot->m_pkthdr.len);
9739			m_freem(mprot);
9740			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9741			len = sizeof(struct ieee80211_frame_cts);
9742		} else {
9743			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9744			    (txhdr->body.old.rts_frame) :
9745			    (txhdr->body.new.rts_frame));
9746			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9747			    isshort);
9748			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9749			    wh->i_addr2, protdur);
9750			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9751			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9752			    mprot->m_pkthdr.len);
9753			m_freem(mprot);
9754			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9755			len = sizeof(struct ieee80211_frame_rts);
9756		}
9757		len += IEEE80211_CRC_LEN;
9758		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9759		    &txhdr->body.old.rts_plcp :
9760		    &txhdr->body.new.rts_plcp), len, rts_rate);
9761		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9762		    rts_rate_fb);
9763
9764		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9765		    (&txhdr->body.old.rts_frame) :
9766		    (&txhdr->body.new.rts_frame));
9767		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9768
9769		if (BWN_ISOFDMRATE(rts_rate)) {
9770			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9771			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9772		} else {
9773			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9774			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9775		}
9776		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9777		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9778	}
9779
9780	if (BWN_ISOLDFMT(mac))
9781		txhdr->body.old.cookie = htole16(cookie);
9782	else
9783		txhdr->body.new.cookie = htole16(cookie);
9784
9785	txhdr->macctl = htole32(macctl);
9786	txhdr->phyctl = htole16(phyctl);
9787
9788	/*
9789	 * TX radio tap
9790	 */
9791	if (ieee80211_radiotap_active_vap(vap)) {
9792		sc->sc_tx_th.wt_flags = 0;
9793		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9794			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9795		if (isshort &&
9796		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9797		     rate == BWN_CCK_RATE_11MB))
9798			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9799		sc->sc_tx_th.wt_rate = rate;
9800
9801		ieee80211_radiotap_tx(vap, m);
9802	}
9803
9804	return (0);
9805}
9806
9807static void
9808bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9809    const uint8_t rate)
9810{
9811	uint32_t d, plen;
9812	uint8_t *raw = plcp->o.raw;
9813
9814	if (BWN_ISOFDMRATE(rate)) {
9815		d = bwn_plcp_getofdm(rate);
9816		KASSERT(!(octets & 0xf000),
9817		    ("%s:%d: fail", __func__, __LINE__));
9818		d |= (octets << 5);
9819		plcp->o.data = htole32(d);
9820	} else {
9821		plen = octets * 16 / rate;
9822		if ((octets * 16 % rate) > 0) {
9823			plen++;
9824			if ((rate == BWN_CCK_RATE_11MB)
9825			    && ((octets * 8 % 11) < 4)) {
9826				raw[1] = 0x84;
9827			} else
9828				raw[1] = 0x04;
9829		} else
9830			raw[1] = 0x04;
9831		plcp->o.data |= htole32(plen << 16);
9832		raw[0] = bwn_plcp_getcck(rate);
9833	}
9834}
9835
9836static uint8_t
9837bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9838{
9839	struct bwn_softc *sc = mac->mac_sc;
9840	uint8_t mask;
9841
9842	if (n == 0)
9843		return (0);
9844	if (mac->mac_phy.gmode)
9845		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9846	else
9847		mask = siba_sprom_get_ant_a(sc->sc_dev);
9848	if (!(mask & (1 << (n - 1))))
9849		return (0);
9850	return (n);
9851}
9852
9853static uint8_t
9854bwn_get_fbrate(uint8_t bitrate)
9855{
9856	switch (bitrate) {
9857	case BWN_CCK_RATE_1MB:
9858		return (BWN_CCK_RATE_1MB);
9859	case BWN_CCK_RATE_2MB:
9860		return (BWN_CCK_RATE_1MB);
9861	case BWN_CCK_RATE_5MB:
9862		return (BWN_CCK_RATE_2MB);
9863	case BWN_CCK_RATE_11MB:
9864		return (BWN_CCK_RATE_5MB);
9865	case BWN_OFDM_RATE_6MB:
9866		return (BWN_CCK_RATE_5MB);
9867	case BWN_OFDM_RATE_9MB:
9868		return (BWN_OFDM_RATE_6MB);
9869	case BWN_OFDM_RATE_12MB:
9870		return (BWN_OFDM_RATE_9MB);
9871	case BWN_OFDM_RATE_18MB:
9872		return (BWN_OFDM_RATE_12MB);
9873	case BWN_OFDM_RATE_24MB:
9874		return (BWN_OFDM_RATE_18MB);
9875	case BWN_OFDM_RATE_36MB:
9876		return (BWN_OFDM_RATE_24MB);
9877	case BWN_OFDM_RATE_48MB:
9878		return (BWN_OFDM_RATE_36MB);
9879	case BWN_OFDM_RATE_54MB:
9880		return (BWN_OFDM_RATE_48MB);
9881	}
9882	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9883	return (0);
9884}
9885
9886static uint32_t
9887bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9888    uint32_t ctl, const void *_data, int len)
9889{
9890	struct bwn_softc *sc = mac->mac_sc;
9891	uint32_t value = 0;
9892	const uint8_t *data = _data;
9893
9894	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9895	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9896	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9897
9898	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9899	    tq->tq_base + BWN_PIO8_TXDATA);
9900	if (len & 3) {
9901		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9902		    BWN_PIO8_TXCTL_24_31);
9903		data = &(data[len - 1]);
9904		switch (len & 3) {
9905		case 3:
9906			ctl |= BWN_PIO8_TXCTL_16_23;
9907			value |= (uint32_t)(*data) << 16;
9908			data--;
9909		case 2:
9910			ctl |= BWN_PIO8_TXCTL_8_15;
9911			value |= (uint32_t)(*data) << 8;
9912			data--;
9913		case 1:
9914			value |= (uint32_t)(*data);
9915		}
9916		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9917		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9918	}
9919
9920	return (ctl);
9921}
9922
9923static void
9924bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9925    uint16_t offset, uint32_t value)
9926{
9927
9928	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9929}
9930
9931static uint16_t
9932bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9933    uint16_t ctl, const void *_data, int len)
9934{
9935	struct bwn_softc *sc = mac->mac_sc;
9936	const uint8_t *data = _data;
9937
9938	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9939	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9940
9941	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9942	    tq->tq_base + BWN_PIO_TXDATA);
9943	if (len & 1) {
9944		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9945		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9946		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9947	}
9948
9949	return (ctl);
9950}
9951
9952static uint16_t
9953bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9954    uint16_t ctl, struct mbuf *m0)
9955{
9956	int i, j = 0;
9957	uint16_t data = 0;
9958	const uint8_t *buf;
9959	struct mbuf *m = m0;
9960
9961	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9962	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9963
9964	for (; m != NULL; m = m->m_next) {
9965		buf = mtod(m, const uint8_t *);
9966		for (i = 0; i < m->m_len; i++) {
9967			if (!((j++) % 2))
9968				data |= buf[i];
9969			else {
9970				data |= (buf[i] << 8);
9971				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9972				data = 0;
9973			}
9974		}
9975	}
9976	if (m0->m_pkthdr.len % 2) {
9977		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9978		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9979		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9980	}
9981
9982	return (ctl);
9983}
9984
9985static void
9986bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9987{
9988
9989	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9990		return;
9991	BWN_WRITE_2(mac, 0x684, 510 + time);
9992	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9993}
9994
9995static struct bwn_dma_ring *
9996bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9997{
9998
9999	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10000		return (mac->mac_method.dma.wme[WME_AC_BE]);
10001
10002	switch (prio) {
10003	case 3:
10004		return (mac->mac_method.dma.wme[WME_AC_VO]);
10005	case 2:
10006		return (mac->mac_method.dma.wme[WME_AC_VI]);
10007	case 0:
10008		return (mac->mac_method.dma.wme[WME_AC_BE]);
10009	case 1:
10010		return (mac->mac_method.dma.wme[WME_AC_BK]);
10011	}
10012	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10013	return (NULL);
10014}
10015
10016static int
10017bwn_dma_getslot(struct bwn_dma_ring *dr)
10018{
10019	int slot;
10020
10021	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10022
10023	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10024	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10025	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10026
10027	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10028	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10029	dr->dr_curslot = slot;
10030	dr->dr_usedslot++;
10031
10032	return (slot);
10033}
10034
10035static int
10036bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10037{
10038	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10039	unsigned int a, b, c, d;
10040	unsigned int avg;
10041	uint32_t tmp;
10042
10043	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10044	a = tmp & 0xff;
10045	b = (tmp >> 8) & 0xff;
10046	c = (tmp >> 16) & 0xff;
10047	d = (tmp >> 24) & 0xff;
10048	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10049	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10050		return (ENOENT);
10051	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10052	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10053	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10054
10055	if (ofdm) {
10056		a = (a + 32) & 0x3f;
10057		b = (b + 32) & 0x3f;
10058		c = (c + 32) & 0x3f;
10059		d = (d + 32) & 0x3f;
10060	}
10061
10062	avg = (a + b + c + d + 2) / 4;
10063	if (ofdm) {
10064		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10065		    & BWN_HF_4DB_CCK_POWERBOOST)
10066			avg = (avg >= 13) ? (avg - 13) : 0;
10067	}
10068	return (avg);
10069}
10070
10071static void
10072bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10073{
10074	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10075	int rfatt = *rfattp;
10076	int bbatt = *bbattp;
10077
10078	while (1) {
10079		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10080			break;
10081		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10082			break;
10083		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10084			break;
10085		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10086			break;
10087		if (bbatt > lo->bbatt.max) {
10088			bbatt -= 4;
10089			rfatt += 1;
10090			continue;
10091		}
10092		if (bbatt < lo->bbatt.min) {
10093			bbatt += 4;
10094			rfatt -= 1;
10095			continue;
10096		}
10097		if (rfatt > lo->rfatt.max) {
10098			rfatt -= 1;
10099			bbatt += 4;
10100			continue;
10101		}
10102		if (rfatt < lo->rfatt.min) {
10103			rfatt += 1;
10104			bbatt -= 4;
10105			continue;
10106		}
10107		break;
10108	}
10109
10110	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10111	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10112}
10113
10114static void
10115bwn_phy_lock(struct bwn_mac *mac)
10116{
10117	struct bwn_softc *sc = mac->mac_sc;
10118	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10119
10120	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10121	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10122
10123	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10124		bwn_psctl(mac, BWN_PS_AWAKE);
10125}
10126
10127static void
10128bwn_phy_unlock(struct bwn_mac *mac)
10129{
10130	struct bwn_softc *sc = mac->mac_sc;
10131	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10132
10133	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10134	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10135
10136	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10137		bwn_psctl(mac, 0);
10138}
10139
10140static void
10141bwn_rf_lock(struct bwn_mac *mac)
10142{
10143
10144	BWN_WRITE_4(mac, BWN_MACCTL,
10145	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10146	BWN_READ_4(mac, BWN_MACCTL);
10147	DELAY(10);
10148}
10149
10150static void
10151bwn_rf_unlock(struct bwn_mac *mac)
10152{
10153
10154	BWN_READ_2(mac, BWN_PHYVER);
10155	BWN_WRITE_4(mac, BWN_MACCTL,
10156	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10157}
10158
10159static struct bwn_pio_txqueue *
10160bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10161    struct bwn_pio_txpkt **pack)
10162{
10163	struct bwn_pio *pio = &mac->mac_method.pio;
10164	struct bwn_pio_txqueue *tq = NULL;
10165	unsigned int index;
10166
10167	switch (cookie & 0xf000) {
10168	case 0x1000:
10169		tq = &pio->wme[WME_AC_BK];
10170		break;
10171	case 0x2000:
10172		tq = &pio->wme[WME_AC_BE];
10173		break;
10174	case 0x3000:
10175		tq = &pio->wme[WME_AC_VI];
10176		break;
10177	case 0x4000:
10178		tq = &pio->wme[WME_AC_VO];
10179		break;
10180	case 0x5000:
10181		tq = &pio->mcast;
10182		break;
10183	}
10184	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10185	if (tq == NULL)
10186		return (NULL);
10187	index = (cookie & 0x0fff);
10188	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10189	if (index >= N(tq->tq_pkts))
10190		return (NULL);
10191	*pack = &tq->tq_pkts[index];
10192	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10193	return (tq);
10194}
10195
10196static void
10197bwn_txpwr(void *arg, int npending)
10198{
10199	struct bwn_mac *mac = arg;
10200	struct bwn_softc *sc = mac->mac_sc;
10201
10202	BWN_LOCK(sc);
10203	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10204	    mac->mac_phy.set_txpwr != NULL)
10205		mac->mac_phy.set_txpwr(mac);
10206	BWN_UNLOCK(sc);
10207}
10208
10209static void
10210bwn_task_15s(struct bwn_mac *mac)
10211{
10212	uint16_t reg;
10213
10214	if (mac->mac_fw.opensource) {
10215		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10216		if (reg) {
10217			bwn_restart(mac, "fw watchdog");
10218			return;
10219		}
10220		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10221	}
10222	if (mac->mac_phy.task_15s)
10223		mac->mac_phy.task_15s(mac);
10224
10225	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10226}
10227
10228static void
10229bwn_task_30s(struct bwn_mac *mac)
10230{
10231
10232	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10233		return;
10234	mac->mac_noise.noi_running = 1;
10235	mac->mac_noise.noi_nsamples = 0;
10236
10237	bwn_noise_gensample(mac);
10238}
10239
10240static void
10241bwn_task_60s(struct bwn_mac *mac)
10242{
10243
10244	if (mac->mac_phy.task_60s)
10245		mac->mac_phy.task_60s(mac);
10246	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10247}
10248
10249static void
10250bwn_tasks(void *arg)
10251{
10252	struct bwn_mac *mac = arg;
10253	struct bwn_softc *sc = mac->mac_sc;
10254
10255	BWN_ASSERT_LOCKED(sc);
10256	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10257		return;
10258
10259	if (mac->mac_task_state % 4 == 0)
10260		bwn_task_60s(mac);
10261	if (mac->mac_task_state % 2 == 0)
10262		bwn_task_30s(mac);
10263	bwn_task_15s(mac);
10264
10265	mac->mac_task_state++;
10266	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10267}
10268
10269static int
10270bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10271{
10272	struct bwn_softc *sc = mac->mac_sc;
10273
10274	KASSERT(a == 0, ("not support APHY\n"));
10275
10276	switch (plcp->o.raw[0] & 0xf) {
10277	case 0xb:
10278		return (BWN_OFDM_RATE_6MB);
10279	case 0xf:
10280		return (BWN_OFDM_RATE_9MB);
10281	case 0xa:
10282		return (BWN_OFDM_RATE_12MB);
10283	case 0xe:
10284		return (BWN_OFDM_RATE_18MB);
10285	case 0x9:
10286		return (BWN_OFDM_RATE_24MB);
10287	case 0xd:
10288		return (BWN_OFDM_RATE_36MB);
10289	case 0x8:
10290		return (BWN_OFDM_RATE_48MB);
10291	case 0xc:
10292		return (BWN_OFDM_RATE_54MB);
10293	}
10294	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10295	    plcp->o.raw[0] & 0xf);
10296	return (-1);
10297}
10298
10299static int
10300bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10301{
10302	struct bwn_softc *sc = mac->mac_sc;
10303
10304	switch (plcp->o.raw[0]) {
10305	case 0x0a:
10306		return (BWN_CCK_RATE_1MB);
10307	case 0x14:
10308		return (BWN_CCK_RATE_2MB);
10309	case 0x37:
10310		return (BWN_CCK_RATE_5MB);
10311	case 0x6e:
10312		return (BWN_CCK_RATE_11MB);
10313	}
10314	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10315	return (-1);
10316}
10317
10318static void
10319bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10320    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10321    int rssi, int noise)
10322{
10323	struct bwn_softc *sc = mac->mac_sc;
10324	const struct ieee80211_frame_min *wh;
10325	uint64_t tsf;
10326	uint16_t low_mactime_now;
10327
10328	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10329		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10330
10331	wh = mtod(m, const struct ieee80211_frame_min *);
10332	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10333		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10334
10335	bwn_tsf_read(mac, &tsf);
10336	low_mactime_now = tsf;
10337	tsf = tsf & ~0xffffULL;
10338	tsf += le16toh(rxhdr->mac_time);
10339	if (low_mactime_now < le16toh(rxhdr->mac_time))
10340		tsf -= 0x10000;
10341
10342	sc->sc_rx_th.wr_tsf = tsf;
10343	sc->sc_rx_th.wr_rate = rate;
10344	sc->sc_rx_th.wr_antsignal = rssi;
10345	sc->sc_rx_th.wr_antnoise = noise;
10346}
10347
10348static void
10349bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10350{
10351	uint32_t low, high;
10352
10353	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10354	    ("%s:%d: fail", __func__, __LINE__));
10355
10356	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10357	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10358	*tsf = high;
10359	*tsf <<= 32;
10360	*tsf |= low;
10361}
10362
10363static int
10364bwn_dma_attach(struct bwn_mac *mac)
10365{
10366	struct bwn_dma *dma = &mac->mac_method.dma;
10367	struct bwn_softc *sc = mac->mac_sc;
10368	bus_addr_t lowaddr = 0;
10369	int error;
10370
10371	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10372		return (0);
10373
10374	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10375
10376	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10377
10378	dma->dmatype = bwn_dma_gettype(mac);
10379	if (dma->dmatype == BWN_DMA_30BIT)
10380		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10381	else if (dma->dmatype == BWN_DMA_32BIT)
10382		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10383	else
10384		lowaddr = BUS_SPACE_MAXADDR;
10385
10386	/*
10387	 * Create top level DMA tag
10388	 */
10389	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10390			       BWN_ALIGN, 0,		/* alignment, bounds */
10391			       lowaddr,			/* lowaddr */
10392			       BUS_SPACE_MAXADDR,	/* highaddr */
10393			       NULL, NULL,		/* filter, filterarg */
10394			       MAXBSIZE,		/* maxsize */
10395			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10396			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10397			       0,			/* flags */
10398			       NULL, NULL,		/* lockfunc, lockarg */
10399			       &dma->parent_dtag);
10400	if (error) {
10401		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10402		return (error);
10403	}
10404
10405	/*
10406	 * Create TX/RX mbuf DMA tag
10407	 */
10408	error = bus_dma_tag_create(dma->parent_dtag,
10409				1,
10410				0,
10411				BUS_SPACE_MAXADDR,
10412				BUS_SPACE_MAXADDR,
10413				NULL, NULL,
10414				MCLBYTES,
10415				1,
10416				BUS_SPACE_MAXSIZE_32BIT,
10417				0,
10418				NULL, NULL,
10419				&dma->rxbuf_dtag);
10420	if (error) {
10421		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10422		goto fail0;
10423	}
10424	error = bus_dma_tag_create(dma->parent_dtag,
10425				1,
10426				0,
10427				BUS_SPACE_MAXADDR,
10428				BUS_SPACE_MAXADDR,
10429				NULL, NULL,
10430				MCLBYTES,
10431				1,
10432				BUS_SPACE_MAXSIZE_32BIT,
10433				0,
10434				NULL, NULL,
10435				&dma->txbuf_dtag);
10436	if (error) {
10437		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10438		goto fail1;
10439	}
10440
10441	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10442	if (!dma->wme[WME_AC_BK])
10443		goto fail2;
10444
10445	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10446	if (!dma->wme[WME_AC_BE])
10447		goto fail3;
10448
10449	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10450	if (!dma->wme[WME_AC_VI])
10451		goto fail4;
10452
10453	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10454	if (!dma->wme[WME_AC_VO])
10455		goto fail5;
10456
10457	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10458	if (!dma->mcast)
10459		goto fail6;
10460	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10461	if (!dma->rx)
10462		goto fail7;
10463
10464	return (error);
10465
10466fail7:	bwn_dma_ringfree(&dma->mcast);
10467fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10468fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10469fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10470fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10471fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10472fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10473fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10474	return (error);
10475}
10476
10477static struct bwn_dma_ring *
10478bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10479    uint16_t cookie, int *slot)
10480{
10481	struct bwn_dma *dma = &mac->mac_method.dma;
10482	struct bwn_dma_ring *dr;
10483	struct bwn_softc *sc = mac->mac_sc;
10484
10485	BWN_ASSERT_LOCKED(mac->mac_sc);
10486
10487	switch (cookie & 0xf000) {
10488	case 0x1000:
10489		dr = dma->wme[WME_AC_BK];
10490		break;
10491	case 0x2000:
10492		dr = dma->wme[WME_AC_BE];
10493		break;
10494	case 0x3000:
10495		dr = dma->wme[WME_AC_VI];
10496		break;
10497	case 0x4000:
10498		dr = dma->wme[WME_AC_VO];
10499		break;
10500	case 0x5000:
10501		dr = dma->mcast;
10502		break;
10503	default:
10504		dr = NULL;
10505		KASSERT(0 == 1,
10506		    ("invalid cookie value %d", cookie & 0xf000));
10507	}
10508	*slot = (cookie & 0x0fff);
10509	if (*slot < 0 || *slot >= dr->dr_numslots) {
10510		/*
10511		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10512		 * that it occurs events which have same H/W sequence numbers.
10513		 * When it's occurred just prints a WARNING msgs and ignores.
10514		 */
10515		KASSERT(status->seq == dma->lastseq,
10516		    ("%s:%d: fail", __func__, __LINE__));
10517		device_printf(sc->sc_dev,
10518		    "out of slot ranges (0 < %d < %d)\n", *slot,
10519		    dr->dr_numslots);
10520		return (NULL);
10521	}
10522	dma->lastseq = status->seq;
10523	return (dr);
10524}
10525
10526static void
10527bwn_dma_stop(struct bwn_mac *mac)
10528{
10529	struct bwn_dma *dma;
10530
10531	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10532		return;
10533	dma = &mac->mac_method.dma;
10534
10535	bwn_dma_ringstop(&dma->rx);
10536	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10537	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10538	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10539	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10540	bwn_dma_ringstop(&dma->mcast);
10541}
10542
10543static void
10544bwn_dma_ringstop(struct bwn_dma_ring **dr)
10545{
10546
10547	if (dr == NULL)
10548		return;
10549
10550	bwn_dma_cleanup(*dr);
10551}
10552
10553static void
10554bwn_pio_stop(struct bwn_mac *mac)
10555{
10556	struct bwn_pio *pio;
10557
10558	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10559		return;
10560	pio = &mac->mac_method.pio;
10561
10562	bwn_destroy_queue_tx(&pio->mcast);
10563	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10564	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10565	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10566	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10567}
10568
10569static void
10570bwn_led_attach(struct bwn_mac *mac)
10571{
10572	struct bwn_softc *sc = mac->mac_sc;
10573	const uint8_t *led_act = NULL;
10574	uint16_t val[BWN_LED_MAX];
10575	int i;
10576
10577	sc->sc_led_idle = (2350 * hz) / 1000;
10578	sc->sc_led_blink = 1;
10579
10580	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10581		if (siba_get_pci_subvendor(sc->sc_dev) ==
10582		    bwn_vendor_led_act[i].vid) {
10583			led_act = bwn_vendor_led_act[i].led_act;
10584			break;
10585		}
10586	}
10587	if (led_act == NULL)
10588		led_act = bwn_default_led_act;
10589
10590	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10591	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10592	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10593	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10594
10595	for (i = 0; i < BWN_LED_MAX; ++i) {
10596		struct bwn_led *led = &sc->sc_leds[i];
10597
10598		if (val[i] == 0xff) {
10599			led->led_act = led_act[i];
10600		} else {
10601			if (val[i] & BWN_LED_ACT_LOW)
10602				led->led_flags |= BWN_LED_F_ACTLOW;
10603			led->led_act = val[i] & BWN_LED_ACT_MASK;
10604		}
10605		led->led_mask = (1 << i);
10606
10607		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10608		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10609		    led->led_act == BWN_LED_ACT_BLINK) {
10610			led->led_flags |= BWN_LED_F_BLINK;
10611			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10612				led->led_flags |= BWN_LED_F_POLLABLE;
10613			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10614				led->led_flags |= BWN_LED_F_SLOW;
10615
10616			if (sc->sc_blink_led == NULL) {
10617				sc->sc_blink_led = led;
10618				if (led->led_flags & BWN_LED_F_SLOW)
10619					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10620			}
10621		}
10622
10623		DPRINTF(sc, BWN_DEBUG_LED,
10624		    "%dth led, act %d, lowact %d\n", i,
10625		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10626	}
10627	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10628}
10629
10630static __inline uint16_t
10631bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10632{
10633
10634	if (led->led_flags & BWN_LED_F_ACTLOW)
10635		on = !on;
10636	if (on)
10637		val |= led->led_mask;
10638	else
10639		val &= ~led->led_mask;
10640	return val;
10641}
10642
10643static void
10644bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10645{
10646	struct bwn_softc *sc = mac->mac_sc;
10647	struct ifnet *ifp = sc->sc_ifp;
10648	struct ieee80211com *ic = ifp->if_l2com;
10649	uint16_t val;
10650	int i;
10651
10652	if (nstate == IEEE80211_S_INIT) {
10653		callout_stop(&sc->sc_led_blink_ch);
10654		sc->sc_led_blinking = 0;
10655	}
10656
10657	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10658		return;
10659
10660	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10661	for (i = 0; i < BWN_LED_MAX; ++i) {
10662		struct bwn_led *led = &sc->sc_leds[i];
10663		int on;
10664
10665		if (led->led_act == BWN_LED_ACT_UNKN ||
10666		    led->led_act == BWN_LED_ACT_NULL)
10667			continue;
10668
10669		if ((led->led_flags & BWN_LED_F_BLINK) &&
10670		    nstate != IEEE80211_S_INIT)
10671			continue;
10672
10673		switch (led->led_act) {
10674		case BWN_LED_ACT_ON:    /* Always on */
10675			on = 1;
10676			break;
10677		case BWN_LED_ACT_OFF:   /* Always off */
10678		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10679			on = 0;
10680			break;
10681		default:
10682			on = 1;
10683			switch (nstate) {
10684			case IEEE80211_S_INIT:
10685				on = 0;
10686				break;
10687			case IEEE80211_S_RUN:
10688				if (led->led_act == BWN_LED_ACT_11G &&
10689				    ic->ic_curmode != IEEE80211_MODE_11G)
10690					on = 0;
10691				break;
10692			default:
10693				if (led->led_act == BWN_LED_ACT_ASSOC)
10694					on = 0;
10695				break;
10696			}
10697			break;
10698		}
10699
10700		val = bwn_led_onoff(led, val, on);
10701	}
10702	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10703}
10704
10705static void
10706bwn_led_event(struct bwn_mac *mac, int event)
10707{
10708	struct bwn_softc *sc = mac->mac_sc;
10709	struct bwn_led *led = sc->sc_blink_led;
10710	int rate;
10711
10712	if (event == BWN_LED_EVENT_POLL) {
10713		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10714			return;
10715		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10716			return;
10717	}
10718
10719	sc->sc_led_ticks = ticks;
10720	if (sc->sc_led_blinking)
10721		return;
10722
10723	switch (event) {
10724	case BWN_LED_EVENT_RX:
10725		rate = sc->sc_rx_rate;
10726		break;
10727	case BWN_LED_EVENT_TX:
10728		rate = sc->sc_tx_rate;
10729		break;
10730	case BWN_LED_EVENT_POLL:
10731		rate = 0;
10732		break;
10733	default:
10734		panic("unknown LED event %d\n", event);
10735		break;
10736	}
10737	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10738	    bwn_led_duration[rate].off_dur);
10739}
10740
10741static void
10742bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10743{
10744	struct bwn_softc *sc = mac->mac_sc;
10745	struct bwn_led *led = sc->sc_blink_led;
10746	uint16_t val;
10747
10748	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10749	val = bwn_led_onoff(led, val, 1);
10750	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10751
10752	if (led->led_flags & BWN_LED_F_SLOW) {
10753		BWN_LED_SLOWDOWN(on_dur);
10754		BWN_LED_SLOWDOWN(off_dur);
10755	}
10756
10757	sc->sc_led_blinking = 1;
10758	sc->sc_led_blink_offdur = off_dur;
10759
10760	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10761}
10762
10763static void
10764bwn_led_blink_next(void *arg)
10765{
10766	struct bwn_mac *mac = arg;
10767	struct bwn_softc *sc = mac->mac_sc;
10768	uint16_t val;
10769
10770	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10771	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10772	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10773
10774	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10775	    bwn_led_blink_end, mac);
10776}
10777
10778static void
10779bwn_led_blink_end(void *arg)
10780{
10781	struct bwn_mac *mac = arg;
10782	struct bwn_softc *sc = mac->mac_sc;
10783
10784	sc->sc_led_blinking = 0;
10785}
10786
10787static int
10788bwn_suspend(device_t dev)
10789{
10790	struct bwn_softc *sc = device_get_softc(dev);
10791
10792	bwn_stop(sc, 1);
10793	return (0);
10794}
10795
10796static int
10797bwn_resume(device_t dev)
10798{
10799	struct bwn_softc *sc = device_get_softc(dev);
10800	struct ifnet *ifp = sc->sc_ifp;
10801
10802	if (ifp->if_flags & IFF_UP)
10803		bwn_init(sc);
10804	return (0);
10805}
10806
10807static void
10808bwn_rfswitch(void *arg)
10809{
10810	struct bwn_softc *sc = arg;
10811	struct bwn_mac *mac = sc->sc_curmac;
10812	int cur = 0, prev = 0;
10813
10814	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10815	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10816
10817	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10818		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10819			& BWN_RF_HWENABLED_HI_MASK))
10820			cur = 1;
10821	} else {
10822		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10823		    & BWN_RF_HWENABLED_LO_MASK)
10824			cur = 1;
10825	}
10826
10827	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10828		prev = 1;
10829
10830	if (cur != prev) {
10831		if (cur)
10832			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10833		else
10834			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10835
10836		device_printf(sc->sc_dev,
10837		    "status of RF switch is changed to %s\n",
10838		    cur ? "ON" : "OFF");
10839		if (cur != mac->mac_phy.rf_on) {
10840			if (cur)
10841				bwn_rf_turnon(mac);
10842			else
10843				bwn_rf_turnoff(mac);
10844		}
10845	}
10846
10847	callout_schedule(&sc->sc_rfswitch_ch, hz);
10848}
10849
10850static void
10851bwn_phy_lp_init_pre(struct bwn_mac *mac)
10852{
10853	struct bwn_phy *phy = &mac->mac_phy;
10854	struct bwn_phy_lp *plp = &phy->phy_lp;
10855
10856	plp->plp_antenna = BWN_ANT_DEFAULT;
10857}
10858
10859static int
10860bwn_phy_lp_init(struct bwn_mac *mac)
10861{
10862	static const struct bwn_stxtable tables[] = {
10863		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10864		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10865		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10866		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10867		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10868		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10869		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10870		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10871		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10872		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10873		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10874		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10875		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10876		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10877		{ 2, 11, 0x40, 0, 0x0f }
10878	};
10879	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10880	struct bwn_softc *sc = mac->mac_sc;
10881	const struct bwn_stxtable *st;
10882	struct ifnet *ifp = sc->sc_ifp;
10883	struct ieee80211com *ic = ifp->if_l2com;
10884	int i, error;
10885	uint16_t tmp;
10886
10887	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10888	bwn_phy_lp_bbinit(mac);
10889
10890	/* initialize RF */
10891	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10892	DELAY(1);
10893	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10894	DELAY(1);
10895
10896	if (mac->mac_phy.rf_ver == 0x2062)
10897		bwn_phy_lp_b2062_init(mac);
10898	else {
10899		bwn_phy_lp_b2063_init(mac);
10900
10901		/* synchronize stx table. */
10902		for (i = 0; i < N(tables); i++) {
10903			st = &tables[i];
10904			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10905			tmp >>= st->st_rfshift;
10906			tmp <<= st->st_physhift;
10907			BWN_PHY_SETMASK(mac,
10908			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10909			    ~(st->st_mask << st->st_physhift), tmp);
10910		}
10911
10912		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10913		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10914	}
10915
10916	/* calibrate RC */
10917	if (mac->mac_phy.rev >= 2)
10918		bwn_phy_lp_rxcal_r2(mac);
10919	else if (!plp->plp_rccap) {
10920		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10921			bwn_phy_lp_rccal_r12(mac);
10922	} else
10923		bwn_phy_lp_set_rccap(mac);
10924
10925	error = bwn_phy_lp_switch_channel(mac, 7);
10926	if (error)
10927		device_printf(sc->sc_dev,
10928		    "failed to change channel 7 (%d)\n", error);
10929	bwn_phy_lp_txpctl_init(mac);
10930	bwn_phy_lp_calib(mac);
10931	return (0);
10932}
10933
10934static uint16_t
10935bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10936{
10937
10938	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10939	return (BWN_READ_2(mac, BWN_PHYDATA));
10940}
10941
10942static void
10943bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10944{
10945
10946	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10947	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10948}
10949
10950static void
10951bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10952    uint16_t set)
10953{
10954
10955	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10956	BWN_WRITE_2(mac, BWN_PHYDATA,
10957	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10958}
10959
10960static uint16_t
10961bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10962{
10963
10964	KASSERT(reg != 1, ("unaccessible register %d", reg));
10965	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10966		reg |= 0x100;
10967	if (mac->mac_phy.rev >= 2)
10968		reg |= 0x200;
10969	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10970	return BWN_READ_2(mac, BWN_RFDATALO);
10971}
10972
10973static void
10974bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10975{
10976
10977	KASSERT(reg != 1, ("unaccessible register %d", reg));
10978	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10979	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10980}
10981
10982static void
10983bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10984{
10985
10986	if (on) {
10987		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10988		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10989		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10990		return;
10991	}
10992
10993	if (mac->mac_phy.rev >= 2) {
10994		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10995		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10996		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10997		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10998		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10999		return;
11000	}
11001
11002	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11003	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11004	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11005	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11006}
11007
11008static int
11009bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11010{
11011	struct bwn_phy *phy = &mac->mac_phy;
11012	struct bwn_phy_lp *plp = &phy->phy_lp;
11013	int error;
11014
11015	if (phy->rf_ver == 0x2063) {
11016		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11017		if (error)
11018			return (error);
11019	} else {
11020		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11021		if (error)
11022			return (error);
11023		bwn_phy_lp_set_anafilter(mac, chan);
11024		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11025	}
11026
11027	plp->plp_chan = chan;
11028	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11029	return (0);
11030}
11031
11032static uint32_t
11033bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11034{
11035	struct bwn_softc *sc = mac->mac_sc;
11036	struct ifnet *ifp = sc->sc_ifp;
11037	struct ieee80211com *ic = ifp->if_l2com;
11038
11039	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11040}
11041
11042static void
11043bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11044{
11045	struct bwn_phy *phy = &mac->mac_phy;
11046	struct bwn_phy_lp *plp = &phy->phy_lp;
11047
11048	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11049		return;
11050
11051	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11052	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11053	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11054	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11055	plp->plp_antenna = antenna;
11056}
11057
11058static void
11059bwn_phy_lp_task_60s(struct bwn_mac *mac)
11060{
11061
11062	bwn_phy_lp_calib(mac);
11063}
11064
11065static void
11066bwn_phy_lp_readsprom(struct bwn_mac *mac)
11067{
11068	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11069	struct bwn_softc *sc = mac->mac_sc;
11070	struct ifnet *ifp = sc->sc_ifp;
11071	struct ieee80211com *ic = ifp->if_l2com;
11072
11073	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11074		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11075		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11076		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11077		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11078		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11079		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11080		return;
11081	}
11082
11083	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11084	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11085	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11086	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11087	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11088	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11089	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11090	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11091}
11092
11093static void
11094bwn_phy_lp_bbinit(struct bwn_mac *mac)
11095{
11096
11097	bwn_phy_lp_tblinit(mac);
11098	if (mac->mac_phy.rev >= 2)
11099		bwn_phy_lp_bbinit_r2(mac);
11100	else
11101		bwn_phy_lp_bbinit_r01(mac);
11102}
11103
11104static void
11105bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11106{
11107	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11108	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11109	struct bwn_softc *sc = mac->mac_sc;
11110	struct ifnet *ifp = sc->sc_ifp;
11111	struct ieee80211com *ic = ifp->if_l2com;
11112
11113	bwn_phy_lp_set_txgain(mac,
11114	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11115	bwn_phy_lp_set_bbmult(mac, 150);
11116}
11117
11118static void
11119bwn_phy_lp_calib(struct bwn_mac *mac)
11120{
11121	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11122	struct bwn_softc *sc = mac->mac_sc;
11123	struct ifnet *ifp = sc->sc_ifp;
11124	struct ieee80211com *ic = ifp->if_l2com;
11125	const struct bwn_rxcompco *rc = NULL;
11126	struct bwn_txgain ogain;
11127	int i, omode, oafeovr, orf, obbmult;
11128	uint8_t mode, fc = 0;
11129
11130	if (plp->plp_chanfullcal != plp->plp_chan) {
11131		plp->plp_chanfullcal = plp->plp_chan;
11132		fc = 1;
11133	}
11134
11135	bwn_mac_suspend(mac);
11136
11137	/* BlueTooth Coexistance Override */
11138	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11139	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11140
11141	if (mac->mac_phy.rev >= 2)
11142		bwn_phy_lp_digflt_save(mac);
11143	bwn_phy_lp_get_txpctlmode(mac);
11144	mode = plp->plp_txpctlmode;
11145	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11146	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11147		bwn_phy_lp_bugfix(mac);
11148	if (mac->mac_phy.rev >= 2 && fc == 1) {
11149		bwn_phy_lp_get_txpctlmode(mac);
11150		omode = plp->plp_txpctlmode;
11151		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11152		if (oafeovr)
11153			ogain = bwn_phy_lp_get_txgain(mac);
11154		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11155		obbmult = bwn_phy_lp_get_bbmult(mac);
11156		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11157		if (oafeovr)
11158			bwn_phy_lp_set_txgain(mac, &ogain);
11159		bwn_phy_lp_set_bbmult(mac, obbmult);
11160		bwn_phy_lp_set_txpctlmode(mac, omode);
11161		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11162	}
11163	bwn_phy_lp_set_txpctlmode(mac, mode);
11164	if (mac->mac_phy.rev >= 2)
11165		bwn_phy_lp_digflt_restore(mac);
11166
11167	/* do RX IQ Calculation; assumes that noise is true. */
11168	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11169		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11170			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11171				rc = &bwn_rxcompco_5354[i];
11172		}
11173	} else if (mac->mac_phy.rev >= 2)
11174		rc = &bwn_rxcompco_r2;
11175	else {
11176		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11177			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11178				rc = &bwn_rxcompco_r12[i];
11179		}
11180	}
11181	if (rc == NULL)
11182		goto fail;
11183
11184	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11185	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11186
11187	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11188
11189	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11190		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11191		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11192	} else {
11193		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11194		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11195	}
11196
11197	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11198	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11199	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11200	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11201	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11202	bwn_phy_lp_set_deaf(mac, 0);
11203	/* XXX no checking return value? */
11204	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11205	bwn_phy_lp_clear_deaf(mac, 0);
11206	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11207	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11208	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11209
11210	/* disable RX GAIN override. */
11211	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11212	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11213	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11214	if (mac->mac_phy.rev >= 2) {
11215		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11216		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11217			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11218			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11219		}
11220	} else {
11221		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11222	}
11223
11224	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11225	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11226fail:
11227	bwn_mac_enable(mac);
11228}
11229
11230static void
11231bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11232{
11233
11234	if (on) {
11235		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11236		return;
11237	}
11238
11239	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11240	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11241}
11242
11243static int
11244bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11245{
11246	static const struct bwn_b206x_chan *bc = NULL;
11247	struct bwn_softc *sc = mac->mac_sc;
11248	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11249	    tmp[6];
11250	uint16_t old, scale, tmp16;
11251	int i, div;
11252
11253	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11254		if (bwn_b2063_chantable[i].bc_chan == chan) {
11255			bc = &bwn_b2063_chantable[i];
11256			break;
11257		}
11258	}
11259	if (bc == NULL)
11260		return (EINVAL);
11261
11262	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11263	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11264	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11265	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11266	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11267	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11268	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11269	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11270	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11271	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11272	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11273	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11274
11275	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11276	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11277
11278	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11279	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11280	freqref = freqxtal * 3;
11281	div = (freqxtal <= 26000000 ? 1 : 2);
11282	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11283	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11284		999999) / 1000000) + 1;
11285
11286	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11287	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11288	    0xfff8, timeout >> 2);
11289	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11290	    0xff9f,timeout << 5);
11291	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11292
11293	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11294	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11295	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11296
11297	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11298	    (timeoutref + 1)) - 1;
11299	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11300	    0xf0, count >> 8);
11301	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11302
11303	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11304	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11305	while (tmp[1] >= freqref) {
11306		tmp[0]++;
11307		tmp[1] -= freqref;
11308	}
11309	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11310	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11311	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11312	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11313	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11314
11315	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11316	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11317	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11318	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11319
11320	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11321	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11322
11323	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11324		scale = 1;
11325		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11326	} else {
11327		scale = 0;
11328		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11329	}
11330	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11331	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11332
11333	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11334	    (scale + 1);
11335	if (tmp[5] > 150)
11336		tmp[5] = 0;
11337
11338	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11339	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11340
11341	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11342	if (freqxtal > 26000000)
11343		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11344	else
11345		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11346
11347	if (val[0] == 45)
11348		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11349	else
11350		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11351
11352	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11353	DELAY(1);
11354	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11355
11356	/* VCO Calibration */
11357	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11358	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11359	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11360	DELAY(1);
11361	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11362	DELAY(1);
11363	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11364	DELAY(1);
11365	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11366	DELAY(300);
11367	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11368
11369	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11370	return (0);
11371}
11372
11373static int
11374bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11375{
11376	struct bwn_softc *sc = mac->mac_sc;
11377	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11378	const struct bwn_b206x_chan *bc = NULL;
11379	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11380	uint32_t tmp[9];
11381	int i;
11382
11383	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11384		if (bwn_b2062_chantable[i].bc_chan == chan) {
11385			bc = &bwn_b2062_chantable[i];
11386			break;
11387		}
11388	}
11389
11390	if (bc == NULL)
11391		return (EINVAL);
11392
11393	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11394	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11395	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11396	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11397	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11398	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11399	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11400	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11401	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11402	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11403
11404	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11405	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11406	bwn_phy_lp_b2062_reset_pllbias(mac);
11407	tmp[0] = freqxtal / 1000;
11408	tmp[1] = plp->plp_div * 1000;
11409	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11410	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11411		tmp[2] *= 2;
11412	tmp[3] = 48 * tmp[0];
11413	tmp[5] = tmp[2] / tmp[3];
11414	tmp[6] = tmp[2] % tmp[3];
11415	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11416	tmp[4] = tmp[6] * 0x100;
11417	tmp[5] = tmp[4] / tmp[3];
11418	tmp[6] = tmp[4] % tmp[3];
11419	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11420	tmp[4] = tmp[6] * 0x100;
11421	tmp[5] = tmp[4] / tmp[3];
11422	tmp[6] = tmp[4] % tmp[3];
11423	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11424	tmp[4] = tmp[6] * 0x100;
11425	tmp[5] = tmp[4] / tmp[3];
11426	tmp[6] = tmp[4] % tmp[3];
11427	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11428	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11429	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11430	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11431	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11432	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11433
11434	bwn_phy_lp_b2062_vco_calib(mac);
11435	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11436		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11437		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11438		bwn_phy_lp_b2062_reset_pllbias(mac);
11439		bwn_phy_lp_b2062_vco_calib(mac);
11440		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11441			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11442			return (EIO);
11443		}
11444	}
11445	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11446	return (0);
11447}
11448
11449static void
11450bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11451{
11452	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11453	uint16_t tmp = (channel == 14);
11454
11455	if (mac->mac_phy.rev < 2) {
11456		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11457		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11458			bwn_phy_lp_set_rccap(mac);
11459		return;
11460	}
11461
11462	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11463}
11464
11465static void
11466bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11467{
11468	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11469	struct bwn_softc *sc = mac->mac_sc;
11470	struct ifnet *ifp = sc->sc_ifp;
11471	struct ieee80211com *ic = ifp->if_l2com;
11472	uint16_t iso, tmp[3];
11473
11474	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11475
11476	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11477		iso = plp->plp_txisoband_m;
11478	else if (freq <= 5320)
11479		iso = plp->plp_txisoband_l;
11480	else if (freq <= 5700)
11481		iso = plp->plp_txisoband_m;
11482	else
11483		iso = plp->plp_txisoband_h;
11484
11485	tmp[0] = ((iso - 26) / 12) << 12;
11486	tmp[1] = tmp[0] + 0x1000;
11487	tmp[2] = tmp[0] + 0x2000;
11488
11489	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11490	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11491}
11492
11493static void
11494bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11495{
11496	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11497	int i;
11498	static const uint16_t addr[] = {
11499		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11500		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11501		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11502		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11503		BWN_PHY_OFDM(0xcf),
11504	};
11505	static const uint16_t val[] = {
11506		0xde5e, 0xe832, 0xe331, 0x4d26,
11507		0x0026, 0x1420, 0x0020, 0xfe08,
11508		0x0008,
11509	};
11510
11511	for (i = 0; i < N(addr); i++) {
11512		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11513		BWN_PHY_WRITE(mac, addr[i], val[i]);
11514	}
11515}
11516
11517static void
11518bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11519{
11520	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11521	struct bwn_softc *sc = mac->mac_sc;
11522	uint16_t ctl;
11523
11524	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11525	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11526	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11527		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11528		break;
11529	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11530		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11531		break;
11532	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11533		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11534		break;
11535	default:
11536		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11537		device_printf(sc->sc_dev, "unknown command mode\n");
11538		break;
11539	}
11540}
11541
11542static void
11543bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11544{
11545	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11546	uint16_t ctl;
11547	uint8_t old;
11548
11549	bwn_phy_lp_get_txpctlmode(mac);
11550	old = plp->plp_txpctlmode;
11551	if (old == mode)
11552		return;
11553	plp->plp_txpctlmode = mode;
11554
11555	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11556		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11557		    plp->plp_tssiidx);
11558		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11559		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11560
11561		/* disable TX GAIN override */
11562		if (mac->mac_phy.rev < 2)
11563			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11564		else {
11565			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11566			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11567		}
11568		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11569
11570		plp->plp_txpwridx = -1;
11571	}
11572	if (mac->mac_phy.rev >= 2) {
11573		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11574			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11575		else
11576			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11577	}
11578
11579	/* writes TX Power Control mode */
11580	switch (plp->plp_txpctlmode) {
11581	case BWN_PHYLP_TXPCTL_OFF:
11582		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11583		break;
11584	case BWN_PHYLP_TXPCTL_ON_HW:
11585		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11586		break;
11587	case BWN_PHYLP_TXPCTL_ON_SW:
11588		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11589		break;
11590	default:
11591		ctl = 0;
11592		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11593	}
11594	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11595	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11596}
11597
11598static void
11599bwn_phy_lp_bugfix(struct bwn_mac *mac)
11600{
11601	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11602	struct bwn_softc *sc = mac->mac_sc;
11603	const unsigned int size = 256;
11604	struct bwn_txgain tg;
11605	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11606	uint16_t tssinpt, tssiidx, value[2];
11607	uint8_t mode;
11608	int8_t txpwridx;
11609
11610	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11611	    M_NOWAIT | M_ZERO);
11612	if (tabs == NULL) {
11613		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11614		return;
11615	}
11616
11617	bwn_phy_lp_get_txpctlmode(mac);
11618	mode = plp->plp_txpctlmode;
11619	txpwridx = plp->plp_txpwridx;
11620	tssinpt = plp->plp_tssinpt;
11621	tssiidx = plp->plp_tssiidx;
11622
11623	bwn_tab_read_multi(mac,
11624	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11625	    BWN_TAB_4(7, 0x140), size, tabs);
11626
11627	bwn_phy_lp_tblinit(mac);
11628	bwn_phy_lp_bbinit(mac);
11629	bwn_phy_lp_txpctl_init(mac);
11630	bwn_phy_lp_rf_onoff(mac, 1);
11631	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11632
11633	bwn_tab_write_multi(mac,
11634	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11635	    BWN_TAB_4(7, 0x140), size, tabs);
11636
11637	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11638	plp->plp_tssinpt = tssinpt;
11639	plp->plp_tssiidx = tssiidx;
11640	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11641	if (txpwridx != -1) {
11642		/* set TX power by index */
11643		plp->plp_txpwridx = txpwridx;
11644		bwn_phy_lp_get_txpctlmode(mac);
11645		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11646			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11647		if (mac->mac_phy.rev >= 2) {
11648			rxcomp = bwn_tab_read(mac,
11649			    BWN_TAB_4(7, txpwridx + 320));
11650			txgain = bwn_tab_read(mac,
11651			    BWN_TAB_4(7, txpwridx + 192));
11652			tg.tg_pad = (txgain >> 16) & 0xff;
11653			tg.tg_gm = txgain & 0xff;
11654			tg.tg_pga = (txgain >> 8) & 0xff;
11655			tg.tg_dac = (rxcomp >> 28) & 0xff;
11656			bwn_phy_lp_set_txgain(mac, &tg);
11657		} else {
11658			rxcomp = bwn_tab_read(mac,
11659			    BWN_TAB_4(10, txpwridx + 320));
11660			txgain = bwn_tab_read(mac,
11661			    BWN_TAB_4(10, txpwridx + 192));
11662			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11663			    0xf800, (txgain >> 4) & 0x7fff);
11664			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11665			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11666		}
11667		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11668
11669		/* set TX IQCC */
11670		value[0] = (rxcomp >> 10) & 0x3ff;
11671		value[1] = rxcomp & 0x3ff;
11672		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11673
11674		coeff = bwn_tab_read(mac,
11675		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11676		    BWN_TAB_4(10, txpwridx + 448));
11677		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11678		if (mac->mac_phy.rev >= 2) {
11679			rfpwr = bwn_tab_read(mac,
11680			    BWN_TAB_4(7, txpwridx + 576));
11681			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11682			    rfpwr & 0xffff);
11683		}
11684		bwn_phy_lp_set_txgain_override(mac);
11685	}
11686	if (plp->plp_rccap)
11687		bwn_phy_lp_set_rccap(mac);
11688	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11689	bwn_phy_lp_set_txpctlmode(mac, mode);
11690	free(tabs, M_DEVBUF);
11691}
11692
11693static void
11694bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11695{
11696	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11697	int i;
11698	static const uint16_t addr[] = {
11699		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11700		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11701		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11702		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11703		BWN_PHY_OFDM(0xcf),
11704	};
11705
11706	for (i = 0; i < N(addr); i++)
11707		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11708}
11709
11710static void
11711bwn_phy_lp_tblinit(struct bwn_mac *mac)
11712{
11713	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11714
11715	if (mac->mac_phy.rev < 2) {
11716		bwn_phy_lp_tblinit_r01(mac);
11717		bwn_phy_lp_tblinit_txgain(mac);
11718		bwn_phy_lp_set_gaintbl(mac, freq);
11719		return;
11720	}
11721
11722	bwn_phy_lp_tblinit_r2(mac);
11723	bwn_phy_lp_tblinit_txgain(mac);
11724}
11725
11726struct bwn_wpair {
11727	uint16_t		reg;
11728	uint16_t		value;
11729};
11730
11731struct bwn_smpair {
11732	uint16_t		offset;
11733	uint16_t		mask;
11734	uint16_t		set;
11735};
11736
11737static void
11738bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11739{
11740	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11741	struct bwn_softc *sc = mac->mac_sc;
11742	struct ifnet *ifp = sc->sc_ifp;
11743	struct ieee80211com *ic = ifp->if_l2com;
11744	static const struct bwn_wpair v1[] = {
11745		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11746		{ BWN_PHY_AFE_CTL, 0x8800 },
11747		{ BWN_PHY_AFE_CTL_OVR, 0 },
11748		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11749		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11750		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11751		{ BWN_PHY_OFDM(0xf9), 0 },
11752		{ BWN_PHY_TR_LOOKUP_1, 0 }
11753	};
11754	static const struct bwn_smpair v2[] = {
11755		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11756		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11757		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11758		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11759		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11760	};
11761	static const struct bwn_smpair v3[] = {
11762		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11763		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11764		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11765		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11766		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11767		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11768		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11769		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11770		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11771		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11772
11773	};
11774	int i;
11775
11776	for (i = 0; i < N(v1); i++)
11777		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11778	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11779	for (i = 0; i < N(v2); i++)
11780		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11781
11782	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11783	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11784	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11785	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11786		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11787		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11788	} else {
11789		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11790	}
11791	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11792	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11793	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11794	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11795	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11796	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11797	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11798	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11799	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11800	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11801	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11802	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11803	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11804		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11805		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11806	} else {
11807		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11808		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11809	}
11810	for (i = 0; i < N(v3); i++)
11811		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11812	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11813	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11814		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11815		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11816	}
11817
11818	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11819		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11820		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11821		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11822		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11823		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11824		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11825	} else
11826		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11827
11828	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11829	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11830	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11831	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11832	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11833	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11834	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11835	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11836	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11837
11838	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11839	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11840		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11841		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11842		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11843	}
11844
11845	bwn_phy_lp_digflt_save(mac);
11846}
11847
11848static void
11849bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11850{
11851	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11852	struct bwn_softc *sc = mac->mac_sc;
11853	struct ifnet *ifp = sc->sc_ifp;
11854	struct ieee80211com *ic = ifp->if_l2com;
11855	static const struct bwn_smpair v1[] = {
11856		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11857		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11858		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11859		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11860		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11861		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11862		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11863	};
11864	static const struct bwn_smpair v2[] = {
11865		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11866		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11867		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11868		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11869		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11870		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11871		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11872		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11873		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11874		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11875		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11876		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11877		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11878		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11879		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11880		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11881	};
11882	static const struct bwn_smpair v3[] = {
11883		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11884		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11885		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11886		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11887		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11888		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11889		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11890		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11891	};
11892	static const struct bwn_smpair v4[] = {
11893		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11894		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11895		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11896		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11897		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11898		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11899		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11900		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11901	};
11902	static const struct bwn_smpair v5[] = {
11903		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11904		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11905		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11906		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11907		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11908		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11909		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11910		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11911	};
11912	int i;
11913	uint16_t tmp, tmp2;
11914
11915	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11916	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11917	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11918	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11919	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11920	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11921	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11922	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11923	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11924	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11925	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11926	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11927	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11928	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11929	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11930	for (i = 0; i < N(v1); i++)
11931		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11932	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11933	    0xff00, plp->plp_rxpwroffset);
11934	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11935	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11936	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11937		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11938		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11939		if (mac->mac_phy.rev == 0)
11940			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11941			    0xffcf, 0x0010);
11942		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11943	} else {
11944		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11945		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11946		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11947	}
11948	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11949	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11950	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11951		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11952	else
11953		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11954	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11955	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11956	    0xfff9, (plp->plp_bxarch << 1));
11957	if (mac->mac_phy.rev == 1 &&
11958	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11959		for (i = 0; i < N(v2); i++)
11960			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11961			    v2[i].set);
11962	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11963	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11964	    ((mac->mac_phy.rev == 0) &&
11965	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11966		for (i = 0; i < N(v3); i++)
11967			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11968			    v3[i].set);
11969	} else if (mac->mac_phy.rev == 1 ||
11970		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11971		for (i = 0; i < N(v4); i++)
11972			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11973			    v4[i].set);
11974	} else {
11975		for (i = 0; i < N(v5); i++)
11976			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11977			    v5[i].set);
11978	}
11979	if (mac->mac_phy.rev == 1 &&
11980	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11981		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11982		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11983		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11984		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11985	}
11986	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11987	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11988	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11989		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11990		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11991		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11992		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11993	}
11994	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11995		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11996		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11997		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11998		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11999		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12000		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12001		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12002		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12003	} else {
12004		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12005		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12006	}
12007	if (mac->mac_phy.rev == 1) {
12008		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12009		tmp2 = (tmp & 0x03e0) >> 5;
12010		tmp2 |= tmp2 << 5;
12011		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12012		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12013		tmp2 = (tmp & 0x1f00) >> 8;
12014		tmp2 |= tmp2 << 5;
12015		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12016		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12017		tmp2 = tmp & 0x00ff;
12018		tmp2 |= tmp << 8;
12019		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12020	}
12021}
12022
12023struct bwn_b2062_freq {
12024	uint16_t		freq;
12025	uint8_t			value[6];
12026};
12027
12028static void
12029bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12030{
12031#define	CALC_CTL7(freq, div)						\
12032	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12033#define	CALC_CTL18(freq, div)						\
12034	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12035#define	CALC_CTL19(freq, div)						\
12036	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12037	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12038	struct bwn_softc *sc = mac->mac_sc;
12039	struct ifnet *ifp = sc->sc_ifp;
12040	struct ieee80211com *ic = ifp->if_l2com;
12041	static const struct bwn_b2062_freq freqdata_tab[] = {
12042		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12043		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12044		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12045		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12046		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12047		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12048	};
12049	static const struct bwn_wpair v1[] = {
12050		{ BWN_B2062_N_TXCTL3, 0 },
12051		{ BWN_B2062_N_TXCTL4, 0 },
12052		{ BWN_B2062_N_TXCTL5, 0 },
12053		{ BWN_B2062_N_TXCTL6, 0 },
12054		{ BWN_B2062_N_PDNCTL0, 0x40 },
12055		{ BWN_B2062_N_PDNCTL0, 0 },
12056		{ BWN_B2062_N_CALIB_TS, 0x10 },
12057		{ BWN_B2062_N_CALIB_TS, 0 }
12058	};
12059	const struct bwn_b2062_freq *f = NULL;
12060	uint32_t xtalfreq, ref;
12061	unsigned int i;
12062
12063	bwn_phy_lp_b2062_tblinit(mac);
12064
12065	for (i = 0; i < N(v1); i++)
12066		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12067	if (mac->mac_phy.rev > 0)
12068		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12069		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12070	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12071		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12072	else
12073		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12074
12075	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12076	    ("%s:%d: fail", __func__, __LINE__));
12077	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12078	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12079
12080	if (xtalfreq <= 30000000) {
12081		plp->plp_div = 1;
12082		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12083	} else {
12084		plp->plp_div = 2;
12085		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12086	}
12087
12088	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12089	    CALC_CTL7(xtalfreq, plp->plp_div));
12090	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12091	    CALC_CTL18(xtalfreq, plp->plp_div));
12092	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12093	    CALC_CTL19(xtalfreq, plp->plp_div));
12094
12095	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12096	ref &= 0xffff;
12097	for (i = 0; i < N(freqdata_tab); i++) {
12098		if (ref < freqdata_tab[i].freq) {
12099			f = &freqdata_tab[i];
12100			break;
12101		}
12102	}
12103	if (f == NULL)
12104		f = &freqdata_tab[N(freqdata_tab) - 1];
12105	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12106	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12107	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12108	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12109	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12110	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12111#undef CALC_CTL7
12112#undef CALC_CTL18
12113#undef CALC_CTL19
12114}
12115
12116static void
12117bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12118{
12119
12120	bwn_phy_lp_b2063_tblinit(mac);
12121	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12122	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12123	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12124	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12125	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12126	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12127	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12128	if (mac->mac_phy.rev == 2) {
12129		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12130		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12131		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12132	} else {
12133		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12134		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12135	}
12136}
12137
12138static void
12139bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12140{
12141	struct bwn_softc *sc = mac->mac_sc;
12142	static const struct bwn_wpair v1[] = {
12143		{ BWN_B2063_RX_BB_SP8, 0x0 },
12144		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12145		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12146		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12147		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12148		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12149		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12150		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12151	};
12152	static const struct bwn_wpair v2[] = {
12153		{ BWN_B2063_TX_BB_SP3, 0x0 },
12154		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12155		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12156		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12157		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12158	};
12159	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12160	int i;
12161	uint8_t tmp;
12162
12163	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12164
12165	for (i = 0; i < 2; i++)
12166		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12167	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12168	for (i = 2; i < N(v1); i++)
12169		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12170	for (i = 0; i < 10000; i++) {
12171		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12172			break;
12173		DELAY(1000);
12174	}
12175
12176	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12177		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12178
12179	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12180
12181	for (i = 0; i < N(v2); i++)
12182		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12183	if (freqxtal == 24000000) {
12184		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12185		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12186	} else {
12187		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12188		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12189	}
12190	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12191	for (i = 0; i < 10000; i++) {
12192		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12193			break;
12194		DELAY(1000);
12195	}
12196	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12197		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12198	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12199}
12200
12201static void
12202bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12203{
12204	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12205	struct bwn_softc *sc = mac->mac_sc;
12206	struct bwn_phy_lp_iq_est ie;
12207	struct bwn_txgain tx_gains;
12208	static const uint32_t pwrtbl[21] = {
12209		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12210		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12211		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12212		0x0004c, 0x0002c, 0x0001a,
12213	};
12214	uint32_t npwr, ipwr, sqpwr, tmp;
12215	int loopback, i, j, sum, error;
12216	uint16_t save[7];
12217	uint8_t txo, bbmult, txpctlmode;
12218
12219	error = bwn_phy_lp_switch_channel(mac, 7);
12220	if (error)
12221		device_printf(sc->sc_dev,
12222		    "failed to change channel to 7 (%d)\n", error);
12223	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12224	bbmult = bwn_phy_lp_get_bbmult(mac);
12225	if (txo)
12226		tx_gains = bwn_phy_lp_get_txgain(mac);
12227
12228	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12229	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12230	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12231	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12232	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12233	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12234	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12235
12236	bwn_phy_lp_get_txpctlmode(mac);
12237	txpctlmode = plp->plp_txpctlmode;
12238	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12239
12240	/* disable CRS */
12241	bwn_phy_lp_set_deaf(mac, 1);
12242	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12243	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12244	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12245	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12246	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12247	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12248	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12249	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12250	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12251	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12252	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12253	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12254	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12255	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12256	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12257	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12258	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12259	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12260	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12261	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12262	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12263	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12264	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12265	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12266
12267	loopback = bwn_phy_lp_loopback(mac);
12268	if (loopback == -1)
12269		goto done;
12270	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12271	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12272	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12273	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12274	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12275
12276	tmp = 0;
12277	memset(&ie, 0, sizeof(ie));
12278	for (i = 128; i <= 159; i++) {
12279		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12280		sum = 0;
12281		for (j = 5; j <= 25; j++) {
12282			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12283			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12284				goto done;
12285			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12286			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12287			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12288			    12);
12289			sum += ((ipwr - npwr) * (ipwr - npwr));
12290			if ((i == 128) || (sum < tmp)) {
12291				plp->plp_rccap = i;
12292				tmp = sum;
12293			}
12294		}
12295	}
12296	bwn_phy_lp_ddfs_turnoff(mac);
12297done:
12298	/* restore CRS */
12299	bwn_phy_lp_clear_deaf(mac, 1);
12300	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12301	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12302
12303	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12304	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12305	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12306	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12307	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12308	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12309	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12310
12311	bwn_phy_lp_set_bbmult(mac, bbmult);
12312	if (txo)
12313		bwn_phy_lp_set_txgain(mac, &tx_gains);
12314	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12315	if (plp->plp_rccap)
12316		bwn_phy_lp_set_rccap(mac);
12317}
12318
12319static void
12320bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12321{
12322	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12323	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12324
12325	if (mac->mac_phy.rev == 1)
12326		rc_cap = MIN(rc_cap + 5, 15);
12327
12328	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12329	    MAX(plp->plp_rccap - 4, 0x80));
12330	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12331	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12332	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12333}
12334
12335static uint32_t
12336bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12337{
12338	uint32_t i, q, r;
12339
12340	if (div == 0)
12341		return (0);
12342
12343	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12344		q <<= 1;
12345		if (r << 1 >= div) {
12346			q++;
12347			r = (r << 1) - div;
12348		}
12349	}
12350	if (r << 1 >= div)
12351		q++;
12352	return (q);
12353}
12354
12355static void
12356bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12357{
12358	struct bwn_softc *sc = mac->mac_sc;
12359
12360	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12361	DELAY(20);
12362	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12363		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12364		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12365	} else {
12366		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12367	}
12368	DELAY(5);
12369}
12370
12371static void
12372bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12373{
12374
12375	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12376	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12377	DELAY(200);
12378}
12379
12380static void
12381bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12382{
12383#define	FLAG_A	0x01
12384#define	FLAG_G	0x02
12385	struct bwn_softc *sc = mac->mac_sc;
12386	struct ifnet *ifp = sc->sc_ifp;
12387	struct ieee80211com *ic = ifp->if_l2com;
12388	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12389		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12390		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12391		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12392		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12393		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12394		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12399		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12400		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12427		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12428		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12429		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12430		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12431		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12432		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12433		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12434		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12435		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12436	};
12437	const struct bwn_b206x_rfinit_entry *br;
12438	unsigned int i;
12439
12440	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12441		br = &bwn_b2062_init_tab[i];
12442		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12443			if (br->br_flags & FLAG_G)
12444				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12445		} else {
12446			if (br->br_flags & FLAG_A)
12447				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12448		}
12449	}
12450#undef FLAG_A
12451#undef FLAG_B
12452}
12453
12454static void
12455bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12456{
12457#define	FLAG_A	0x01
12458#define	FLAG_G	0x02
12459	struct bwn_softc *sc = mac->mac_sc;
12460	struct ifnet *ifp = sc->sc_ifp;
12461	struct ieee80211com *ic = ifp->if_l2com;
12462	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12463		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12464		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12465		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12466		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12467		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12468		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12469		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12470		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12471		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12472		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12473		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12474		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12475		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12476		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12477		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12478		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12479		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12480		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12482		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12483		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12484		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12485		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12487		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12488		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12491		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12492		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12493		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12494		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12495		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12496		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12497		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12498		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12499		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12500		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12501		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12502		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12503		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12504		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12505	};
12506	const struct bwn_b206x_rfinit_entry *br;
12507	unsigned int i;
12508
12509	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12510		br = &bwn_b2063_init_tab[i];
12511		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12512			if (br->br_flags & FLAG_G)
12513				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12514		} else {
12515			if (br->br_flags & FLAG_A)
12516				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12517		}
12518	}
12519#undef FLAG_A
12520#undef FLAG_B
12521}
12522
12523static void
12524bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12525    int count, void *_data)
12526{
12527	unsigned int i;
12528	uint32_t offset, type;
12529	uint8_t *data = _data;
12530
12531	type = BWN_TAB_GETTYPE(typenoffset);
12532	offset = BWN_TAB_GETOFFSET(typenoffset);
12533	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12534
12535	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12536
12537	for (i = 0; i < count; i++) {
12538		switch (type) {
12539		case BWN_TAB_8BIT:
12540			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12541			data++;
12542			break;
12543		case BWN_TAB_16BIT:
12544			*((uint16_t *)data) = BWN_PHY_READ(mac,
12545			    BWN_PHY_TABLEDATALO);
12546			data += 2;
12547			break;
12548		case BWN_TAB_32BIT:
12549			*((uint32_t *)data) = BWN_PHY_READ(mac,
12550			    BWN_PHY_TABLEDATAHI);
12551			*((uint32_t *)data) <<= 16;
12552			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12553			    BWN_PHY_TABLEDATALO);
12554			data += 4;
12555			break;
12556		default:
12557			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12558		}
12559	}
12560}
12561
12562static void
12563bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12564    int count, const void *_data)
12565{
12566	uint32_t offset, type, value;
12567	const uint8_t *data = _data;
12568	unsigned int i;
12569
12570	type = BWN_TAB_GETTYPE(typenoffset);
12571	offset = BWN_TAB_GETOFFSET(typenoffset);
12572	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12573
12574	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12575
12576	for (i = 0; i < count; i++) {
12577		switch (type) {
12578		case BWN_TAB_8BIT:
12579			value = *data;
12580			data++;
12581			KASSERT(!(value & ~0xff),
12582			    ("%s:%d: fail", __func__, __LINE__));
12583			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12584			break;
12585		case BWN_TAB_16BIT:
12586			value = *((const uint16_t *)data);
12587			data += 2;
12588			KASSERT(!(value & ~0xffff),
12589			    ("%s:%d: fail", __func__, __LINE__));
12590			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12591			break;
12592		case BWN_TAB_32BIT:
12593			value = *((const uint32_t *)data);
12594			data += 4;
12595			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12596			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12597			break;
12598		default:
12599			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12600		}
12601	}
12602}
12603
12604static struct bwn_txgain
12605bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12606{
12607	struct bwn_txgain tg;
12608	uint16_t tmp;
12609
12610	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12611	if (mac->mac_phy.rev < 2) {
12612		tmp = BWN_PHY_READ(mac,
12613		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12614		tg.tg_gm = tmp & 0x0007;
12615		tg.tg_pga = (tmp & 0x0078) >> 3;
12616		tg.tg_pad = (tmp & 0x780) >> 7;
12617		return (tg);
12618	}
12619
12620	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12621	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12622	tg.tg_gm = tmp & 0xff;
12623	tg.tg_pga = (tmp >> 8) & 0xff;
12624	return (tg);
12625}
12626
12627static uint8_t
12628bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12629{
12630
12631	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12632}
12633
12634static void
12635bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12636{
12637	uint16_t pa;
12638
12639	if (mac->mac_phy.rev < 2) {
12640		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12641		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12642		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12643		bwn_phy_lp_set_txgain_override(mac);
12644		return;
12645	}
12646
12647	pa = bwn_phy_lp_get_pa_gain(mac);
12648	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12649	    (tg->tg_pga << 8) | tg->tg_gm);
12650	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12651	    tg->tg_pad | (pa << 6));
12652	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12653	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12654	    tg->tg_pad | (pa << 8));
12655	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12656	bwn_phy_lp_set_txgain_override(mac);
12657}
12658
12659static void
12660bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12661{
12662
12663	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12664}
12665
12666static void
12667bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12668{
12669	uint16_t trsw = (tx << 1) | rx;
12670
12671	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12672	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12673}
12674
12675static void
12676bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12677{
12678	struct bwn_softc *sc = mac->mac_sc;
12679	struct ifnet *ifp = sc->sc_ifp;
12680	struct ieee80211com *ic = ifp->if_l2com;
12681	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12682
12683	if (mac->mac_phy.rev < 2) {
12684		trsw = gain & 0x1;
12685		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12686		ext_lna = (gain & 2) >> 1;
12687
12688		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12689		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12690		    0xfbff, ext_lna << 10);
12691		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12692		    0xf7ff, ext_lna << 11);
12693		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12694	} else {
12695		low_gain = gain & 0xffff;
12696		high_gain = (gain >> 16) & 0xf;
12697		ext_lna = (gain >> 21) & 0x1;
12698		trsw = ~(gain >> 20) & 0x1;
12699
12700		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12701		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12702		    0xfdff, ext_lna << 9);
12703		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12704		    0xfbff, ext_lna << 10);
12705		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12706		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12707		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12708			tmp = (gain >> 2) & 0x3;
12709			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12710			    0xe7ff, tmp<<11);
12711			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12712			    tmp << 3);
12713		}
12714	}
12715
12716	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12717	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12718	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12719	if (mac->mac_phy.rev >= 2) {
12720		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12721		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12722			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12723			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12724		}
12725		return;
12726	}
12727	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12728}
12729
12730static void
12731bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12732{
12733	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12734
12735	if (user)
12736		plp->plp_crsusr_off = 1;
12737	else
12738		plp->plp_crssys_off = 1;
12739
12740	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12741}
12742
12743static void
12744bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12745{
12746	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12747	struct bwn_softc *sc = mac->mac_sc;
12748	struct ifnet *ifp = sc->sc_ifp;
12749	struct ieee80211com *ic = ifp->if_l2com;
12750
12751	if (user)
12752		plp->plp_crsusr_off = 0;
12753	else
12754		plp->plp_crssys_off = 0;
12755
12756	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12757		return;
12758
12759	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12760		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12761	else
12762		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12763}
12764
12765static unsigned int
12766bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12767{
12768	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12769	static uint8_t sqrt_table[256] = {
12770		10, 14, 17, 20, 22, 24, 26, 28,
12771		30, 31, 33, 34, 36, 37, 38, 40,
12772		41, 42, 43, 44, 45, 46, 47, 48,
12773		50, 50, 51, 52, 53, 54, 55, 56,
12774		57, 58, 59, 60, 60, 61, 62, 63,
12775		64, 64, 65, 66, 67, 67, 68, 69,
12776		70, 70, 71, 72, 72, 73, 74, 74,
12777		75, 76, 76, 77, 78, 78, 79, 80,
12778		80, 81, 81, 82, 83, 83, 84, 84,
12779		85, 86, 86, 87, 87, 88, 88, 89,
12780		90, 90, 91, 91, 92, 92, 93, 93,
12781		94, 94, 95, 95, 96, 96, 97, 97,
12782		98, 98, 99, 100, 100, 100, 101, 101,
12783		102, 102, 103, 103, 104, 104, 105, 105,
12784		106, 106, 107, 107, 108, 108, 109, 109,
12785		110, 110, 110, 111, 111, 112, 112, 113,
12786		113, 114, 114, 114, 115, 115, 116, 116,
12787		117, 117, 117, 118, 118, 119, 119, 120,
12788		120, 120, 121, 121, 122, 122, 122, 123,
12789		123, 124, 124, 124, 125, 125, 126, 126,
12790		126, 127, 127, 128, 128, 128, 129, 129,
12791		130, 130, 130, 131, 131, 131, 132, 132,
12792		133, 133, 133, 134, 134, 134, 135, 135,
12793		136, 136, 136, 137, 137, 137, 138, 138,
12794		138, 139, 139, 140, 140, 140, 141, 141,
12795		141, 142, 142, 142, 143, 143, 143, 144,
12796		144, 144, 145, 145, 145, 146, 146, 146,
12797		147, 147, 147, 148, 148, 148, 149, 149,
12798		150, 150, 150, 150, 151, 151, 151, 152,
12799		152, 152, 153, 153, 153, 154, 154, 154,
12800		155, 155, 155, 156, 156, 156, 157, 157,
12801		157, 158, 158, 158, 159, 159, 159, 160
12802	};
12803
12804	if (x == 0)
12805		return (0);
12806	if (x >= 256) {
12807		unsigned int tmp;
12808
12809		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12810			/* do nothing */ ;
12811		return (tmp);
12812	}
12813	return (sqrt_table[x - 1] / 10);
12814}
12815
12816static int
12817bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12818{
12819#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12820	int _t;								\
12821	_t = _x - 20;							\
12822	if (_t >= 0) {							\
12823		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12824	} else {							\
12825		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12826	}								\
12827} while (0)
12828#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12829	int _t;								\
12830	_t = _x - 11;							\
12831	if (_t >= 0)							\
12832		_v = (_y << (31 - _x)) / (_z >> _t);			\
12833	else								\
12834		_v = (_y << (31 - _x)) / (_z << -_t);			\
12835} while (0)
12836	struct bwn_phy_lp_iq_est ie;
12837	uint16_t v0, v1;
12838	int tmp[2], ret;
12839
12840	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12841	v0 = v1 >> 8;
12842	v1 |= 0xff;
12843
12844	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12845	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12846
12847	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12848	if (ret == 0)
12849		goto done;
12850
12851	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12852		ret = 0;
12853		goto done;
12854	}
12855
12856	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12857	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12858
12859	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12860	v0 = tmp[0] >> 3;
12861	v1 = tmp[1] >> 4;
12862done:
12863	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12864	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12865	return ret;
12866#undef CALC_COEFF
12867#undef CALC_COEFF2
12868}
12869
12870static void
12871bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12872{
12873	static const uint16_t noisescale[] = {
12874		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12875		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12876		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12877		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12878		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12879	};
12880	static const uint16_t crsgainnft[] = {
12881		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12882		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12883		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12884		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12885		0x013d,
12886	};
12887	static const uint16_t filterctl[] = {
12888		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12889		0xff53, 0x0127,
12890	};
12891	static const uint32_t psctl[] = {
12892		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12893		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12894		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12895		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12896		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12897		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12898		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12899		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12900	};
12901	static const uint16_t ofdmcckgain_r0[] = {
12902		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12903		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12904		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12905		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12906		0x755d,
12907	};
12908	static const uint16_t ofdmcckgain_r1[] = {
12909		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12910		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12911		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12912		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12913		0x755d,
12914	};
12915	static const uint16_t gaindelta[] = {
12916		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12917		0x0000,
12918	};
12919	static const uint32_t txpwrctl[] = {
12920		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12921		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12922		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12923		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12924		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12925		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12926		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12927		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12928		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12929		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12930		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12931		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12932		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12933		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12950		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12951		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12952		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12953		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12954		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12955		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12956		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12957		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12958		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12959		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12960		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12961		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12962		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12963		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12964		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12965		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12966		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12967		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12968		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12969		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12970		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12971		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12972		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12973		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12974		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12975		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12976		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12977		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12978		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12979		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12980		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12981		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12982		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12983		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12984		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13000		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13001		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13002		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13003		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13004		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13005		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13006		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13007		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13008		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13009		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13010		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13011		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13012		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13013		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13014		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13015		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13016		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13017		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13018		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13019		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13020		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13021		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13022		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13023		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13024		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13025		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13026		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13027		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13028		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13029		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13030		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13031		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13032		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13033		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13034		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13035		0x00000702,
13036	};
13037
13038	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13039
13040	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13041	    bwn_tab_sigsq_tbl);
13042	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13043	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13044	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13045	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13046	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13047	    bwn_tab_pllfrac_tbl);
13048	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13049	    bwn_tabl_iqlocal_tbl);
13050	if (mac->mac_phy.rev == 0) {
13051		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13052		    ofdmcckgain_r0);
13053		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13054		    ofdmcckgain_r0);
13055	} else {
13056		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13057		    ofdmcckgain_r1);
13058		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13059		    ofdmcckgain_r1);
13060	}
13061	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13062	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13063}
13064
13065static void
13066bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13067{
13068	struct bwn_softc *sc = mac->mac_sc;
13069	int i;
13070	static const uint16_t noisescale[] = {
13071		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13072		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13073		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13074		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13075		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13076		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13077		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13078	};
13079	static const uint32_t filterctl[] = {
13080		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13081		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13082	};
13083	static const uint32_t psctl[] = {
13084		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13085		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13086		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13087		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13088	};
13089	static const uint32_t gainidx[] = {
13090		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13091		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13092		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13093		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13094		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13095		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13096		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13097		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13098		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13099		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13100		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13101		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13102		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13103		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13104		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13105		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13106		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13107		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13108		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13109		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13110		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13111		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13112		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13113		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13114		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13115		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13116		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13117		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13118		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13119		0x0000001a, 0x64ca55ad, 0x0000001a
13120	};
13121	static const uint16_t auxgainidx[] = {
13122		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13123		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13124		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13125		0x0004, 0x0016
13126	};
13127	static const uint16_t swctl[] = {
13128		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13129		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13130		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13131		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13132		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13133		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13134		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13135		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13136	};
13137	static const uint8_t hf[] = {
13138		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13139		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13140	};
13141	static const uint32_t gainval[] = {
13142		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13143		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13144		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13145		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13146		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13147		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13148		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13149		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13150		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13151		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13152		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13153		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13154		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13155		0x000000f1, 0x00000000, 0x00000000
13156	};
13157	static const uint16_t gain[] = {
13158		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13159		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13160		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13161		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13162		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13163		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13164		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13165		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13166		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13167		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13168		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13169		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13170	};
13171	static const uint32_t papdeps[] = {
13172		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13173		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13174		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13175		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13176		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13177		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13178		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13179		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13180		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13181		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13182		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13183		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13184		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13185	};
13186	static const uint32_t papdmult[] = {
13187		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13188		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13189		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13190		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13191		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13192		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13193		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13194		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13195		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13196		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13197		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13198		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13199		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13200	};
13201	static const uint32_t gainidx_a0[] = {
13202		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13203		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13204		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13205		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13206		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13207		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13208		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13209		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13210		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13211		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13212		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13213		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13214		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13215	};
13216	static const uint16_t auxgainidx_a0[] = {
13217		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13218		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13219		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13220		0x0002, 0x0014
13221	};
13222	static const uint32_t gainval_a0[] = {
13223		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13224		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13225		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13226		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13227		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13228		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13231		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13232		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13233		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13234		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13235		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13236		0x000000f7, 0x00000000, 0x00000000
13237	};
13238	static const uint16_t gain_a0[] = {
13239		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13240		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13241		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13242		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13243		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13244		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13245		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13246		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13250		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13251	};
13252
13253	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13254
13255	for (i = 0; i < 704; i++)
13256		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13257
13258	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13259	    bwn_tab_sigsq_tbl);
13260	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13261	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13262	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13263	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13264	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13265	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13266	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13267	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13268	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13269	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13270	    bwn_tab_pllfrac_tbl);
13271	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13272	    bwn_tabl_iqlocal_tbl);
13273	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13274	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13275
13276	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13277	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13278		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13279		    gainidx_a0);
13280		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13281		    auxgainidx_a0);
13282		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13283		    gainval_a0);
13284		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13285	}
13286}
13287
13288static void
13289bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13290{
13291	struct bwn_softc *sc = mac->mac_sc;
13292	struct ifnet *ifp = sc->sc_ifp;
13293	struct ieee80211com *ic = ifp->if_l2com;
13294	static struct bwn_txgain_entry txgain_r2[] = {
13295		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13296		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13297		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13298		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13299		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13300		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13301		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13302		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13303		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13304		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13305		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13306		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13307		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13308		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13309		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13310		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13311		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13312		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13313		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13314		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13315		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13316		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13317		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13318		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13319		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13320		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13321		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13322		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13323		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13324		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13325		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13326		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13327		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13328		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13329		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13330		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13331		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13332		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13333		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13334		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13335		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13336		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13337		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13338		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13339		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13340		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13341		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13342		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13343		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13344		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13345		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13346		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13347		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13348		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13349		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13350		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13351		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13352		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13353		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13354		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13355		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13356		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13357		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13358		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13359	};
13360	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13361		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13362		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13363		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13364		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13365		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13366		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13367		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13368		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13369		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13370		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13371		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13372		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13373		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13374		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13375		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13376		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13377		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13378		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13379		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13380		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13381		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13382		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13383		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13384		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13385		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13386		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13387		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13388		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13389		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13390		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13391		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13392		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13393		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13394		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13395		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13396		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13397		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13398		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13399		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13400		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13401		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13402		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13403		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13404		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13405		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13406		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13407		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13408		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13409		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13410		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13411		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13412		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13413		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13414		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13415		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13416		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13417		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13418		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13419		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13420		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13421		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13422		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13423		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13424		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13425	};
13426	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13427		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13428		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13429		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13430		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13431		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13432		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13433		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13434		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13435		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13436		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13437		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13438		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13439		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13440		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13441		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13442		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13443		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13444		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13445		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13446		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13447		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13448		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13449		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13450		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13451		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13452		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13453		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13454		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13455		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13456		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13457		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13458		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13459		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13460		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13461		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13462		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13463		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13464		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13465		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13466		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13467		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13468		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13469		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13470		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13471		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13472		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13473		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13474		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13475		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13476		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13477		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13478		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13479		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13480		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13481		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13482		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13483		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13484		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13485		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13486		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13487		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13488		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13489		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13490		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13491	};
13492	static struct bwn_txgain_entry txgain_r0[] = {
13493		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13494		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13495		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13496		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13497		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13498		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13499		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13500		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13501		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13502		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13503		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13504		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13505		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13506		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13507		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13508		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13509		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13510		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13511		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13512		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13513		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13514		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13515		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13516		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13517		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13518		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13519		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13520		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13521		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13522		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13523		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13524		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13525		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13526		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13527		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13528		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13529		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13530		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13531		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13532		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13533		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13534		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13535		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13536		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13537		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13538		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13539		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13540		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13541		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13542		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13543		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13544		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13545		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13546		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13547		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13548		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13549		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13550		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13551		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13552		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13553		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13554		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13555		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13556		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13557	};
13558	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13559		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13560		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13561		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13562		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13563		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13564		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13565		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13566		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13567		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13568		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13569		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13570		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13571		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13572		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13573		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13574		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13575		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13576		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13577		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13578		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13579		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13580		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13581		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13582		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13583		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13584		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13585		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13586		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13587		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13588		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13589		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13590		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13591		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13592		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13593		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13594		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13595		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13596		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13597		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13598		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13599		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13600		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13601		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13602		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13603		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13604		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13605		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13606		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13607		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13608		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13609		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13610		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13611		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13612		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13613		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13614		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13615		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13616		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13617		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13618		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13619		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13620		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13621		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13622		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13623	};
13624	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13625		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13626		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13627		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13628		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13629		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13630		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13631		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13632		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13633		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13634		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13635		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13636		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13637		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13638		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13639		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13640		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13641		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13642		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13643		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13644		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13645		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13646		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13647		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13648		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13649		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13650		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13651		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13652		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13653		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13654		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13655		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13656		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13657		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13658		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13659		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13660		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13661		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13662		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13663		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13664		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13665		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13666		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13667		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13668		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13669		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13670		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13671		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13672		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13673		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13674		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13675		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13676		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13677		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13678		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13679		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13680		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13681		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13682		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13683		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13684		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13685		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13686		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13687		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13688		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13689	};
13690	static struct bwn_txgain_entry txgain_r1[] = {
13691		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13692		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13693		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13694		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13695		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13696		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13697		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13698		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13699		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13700		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13701		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13702		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13703		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13704		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13705		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13706		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13707		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13708		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13709		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13710		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13711		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13712		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13713		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13714		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13715		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13716		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13717		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13718		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13719		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13720		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13721		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13722		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13723		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13724		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13725		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13726		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13727		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13728		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13729		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13730		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13731		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13732		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13733		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13734		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13735		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13736		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13737		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13738		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13739		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13740		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13741		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13742		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13743		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13744		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13745		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13746		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13747		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13748		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13749		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13750		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13751		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13752		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13753		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13754		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13755		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13756		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13757		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13758		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13759		{ 7, 11, 6, 0, 71 }
13760	};
13761	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13762		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13763		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13764		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13765		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13766		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13767		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13768		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13769		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13770		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13771		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13772		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13773		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13774		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13775		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13776		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13777		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13778		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13779		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13780		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13781		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13782		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13783		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13784		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13785		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13786		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13787		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13788		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13789		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13790		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13791		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13792		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13793		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13794		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13795		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13796		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13797		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13798		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13799		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13800		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13801		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13802		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13803		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13804		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13805		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13806		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13807		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13808		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13809		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13810		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13811		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13812		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13813		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13814		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13815		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13816		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13817		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13818		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13819		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13820		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13821		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13822		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13823		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13824		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13825		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13826	};
13827	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13828		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13829		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13830		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13831		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13832		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13833		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13834		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13835		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13836		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13837		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13838		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13839		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13840		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13841		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13842		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13843		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13844		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13845		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13846		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13847		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13848		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13849		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13850		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13851		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13852		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13853		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13854		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13855		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13856		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13857		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13858		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13859		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13860		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13861		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13862		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13863		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13864		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13865		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13866		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13867		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13868		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13869		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13870		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13871		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13872		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13873		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13874		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13875		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13876		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13877		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13878		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13879		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13880		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13881		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13882		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13883		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13884		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13885		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13886		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13887		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13888		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13889		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13890		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13891		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13892	};
13893
13894	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13895		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13896			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13897		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13898			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13899			    txgain_2ghz_r2);
13900		else
13901			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902			    txgain_5ghz_r2);
13903		return;
13904	}
13905
13906	if (mac->mac_phy.rev == 0) {
13907		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13908		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13909			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13910		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13911			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13912			    txgain_2ghz_r0);
13913		else
13914			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13915			    txgain_5ghz_r0);
13916		return;
13917	}
13918
13919	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13920	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13921		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13922	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13923		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13924	else
13925		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13926}
13927
13928static void
13929bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13930{
13931	uint32_t offset, type;
13932
13933	type = BWN_TAB_GETTYPE(typeoffset);
13934	offset = BWN_TAB_GETOFFSET(typeoffset);
13935	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13936
13937	switch (type) {
13938	case BWN_TAB_8BIT:
13939		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13940		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13941		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13942		break;
13943	case BWN_TAB_16BIT:
13944		KASSERT(!(value & ~0xffff),
13945		    ("%s:%d: fail", __func__, __LINE__));
13946		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13947		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13948		break;
13949	case BWN_TAB_32BIT:
13950		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13951		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13952		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13953		break;
13954	default:
13955		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13956	}
13957}
13958
13959static int
13960bwn_phy_lp_loopback(struct bwn_mac *mac)
13961{
13962	struct bwn_phy_lp_iq_est ie;
13963	int i, index = -1;
13964	uint32_t tmp;
13965
13966	memset(&ie, 0, sizeof(ie));
13967
13968	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13969	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13970	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13971	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13972	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13973	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13974	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13975	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13976	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13977	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13978	for (i = 0; i < 32; i++) {
13979		bwn_phy_lp_set_rxgain_idx(mac, i);
13980		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13981		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13982			continue;
13983		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13984		if ((tmp > 4000) && (tmp < 10000)) {
13985			index = i;
13986			break;
13987		}
13988	}
13989	bwn_phy_lp_ddfs_turnoff(mac);
13990	return (index);
13991}
13992
13993static void
13994bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13995{
13996
13997	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13998}
13999
14000static void
14001bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14002    int incr1, int incr2, int scale_idx)
14003{
14004
14005	bwn_phy_lp_ddfs_turnoff(mac);
14006	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14007	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14008	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14009	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14010	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14011	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14012	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14013	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14014	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14015	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14016}
14017
14018static uint8_t
14019bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14020    struct bwn_phy_lp_iq_est *ie)
14021{
14022	int i;
14023
14024	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14025	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14026	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14027	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14028	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14029
14030	for (i = 0; i < 500; i++) {
14031		if (!(BWN_PHY_READ(mac,
14032		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14033			break;
14034		DELAY(1000);
14035	}
14036	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14037		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14038		return 0;
14039	}
14040
14041	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14042	ie->ie_iqprod <<= 16;
14043	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14044	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14045	ie->ie_ipwr <<= 16;
14046	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14047	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14048	ie->ie_qpwr <<= 16;
14049	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14050
14051	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14052	return 1;
14053}
14054
14055static uint32_t
14056bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14057{
14058	uint32_t offset, type, value;
14059
14060	type = BWN_TAB_GETTYPE(typeoffset);
14061	offset = BWN_TAB_GETOFFSET(typeoffset);
14062	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14063
14064	switch (type) {
14065	case BWN_TAB_8BIT:
14066		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14067		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14068		break;
14069	case BWN_TAB_16BIT:
14070		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14071		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14072		break;
14073	case BWN_TAB_32BIT:
14074		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14075		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14076		value <<= 16;
14077		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14078		break;
14079	default:
14080		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14081		value = 0;
14082	}
14083
14084	return (value);
14085}
14086
14087static void
14088bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14089{
14090
14091	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14092	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14093}
14094
14095static void
14096bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14097{
14098	uint16_t ctl;
14099
14100	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14101	ctl |= dac << 7;
14102	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14103}
14104
14105static void
14106bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14107{
14108
14109	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14110	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14111}
14112
14113static void
14114bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14115{
14116
14117	if (mac->mac_phy.rev < 2)
14118		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14119	else {
14120		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14121		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14122	}
14123	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14124}
14125
14126static uint16_t
14127bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14128{
14129
14130	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14131}
14132
14133static uint8_t
14134bwn_nbits(int32_t val)
14135{
14136	uint32_t tmp;
14137	uint8_t nbits = 0;
14138
14139	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14140		nbits++;
14141	return (nbits);
14142}
14143
14144static void
14145bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14146    struct bwn_txgain_entry *table)
14147{
14148	int i;
14149
14150	for (i = offset; i < count; i++)
14151		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14152}
14153
14154static void
14155bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14156    struct bwn_txgain_entry data)
14157{
14158
14159	if (mac->mac_phy.rev >= 2)
14160		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14161	else
14162		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14163}
14164
14165static void
14166bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14167    struct bwn_txgain_entry te)
14168{
14169	struct bwn_softc *sc = mac->mac_sc;
14170	struct ifnet *ifp = sc->sc_ifp;
14171	struct ieee80211com *ic = ifp->if_l2com;
14172	uint32_t tmp;
14173
14174	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14175
14176	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14177	if (mac->mac_phy.rev >= 3) {
14178		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14179		    (0x10 << 24) : (0x70 << 24));
14180	} else {
14181		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14182		    (0x14 << 24) : (0x7f << 24));
14183	}
14184	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14185	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14186	    te.te_bbmult << 20 | te.te_dac << 28);
14187}
14188
14189static void
14190bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14191    struct bwn_txgain_entry te)
14192{
14193
14194	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14195
14196	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14197	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14198	    te.te_dac);
14199	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14200}
14201
14202static void
14203bwn_sysctl_node(struct bwn_softc *sc)
14204{
14205	device_t dev = sc->sc_dev;
14206	struct bwn_mac *mac;
14207	struct bwn_stats *stats;
14208
14209	/* XXX assume that count of MAC is only 1. */
14210
14211	if ((mac = sc->sc_curmac) == NULL)
14212		return;
14213	stats = &mac->mac_stats;
14214
14215	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14216	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14217	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14218	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14219	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14220	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14221	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14222	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14223	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14224
14225#ifdef BWN_DEBUG
14226	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14227	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14228	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14229#endif
14230}
14231
14232static device_method_t bwn_methods[] = {
14233	/* Device interface */
14234	DEVMETHOD(device_probe,		bwn_probe),
14235	DEVMETHOD(device_attach,	bwn_attach),
14236	DEVMETHOD(device_detach,	bwn_detach),
14237	DEVMETHOD(device_suspend,	bwn_suspend),
14238	DEVMETHOD(device_resume,	bwn_resume),
14239	KOBJMETHOD_END
14240};
14241static driver_t bwn_driver = {
14242	"bwn",
14243	bwn_methods,
14244	sizeof(struct bwn_softc)
14245};
14246static devclass_t bwn_devclass;
14247DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14248MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14249MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14250MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14251MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14252