if_bwn.c revision 226146
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 226146 2011-10-08 10:50:48Z brueffer $");
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_cap(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		;
1074
1075	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1076
1077	/* call MI attach routine. */
1078	ieee80211_ifattach(ic,
1079	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1080	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1081	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1082
1083	ic->ic_headroom = sizeof(struct bwn_txhdr);
1084
1085	/* override default methods */
1086	ic->ic_raw_xmit = bwn_raw_xmit;
1087	ic->ic_updateslot = bwn_updateslot;
1088	ic->ic_update_promisc = bwn_update_promisc;
1089	ic->ic_wme.wme_update = bwn_wme_update;
1090
1091	ic->ic_scan_start = bwn_scan_start;
1092	ic->ic_scan_end = bwn_scan_end;
1093	ic->ic_set_channel = bwn_set_channel;
1094
1095	ic->ic_vap_create = bwn_vap_create;
1096	ic->ic_vap_delete = bwn_vap_delete;
1097
1098	ieee80211_radiotap_attach(ic,
1099	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1100	    BWN_TX_RADIOTAP_PRESENT,
1101	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1102	    BWN_RX_RADIOTAP_PRESENT);
1103
1104	bwn_sysctl_node(sc);
1105
1106	if (bootverbose)
1107		ieee80211_announce(ic);
1108	return (0);
1109}
1110
1111static void
1112bwn_phy_detach(struct bwn_mac *mac)
1113{
1114
1115	if (mac->mac_phy.detach != NULL)
1116		mac->mac_phy.detach(mac);
1117}
1118
1119static int
1120bwn_detach(device_t dev)
1121{
1122	struct bwn_softc *sc = device_get_softc(dev);
1123	struct bwn_mac *mac = sc->sc_curmac;
1124	struct ifnet *ifp = sc->sc_ifp;
1125	struct ieee80211com *ic = ifp->if_l2com;
1126	int i;
1127
1128	sc->sc_flags |= BWN_FLAG_INVALID;
1129
1130	if (device_is_attached(sc->sc_dev)) {
1131		bwn_stop(sc, 1);
1132		bwn_dma_free(mac);
1133		callout_drain(&sc->sc_led_blink_ch);
1134		callout_drain(&sc->sc_rfswitch_ch);
1135		callout_drain(&sc->sc_task_ch);
1136		callout_drain(&sc->sc_watchdog_ch);
1137		bwn_phy_detach(mac);
1138		if (ifp != NULL) {
1139			ieee80211_draintask(ic, &mac->mac_hwreset);
1140			ieee80211_draintask(ic, &mac->mac_txpower);
1141			ieee80211_ifdetach(ic);
1142			if_free(ifp);
1143		}
1144	}
1145	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1146	taskqueue_free(sc->sc_tq);
1147
1148	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1149		if (mac->mac_intrhand[i] != NULL) {
1150			bus_teardown_intr(dev, mac->mac_res_irq[i],
1151			    mac->mac_intrhand[i]);
1152			mac->mac_intrhand[i] = NULL;
1153		}
1154	}
1155	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1156	if (mac->mac_msi != 0)
1157		pci_release_msi(dev);
1158
1159	BWN_LOCK_DESTROY(sc);
1160	return (0);
1161}
1162
1163static int
1164bwn_attach_pre(struct bwn_softc *sc)
1165{
1166	struct ifnet *ifp;
1167	int error = 0;
1168
1169	BWN_LOCK_INIT(sc);
1170	TAILQ_INIT(&sc->sc_maclist);
1171	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1172	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1173	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1174
1175	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1176		taskqueue_thread_enqueue, &sc->sc_tq);
1177	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1178		"%s taskq", device_get_nameunit(sc->sc_dev));
1179
1180	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1181	if (ifp == NULL) {
1182		device_printf(sc->sc_dev, "can not if_alloc()\n");
1183		error = ENOSPC;
1184		goto fail;
1185	}
1186
1187	/* set these up early for if_printf use */
1188	if_initname(ifp, device_get_name(sc->sc_dev),
1189	    device_get_unit(sc->sc_dev));
1190
1191	ifp->if_softc = sc;
1192	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1193	ifp->if_init = bwn_init;
1194	ifp->if_ioctl = bwn_ioctl;
1195	ifp->if_start = bwn_start;
1196	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1197	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1198	IFQ_SET_READY(&ifp->if_snd);
1199
1200	return (0);
1201
1202fail:	BWN_LOCK_DESTROY(sc);
1203	return (error);
1204}
1205
1206static void
1207bwn_sprom_bugfixes(device_t dev)
1208{
1209#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1210	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1211	 (siba_get_pci_device(dev) == _device) &&			\
1212	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1213	 (siba_get_pci_subdevice(dev) == _subdevice))
1214
1215	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1216	    siba_get_pci_subdevice(dev) == 0x4e &&
1217	    siba_get_pci_revid(dev) > 0x40)
1218		siba_sprom_set_bf_lo(dev,
1219		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1220	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1221	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1222		siba_sprom_set_bf_lo(dev,
1223		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1224	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1225		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1226		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1227		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1228		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1232			siba_sprom_set_bf_lo(dev,
1233			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1234	}
1235#undef	BWN_ISDEV
1236}
1237
1238static int
1239bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1240{
1241#define	IS_RUNNING(ifp) \
1242	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1243	struct bwn_softc *sc = ifp->if_softc;
1244	struct ieee80211com *ic = ifp->if_l2com;
1245	struct ifreq *ifr = (struct ifreq *)data;
1246	int error = 0, startall;
1247
1248	switch (cmd) {
1249	case SIOCSIFFLAGS:
1250		startall = 0;
1251		if (IS_RUNNING(ifp)) {
1252			bwn_update_promisc(ifp);
1253		} else if (ifp->if_flags & IFF_UP) {
1254			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1255				bwn_init(sc);
1256				startall = 1;
1257			}
1258		} else
1259			bwn_stop(sc, 1);
1260		if (startall)
1261			ieee80211_start_all(ic);
1262		break;
1263	case SIOCGIFMEDIA:
1264		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1265		break;
1266	case SIOCGIFADDR:
1267		error = ether_ioctl(ifp, cmd, data);
1268		break;
1269	default:
1270		error = EINVAL;
1271		break;
1272	}
1273	return (error);
1274}
1275
1276static void
1277bwn_start(struct ifnet *ifp)
1278{
1279	struct bwn_softc *sc = ifp->if_softc;
1280
1281	BWN_LOCK(sc);
1282	bwn_start_locked(ifp);
1283	BWN_UNLOCK(sc);
1284}
1285
1286static void
1287bwn_start_locked(struct ifnet *ifp)
1288{
1289	struct bwn_softc *sc = ifp->if_softc;
1290	struct bwn_mac *mac = sc->sc_curmac;
1291	struct ieee80211_frame *wh;
1292	struct ieee80211_node *ni;
1293	struct ieee80211_key *k;
1294	struct mbuf *m;
1295
1296	BWN_ASSERT_LOCKED(sc);
1297
1298	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1299	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1300		return;
1301
1302	for (;;) {
1303		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1304		if (m == NULL)
1305			break;
1306
1307		if (bwn_tx_isfull(sc, m))
1308			break;
1309		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1310		if (ni == NULL) {
1311			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1312			m_freem(m);
1313			ifp->if_oerrors++;
1314			continue;
1315		}
1316		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1317		wh = mtod(m, struct ieee80211_frame *);
1318		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1319			k = ieee80211_crypto_encap(ni, m);
1320			if (k == NULL) {
1321				ieee80211_free_node(ni);
1322				m_freem(m);
1323				ifp->if_oerrors++;
1324				continue;
1325			}
1326		}
1327		wh = NULL;	/* Catch any invalid use */
1328
1329		if (bwn_tx_start(sc, ni, m) != 0) {
1330			if (ni != NULL)
1331				ieee80211_free_node(ni);
1332			ifp->if_oerrors++;
1333			continue;
1334		}
1335
1336		sc->sc_watchdog_timer = 5;
1337	}
1338}
1339
1340static int
1341bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1342{
1343	struct bwn_dma_ring *dr;
1344	struct bwn_mac *mac = sc->sc_curmac;
1345	struct bwn_pio_txqueue *tq;
1346	struct ifnet *ifp = sc->sc_ifp;
1347	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1348
1349	BWN_ASSERT_LOCKED(sc);
1350
1351	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1352		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1353		if (dr->dr_stop == 1 ||
1354		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1355			dr->dr_stop = 1;
1356			goto full;
1357		}
1358	} else {
1359		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1360		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1361		    pktlen > (tq->tq_size - tq->tq_used)) {
1362			tq->tq_stop = 1;
1363			goto full;
1364		}
1365	}
1366	return (0);
1367full:
1368	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1369	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1370	return (1);
1371}
1372
1373static int
1374bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1375{
1376	struct bwn_mac *mac = sc->sc_curmac;
1377	int error;
1378
1379	BWN_ASSERT_LOCKED(sc);
1380
1381	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1382		m_freem(m);
1383		return (ENXIO);
1384	}
1385
1386	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1387	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1388	if (error) {
1389		m_freem(m);
1390		return (error);
1391	}
1392	return (0);
1393}
1394
1395static int
1396bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1397{
1398	struct bwn_pio_txpkt *tp;
1399	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1400	struct bwn_softc *sc = mac->mac_sc;
1401	struct bwn_txhdr txhdr;
1402	struct mbuf *m_new;
1403	uint32_t ctl32;
1404	int error;
1405	uint16_t ctl16;
1406
1407	BWN_ASSERT_LOCKED(sc);
1408
1409	/* XXX TODO send packets after DTIM */
1410
1411	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1412	tp = TAILQ_FIRST(&tq->tq_pktlist);
1413	tp->tp_ni = ni;
1414	tp->tp_m = m;
1415
1416	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1417	if (error) {
1418		device_printf(sc->sc_dev, "tx fail\n");
1419		return (error);
1420	}
1421
1422	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1423	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1424	tq->tq_free--;
1425
1426	if (siba_get_revid(sc->sc_dev) >= 8) {
1427		/*
1428		 * XXX please removes m_defrag(9)
1429		 */
1430		m_new = m_defrag(m, M_DONTWAIT);
1431		if (m_new == NULL) {
1432			device_printf(sc->sc_dev,
1433			    "%s: can't defrag TX buffer\n",
1434			    __func__);
1435			return (ENOBUFS);
1436		}
1437		if (m_new->m_next != NULL)
1438			device_printf(sc->sc_dev,
1439			    "TODO: fragmented packets for PIO\n");
1440		tp->tp_m = m_new;
1441
1442		/* send HEADER */
1443		ctl32 = bwn_pio_write_multi_4(mac, tq,
1444		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1445			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1446		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1447		/* send BODY */
1448		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1449		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1450		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1451		    ctl32 | BWN_PIO8_TXCTL_EOF);
1452	} else {
1453		ctl16 = bwn_pio_write_multi_2(mac, tq,
1454		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1455			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1456		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1457		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1458		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1459		    ctl16 | BWN_PIO_TXCTL_EOF);
1460	}
1461
1462	return (0);
1463}
1464
1465static struct bwn_pio_txqueue *
1466bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1467{
1468
1469	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1470		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1471
1472	switch (prio) {
1473	case 0:
1474		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1475	case 1:
1476		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1477	case 2:
1478		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1479	case 3:
1480		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1481	}
1482	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1483	return (NULL);
1484}
1485
1486static int
1487bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1488{
1489#define	BWN_GET_TXHDRCACHE(slot)					\
1490	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1491	struct bwn_dma *dma = &mac->mac_method.dma;
1492	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1493	struct bwn_dmadesc_generic *desc;
1494	struct bwn_dmadesc_meta *mt;
1495	struct bwn_softc *sc = mac->mac_sc;
1496	struct ifnet *ifp = sc->sc_ifp;
1497	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1498	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1499
1500	BWN_ASSERT_LOCKED(sc);
1501	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1502
1503	/* XXX send after DTIM */
1504
1505	slot = bwn_dma_getslot(dr);
1506	dr->getdesc(dr, slot, &desc, &mt);
1507	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1508	    ("%s:%d: fail", __func__, __LINE__));
1509
1510	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1511	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1512	    BWN_DMA_COOKIE(dr, slot));
1513	if (error)
1514		goto fail;
1515	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1516	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1517	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1518	if (error) {
1519		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1520		    __func__, error);
1521		goto fail;
1522	}
1523	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1524	    BUS_DMASYNC_PREWRITE);
1525	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1526	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1527	    BUS_DMASYNC_PREWRITE);
1528
1529	slot = bwn_dma_getslot(dr);
1530	dr->getdesc(dr, slot, &desc, &mt);
1531	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1532	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1533	mt->mt_m = m;
1534	mt->mt_ni = ni;
1535
1536	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1537	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1538	if (error && error != EFBIG) {
1539		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1540		    __func__, error);
1541		goto fail;
1542	}
1543	if (error) {    /* error == EFBIG */
1544		struct mbuf *m_new;
1545
1546		m_new = m_defrag(m, M_DONTWAIT);
1547		if (m_new == NULL) {
1548			if_printf(ifp, "%s: can't defrag TX buffer\n",
1549			    __func__);
1550			error = ENOBUFS;
1551			goto fail;
1552		} else {
1553			m = m_new;
1554		}
1555
1556		mt->mt_m = m;
1557		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1558		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1559		if (error) {
1560			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1561			    __func__, error);
1562			goto fail;
1563		}
1564	}
1565	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1566	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1567	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1568	    BUS_DMASYNC_PREWRITE);
1569
1570	/* XXX send after DTIM */
1571
1572	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1573	return (0);
1574fail:
1575	dr->dr_curslot = backup[0];
1576	dr->dr_usedslot = backup[1];
1577	return (error);
1578#undef BWN_GET_TXHDRCACHE
1579}
1580
1581static void
1582bwn_watchdog(void *arg)
1583{
1584	struct bwn_softc *sc = arg;
1585	struct ifnet *ifp = sc->sc_ifp;
1586
1587	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1588		if_printf(ifp, "device timeout\n");
1589		ifp->if_oerrors++;
1590	}
1591	callout_schedule(&sc->sc_watchdog_ch, hz);
1592}
1593
1594static int
1595bwn_attach_core(struct bwn_mac *mac)
1596{
1597	struct bwn_softc *sc = mac->mac_sc;
1598	int error, have_bg = 0, have_a = 0;
1599	uint32_t high;
1600
1601	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1602	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1603
1604	siba_powerup(sc->sc_dev, 0);
1605
1606	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1607	bwn_reset_core(mac,
1608	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1609	error = bwn_phy_getinfo(mac, high);
1610	if (error)
1611		goto fail;
1612
1613	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1614	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1615	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1616	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1617	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1618		have_a = have_bg = 0;
1619		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1620			have_a = 1;
1621		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1622		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1623		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1624			have_bg = 1;
1625		else
1626			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1627			    mac->mac_phy.type));
1628	}
1629	/* XXX turns off PHY A because it's not supported */
1630	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1631	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1632		have_a = 0;
1633		have_bg = 1;
1634	}
1635
1636	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1637		mac->mac_phy.attach = bwn_phy_g_attach;
1638		mac->mac_phy.detach = bwn_phy_g_detach;
1639		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1640		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1641		mac->mac_phy.init = bwn_phy_g_init;
1642		mac->mac_phy.exit = bwn_phy_g_exit;
1643		mac->mac_phy.phy_read = bwn_phy_g_read;
1644		mac->mac_phy.phy_write = bwn_phy_g_write;
1645		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1646		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1647		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1648		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1649		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1650		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1651		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1652		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1653		mac->mac_phy.set_im = bwn_phy_g_im;
1654		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1655		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1656		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1657		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1658	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1659		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1660		mac->mac_phy.init = bwn_phy_lp_init;
1661		mac->mac_phy.phy_read = bwn_phy_lp_read;
1662		mac->mac_phy.phy_write = bwn_phy_lp_write;
1663		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1664		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1665		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1666		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1667		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1668		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1669		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1670		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1671		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1672	} else {
1673		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1674		    mac->mac_phy.type);
1675		error = ENXIO;
1676		goto fail;
1677	}
1678
1679	mac->mac_phy.gmode = have_bg;
1680	if (mac->mac_phy.attach != NULL) {
1681		error = mac->mac_phy.attach(mac);
1682		if (error) {
1683			device_printf(sc->sc_dev, "failed\n");
1684			goto fail;
1685		}
1686	}
1687
1688	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1689
1690	error = bwn_chiptest(mac);
1691	if (error)
1692		goto fail;
1693	error = bwn_setup_channels(mac, have_bg, have_a);
1694	if (error) {
1695		device_printf(sc->sc_dev, "failed to setup channels\n");
1696		goto fail;
1697	}
1698
1699	if (sc->sc_curmac == NULL)
1700		sc->sc_curmac = mac;
1701
1702	error = bwn_dma_attach(mac);
1703	if (error != 0) {
1704		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1705		goto fail;
1706	}
1707
1708	mac->mac_phy.switch_analog(mac, 0);
1709
1710	siba_dev_down(sc->sc_dev, 0);
1711fail:
1712	siba_powerdown(sc->sc_dev);
1713	return (error);
1714}
1715
1716static void
1717bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1718{
1719	struct bwn_softc *sc = mac->mac_sc;
1720	uint32_t low, ctl;
1721
1722	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1723
1724	siba_dev_up(sc->sc_dev, flags);
1725	DELAY(2000);
1726
1727	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1728	    ~BWN_TGSLOW_PHYRESET;
1729	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1730	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1731	DELAY(1000);
1732	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1733	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734	DELAY(1000);
1735
1736	if (mac->mac_phy.switch_analog != NULL)
1737		mac->mac_phy.switch_analog(mac, 1);
1738
1739	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1740	if (flags & BWN_TGSLOW_SUPPORT_G)
1741		ctl |= BWN_MACCTL_GMODE;
1742	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1743}
1744
1745static int
1746bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1747{
1748	struct bwn_phy *phy = &mac->mac_phy;
1749	struct bwn_softc *sc = mac->mac_sc;
1750	uint32_t tmp;
1751
1752	/* PHY */
1753	tmp = BWN_READ_2(mac, BWN_PHYVER);
1754	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1755	phy->rf_on = 1;
1756	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1757	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1758	phy->rev = (tmp & BWN_PHYVER_VERSION);
1759	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1760	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1761		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1762	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1763	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1764	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1765		goto unsupphy;
1766
1767	/* RADIO */
1768	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1769		if (siba_get_chiprev(sc->sc_dev) == 0)
1770			tmp = 0x3205017f;
1771		else if (siba_get_chiprev(sc->sc_dev) == 1)
1772			tmp = 0x4205017f;
1773		else
1774			tmp = 0x5205017f;
1775	} else {
1776		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1777		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1778		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1779		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1780	}
1781	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1782	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1783	phy->rf_manuf = (tmp & 0x00000fff);
1784	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1785		goto unsupradio;
1786	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1787	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1788	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1789	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1790	    (phy->type == BWN_PHYTYPE_N &&
1791	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1792	    (phy->type == BWN_PHYTYPE_LP &&
1793	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1794		goto unsupradio;
1795
1796	return (0);
1797unsupphy:
1798	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1799	    "analog %#x)\n",
1800	    phy->type, phy->rev, phy->analog);
1801	return (ENXIO);
1802unsupradio:
1803	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1804	    "rev %#x)\n",
1805	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1806	return (ENXIO);
1807}
1808
1809static int
1810bwn_chiptest(struct bwn_mac *mac)
1811{
1812#define	TESTVAL0	0x55aaaa55
1813#define	TESTVAL1	0xaa5555aa
1814	struct bwn_softc *sc = mac->mac_sc;
1815	uint32_t v, backup;
1816
1817	BWN_LOCK(sc);
1818
1819	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1820
1821	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1822	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1823		goto error;
1824	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1825	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1826		goto error;
1827
1828	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1829
1830	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1831	    (siba_get_revid(sc->sc_dev) <= 10)) {
1832		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1833		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1834		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1835			goto error;
1836		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1837			goto error;
1838	}
1839	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1840
1841	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1842	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1843		goto error;
1844
1845	BWN_UNLOCK(sc);
1846	return (0);
1847error:
1848	BWN_UNLOCK(sc);
1849	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1850	return (ENODEV);
1851}
1852
1853#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1854#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1855
1856static int
1857bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1858{
1859	struct bwn_softc *sc = mac->mac_sc;
1860	struct ifnet *ifp = sc->sc_ifp;
1861	struct ieee80211com *ic = ifp->if_l2com;
1862
1863	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1864	ic->ic_nchans = 0;
1865
1866	if (have_bg)
1867		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1868		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1869	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1870		if (have_a)
1871			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1872			    &ic->ic_nchans, &bwn_chantable_n,
1873			    IEEE80211_CHAN_HTA);
1874	} else {
1875		if (have_a)
1876			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1877			    &ic->ic_nchans, &bwn_chantable_a,
1878			    IEEE80211_CHAN_A);
1879	}
1880
1881	mac->mac_phy.supports_2ghz = have_bg;
1882	mac->mac_phy.supports_5ghz = have_a;
1883
1884	return (ic->ic_nchans == 0 ? ENXIO : 0);
1885}
1886
1887static uint32_t
1888bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1889{
1890	uint32_t ret;
1891
1892	BWN_ASSERT_LOCKED(mac->mac_sc);
1893
1894	if (way == BWN_SHARED) {
1895		KASSERT((offset & 0x0001) == 0,
1896		    ("%s:%d warn", __func__, __LINE__));
1897		if (offset & 0x0003) {
1898			bwn_shm_ctlword(mac, way, offset >> 2);
1899			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1900			ret <<= 16;
1901			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1902			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1903			goto out;
1904		}
1905		offset >>= 2;
1906	}
1907	bwn_shm_ctlword(mac, way, offset);
1908	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1909out:
1910	return (ret);
1911}
1912
1913static uint16_t
1914bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1915{
1916	uint16_t ret;
1917
1918	BWN_ASSERT_LOCKED(mac->mac_sc);
1919
1920	if (way == BWN_SHARED) {
1921		KASSERT((offset & 0x0001) == 0,
1922		    ("%s:%d warn", __func__, __LINE__));
1923		if (offset & 0x0003) {
1924			bwn_shm_ctlword(mac, way, offset >> 2);
1925			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1926			goto out;
1927		}
1928		offset >>= 2;
1929	}
1930	bwn_shm_ctlword(mac, way, offset);
1931	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1932out:
1933
1934	return (ret);
1935}
1936
1937static void
1938bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1939    uint16_t offset)
1940{
1941	uint32_t control;
1942
1943	control = way;
1944	control <<= 16;
1945	control |= offset;
1946	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1947}
1948
1949static void
1950bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1951    uint32_t value)
1952{
1953	BWN_ASSERT_LOCKED(mac->mac_sc);
1954
1955	if (way == BWN_SHARED) {
1956		KASSERT((offset & 0x0001) == 0,
1957		    ("%s:%d warn", __func__, __LINE__));
1958		if (offset & 0x0003) {
1959			bwn_shm_ctlword(mac, way, offset >> 2);
1960			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1961				    (value >> 16) & 0xffff);
1962			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1963			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1964			return;
1965		}
1966		offset >>= 2;
1967	}
1968	bwn_shm_ctlword(mac, way, offset);
1969	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1970}
1971
1972static void
1973bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1974    uint16_t value)
1975{
1976	BWN_ASSERT_LOCKED(mac->mac_sc);
1977
1978	if (way == BWN_SHARED) {
1979		KASSERT((offset & 0x0001) == 0,
1980		    ("%s:%d warn", __func__, __LINE__));
1981		if (offset & 0x0003) {
1982			bwn_shm_ctlword(mac, way, offset >> 2);
1983			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1984			return;
1985		}
1986		offset >>= 2;
1987	}
1988	bwn_shm_ctlword(mac, way, offset);
1989	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1990}
1991
1992static void
1993bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1994    int txpow)
1995{
1996
1997	c->ic_freq = freq;
1998	c->ic_flags = flags;
1999	c->ic_ieee = ieee;
2000	c->ic_minpower = 0;
2001	c->ic_maxpower = 2 * txpow;
2002	c->ic_maxregpower = txpow;
2003}
2004
2005static void
2006bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2007    const struct bwn_channelinfo *ci, int flags)
2008{
2009	struct ieee80211_channel *c;
2010	int i;
2011
2012	c = &chans[*nchans];
2013
2014	for (i = 0; i < ci->nchannels; i++) {
2015		const struct bwn_channel *hc;
2016
2017		hc = &ci->channels[i];
2018		if (*nchans >= maxchans)
2019			break;
2020		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2021		c++, (*nchans)++;
2022		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2023			/* g channel have a separate b-only entry */
2024			if (*nchans >= maxchans)
2025				break;
2026			c[0] = c[-1];
2027			c[-1].ic_flags = IEEE80211_CHAN_B;
2028			c++, (*nchans)++;
2029		}
2030		if (flags == IEEE80211_CHAN_HTG) {
2031			/* HT g channel have a separate g-only entry */
2032			if (*nchans >= maxchans)
2033				break;
2034			c[-1].ic_flags = IEEE80211_CHAN_G;
2035			c[0] = c[-1];
2036			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2037			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2038			c++, (*nchans)++;
2039		}
2040		if (flags == IEEE80211_CHAN_HTA) {
2041			/* HT a channel have a separate a-only entry */
2042			if (*nchans >= maxchans)
2043				break;
2044			c[-1].ic_flags = IEEE80211_CHAN_A;
2045			c[0] = c[-1];
2046			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2047			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2048			c++, (*nchans)++;
2049		}
2050	}
2051}
2052
2053static int
2054bwn_phy_g_attach(struct bwn_mac *mac)
2055{
2056	struct bwn_softc *sc = mac->mac_sc;
2057	struct bwn_phy *phy = &mac->mac_phy;
2058	struct bwn_phy_g *pg = &phy->phy_g;
2059	unsigned int i;
2060	int16_t pab0, pab1, pab2;
2061	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2062	int8_t bg;
2063
2064	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2065	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2066	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2067	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2068
2069	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2070		device_printf(sc->sc_dev, "not supported anymore\n");
2071
2072	pg->pg_flags = 0;
2073	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2074	    pab2 == -1) {
2075		pg->pg_idletssi = 52;
2076		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2077		return (0);
2078	}
2079
2080	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2081	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2082	if (pg->pg_tssi2dbm == NULL) {
2083		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2084		return (ENOMEM);
2085	}
2086	for (i = 0; i < 64; i++) {
2087		int32_t m1, m2, f, q, delta;
2088		int8_t j = 0;
2089
2090		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2091		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2092		f = 256;
2093
2094		do {
2095			if (j > 15) {
2096				device_printf(sc->sc_dev,
2097				    "failed to generate tssi2dBm\n");
2098				free(pg->pg_tssi2dbm, M_DEVBUF);
2099				return (ENOMEM);
2100			}
2101			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2102			    f, 2048);
2103			delta = abs(q - f);
2104			f = q;
2105			j++;
2106		} while (delta >= 2);
2107
2108		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2109		    128);
2110	}
2111
2112	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2113	return (0);
2114}
2115
2116static void
2117bwn_phy_g_detach(struct bwn_mac *mac)
2118{
2119	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2120
2121	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2122		free(pg->pg_tssi2dbm, M_DEVBUF);
2123		pg->pg_tssi2dbm = NULL;
2124	}
2125	pg->pg_flags = 0;
2126}
2127
2128static void
2129bwn_phy_g_init_pre(struct bwn_mac *mac)
2130{
2131	struct bwn_phy *phy = &mac->mac_phy;
2132	struct bwn_phy_g *pg = &phy->phy_g;
2133	void *tssi2dbm;
2134	int idletssi;
2135	unsigned int i;
2136
2137	tssi2dbm = pg->pg_tssi2dbm;
2138	idletssi = pg->pg_idletssi;
2139
2140	memset(pg, 0, sizeof(*pg));
2141
2142	pg->pg_tssi2dbm = tssi2dbm;
2143	pg->pg_idletssi = idletssi;
2144
2145	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2146
2147	for (i = 0; i < N(pg->pg_nrssi); i++)
2148		pg->pg_nrssi[i] = -1000;
2149	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2150		pg->pg_nrssi_lt[i] = i;
2151	pg->pg_lofcal = 0xffff;
2152	pg->pg_initval = 0xffff;
2153	pg->pg_immode = BWN_IMMODE_NONE;
2154	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2155	pg->pg_avgtssi = 0xff;
2156
2157	pg->pg_loctl.tx_bias = 0xff;
2158	TAILQ_INIT(&pg->pg_loctl.calib_list);
2159}
2160
2161static int
2162bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2163{
2164	struct bwn_phy *phy = &mac->mac_phy;
2165	struct bwn_phy_g *pg = &phy->phy_g;
2166	struct bwn_softc *sc = mac->mac_sc;
2167	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2168	static const struct bwn_rfatt rfatt0[] = {
2169		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2170		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2171		{ 3, 1 }, { 4, 1 }
2172	};
2173	static const struct bwn_rfatt rfatt1[] = {
2174		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2175		{ 14, 1 }
2176	};
2177	static const struct bwn_rfatt rfatt2[] = {
2178		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2179		{ 9, 1 }
2180	};
2181	static const struct bwn_bbatt bbatt_0[] = {
2182		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2183	};
2184
2185	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2186
2187	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2188		pg->pg_bbatt.att = 0;
2189	else
2190		pg->pg_bbatt.att = 2;
2191
2192	/* prepare Radio Attenuation */
2193	pg->pg_rfatt.padmix = 0;
2194
2195	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2196	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2197		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2198			pg->pg_rfatt.att = 2;
2199			goto done;
2200		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2201			pg->pg_rfatt.att = 3;
2202			goto done;
2203		}
2204	}
2205
2206	if (phy->type == BWN_PHYTYPE_A) {
2207		pg->pg_rfatt.att = 0x60;
2208		goto done;
2209	}
2210
2211	switch (phy->rf_ver) {
2212	case 0x2050:
2213		switch (phy->rf_rev) {
2214		case 0:
2215			pg->pg_rfatt.att = 5;
2216			goto done;
2217		case 1:
2218			if (phy->type == BWN_PHYTYPE_G) {
2219				if (siba_get_pci_subvendor(sc->sc_dev) ==
2220				    SIBA_BOARDVENDOR_BCM &&
2221				    siba_get_pci_subdevice(sc->sc_dev) ==
2222				    SIBA_BOARD_BCM4309G &&
2223				    siba_get_pci_revid(sc->sc_dev) >= 30)
2224					pg->pg_rfatt.att = 3;
2225				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2226				    SIBA_BOARDVENDOR_BCM &&
2227				    siba_get_pci_subdevice(sc->sc_dev) ==
2228				    SIBA_BOARD_BU4306)
2229					pg->pg_rfatt.att = 3;
2230				else
2231					pg->pg_rfatt.att = 1;
2232			} else {
2233				if (siba_get_pci_subvendor(sc->sc_dev) ==
2234				    SIBA_BOARDVENDOR_BCM &&
2235				    siba_get_pci_subdevice(sc->sc_dev) ==
2236				    SIBA_BOARD_BCM4309G &&
2237				    siba_get_pci_revid(sc->sc_dev) >= 30)
2238					pg->pg_rfatt.att = 7;
2239				else
2240					pg->pg_rfatt.att = 6;
2241			}
2242			goto done;
2243		case 2:
2244			if (phy->type == BWN_PHYTYPE_G) {
2245				if (siba_get_pci_subvendor(sc->sc_dev) ==
2246				    SIBA_BOARDVENDOR_BCM &&
2247				    siba_get_pci_subdevice(sc->sc_dev) ==
2248				    SIBA_BOARD_BCM4309G &&
2249				    siba_get_pci_revid(sc->sc_dev) >= 30)
2250					pg->pg_rfatt.att = 3;
2251				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2252				    SIBA_BOARDVENDOR_BCM &&
2253				    siba_get_pci_subdevice(sc->sc_dev) ==
2254				    SIBA_BOARD_BU4306)
2255					pg->pg_rfatt.att = 5;
2256				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2257					pg->pg_rfatt.att = 4;
2258				else
2259					pg->pg_rfatt.att = 3;
2260			} else
2261				pg->pg_rfatt.att = 6;
2262			goto done;
2263		case 3:
2264			pg->pg_rfatt.att = 5;
2265			goto done;
2266		case 4:
2267		case 5:
2268			pg->pg_rfatt.att = 1;
2269			goto done;
2270		case 6:
2271		case 7:
2272			pg->pg_rfatt.att = 5;
2273			goto done;
2274		case 8:
2275			pg->pg_rfatt.att = 0xa;
2276			pg->pg_rfatt.padmix = 1;
2277			goto done;
2278		case 9:
2279		default:
2280			pg->pg_rfatt.att = 5;
2281			goto done;
2282		}
2283		break;
2284	case 0x2053:
2285		switch (phy->rf_rev) {
2286		case 1:
2287			pg->pg_rfatt.att = 6;
2288			goto done;
2289		}
2290		break;
2291	}
2292	pg->pg_rfatt.att = 5;
2293done:
2294	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2295
2296	if (!bwn_has_hwpctl(mac)) {
2297		lo->rfatt.array = rfatt0;
2298		lo->rfatt.len = N(rfatt0);
2299		lo->rfatt.min = 0;
2300		lo->rfatt.max = 9;
2301		goto genbbatt;
2302	}
2303	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2304		lo->rfatt.array = rfatt1;
2305		lo->rfatt.len = N(rfatt1);
2306		lo->rfatt.min = 0;
2307		lo->rfatt.max = 14;
2308		goto genbbatt;
2309	}
2310	lo->rfatt.array = rfatt2;
2311	lo->rfatt.len = N(rfatt2);
2312	lo->rfatt.min = 0;
2313	lo->rfatt.max = 9;
2314genbbatt:
2315	lo->bbatt.array = bbatt_0;
2316	lo->bbatt.len = N(bbatt_0);
2317	lo->bbatt.min = 0;
2318	lo->bbatt.max = 8;
2319
2320	BWN_READ_4(mac, BWN_MACCTL);
2321	if (phy->rev == 1) {
2322		phy->gmode = 0;
2323		bwn_reset_core(mac, 0);
2324		bwn_phy_g_init_sub(mac);
2325		phy->gmode = 1;
2326		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2327	}
2328	return (0);
2329}
2330
2331static uint16_t
2332bwn_phy_g_txctl(struct bwn_mac *mac)
2333{
2334	struct bwn_phy *phy = &mac->mac_phy;
2335
2336	if (phy->rf_ver != 0x2050)
2337		return (0);
2338	if (phy->rf_rev == 1)
2339		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2340	if (phy->rf_rev < 6)
2341		return (BWN_TXCTL_PA2DB);
2342	if (phy->rf_rev == 8)
2343		return (BWN_TXCTL_TXMIX);
2344	return (0);
2345}
2346
2347static int
2348bwn_phy_g_init(struct bwn_mac *mac)
2349{
2350
2351	bwn_phy_g_init_sub(mac);
2352	return (0);
2353}
2354
2355static void
2356bwn_phy_g_exit(struct bwn_mac *mac)
2357{
2358	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2359	struct bwn_lo_calib *cal, *tmp;
2360
2361	if (lo == NULL)
2362		return;
2363	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2364		TAILQ_REMOVE(&lo->calib_list, cal, list);
2365		free(cal, M_DEVBUF);
2366	}
2367}
2368
2369static uint16_t
2370bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2371{
2372
2373	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2374	return (BWN_READ_2(mac, BWN_PHYDATA));
2375}
2376
2377static void
2378bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2379{
2380
2381	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2382	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2383}
2384
2385static uint16_t
2386bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2387{
2388
2389	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2390	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2391	return (BWN_READ_2(mac, BWN_RFDATALO));
2392}
2393
2394static void
2395bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2396{
2397
2398	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2400	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2401}
2402
2403static int
2404bwn_phy_g_hwpctl(struct bwn_mac *mac)
2405{
2406
2407	return (mac->mac_phy.rev >= 6);
2408}
2409
2410static void
2411bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2412{
2413	struct bwn_phy *phy = &mac->mac_phy;
2414	struct bwn_phy_g *pg = &phy->phy_g;
2415	unsigned int channel;
2416	uint16_t rfover, rfoverval;
2417
2418	if (on) {
2419		if (phy->rf_on)
2420			return;
2421
2422		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2423		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2424		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2425		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2426			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2427			    pg->pg_radioctx_over);
2428			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2429			    pg->pg_radioctx_overval);
2430			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2431		}
2432		channel = phy->chan;
2433		bwn_phy_g_switch_chan(mac, 6, 1);
2434		bwn_phy_g_switch_chan(mac, channel, 0);
2435		return;
2436	}
2437
2438	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2439	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2440	pg->pg_radioctx_over = rfover;
2441	pg->pg_radioctx_overval = rfoverval;
2442	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2443	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2444	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2445}
2446
2447static int
2448bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2449{
2450
2451	if ((newchan < 1) || (newchan > 14))
2452		return (EINVAL);
2453	bwn_phy_g_switch_chan(mac, newchan, 0);
2454
2455	return (0);
2456}
2457
2458static uint32_t
2459bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2460{
2461
2462	return (1);
2463}
2464
2465static void
2466bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2467{
2468	struct bwn_phy *phy = &mac->mac_phy;
2469	uint64_t hf;
2470	int autodiv = 0;
2471	uint16_t tmp;
2472
2473	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2474		autodiv = 1;
2475
2476	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2477	bwn_hf_write(mac, hf);
2478
2479	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2480	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2481	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2482		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2483
2484	if (autodiv) {
2485		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2486		if (antenna == BWN_ANTAUTO1)
2487			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2488		else
2489			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2490		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2491	}
2492	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2493	if (autodiv)
2494		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2495	else
2496		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2497	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2498	if (phy->rev >= 2) {
2499		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2500		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2501		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2502		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2503		    0x15);
2504		if (phy->rev == 2)
2505			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2506		else
2507			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2508			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2509			    8);
2510	}
2511	if (phy->rev >= 6)
2512		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2513
2514	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2515	bwn_hf_write(mac, hf);
2516}
2517
2518static int
2519bwn_phy_g_im(struct bwn_mac *mac, int mode)
2520{
2521	struct bwn_phy *phy = &mac->mac_phy;
2522	struct bwn_phy_g *pg = &phy->phy_g;
2523
2524	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2525	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2526
2527	if (phy->rev == 0 || !phy->gmode)
2528		return (ENODEV);
2529
2530	pg->pg_aci_wlan_automatic = 0;
2531	return (0);
2532}
2533
2534static int
2535bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2536{
2537	struct bwn_phy *phy = &mac->mac_phy;
2538	struct bwn_phy_g *pg = &phy->phy_g;
2539	struct bwn_softc *sc = mac->mac_sc;
2540	unsigned int tssi;
2541	int cck, ofdm;
2542	int power;
2543	int rfatt, bbatt;
2544	unsigned int max;
2545
2546	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2547
2548	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2549	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2550	if (cck < 0 && ofdm < 0) {
2551		if (ignore_tssi == 0)
2552			return (BWN_TXPWR_RES_DONE);
2553		cck = 0;
2554		ofdm = 0;
2555	}
2556	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2557	if (pg->pg_avgtssi != 0xff)
2558		tssi = (tssi + pg->pg_avgtssi) / 2;
2559	pg->pg_avgtssi = tssi;
2560	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2561
2562	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2563	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2564		max -= 3;
2565	if (max >= 120) {
2566		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2567		max = 80;
2568		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2569	}
2570
2571	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2572	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2573	     tssi, 0x00), 0x3f)]);
2574	if (power == 0)
2575		return (BWN_TXPWR_RES_DONE);
2576
2577	rfatt = -((power + 7) / 8);
2578	bbatt = (-(power / 2)) - (4 * rfatt);
2579	if ((rfatt == 0) && (bbatt == 0))
2580		return (BWN_TXPWR_RES_DONE);
2581	pg->pg_bbatt_delta = bbatt;
2582	pg->pg_rfatt_delta = rfatt;
2583	return (BWN_TXPWR_RES_NEED_ADJUST);
2584}
2585
2586static void
2587bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2588{
2589	struct bwn_phy *phy = &mac->mac_phy;
2590	struct bwn_phy_g *pg = &phy->phy_g;
2591	struct bwn_softc *sc = mac->mac_sc;
2592	int rfatt, bbatt;
2593	uint8_t txctl;
2594
2595	bwn_mac_suspend(mac);
2596
2597	BWN_ASSERT_LOCKED(sc);
2598
2599	bbatt = pg->pg_bbatt.att;
2600	bbatt += pg->pg_bbatt_delta;
2601	rfatt = pg->pg_rfatt.att;
2602	rfatt += pg->pg_rfatt_delta;
2603
2604	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2605	txctl = pg->pg_txctl;
2606	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2607		if (rfatt <= 1) {
2608			if (txctl == 0) {
2609				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2610				rfatt += 2;
2611				bbatt += 2;
2612			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2613			    BWN_BFL_PACTRL) {
2614				bbatt += 4 * (rfatt - 2);
2615				rfatt = 2;
2616			}
2617		} else if (rfatt > 4 && txctl) {
2618			txctl = 0;
2619			if (bbatt < 3) {
2620				rfatt -= 3;
2621				bbatt += 2;
2622			} else {
2623				rfatt -= 2;
2624				bbatt -= 2;
2625			}
2626		}
2627	}
2628	pg->pg_txctl = txctl;
2629	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2630	pg->pg_rfatt.att = rfatt;
2631	pg->pg_bbatt.att = bbatt;
2632
2633	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2634
2635	bwn_phy_lock(mac);
2636	bwn_rf_lock(mac);
2637	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2638	    pg->pg_txctl);
2639	bwn_rf_unlock(mac);
2640	bwn_phy_unlock(mac);
2641
2642	bwn_mac_enable(mac);
2643}
2644
2645static void
2646bwn_phy_g_task_15s(struct bwn_mac *mac)
2647{
2648	struct bwn_phy *phy = &mac->mac_phy;
2649	struct bwn_phy_g *pg = &phy->phy_g;
2650	struct bwn_softc *sc = mac->mac_sc;
2651	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2652	unsigned long expire, now;
2653	struct bwn_lo_calib *cal, *tmp;
2654	uint8_t expired = 0;
2655
2656	bwn_mac_suspend(mac);
2657
2658	if (lo == NULL)
2659		goto fail;
2660
2661	BWN_GETTIME(now);
2662	if (bwn_has_hwpctl(mac)) {
2663		expire = now - BWN_LO_PWRVEC_EXPIRE;
2664		if (time_before(lo->pwr_vec_read_time, expire)) {
2665			bwn_lo_get_powervector(mac);
2666			bwn_phy_g_dc_lookup_init(mac, 0);
2667		}
2668		goto fail;
2669	}
2670
2671	expire = now - BWN_LO_CALIB_EXPIRE;
2672	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2673		if (!time_before(cal->calib_time, expire))
2674			continue;
2675		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2676		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2677			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2678			expired = 1;
2679		}
2680
2681		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2682		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2683		    cal->ctl.i, cal->ctl.q);
2684
2685		TAILQ_REMOVE(&lo->calib_list, cal, list);
2686		free(cal, M_DEVBUF);
2687	}
2688	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2689		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2690		    &pg->pg_rfatt);
2691		if (cal == NULL) {
2692			device_printf(sc->sc_dev,
2693			    "failed to recalibrate LO\n");
2694			goto fail;
2695		}
2696		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2697		bwn_lo_write(mac, &cal->ctl);
2698	}
2699
2700fail:
2701	bwn_mac_enable(mac);
2702}
2703
2704static void
2705bwn_phy_g_task_60s(struct bwn_mac *mac)
2706{
2707	struct bwn_phy *phy = &mac->mac_phy;
2708	struct bwn_softc *sc = mac->mac_sc;
2709	uint8_t old = phy->chan;
2710
2711	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2712		return;
2713
2714	bwn_mac_suspend(mac);
2715	bwn_nrssi_slope_11g(mac);
2716	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2717		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2718		bwn_switch_channel(mac, old);
2719	}
2720	bwn_mac_enable(mac);
2721}
2722
2723static void
2724bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2725{
2726
2727	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2728}
2729
2730static int
2731bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2732	const struct ieee80211_bpf_params *params)
2733{
2734	struct ieee80211com *ic = ni->ni_ic;
2735	struct ifnet *ifp = ic->ic_ifp;
2736	struct bwn_softc *sc = ifp->if_softc;
2737	struct bwn_mac *mac = sc->sc_curmac;
2738
2739	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2740	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2741		ieee80211_free_node(ni);
2742		m_freem(m);
2743		return (ENETDOWN);
2744	}
2745
2746	BWN_LOCK(sc);
2747	if (bwn_tx_isfull(sc, m)) {
2748		ieee80211_free_node(ni);
2749		m_freem(m);
2750		ifp->if_oerrors++;
2751		BWN_UNLOCK(sc);
2752		return (ENOBUFS);
2753	}
2754
2755	if (bwn_tx_start(sc, ni, m) != 0) {
2756		if (ni != NULL)
2757			ieee80211_free_node(ni);
2758		ifp->if_oerrors++;
2759	}
2760	sc->sc_watchdog_timer = 5;
2761	BWN_UNLOCK(sc);
2762	return (0);
2763}
2764
2765/*
2766 * Callback from the 802.11 layer to update the slot time
2767 * based on the current setting.  We use it to notify the
2768 * firmware of ERP changes and the f/w takes care of things
2769 * like slot time and preamble.
2770 */
2771static void
2772bwn_updateslot(struct ifnet *ifp)
2773{
2774	struct bwn_softc *sc = ifp->if_softc;
2775	struct ieee80211com *ic = ifp->if_l2com;
2776	struct bwn_mac *mac;
2777
2778	BWN_LOCK(sc);
2779	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2780		mac = (struct bwn_mac *)sc->sc_curmac;
2781		bwn_set_slot_time(mac,
2782		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2783	}
2784	BWN_UNLOCK(sc);
2785}
2786
2787/*
2788 * Callback from the 802.11 layer after a promiscuous mode change.
2789 * Note this interface does not check the operating mode as this
2790 * is an internal callback and we are expected to honor the current
2791 * state (e.g. this is used for setting the interface in promiscuous
2792 * mode when operating in hostap mode to do ACS).
2793 */
2794static void
2795bwn_update_promisc(struct ifnet *ifp)
2796{
2797	struct bwn_softc *sc = ifp->if_softc;
2798	struct bwn_mac *mac = sc->sc_curmac;
2799
2800	BWN_LOCK(sc);
2801	mac = sc->sc_curmac;
2802	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2803		if (ifp->if_flags & IFF_PROMISC)
2804			sc->sc_filters |= BWN_MACCTL_PROMISC;
2805		else
2806			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2807		bwn_set_opmode(mac);
2808	}
2809	BWN_UNLOCK(sc);
2810}
2811
2812/*
2813 * Callback from the 802.11 layer to update WME parameters.
2814 */
2815static int
2816bwn_wme_update(struct ieee80211com *ic)
2817{
2818	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2819	struct bwn_mac *mac = sc->sc_curmac;
2820	struct wmeParams *wmep;
2821	int i;
2822
2823	BWN_LOCK(sc);
2824	mac = sc->sc_curmac;
2825	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826		bwn_mac_suspend(mac);
2827		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2828			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2829			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2830		}
2831		bwn_mac_enable(mac);
2832	}
2833	BWN_UNLOCK(sc);
2834	return (0);
2835}
2836
2837static void
2838bwn_scan_start(struct ieee80211com *ic)
2839{
2840	struct ifnet *ifp = ic->ic_ifp;
2841	struct bwn_softc *sc = ifp->if_softc;
2842	struct bwn_mac *mac;
2843
2844	BWN_LOCK(sc);
2845	mac = sc->sc_curmac;
2846	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2848		bwn_set_opmode(mac);
2849		/* disable CFP update during scan */
2850		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2851	}
2852	BWN_UNLOCK(sc);
2853}
2854
2855static void
2856bwn_scan_end(struct ieee80211com *ic)
2857{
2858	struct ifnet *ifp = ic->ic_ifp;
2859	struct bwn_softc *sc = ifp->if_softc;
2860	struct bwn_mac *mac;
2861
2862	BWN_LOCK(sc);
2863	mac = sc->sc_curmac;
2864	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2865		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2866		bwn_set_opmode(mac);
2867		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2868	}
2869	BWN_UNLOCK(sc);
2870}
2871
2872static void
2873bwn_set_channel(struct ieee80211com *ic)
2874{
2875	struct ifnet *ifp = ic->ic_ifp;
2876	struct bwn_softc *sc = ifp->if_softc;
2877	struct bwn_mac *mac = sc->sc_curmac;
2878	struct bwn_phy *phy = &mac->mac_phy;
2879	int chan, error;
2880
2881	BWN_LOCK(sc);
2882
2883	error = bwn_switch_band(sc, ic->ic_curchan);
2884	if (error)
2885		goto fail;
2886	bwn_mac_suspend(mac);
2887	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2888	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2889	if (chan != phy->chan)
2890		bwn_switch_channel(mac, chan);
2891
2892	/* TX power level */
2893	if (ic->ic_curchan->ic_maxpower != 0 &&
2894	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2895		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2896		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2897		    BWN_TXPWR_IGNORE_TSSI);
2898	}
2899
2900	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2901	if (phy->set_antenna)
2902		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2903
2904	if (sc->sc_rf_enabled != phy->rf_on) {
2905		if (sc->sc_rf_enabled) {
2906			bwn_rf_turnon(mac);
2907			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2908				device_printf(sc->sc_dev,
2909				    "please turn on the RF switch\n");
2910		} else
2911			bwn_rf_turnoff(mac);
2912	}
2913
2914	bwn_mac_enable(mac);
2915
2916fail:
2917	/*
2918	 * Setup radio tap channel freq and flags
2919	 */
2920	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2921		htole16(ic->ic_curchan->ic_freq);
2922	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2923		htole16(ic->ic_curchan->ic_flags & 0xffff);
2924
2925	BWN_UNLOCK(sc);
2926}
2927
2928static struct ieee80211vap *
2929bwn_vap_create(struct ieee80211com *ic,
2930	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2931	const uint8_t bssid[IEEE80211_ADDR_LEN],
2932	const uint8_t mac0[IEEE80211_ADDR_LEN])
2933{
2934	struct ifnet *ifp = ic->ic_ifp;
2935	struct bwn_softc *sc = ifp->if_softc;
2936	struct ieee80211vap *vap;
2937	struct bwn_vap *bvp;
2938	uint8_t mac[IEEE80211_ADDR_LEN];
2939
2940	IEEE80211_ADDR_COPY(mac, mac0);
2941	switch (opmode) {
2942	case IEEE80211_M_HOSTAP:
2943	case IEEE80211_M_MBSS:
2944	case IEEE80211_M_STA:
2945	case IEEE80211_M_WDS:
2946	case IEEE80211_M_MONITOR:
2947	case IEEE80211_M_IBSS:
2948	case IEEE80211_M_AHDEMO:
2949		break;
2950	default:
2951		return (NULL);
2952	}
2953
2954	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2955
2956	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2957	    M_80211_VAP, M_NOWAIT | M_ZERO);
2958	if (bvp == NULL) {
2959		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2960		return (NULL);
2961	}
2962	vap = &bvp->bv_vap;
2963	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2964	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2965	/* override with driver methods */
2966	bvp->bv_newstate = vap->iv_newstate;
2967	vap->iv_newstate = bwn_newstate;
2968
2969	/* override max aid so sta's cannot assoc when we're out of sta id's */
2970	vap->iv_max_aid = BWN_STAID_MAX;
2971
2972	ieee80211_ratectl_init(vap);
2973
2974	/* complete setup */
2975	ieee80211_vap_attach(vap, ieee80211_media_change,
2976	    ieee80211_media_status);
2977	return (vap);
2978}
2979
2980static void
2981bwn_vap_delete(struct ieee80211vap *vap)
2982{
2983	struct bwn_vap *bvp = BWN_VAP(vap);
2984
2985	ieee80211_ratectl_deinit(vap);
2986	ieee80211_vap_detach(vap);
2987	free(bvp, M_80211_VAP);
2988}
2989
2990static void
2991bwn_init(void *arg)
2992{
2993	struct bwn_softc *sc = arg;
2994	struct ifnet *ifp = sc->sc_ifp;
2995	struct ieee80211com *ic = ifp->if_l2com;
2996	int error = 0;
2997
2998	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2999		__func__, ifp->if_flags);
3000
3001	BWN_LOCK(sc);
3002	error = bwn_init_locked(sc);
3003	BWN_UNLOCK(sc);
3004
3005	if (error == 0)
3006		ieee80211_start_all(ic);	/* start all vap's */
3007}
3008
3009static int
3010bwn_init_locked(struct bwn_softc *sc)
3011{
3012	struct bwn_mac *mac;
3013	struct ifnet *ifp = sc->sc_ifp;
3014	int error;
3015
3016	BWN_ASSERT_LOCKED(sc);
3017
3018	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3019	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3020	sc->sc_filters = 0;
3021	bwn_wme_clear(sc);
3022	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3023	sc->sc_rf_enabled = 1;
3024
3025	mac = sc->sc_curmac;
3026	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3027		error = bwn_core_init(mac);
3028		if (error != 0)
3029			return (error);
3030	}
3031	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3032		bwn_core_start(mac);
3033
3034	bwn_set_opmode(mac);
3035	bwn_set_pretbtt(mac);
3036	bwn_spu_setdelay(mac, 0);
3037	bwn_set_macaddr(mac);
3038
3039	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3040	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3041	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3042
3043	return (0);
3044}
3045
3046static void
3047bwn_stop(struct bwn_softc *sc, int statechg)
3048{
3049
3050	BWN_LOCK(sc);
3051	bwn_stop_locked(sc, statechg);
3052	BWN_UNLOCK(sc);
3053}
3054
3055static void
3056bwn_stop_locked(struct bwn_softc *sc, int statechg)
3057{
3058	struct bwn_mac *mac = sc->sc_curmac;
3059	struct ifnet *ifp = sc->sc_ifp;
3060
3061	BWN_ASSERT_LOCKED(sc);
3062
3063	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3064		/* XXX FIXME opmode not based on VAP */
3065		bwn_set_opmode(mac);
3066		bwn_set_macaddr(mac);
3067	}
3068
3069	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3070		bwn_core_stop(mac);
3071
3072	callout_stop(&sc->sc_led_blink_ch);
3073	sc->sc_led_blinking = 0;
3074
3075	bwn_core_exit(mac);
3076	sc->sc_rf_enabled = 0;
3077
3078	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3079}
3080
3081static void
3082bwn_wme_clear(struct bwn_softc *sc)
3083{
3084#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3085	struct wmeParams *p;
3086	unsigned int i;
3087
3088	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3089	    ("%s:%d: fail", __func__, __LINE__));
3090
3091	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3092		p = &(sc->sc_wmeParams[i]);
3093
3094		switch (bwn_wme_shm_offsets[i]) {
3095		case BWN_WME_VOICE:
3096			p->wmep_txopLimit = 0;
3097			p->wmep_aifsn = 2;
3098			/* XXX FIXME: log2(cwmin) */
3099			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3100			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3101			break;
3102		case BWN_WME_VIDEO:
3103			p->wmep_txopLimit = 0;
3104			p->wmep_aifsn = 2;
3105			/* XXX FIXME: log2(cwmin) */
3106			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3107			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3108			break;
3109		case BWN_WME_BESTEFFORT:
3110			p->wmep_txopLimit = 0;
3111			p->wmep_aifsn = 3;
3112			/* XXX FIXME: log2(cwmin) */
3113			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3114			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3115			break;
3116		case BWN_WME_BACKGROUND:
3117			p->wmep_txopLimit = 0;
3118			p->wmep_aifsn = 7;
3119			/* XXX FIXME: log2(cwmin) */
3120			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3121			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3122			break;
3123		default:
3124			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3125		}
3126	}
3127}
3128
3129static int
3130bwn_core_init(struct bwn_mac *mac)
3131{
3132	struct bwn_softc *sc = mac->mac_sc;
3133	uint64_t hf;
3134	int error;
3135
3136	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3137	    ("%s:%d: fail", __func__, __LINE__));
3138
3139	siba_powerup(sc->sc_dev, 0);
3140	if (!siba_dev_isup(sc->sc_dev))
3141		bwn_reset_core(mac,
3142		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3143
3144	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3145	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3146	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3147	BWN_GETTIME(mac->mac_phy.nexttime);
3148	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3149	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3150	mac->mac_stats.link_noise = -95;
3151	mac->mac_reason_intr = 0;
3152	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3153	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3154#ifdef BWN_DEBUG
3155	if (sc->sc_debug & BWN_DEBUG_XMIT)
3156		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3157#endif
3158	mac->mac_suspended = 1;
3159	mac->mac_task_state = 0;
3160	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3161
3162	mac->mac_phy.init_pre(mac);
3163
3164	siba_pcicore_intr(sc->sc_dev);
3165
3166	siba_fix_imcfglobug(sc->sc_dev);
3167	bwn_bt_disable(mac);
3168	if (mac->mac_phy.prepare_hw) {
3169		error = mac->mac_phy.prepare_hw(mac);
3170		if (error)
3171			goto fail0;
3172	}
3173	error = bwn_chip_init(mac);
3174	if (error)
3175		goto fail0;
3176	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3177	    siba_get_revid(sc->sc_dev));
3178	hf = bwn_hf_read(mac);
3179	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3180		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3181		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3182			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3183		if (mac->mac_phy.rev == 1)
3184			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3185	}
3186	if (mac->mac_phy.rf_ver == 0x2050) {
3187		if (mac->mac_phy.rf_rev < 6)
3188			hf |= BWN_HF_FORCE_VCO_RECALC;
3189		if (mac->mac_phy.rf_rev == 6)
3190			hf |= BWN_HF_4318_TSSI;
3191	}
3192	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3193		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3194	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3195	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3196		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3197	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3198	bwn_hf_write(mac, hf);
3199
3200	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3201	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3202	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3203	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3204
3205	bwn_rate_init(mac);
3206	bwn_set_phytxctl(mac);
3207
3208	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3209	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3210	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3211
3212	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3213		bwn_pio_init(mac);
3214	else
3215		bwn_dma_init(mac);
3216	bwn_wme_init(mac);
3217	bwn_spu_setdelay(mac, 1);
3218	bwn_bt_enable(mac);
3219
3220	siba_powerup(sc->sc_dev,
3221	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3222	bwn_set_macaddr(mac);
3223	bwn_crypt_init(mac);
3224
3225	/* XXX LED initializatin */
3226
3227	mac->mac_status = BWN_MAC_STATUS_INITED;
3228
3229	return (error);
3230
3231fail0:
3232	siba_powerdown(sc->sc_dev);
3233	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3234	    ("%s:%d: fail", __func__, __LINE__));
3235	return (error);
3236}
3237
3238static void
3239bwn_core_start(struct bwn_mac *mac)
3240{
3241	struct bwn_softc *sc = mac->mac_sc;
3242	uint32_t tmp;
3243
3244	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3245	    ("%s:%d: fail", __func__, __LINE__));
3246
3247	if (siba_get_revid(sc->sc_dev) < 5)
3248		return;
3249
3250	while (1) {
3251		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3252		if (!(tmp & 0x00000001))
3253			break;
3254		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3255	}
3256
3257	bwn_mac_enable(mac);
3258	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3259	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3260
3261	mac->mac_status = BWN_MAC_STATUS_STARTED;
3262}
3263
3264static void
3265bwn_core_exit(struct bwn_mac *mac)
3266{
3267	struct bwn_softc *sc = mac->mac_sc;
3268	uint32_t macctl;
3269
3270	BWN_ASSERT_LOCKED(mac->mac_sc);
3271
3272	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3273	    ("%s:%d: fail", __func__, __LINE__));
3274
3275	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3276		return;
3277	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3278
3279	macctl = BWN_READ_4(mac, BWN_MACCTL);
3280	macctl &= ~BWN_MACCTL_MCODE_RUN;
3281	macctl |= BWN_MACCTL_MCODE_JMP0;
3282	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3283
3284	bwn_dma_stop(mac);
3285	bwn_pio_stop(mac);
3286	bwn_chip_exit(mac);
3287	mac->mac_phy.switch_analog(mac, 0);
3288	siba_dev_down(sc->sc_dev, 0);
3289	siba_powerdown(sc->sc_dev);
3290}
3291
3292static void
3293bwn_bt_disable(struct bwn_mac *mac)
3294{
3295	struct bwn_softc *sc = mac->mac_sc;
3296
3297	(void)sc;
3298	/* XXX do nothing yet */
3299}
3300
3301static int
3302bwn_chip_init(struct bwn_mac *mac)
3303{
3304	struct bwn_softc *sc = mac->mac_sc;
3305	struct bwn_phy *phy = &mac->mac_phy;
3306	uint32_t macctl;
3307	int error;
3308
3309	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3310	if (phy->gmode)
3311		macctl |= BWN_MACCTL_GMODE;
3312	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3313
3314	error = bwn_fw_fillinfo(mac);
3315	if (error)
3316		return (error);
3317	error = bwn_fw_loaducode(mac);
3318	if (error)
3319		return (error);
3320
3321	error = bwn_gpio_init(mac);
3322	if (error)
3323		return (error);
3324
3325	error = bwn_fw_loadinitvals(mac);
3326	if (error) {
3327		siba_gpio_set(sc->sc_dev, 0);
3328		return (error);
3329	}
3330	phy->switch_analog(mac, 1);
3331	error = bwn_phy_init(mac);
3332	if (error) {
3333		siba_gpio_set(sc->sc_dev, 0);
3334		return (error);
3335	}
3336	if (phy->set_im)
3337		phy->set_im(mac, BWN_IMMODE_NONE);
3338	if (phy->set_antenna)
3339		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3340	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3341
3342	if (phy->type == BWN_PHYTYPE_B)
3343		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3344	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3345	if (siba_get_revid(sc->sc_dev) < 5)
3346		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3347
3348	BWN_WRITE_4(mac, BWN_MACCTL,
3349	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3350	BWN_WRITE_4(mac, BWN_MACCTL,
3351	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3352	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3353
3354	bwn_set_opmode(mac);
3355	if (siba_get_revid(sc->sc_dev) < 3) {
3356		BWN_WRITE_2(mac, 0x060e, 0x0000);
3357		BWN_WRITE_2(mac, 0x0610, 0x8000);
3358		BWN_WRITE_2(mac, 0x0604, 0x0000);
3359		BWN_WRITE_2(mac, 0x0606, 0x0200);
3360	} else {
3361		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3362		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3363	}
3364	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3365	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3366	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3367	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3368	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3369	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3370	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3371	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3372	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3373	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3374	return (error);
3375}
3376
3377/* read hostflags */
3378static uint64_t
3379bwn_hf_read(struct bwn_mac *mac)
3380{
3381	uint64_t ret;
3382
3383	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3384	ret <<= 16;
3385	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3386	ret <<= 16;
3387	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3388	return (ret);
3389}
3390
3391static void
3392bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3393{
3394
3395	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3396	    (value & 0x00000000ffffull));
3397	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3398	    (value & 0x0000ffff0000ull) >> 16);
3399	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3400	    (value & 0xffff00000000ULL) >> 32);
3401}
3402
3403static void
3404bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3405{
3406
3407	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3408	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3409}
3410
3411static void
3412bwn_rate_init(struct bwn_mac *mac)
3413{
3414
3415	switch (mac->mac_phy.type) {
3416	case BWN_PHYTYPE_A:
3417	case BWN_PHYTYPE_G:
3418	case BWN_PHYTYPE_LP:
3419	case BWN_PHYTYPE_N:
3420		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3421		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3422		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3423		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3424		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3425		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3427		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3428			break;
3429		/* FALLTHROUGH */
3430	case BWN_PHYTYPE_B:
3431		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3432		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3433		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3434		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3435		break;
3436	default:
3437		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3438	}
3439}
3440
3441static void
3442bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3443{
3444	uint16_t offset;
3445
3446	if (ofdm) {
3447		offset = 0x480;
3448		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3449	} else {
3450		offset = 0x4c0;
3451		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3452	}
3453	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3454	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3455}
3456
3457static uint8_t
3458bwn_plcp_getcck(const uint8_t bitrate)
3459{
3460
3461	switch (bitrate) {
3462	case BWN_CCK_RATE_1MB:
3463		return (0x0a);
3464	case BWN_CCK_RATE_2MB:
3465		return (0x14);
3466	case BWN_CCK_RATE_5MB:
3467		return (0x37);
3468	case BWN_CCK_RATE_11MB:
3469		return (0x6e);
3470	}
3471	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3472	return (0);
3473}
3474
3475static uint8_t
3476bwn_plcp_getofdm(const uint8_t bitrate)
3477{
3478
3479	switch (bitrate) {
3480	case BWN_OFDM_RATE_6MB:
3481		return (0xb);
3482	case BWN_OFDM_RATE_9MB:
3483		return (0xf);
3484	case BWN_OFDM_RATE_12MB:
3485		return (0xa);
3486	case BWN_OFDM_RATE_18MB:
3487		return (0xe);
3488	case BWN_OFDM_RATE_24MB:
3489		return (0x9);
3490	case BWN_OFDM_RATE_36MB:
3491		return (0xd);
3492	case BWN_OFDM_RATE_48MB:
3493		return (0x8);
3494	case BWN_OFDM_RATE_54MB:
3495		return (0xc);
3496	}
3497	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3498	return (0);
3499}
3500
3501static void
3502bwn_set_phytxctl(struct bwn_mac *mac)
3503{
3504	uint16_t ctl;
3505
3506	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3507	    BWN_TX_PHY_TXPWR);
3508	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3509	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3510	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3511}
3512
3513static void
3514bwn_pio_init(struct bwn_mac *mac)
3515{
3516	struct bwn_pio *pio = &mac->mac_method.pio;
3517
3518	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3519	    & ~BWN_MACCTL_BIGENDIAN);
3520	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3521
3522	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3523	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3524	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3525	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3526	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3527	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3528}
3529
3530static void
3531bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3532    int index)
3533{
3534	struct bwn_pio_txpkt *tp;
3535	struct bwn_softc *sc = mac->mac_sc;
3536	unsigned int i;
3537
3538	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3539	tq->tq_index = index;
3540
3541	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3542	if (siba_get_revid(sc->sc_dev) >= 8)
3543		tq->tq_size = 1920;
3544	else {
3545		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3546		tq->tq_size -= 80;
3547	}
3548
3549	TAILQ_INIT(&tq->tq_pktlist);
3550	for (i = 0; i < N(tq->tq_pkts); i++) {
3551		tp = &(tq->tq_pkts[i]);
3552		tp->tp_index = i;
3553		tp->tp_queue = tq;
3554		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3555	}
3556}
3557
3558static uint16_t
3559bwn_pio_idx2base(struct bwn_mac *mac, int index)
3560{
3561	struct bwn_softc *sc = mac->mac_sc;
3562	static const uint16_t bases[] = {
3563		BWN_PIO_BASE0,
3564		BWN_PIO_BASE1,
3565		BWN_PIO_BASE2,
3566		BWN_PIO_BASE3,
3567		BWN_PIO_BASE4,
3568		BWN_PIO_BASE5,
3569		BWN_PIO_BASE6,
3570		BWN_PIO_BASE7,
3571	};
3572	static const uint16_t bases_rev11[] = {
3573		BWN_PIO11_BASE0,
3574		BWN_PIO11_BASE1,
3575		BWN_PIO11_BASE2,
3576		BWN_PIO11_BASE3,
3577		BWN_PIO11_BASE4,
3578		BWN_PIO11_BASE5,
3579	};
3580
3581	if (siba_get_revid(sc->sc_dev) >= 11) {
3582		if (index >= N(bases_rev11))
3583			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3584		return (bases_rev11[index]);
3585	}
3586	if (index >= N(bases))
3587		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3588	return (bases[index]);
3589}
3590
3591static void
3592bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3593    int index)
3594{
3595	struct bwn_softc *sc = mac->mac_sc;
3596
3597	prq->prq_mac = mac;
3598	prq->prq_rev = siba_get_revid(sc->sc_dev);
3599	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3600	bwn_dma_rxdirectfifo(mac, index, 1);
3601}
3602
3603static void
3604bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3605{
3606	if (tq == NULL)
3607		return;
3608	bwn_pio_cancel_tx_packets(tq);
3609}
3610
3611static void
3612bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3613{
3614
3615	bwn_destroy_pioqueue_tx(pio);
3616}
3617
3618static uint16_t
3619bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3620    uint16_t offset)
3621{
3622
3623	return (BWN_READ_2(mac, tq->tq_base + offset));
3624}
3625
3626static void
3627bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3628{
3629	uint32_t ctl;
3630	int type;
3631	uint16_t base;
3632
3633	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3634	base = bwn_dma_base(type, idx);
3635	if (type == BWN_DMA_64BIT) {
3636		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3637		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3638		if (enable)
3639			ctl |= BWN_DMA64_RXDIRECTFIFO;
3640		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3641	} else {
3642		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3643		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3644		if (enable)
3645			ctl |= BWN_DMA32_RXDIRECTFIFO;
3646		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3647	}
3648}
3649
3650static uint64_t
3651bwn_dma_mask(struct bwn_mac *mac)
3652{
3653	uint32_t tmp;
3654	uint16_t base;
3655
3656	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3657	if (tmp & SIBA_TGSHIGH_DMA64)
3658		return (BWN_DMA_BIT_MASK(64));
3659	base = bwn_dma_base(0, 0);
3660	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3661	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3662	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3663		return (BWN_DMA_BIT_MASK(32));
3664
3665	return (BWN_DMA_BIT_MASK(30));
3666}
3667
3668static int
3669bwn_dma_mask2type(uint64_t dmamask)
3670{
3671
3672	if (dmamask == BWN_DMA_BIT_MASK(30))
3673		return (BWN_DMA_30BIT);
3674	if (dmamask == BWN_DMA_BIT_MASK(32))
3675		return (BWN_DMA_32BIT);
3676	if (dmamask == BWN_DMA_BIT_MASK(64))
3677		return (BWN_DMA_64BIT);
3678	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3679	return (BWN_DMA_30BIT);
3680}
3681
3682static void
3683bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3684{
3685	struct bwn_pio_txpkt *tp;
3686	unsigned int i;
3687
3688	for (i = 0; i < N(tq->tq_pkts); i++) {
3689		tp = &(tq->tq_pkts[i]);
3690		if (tp->tp_m) {
3691			m_freem(tp->tp_m);
3692			tp->tp_m = NULL;
3693		}
3694	}
3695}
3696
3697static uint16_t
3698bwn_dma_base(int type, int controller_idx)
3699{
3700	static const uint16_t map64[] = {
3701		BWN_DMA64_BASE0,
3702		BWN_DMA64_BASE1,
3703		BWN_DMA64_BASE2,
3704		BWN_DMA64_BASE3,
3705		BWN_DMA64_BASE4,
3706		BWN_DMA64_BASE5,
3707	};
3708	static const uint16_t map32[] = {
3709		BWN_DMA32_BASE0,
3710		BWN_DMA32_BASE1,
3711		BWN_DMA32_BASE2,
3712		BWN_DMA32_BASE3,
3713		BWN_DMA32_BASE4,
3714		BWN_DMA32_BASE5,
3715	};
3716
3717	if (type == BWN_DMA_64BIT) {
3718		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3719		    ("%s:%d: fail", __func__, __LINE__));
3720		return (map64[controller_idx]);
3721	}
3722	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3723	    ("%s:%d: fail", __func__, __LINE__));
3724	return (map32[controller_idx]);
3725}
3726
3727static void
3728bwn_dma_init(struct bwn_mac *mac)
3729{
3730	struct bwn_dma *dma = &mac->mac_method.dma;
3731
3732	/* setup TX DMA channels. */
3733	bwn_dma_setup(dma->wme[WME_AC_BK]);
3734	bwn_dma_setup(dma->wme[WME_AC_BE]);
3735	bwn_dma_setup(dma->wme[WME_AC_VI]);
3736	bwn_dma_setup(dma->wme[WME_AC_VO]);
3737	bwn_dma_setup(dma->mcast);
3738	/* setup RX DMA channel. */
3739	bwn_dma_setup(dma->rx);
3740}
3741
3742static struct bwn_dma_ring *
3743bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3744    int for_tx, int type)
3745{
3746	struct bwn_dma *dma = &mac->mac_method.dma;
3747	struct bwn_dma_ring *dr;
3748	struct bwn_dmadesc_generic *desc;
3749	struct bwn_dmadesc_meta *mt;
3750	struct bwn_softc *sc = mac->mac_sc;
3751	int error, i;
3752
3753	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3754	if (dr == NULL)
3755		goto out;
3756	dr->dr_numslots = BWN_RXRING_SLOTS;
3757	if (for_tx)
3758		dr->dr_numslots = BWN_TXRING_SLOTS;
3759
3760	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3761	    M_DEVBUF, M_NOWAIT | M_ZERO);
3762	if (dr->dr_meta == NULL)
3763		goto fail0;
3764
3765	dr->dr_type = type;
3766	dr->dr_mac = mac;
3767	dr->dr_base = bwn_dma_base(type, controller_index);
3768	dr->dr_index = controller_index;
3769	if (type == BWN_DMA_64BIT) {
3770		dr->getdesc = bwn_dma_64_getdesc;
3771		dr->setdesc = bwn_dma_64_setdesc;
3772		dr->start_transfer = bwn_dma_64_start_transfer;
3773		dr->suspend = bwn_dma_64_suspend;
3774		dr->resume = bwn_dma_64_resume;
3775		dr->get_curslot = bwn_dma_64_get_curslot;
3776		dr->set_curslot = bwn_dma_64_set_curslot;
3777	} else {
3778		dr->getdesc = bwn_dma_32_getdesc;
3779		dr->setdesc = bwn_dma_32_setdesc;
3780		dr->start_transfer = bwn_dma_32_start_transfer;
3781		dr->suspend = bwn_dma_32_suspend;
3782		dr->resume = bwn_dma_32_resume;
3783		dr->get_curslot = bwn_dma_32_get_curslot;
3784		dr->set_curslot = bwn_dma_32_set_curslot;
3785	}
3786	if (for_tx) {
3787		dr->dr_tx = 1;
3788		dr->dr_curslot = -1;
3789	} else {
3790		if (dr->dr_index == 0) {
3791			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3792			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3793		} else
3794			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3795	}
3796
3797	error = bwn_dma_allocringmemory(dr);
3798	if (error)
3799		goto fail2;
3800
3801	if (for_tx) {
3802		/*
3803		 * Assumption: BWN_TXRING_SLOTS can be divided by
3804		 * BWN_TX_SLOTS_PER_FRAME
3805		 */
3806		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3807		    ("%s:%d: fail", __func__, __LINE__));
3808
3809		dr->dr_txhdr_cache =
3810		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3811			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3812		KASSERT(dr->dr_txhdr_cache != NULL,
3813		    ("%s:%d: fail", __func__, __LINE__));
3814
3815		/*
3816		 * Create TX ring DMA stuffs
3817		 */
3818		error = bus_dma_tag_create(dma->parent_dtag,
3819				    BWN_ALIGN, 0,
3820				    BUS_SPACE_MAXADDR,
3821				    BUS_SPACE_MAXADDR,
3822				    NULL, NULL,
3823				    BWN_HDRSIZE(mac),
3824				    1,
3825				    BUS_SPACE_MAXSIZE_32BIT,
3826				    0,
3827				    NULL, NULL,
3828				    &dr->dr_txring_dtag);
3829		if (error) {
3830			device_printf(sc->sc_dev,
3831			    "can't create TX ring DMA tag: TODO frees\n");
3832			goto fail1;
3833		}
3834
3835		for (i = 0; i < dr->dr_numslots; i += 2) {
3836			dr->getdesc(dr, i, &desc, &mt);
3837
3838			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3839			mt->mt_m = NULL;
3840			mt->mt_ni = NULL;
3841			mt->mt_islast = 0;
3842			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3843			    &mt->mt_dmap);
3844			if (error) {
3845				device_printf(sc->sc_dev,
3846				     "can't create RX buf DMA map\n");
3847				goto fail1;
3848			}
3849
3850			dr->getdesc(dr, i + 1, &desc, &mt);
3851
3852			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3853			mt->mt_m = NULL;
3854			mt->mt_ni = NULL;
3855			mt->mt_islast = 1;
3856			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3857			    &mt->mt_dmap);
3858			if (error) {
3859				device_printf(sc->sc_dev,
3860				     "can't create RX buf DMA map\n");
3861				goto fail1;
3862			}
3863		}
3864	} else {
3865		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3866		    &dr->dr_spare_dmap);
3867		if (error) {
3868			device_printf(sc->sc_dev,
3869			    "can't create RX buf DMA map\n");
3870			goto out;		/* XXX wrong! */
3871		}
3872
3873		for (i = 0; i < dr->dr_numslots; i++) {
3874			dr->getdesc(dr, i, &desc, &mt);
3875
3876			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3877			    &mt->mt_dmap);
3878			if (error) {
3879				device_printf(sc->sc_dev,
3880				    "can't create RX buf DMA map\n");
3881				goto out;	/* XXX wrong! */
3882			}
3883			error = bwn_dma_newbuf(dr, desc, mt, 1);
3884			if (error) {
3885				device_printf(sc->sc_dev,
3886				    "failed to allocate RX buf\n");
3887				goto out;	/* XXX wrong! */
3888			}
3889		}
3890
3891		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3892		    BUS_DMASYNC_PREWRITE);
3893
3894		dr->dr_usedslot = dr->dr_numslots;
3895	}
3896
3897      out:
3898	return (dr);
3899
3900fail2:
3901	free(dr->dr_txhdr_cache, M_DEVBUF);
3902fail1:
3903	free(dr->dr_meta, M_DEVBUF);
3904fail0:
3905	free(dr, M_DEVBUF);
3906	return (NULL);
3907}
3908
3909static void
3910bwn_dma_ringfree(struct bwn_dma_ring **dr)
3911{
3912
3913	if (dr == NULL)
3914		return;
3915
3916	bwn_dma_free_descbufs(*dr);
3917	bwn_dma_free_ringmemory(*dr);
3918
3919	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3920	free((*dr)->dr_meta, M_DEVBUF);
3921	free(*dr, M_DEVBUF);
3922
3923	*dr = NULL;
3924}
3925
3926static void
3927bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3928    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3929{
3930	struct bwn_dmadesc32 *desc;
3931
3932	*meta = &(dr->dr_meta[slot]);
3933	desc = dr->dr_ring_descbase;
3934	desc = &(desc[slot]);
3935
3936	*gdesc = (struct bwn_dmadesc_generic *)desc;
3937}
3938
3939static void
3940bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3941    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3942    int start, int end, int irq)
3943{
3944	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3945	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3946	uint32_t addr, addrext, ctl;
3947	int slot;
3948
3949	slot = (int)(&(desc->dma.dma32) - descbase);
3950	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3951	    ("%s:%d: fail", __func__, __LINE__));
3952
3953	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3954	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3955	addr |= siba_dma_translation(sc->sc_dev);
3956	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3957	if (slot == dr->dr_numslots - 1)
3958		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3959	if (start)
3960		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3961	if (end)
3962		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3963	if (irq)
3964		ctl |= BWN_DMA32_DCTL_IRQ;
3965	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3966	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3967
3968	desc->dma.dma32.control = htole32(ctl);
3969	desc->dma.dma32.address = htole32(addr);
3970}
3971
3972static void
3973bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3974{
3975
3976	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3977	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3978}
3979
3980static void
3981bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3982{
3983
3984	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3985	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3986}
3987
3988static void
3989bwn_dma_32_resume(struct bwn_dma_ring *dr)
3990{
3991
3992	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3993	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3994}
3995
3996static int
3997bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3998{
3999	uint32_t val;
4000
4001	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4002	val &= BWN_DMA32_RXDPTR;
4003
4004	return (val / sizeof(struct bwn_dmadesc32));
4005}
4006
4007static void
4008bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4009{
4010
4011	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4012	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4013}
4014
4015static void
4016bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4017    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4018{
4019	struct bwn_dmadesc64 *desc;
4020
4021	*meta = &(dr->dr_meta[slot]);
4022	desc = dr->dr_ring_descbase;
4023	desc = &(desc[slot]);
4024
4025	*gdesc = (struct bwn_dmadesc_generic *)desc;
4026}
4027
4028static void
4029bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4030    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4031    int start, int end, int irq)
4032{
4033	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4034	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4035	int slot;
4036	uint32_t ctl0 = 0, ctl1 = 0;
4037	uint32_t addrlo, addrhi;
4038	uint32_t addrext;
4039
4040	slot = (int)(&(desc->dma.dma64) - descbase);
4041	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4042	    ("%s:%d: fail", __func__, __LINE__));
4043
4044	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4045	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4046	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4047	    30;
4048	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4049	if (slot == dr->dr_numslots - 1)
4050		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4051	if (start)
4052		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4053	if (end)
4054		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4055	if (irq)
4056		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4057	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4058	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4059	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4060
4061	desc->dma.dma64.control0 = htole32(ctl0);
4062	desc->dma.dma64.control1 = htole32(ctl1);
4063	desc->dma.dma64.address_low = htole32(addrlo);
4064	desc->dma.dma64.address_high = htole32(addrhi);
4065}
4066
4067static void
4068bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4069{
4070
4071	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4072	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4073}
4074
4075static void
4076bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4077{
4078
4079	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4080	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4081}
4082
4083static void
4084bwn_dma_64_resume(struct bwn_dma_ring *dr)
4085{
4086
4087	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4088	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4089}
4090
4091static int
4092bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4093{
4094	uint32_t val;
4095
4096	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4097	val &= BWN_DMA64_RXSTATDPTR;
4098
4099	return (val / sizeof(struct bwn_dmadesc64));
4100}
4101
4102static void
4103bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4104{
4105
4106	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4107	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4108}
4109
4110static int
4111bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4112{
4113	struct bwn_mac *mac = dr->dr_mac;
4114	struct bwn_dma *dma = &mac->mac_method.dma;
4115	struct bwn_softc *sc = mac->mac_sc;
4116	int error;
4117
4118	error = bus_dma_tag_create(dma->parent_dtag,
4119			    BWN_ALIGN, 0,
4120			    BUS_SPACE_MAXADDR,
4121			    BUS_SPACE_MAXADDR,
4122			    NULL, NULL,
4123			    BWN_DMA_RINGMEMSIZE,
4124			    1,
4125			    BUS_SPACE_MAXSIZE_32BIT,
4126			    0,
4127			    NULL, NULL,
4128			    &dr->dr_ring_dtag);
4129	if (error) {
4130		device_printf(sc->sc_dev,
4131		    "can't create TX ring DMA tag: TODO frees\n");
4132		return (-1);
4133	}
4134
4135	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4136	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4137	    &dr->dr_ring_dmap);
4138	if (error) {
4139		device_printf(sc->sc_dev,
4140		    "can't allocate DMA mem: TODO frees\n");
4141		return (-1);
4142	}
4143	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4144	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4145	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4146	if (error) {
4147		device_printf(sc->sc_dev,
4148		    "can't load DMA mem: TODO free\n");
4149		return (-1);
4150	}
4151
4152	return (0);
4153}
4154
4155static void
4156bwn_dma_setup(struct bwn_dma_ring *dr)
4157{
4158	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4159	uint64_t ring64;
4160	uint32_t addrext, ring32, value;
4161	uint32_t trans = siba_dma_translation(sc->sc_dev);
4162
4163	if (dr->dr_tx) {
4164		dr->dr_curslot = -1;
4165
4166		if (dr->dr_type == BWN_DMA_64BIT) {
4167			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4168			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4169			    >> 30;
4170			value = BWN_DMA64_TXENABLE;
4171			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4172			    & BWN_DMA64_TXADDREXT_MASK;
4173			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4174			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4175			    (ring64 & 0xffffffff));
4176			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4177			    ((ring64 >> 32) &
4178			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4179		} else {
4180			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4181			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4182			value = BWN_DMA32_TXENABLE;
4183			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4184			    & BWN_DMA32_TXADDREXT_MASK;
4185			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4186			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4187			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4188		}
4189		return;
4190	}
4191
4192	/*
4193	 * set for RX
4194	 */
4195	dr->dr_usedslot = dr->dr_numslots;
4196
4197	if (dr->dr_type == BWN_DMA_64BIT) {
4198		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4199		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4200		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4201		value |= BWN_DMA64_RXENABLE;
4202		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4203		    & BWN_DMA64_RXADDREXT_MASK;
4204		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4205		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4206		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4207		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4208		    | (trans << 1));
4209		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4210		    sizeof(struct bwn_dmadesc64));
4211	} else {
4212		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4213		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4214		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4215		value |= BWN_DMA32_RXENABLE;
4216		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4217		    & BWN_DMA32_RXADDREXT_MASK;
4218		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4219		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4220		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4221		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4222		    sizeof(struct bwn_dmadesc32));
4223	}
4224}
4225
4226static void
4227bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4228{
4229
4230	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4231	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4232	    dr->dr_ring_dmap);
4233}
4234
4235static void
4236bwn_dma_cleanup(struct bwn_dma_ring *dr)
4237{
4238
4239	if (dr->dr_tx) {
4240		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4241		if (dr->dr_type == BWN_DMA_64BIT) {
4242			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4243			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4244		} else
4245			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4246	} else {
4247		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4248		if (dr->dr_type == BWN_DMA_64BIT) {
4249			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4250			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4251		} else
4252			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4253	}
4254}
4255
4256static void
4257bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4258{
4259	struct bwn_dmadesc_generic *desc;
4260	struct bwn_dmadesc_meta *meta;
4261	struct bwn_mac *mac = dr->dr_mac;
4262	struct bwn_dma *dma = &mac->mac_method.dma;
4263	struct bwn_softc *sc = mac->mac_sc;
4264	int i;
4265
4266	if (!dr->dr_usedslot)
4267		return;
4268	for (i = 0; i < dr->dr_numslots; i++) {
4269		dr->getdesc(dr, i, &desc, &meta);
4270
4271		if (meta->mt_m == NULL) {
4272			if (!dr->dr_tx)
4273				device_printf(sc->sc_dev, "%s: not TX?\n",
4274				    __func__);
4275			continue;
4276		}
4277		if (dr->dr_tx) {
4278			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4279				bus_dmamap_unload(dr->dr_txring_dtag,
4280				    meta->mt_dmap);
4281			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4282				bus_dmamap_unload(dma->txbuf_dtag,
4283				    meta->mt_dmap);
4284		} else
4285			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4286		bwn_dma_free_descbuf(dr, meta);
4287	}
4288}
4289
4290static int
4291bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4292    int type)
4293{
4294	struct bwn_softc *sc = mac->mac_sc;
4295	uint32_t value;
4296	int i;
4297	uint16_t offset;
4298
4299	for (i = 0; i < 10; i++) {
4300		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4301		    BWN_DMA32_TXSTATUS;
4302		value = BWN_READ_4(mac, base + offset);
4303		if (type == BWN_DMA_64BIT) {
4304			value &= BWN_DMA64_TXSTAT;
4305			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4306			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4307			    value == BWN_DMA64_TXSTAT_STOPPED)
4308				break;
4309		} else {
4310			value &= BWN_DMA32_TXSTATE;
4311			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4312			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4313			    value == BWN_DMA32_TXSTAT_STOPPED)
4314				break;
4315		}
4316		DELAY(1000);
4317	}
4318	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4319	BWN_WRITE_4(mac, base + offset, 0);
4320	for (i = 0; i < 10; i++) {
4321		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4322						   BWN_DMA32_TXSTATUS;
4323		value = BWN_READ_4(mac, base + offset);
4324		if (type == BWN_DMA_64BIT) {
4325			value &= BWN_DMA64_TXSTAT;
4326			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4327				i = -1;
4328				break;
4329			}
4330		} else {
4331			value &= BWN_DMA32_TXSTATE;
4332			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4333				i = -1;
4334				break;
4335			}
4336		}
4337		DELAY(1000);
4338	}
4339	if (i != -1) {
4340		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4341		return (ENODEV);
4342	}
4343	DELAY(1000);
4344
4345	return (0);
4346}
4347
4348static int
4349bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4350    int type)
4351{
4352	struct bwn_softc *sc = mac->mac_sc;
4353	uint32_t value;
4354	int i;
4355	uint16_t offset;
4356
4357	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4358	BWN_WRITE_4(mac, base + offset, 0);
4359	for (i = 0; i < 10; i++) {
4360		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4361		    BWN_DMA32_RXSTATUS;
4362		value = BWN_READ_4(mac, base + offset);
4363		if (type == BWN_DMA_64BIT) {
4364			value &= BWN_DMA64_RXSTAT;
4365			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4366				i = -1;
4367				break;
4368			}
4369		} else {
4370			value &= BWN_DMA32_RXSTATE;
4371			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4372				i = -1;
4373				break;
4374			}
4375		}
4376		DELAY(1000);
4377	}
4378	if (i != -1) {
4379		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4380		return (ENODEV);
4381	}
4382
4383	return (0);
4384}
4385
4386static void
4387bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4388    struct bwn_dmadesc_meta *meta)
4389{
4390
4391	if (meta->mt_m != NULL) {
4392		m_freem(meta->mt_m);
4393		meta->mt_m = NULL;
4394	}
4395	if (meta->mt_ni != NULL) {
4396		ieee80211_free_node(meta->mt_ni);
4397		meta->mt_ni = NULL;
4398	}
4399}
4400
4401static void
4402bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4403{
4404	struct bwn_rxhdr4 *rxhdr;
4405	unsigned char *frame;
4406
4407	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4408	rxhdr->frame_len = 0;
4409
4410	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4411	    sizeof(struct bwn_plcp6) + 2,
4412	    ("%s:%d: fail", __func__, __LINE__));
4413	frame = mtod(m, char *) + dr->dr_frameoffset;
4414	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4415}
4416
4417static uint8_t
4418bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4419{
4420	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4421
4422	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4423	    == 0xff);
4424}
4425
4426static void
4427bwn_wme_init(struct bwn_mac *mac)
4428{
4429
4430	bwn_wme_load(mac);
4431
4432	/* enable WME support. */
4433	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4434	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4435	    BWN_IFSCTL_USE_EDCF);
4436}
4437
4438static void
4439bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4440{
4441	struct bwn_softc *sc = mac->mac_sc;
4442	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4443	uint16_t delay;	/* microsec */
4444
4445	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4446	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4447		delay = 500;
4448	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4449		delay = max(delay, (uint16_t)2400);
4450
4451	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4452}
4453
4454static void
4455bwn_bt_enable(struct bwn_mac *mac)
4456{
4457	struct bwn_softc *sc = mac->mac_sc;
4458	uint64_t hf;
4459
4460	if (bwn_bluetooth == 0)
4461		return;
4462	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4463		return;
4464	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4465		return;
4466
4467	hf = bwn_hf_read(mac);
4468	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4469		hf |= BWN_HF_BT_COEXISTALT;
4470	else
4471		hf |= BWN_HF_BT_COEXIST;
4472	bwn_hf_write(mac, hf);
4473}
4474
4475static void
4476bwn_set_macaddr(struct bwn_mac *mac)
4477{
4478
4479	bwn_mac_write_bssid(mac);
4480	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4481}
4482
4483static void
4484bwn_clear_keys(struct bwn_mac *mac)
4485{
4486	int i;
4487
4488	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4489		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4490		    ("%s:%d: fail", __func__, __LINE__));
4491
4492		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4493		    NULL, BWN_SEC_KEYSIZE, NULL);
4494		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4495			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4496			    NULL, BWN_SEC_KEYSIZE, NULL);
4497		}
4498		mac->mac_key[i].keyconf = NULL;
4499	}
4500}
4501
4502static void
4503bwn_crypt_init(struct bwn_mac *mac)
4504{
4505	struct bwn_softc *sc = mac->mac_sc;
4506
4507	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4508	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4509	    ("%s:%d: fail", __func__, __LINE__));
4510	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4511	mac->mac_ktp *= 2;
4512	if (siba_get_revid(sc->sc_dev) >= 5)
4513		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4514	bwn_clear_keys(mac);
4515}
4516
4517static void
4518bwn_chip_exit(struct bwn_mac *mac)
4519{
4520	struct bwn_softc *sc = mac->mac_sc;
4521
4522	bwn_phy_exit(mac);
4523	siba_gpio_set(sc->sc_dev, 0);
4524}
4525
4526static int
4527bwn_fw_fillinfo(struct bwn_mac *mac)
4528{
4529	int error;
4530
4531	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4532	if (error == 0)
4533		return (0);
4534	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4535	if (error == 0)
4536		return (0);
4537	return (error);
4538}
4539
4540static int
4541bwn_gpio_init(struct bwn_mac *mac)
4542{
4543	struct bwn_softc *sc = mac->mac_sc;
4544	uint32_t mask = 0x1f, set = 0xf, value;
4545
4546	BWN_WRITE_4(mac, BWN_MACCTL,
4547	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4548	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4549	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4550
4551	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4552		mask |= 0x0060;
4553		set |= 0x0060;
4554	}
4555	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4556		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4557		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4558		mask |= 0x0200;
4559		set |= 0x0200;
4560	}
4561	if (siba_get_revid(sc->sc_dev) >= 2)
4562		mask |= 0x0010;
4563
4564	value = siba_gpio_get(sc->sc_dev);
4565	if (value == -1)
4566		return (0);
4567	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4568
4569	return (0);
4570}
4571
4572static int
4573bwn_fw_loadinitvals(struct bwn_mac *mac)
4574{
4575#define	GETFWOFFSET(fwp, offset)				\
4576	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4577	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4578	const struct bwn_fwhdr *hdr;
4579	struct bwn_fw *fw = &mac->mac_fw;
4580	int error;
4581
4582	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4583	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4584	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4585	if (error)
4586		return (error);
4587	if (fw->initvals_band.fw) {
4588		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4589		error = bwn_fwinitvals_write(mac,
4590		    GETFWOFFSET(fw->initvals_band, hdr_len),
4591		    be32toh(hdr->size),
4592		    fw->initvals_band.fw->datasize - hdr_len);
4593	}
4594	return (error);
4595#undef GETFWOFFSET
4596}
4597
4598static int
4599bwn_phy_init(struct bwn_mac *mac)
4600{
4601	struct bwn_softc *sc = mac->mac_sc;
4602	int error;
4603
4604	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4605	mac->mac_phy.rf_onoff(mac, 1);
4606	error = mac->mac_phy.init(mac);
4607	if (error) {
4608		device_printf(sc->sc_dev, "PHY init failed\n");
4609		goto fail0;
4610	}
4611	error = bwn_switch_channel(mac,
4612	    mac->mac_phy.get_default_chan(mac));
4613	if (error) {
4614		device_printf(sc->sc_dev,
4615		    "failed to switch default channel\n");
4616		goto fail1;
4617	}
4618	return (0);
4619fail1:
4620	if (mac->mac_phy.exit)
4621		mac->mac_phy.exit(mac);
4622fail0:
4623	mac->mac_phy.rf_onoff(mac, 0);
4624
4625	return (error);
4626}
4627
4628static void
4629bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4630{
4631	uint16_t ant;
4632	uint16_t tmp;
4633
4634	ant = bwn_ant2phy(antenna);
4635
4636	/* For ACK/CTS */
4637	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4638	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4639	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4640	/* For Probe Resposes */
4641	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4642	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4643	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4644}
4645
4646static void
4647bwn_set_opmode(struct bwn_mac *mac)
4648{
4649	struct bwn_softc *sc = mac->mac_sc;
4650	struct ifnet *ifp = sc->sc_ifp;
4651	struct ieee80211com *ic = ifp->if_l2com;
4652	uint32_t ctl;
4653	uint16_t cfp_pretbtt;
4654
4655	ctl = BWN_READ_4(mac, BWN_MACCTL);
4656	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4657	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4658	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4659	ctl |= BWN_MACCTL_STA;
4660
4661	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4662	    ic->ic_opmode == IEEE80211_M_MBSS)
4663		ctl |= BWN_MACCTL_HOSTAP;
4664	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4665		ctl &= ~BWN_MACCTL_STA;
4666	ctl |= sc->sc_filters;
4667
4668	if (siba_get_revid(sc->sc_dev) <= 4)
4669		ctl |= BWN_MACCTL_PROMISC;
4670
4671	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4672
4673	cfp_pretbtt = 2;
4674	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4675		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4676		    siba_get_chiprev(sc->sc_dev) == 3)
4677			cfp_pretbtt = 100;
4678		else
4679			cfp_pretbtt = 50;
4680	}
4681	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4682}
4683
4684static int
4685bwn_dma_gettype(struct bwn_mac *mac)
4686{
4687	uint32_t tmp;
4688	uint16_t base;
4689
4690	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4691	if (tmp & SIBA_TGSHIGH_DMA64)
4692		return (BWN_DMA_64BIT);
4693	base = bwn_dma_base(0, 0);
4694	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4695	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4696	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4697		return (BWN_DMA_32BIT);
4698
4699	return (BWN_DMA_30BIT);
4700}
4701
4702static void
4703bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4704{
4705	if (!error) {
4706		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4707		*((bus_addr_t *)arg) = seg->ds_addr;
4708	}
4709}
4710
4711static void
4712bwn_phy_g_init_sub(struct bwn_mac *mac)
4713{
4714	struct bwn_phy *phy = &mac->mac_phy;
4715	struct bwn_phy_g *pg = &phy->phy_g;
4716	struct bwn_softc *sc = mac->mac_sc;
4717	uint16_t i, tmp;
4718
4719	if (phy->rev == 1)
4720		bwn_phy_init_b5(mac);
4721	else
4722		bwn_phy_init_b6(mac);
4723
4724	if (phy->rev >= 2 || phy->gmode)
4725		bwn_phy_init_a(mac);
4726
4727	if (phy->rev >= 2) {
4728		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4729		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4730	}
4731	if (phy->rev == 2) {
4732		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4733		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4734	}
4735	if (phy->rev > 5) {
4736		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4737		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4738	}
4739	if (phy->gmode || phy->rev >= 2) {
4740		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4741		tmp &= BWN_PHYVER_VERSION;
4742		if (tmp == 3 || tmp == 5) {
4743			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4744			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4745		}
4746		if (tmp == 5) {
4747			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4748			    0x1f00);
4749		}
4750	}
4751	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4752		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4753	if (phy->rf_rev == 8) {
4754		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4755		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4756	}
4757	if (BWN_HAS_LOOPBACK(phy))
4758		bwn_loopback_calcgain(mac);
4759
4760	if (phy->rf_rev != 8) {
4761		if (pg->pg_initval == 0xffff)
4762			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4763		else
4764			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4765	}
4766	bwn_lo_g_init(mac);
4767	if (BWN_HAS_TXMAG(phy)) {
4768		BWN_RF_WRITE(mac, 0x52,
4769		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4770		    | pg->pg_loctl.tx_bias |
4771		    pg->pg_loctl.tx_magn);
4772	} else {
4773		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4774	}
4775	if (phy->rev >= 6) {
4776		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4777		    (pg->pg_loctl.tx_bias << 12));
4778	}
4779	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4780		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4781	else
4782		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4783	if (phy->rev < 2)
4784		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4785	else
4786		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4787	if (phy->gmode || phy->rev >= 2) {
4788		bwn_lo_g_adjust(mac);
4789		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4790	}
4791
4792	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4793		for (i = 0; i < 64; i++) {
4794			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4795			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4796			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4797			    -32), 31));
4798		}
4799		bwn_nrssi_threshold(mac);
4800	} else if (phy->gmode || phy->rev >= 2) {
4801		if (pg->pg_nrssi[0] == -1000) {
4802			KASSERT(pg->pg_nrssi[1] == -1000,
4803			    ("%s:%d: fail", __func__, __LINE__));
4804			bwn_nrssi_slope_11g(mac);
4805		} else
4806			bwn_nrssi_threshold(mac);
4807	}
4808	if (phy->rf_rev == 8)
4809		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4810	bwn_phy_hwpctl_init(mac);
4811	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4812	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4813		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4814		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4815	}
4816}
4817
4818static uint8_t
4819bwn_has_hwpctl(struct bwn_mac *mac)
4820{
4821
4822	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4823		return (0);
4824	return (mac->mac_phy.use_hwpctl(mac));
4825}
4826
4827static void
4828bwn_phy_init_b5(struct bwn_mac *mac)
4829{
4830	struct bwn_phy *phy = &mac->mac_phy;
4831	struct bwn_phy_g *pg = &phy->phy_g;
4832	struct bwn_softc *sc = mac->mac_sc;
4833	uint16_t offset, value;
4834	uint8_t old_channel;
4835
4836	if (phy->analog == 1)
4837		BWN_RF_SET(mac, 0x007a, 0x0050);
4838	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4839	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4840		value = 0x2120;
4841		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4842			BWN_PHY_WRITE(mac, offset, value);
4843			value += 0x202;
4844		}
4845	}
4846	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4847	if (phy->rf_ver == 0x2050)
4848		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4849
4850	if (phy->gmode || phy->rev >= 2) {
4851		if (phy->rf_ver == 0x2050) {
4852			BWN_RF_SET(mac, 0x007a, 0x0020);
4853			BWN_RF_SET(mac, 0x0051, 0x0004);
4854		}
4855		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4856
4857		BWN_PHY_SET(mac, 0x0802, 0x0100);
4858		BWN_PHY_SET(mac, 0x042b, 0x2000);
4859
4860		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4861
4862		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4863		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4864		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4865	}
4866
4867	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4868		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4869
4870	if (phy->analog == 1) {
4871		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4872		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4873		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4874		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4875		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4876	} else
4877		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4878	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4879	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4880
4881	if (phy->analog == 1)
4882		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4883	else
4884		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4885
4886	if (phy->analog == 0)
4887		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4888
4889	old_channel = phy->chan;
4890	bwn_phy_g_switch_chan(mac, 7, 0);
4891
4892	if (phy->rf_ver != 0x2050) {
4893		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4894		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4895	}
4896
4897	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4898	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4899
4900	if (phy->rf_ver == 0x2050) {
4901		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4902		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4903	}
4904
4905	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4906	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4907	BWN_RF_SET(mac, 0x007a, 0x0007);
4908
4909	bwn_phy_g_switch_chan(mac, old_channel, 0);
4910	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4911	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4912	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4913
4914	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4915	    pg->pg_txctl);
4916
4917	if (phy->rf_ver == 0x2050)
4918		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4919
4920	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4921}
4922
4923static void
4924bwn_loopback_calcgain(struct bwn_mac *mac)
4925{
4926	struct bwn_phy *phy = &mac->mac_phy;
4927	struct bwn_phy_g *pg = &phy->phy_g;
4928	struct bwn_softc *sc = mac->mac_sc;
4929	uint16_t backup_phy[16] = { 0 };
4930	uint16_t backup_radio[3];
4931	uint16_t backup_bband;
4932	uint16_t i, j, loop_i_max;
4933	uint16_t trsw_rx;
4934	uint16_t loop1_outer_done, loop1_inner_done;
4935
4936	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4937	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4938	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4939	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4940	if (phy->rev != 1) {
4941		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4942		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4943	}
4944	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4945	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4946	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4947	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4948	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4949	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4950	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4951	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4952	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4953	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4954	backup_bband = pg->pg_bbatt.att;
4955	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4956	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4957	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4958
4959	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4960	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4961	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4962	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4963	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4964	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4965	if (phy->rev != 1) {
4966		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4967		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4968		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4969		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4970	}
4971	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4972	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4973	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4974	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4975
4976	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4977	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4978	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4979
4980	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4981	if (phy->rev != 1) {
4982		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4983		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4984	}
4985	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4986
4987	if (phy->rf_rev == 8)
4988		BWN_RF_WRITE(mac, 0x43, 0x000f);
4989	else {
4990		BWN_RF_WRITE(mac, 0x52, 0);
4991		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4992	}
4993	bwn_phy_g_set_bbatt(mac, 11);
4994
4995	if (phy->rev >= 3)
4996		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4997	else
4998		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4999	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5000
5001	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5002	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5003
5004	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5005	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5006
5007	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5008		if (phy->rev >= 7) {
5009			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5010			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5011		}
5012	}
5013	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5014
5015	j = 0;
5016	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5017	for (i = 0; i < loop_i_max; i++) {
5018		for (j = 0; j < 16; j++) {
5019			BWN_RF_WRITE(mac, 0x43, i);
5020			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5021			    (j << 8));
5022			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5023			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5024			DELAY(20);
5025			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5026				goto done0;
5027		}
5028	}
5029done0:
5030	loop1_outer_done = i;
5031	loop1_inner_done = j;
5032	if (j >= 8) {
5033		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5034		trsw_rx = 0x1b;
5035		for (j = j - 8; j < 16; j++) {
5036			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5037			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5038			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5039			DELAY(20);
5040			trsw_rx -= 3;
5041			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5042				goto done1;
5043		}
5044	} else
5045		trsw_rx = 0x18;
5046done1:
5047
5048	if (phy->rev != 1) {
5049		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5050		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5051	}
5052	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5053	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5054	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5055	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5056	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5061
5062	bwn_phy_g_set_bbatt(mac, backup_bband);
5063
5064	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5065	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5066	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5067
5068	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5069	DELAY(10);
5070	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5071	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5072	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5073	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5074
5075	pg->pg_max_lb_gain =
5076	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5077	pg->pg_trsw_rx_gain = trsw_rx * 2;
5078}
5079
5080static uint16_t
5081bwn_rf_init_bcm2050(struct bwn_mac *mac)
5082{
5083	struct bwn_phy *phy = &mac->mac_phy;
5084	uint32_t tmp1 = 0, tmp2 = 0;
5085	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5086	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5087	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5088	static const uint8_t rcc_table[] = {
5089		0x02, 0x03, 0x01, 0x0f,
5090		0x06, 0x07, 0x05, 0x0f,
5091		0x0a, 0x0b, 0x09, 0x0f,
5092		0x0e, 0x0f, 0x0d, 0x0f,
5093	};
5094
5095	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5096	    rfoverval = rfover = cck3 = 0;
5097	radio0 = BWN_RF_READ(mac, 0x43);
5098	radio1 = BWN_RF_READ(mac, 0x51);
5099	radio2 = BWN_RF_READ(mac, 0x52);
5100	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5101	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5102	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5103	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5104
5105	if (phy->type == BWN_PHYTYPE_B) {
5106		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5107		reg0 = BWN_READ_2(mac, 0x3ec);
5108
5109		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5110		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5111	} else if (phy->gmode || phy->rev >= 2) {
5112		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5113		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5114		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5115		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5116		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5117		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5118
5119		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5120		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5121		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5122		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5123		if (BWN_HAS_LOOPBACK(phy)) {
5124			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5125			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5126			if (phy->rev >= 3)
5127				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5128			else
5129				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5130			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5131		}
5132
5133		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5134		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5135			BWN_LPD(0, 1, 1)));
5136		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5137		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5138	}
5139	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5140
5141	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5142	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5143	reg1 = BWN_READ_2(mac, 0x3e6);
5144	reg2 = BWN_READ_2(mac, 0x3f4);
5145
5146	if (phy->analog == 0)
5147		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5148	else {
5149		if (phy->analog >= 2)
5150			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5151		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5152		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5153	}
5154
5155	reg = BWN_RF_READ(mac, 0x60);
5156	index = (reg & 0x001e) >> 1;
5157	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5158
5159	if (phy->type == BWN_PHYTYPE_B)
5160		BWN_RF_WRITE(mac, 0x78, 0x26);
5161	if (phy->gmode || phy->rev >= 2) {
5162		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5163		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5164			BWN_LPD(0, 1, 1)));
5165	}
5166	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5167	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5168	if (phy->gmode || phy->rev >= 2) {
5169		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5170		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5171			BWN_LPD(0, 0, 1)));
5172	}
5173	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5174	BWN_RF_SET(mac, 0x51, 0x0004);
5175	if (phy->rf_rev == 8)
5176		BWN_RF_WRITE(mac, 0x43, 0x1f);
5177	else {
5178		BWN_RF_WRITE(mac, 0x52, 0);
5179		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5180	}
5181	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5182
5183	for (i = 0; i < 16; i++) {
5184		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5185		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5186		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5187		if (phy->gmode || phy->rev >= 2) {
5188			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5189			    bwn_rf_2050_rfoverval(mac,
5190				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5191		}
5192		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5193		DELAY(10);
5194		if (phy->gmode || phy->rev >= 2) {
5195			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5196			    bwn_rf_2050_rfoverval(mac,
5197				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5198		}
5199		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5200		DELAY(10);
5201		if (phy->gmode || phy->rev >= 2) {
5202			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5203			    bwn_rf_2050_rfoverval(mac,
5204				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5205		}
5206		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5207		DELAY(20);
5208		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5209		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5210		if (phy->gmode || phy->rev >= 2) {
5211			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5212			    bwn_rf_2050_rfoverval(mac,
5213				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5214		}
5215		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5216	}
5217	DELAY(10);
5218
5219	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5220	tmp1++;
5221	tmp1 >>= 9;
5222
5223	for (i = 0; i < 16; i++) {
5224		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5225		BWN_RF_WRITE(mac, 0x78, radio78);
5226		DELAY(10);
5227		for (j = 0; j < 16; j++) {
5228			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5229			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5230			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5231			if (phy->gmode || phy->rev >= 2) {
5232				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5233				    bwn_rf_2050_rfoverval(mac,
5234					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5235			}
5236			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5237			DELAY(10);
5238			if (phy->gmode || phy->rev >= 2) {
5239				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5240				    bwn_rf_2050_rfoverval(mac,
5241					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5242			}
5243			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5244			DELAY(10);
5245			if (phy->gmode || phy->rev >= 2) {
5246				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5247				    bwn_rf_2050_rfoverval(mac,
5248					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5249			}
5250			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5251			DELAY(10);
5252			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5253			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5254			if (phy->gmode || phy->rev >= 2) {
5255				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5256				    bwn_rf_2050_rfoverval(mac,
5257					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5258			}
5259			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5260		}
5261		tmp2++;
5262		tmp2 >>= 8;
5263		if (tmp1 < tmp2)
5264			break;
5265	}
5266
5267	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5268	BWN_RF_WRITE(mac, 0x51, radio1);
5269	BWN_RF_WRITE(mac, 0x52, radio2);
5270	BWN_RF_WRITE(mac, 0x43, radio0);
5271	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5272	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5273	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5274	BWN_WRITE_2(mac, 0x3e6, reg1);
5275	if (phy->analog != 0)
5276		BWN_WRITE_2(mac, 0x3f4, reg2);
5277	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5278	bwn_spu_workaround(mac, phy->chan);
5279	if (phy->type == BWN_PHYTYPE_B) {
5280		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5281		BWN_WRITE_2(mac, 0x3ec, reg0);
5282	} else if (phy->gmode) {
5283		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5284			    BWN_READ_2(mac, BWN_PHY_RADIO)
5285			    & 0x7fff);
5286		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5287		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5288		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5289		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5290			      analogoverval);
5291		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5292		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5293		if (BWN_HAS_LOOPBACK(phy)) {
5294			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5295			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5296		}
5297	}
5298
5299	return ((i > 15) ? radio78 : rcc);
5300}
5301
5302static void
5303bwn_phy_init_b6(struct bwn_mac *mac)
5304{
5305	struct bwn_phy *phy = &mac->mac_phy;
5306	struct bwn_phy_g *pg = &phy->phy_g;
5307	struct bwn_softc *sc = mac->mac_sc;
5308	uint16_t offset, val;
5309	uint8_t old_channel;
5310
5311	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5312	    ("%s:%d: fail", __func__, __LINE__));
5313
5314	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5315	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5316	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5317		BWN_RF_WRITE(mac, 0x51, 0x37);
5318		BWN_RF_WRITE(mac, 0x52, 0x70);
5319		BWN_RF_WRITE(mac, 0x53, 0xb3);
5320		BWN_RF_WRITE(mac, 0x54, 0x9b);
5321		BWN_RF_WRITE(mac, 0x5a, 0x88);
5322		BWN_RF_WRITE(mac, 0x5b, 0x88);
5323		BWN_RF_WRITE(mac, 0x5d, 0x88);
5324		BWN_RF_WRITE(mac, 0x5e, 0x88);
5325		BWN_RF_WRITE(mac, 0x7d, 0x88);
5326		bwn_hf_write(mac,
5327		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5328	}
5329	if (phy->rf_rev == 8) {
5330		BWN_RF_WRITE(mac, 0x51, 0);
5331		BWN_RF_WRITE(mac, 0x52, 0x40);
5332		BWN_RF_WRITE(mac, 0x53, 0xb7);
5333		BWN_RF_WRITE(mac, 0x54, 0x98);
5334		BWN_RF_WRITE(mac, 0x5a, 0x88);
5335		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5336		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5337		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5338			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5339			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5340		} else {
5341			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5342			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5343		}
5344		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5345		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5346		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5347		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5348	}
5349	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5350		BWN_PHY_WRITE(mac, offset, val);
5351		val -= 0x0202;
5352	}
5353	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5354		BWN_PHY_WRITE(mac, offset, val);
5355		val -= 0x0202;
5356	}
5357	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5358		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5359		val += 0x0202;
5360	}
5361	if (phy->type == BWN_PHYTYPE_G) {
5362		BWN_RF_SET(mac, 0x007a, 0x0020);
5363		BWN_RF_SET(mac, 0x0051, 0x0004);
5364		BWN_PHY_SET(mac, 0x0802, 0x0100);
5365		BWN_PHY_SET(mac, 0x042b, 0x2000);
5366		BWN_PHY_WRITE(mac, 0x5b, 0);
5367		BWN_PHY_WRITE(mac, 0x5c, 0);
5368	}
5369
5370	old_channel = phy->chan;
5371	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5372
5373	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5374	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5375	DELAY(40);
5376	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5377		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5378		BWN_RF_WRITE(mac, 0x50, 0x20);
5379	}
5380	if (phy->rf_rev <= 2) {
5381		BWN_RF_WRITE(mac, 0x7c, 0x20);
5382		BWN_RF_WRITE(mac, 0x5a, 0x70);
5383		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5384		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5385	}
5386	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5387
5388	bwn_phy_g_switch_chan(mac, old_channel, 0);
5389
5390	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5391	if (phy->rf_rev >= 6)
5392		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5393	else
5394		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5395	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5396	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5397	    pg->pg_txctl);
5398	if (phy->rf_rev <= 5)
5399		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5400	if (phy->rf_rev <= 2)
5401		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5402
5403	if (phy->analog == 4) {
5404		BWN_WRITE_2(mac, 0x3e4, 9);
5405		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5406	} else
5407		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5408	if (phy->type == BWN_PHYTYPE_B)
5409		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5410	else if (phy->type == BWN_PHYTYPE_G)
5411		BWN_WRITE_2(mac, 0x03e6, 0x0);
5412}
5413
5414static void
5415bwn_phy_init_a(struct bwn_mac *mac)
5416{
5417	struct bwn_phy *phy = &mac->mac_phy;
5418	struct bwn_softc *sc = mac->mac_sc;
5419
5420	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5421	    ("%s:%d: fail", __func__, __LINE__));
5422
5423	if (phy->rev >= 6) {
5424		if (phy->type == BWN_PHYTYPE_A)
5425			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5426		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5427			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5428		else
5429			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5430	}
5431
5432	bwn_wa_init(mac);
5433
5434	if (phy->type == BWN_PHYTYPE_G &&
5435	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5436		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5437}
5438
5439static void
5440bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5441{
5442	int i;
5443
5444	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5445		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5446}
5447
5448static void
5449bwn_wa_agc(struct bwn_mac *mac)
5450{
5451	struct bwn_phy *phy = &mac->mac_phy;
5452
5453	if (phy->rev == 1) {
5454		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5455		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5456		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5457		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5462		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5463	} else {
5464		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5465		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5466		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5467		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5468	}
5469
5470	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5471	    0x5700);
5472	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5473	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5474	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5475	BWN_RF_SET(mac, 0x7a, 0x0008);
5476	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5478	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5479	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5480	if (phy->rev == 1)
5481		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5482	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5483	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5484	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5485	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5491	if (phy->rev == 1) {
5492		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5493		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5494	} else {
5495		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5496		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5497		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5498		if (phy->rev >= 6) {
5499			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5500			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5501			    (uint16_t)~0xf000, 0x3000);
5502		}
5503	}
5504	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5505	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5506	if (phy->rev == 1) {
5507		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5508		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5509		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5510		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5511		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5512		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5513		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5515	} else {
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5520	}
5521	if (phy->rev >= 6) {
5522		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5523		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5524	}
5525	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5526}
5527
5528static void
5529bwn_wa_grev1(struct bwn_mac *mac)
5530{
5531	struct bwn_phy *phy = &mac->mac_phy;
5532	int i;
5533	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5534	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5535	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5536
5537	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5538
5539	/* init CRSTHRES and ANTDWELL */
5540	if (phy->rev == 1) {
5541		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5542	} else if (phy->rev == 2) {
5543		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5544		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5545		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5546	} else {
5547		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5548		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5549		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5550		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5551	}
5552	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5553	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5554	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5555
5556	/* XXX support PHY-A??? */
5557	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5558		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5559		    bwn_tab_finefreqg[i]);
5560
5561	/* XXX support PHY-A??? */
5562	if (phy->rev == 1)
5563		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5564			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5565			    bwn_tab_noise_g1[i]);
5566	else
5567		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5568			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5569			    bwn_tab_noise_g2[i]);
5570
5571
5572	for (i = 0; i < N(bwn_tab_rotor); i++)
5573		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5574		    bwn_tab_rotor[i]);
5575
5576	/* XXX support PHY-A??? */
5577	if (phy->rev >= 6) {
5578		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5579		    BWN_PHY_ENCORE_EN)
5580			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5581		else
5582			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5583	} else
5584		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5585
5586	for (i = 0; i < N(bwn_tab_retard); i++)
5587		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5588		    bwn_tab_retard[i]);
5589
5590	if (phy->rev == 1) {
5591		for (i = 0; i < 16; i++)
5592			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5593			    i, 0x0020);
5594	} else {
5595		for (i = 0; i < 32; i++)
5596			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5597	}
5598
5599	bwn_wa_agc(mac);
5600}
5601
5602static void
5603bwn_wa_grev26789(struct bwn_mac *mac)
5604{
5605	struct bwn_phy *phy = &mac->mac_phy;
5606	int i;
5607	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5608	uint16_t ofdmrev;
5609
5610	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5611
5612	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5613
5614	/* init CRSTHRES and ANTDWELL */
5615	if (phy->rev == 1)
5616		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5617	else if (phy->rev == 2) {
5618		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5619		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5620		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5621	} else {
5622		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5623		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5624		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5625		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5626	}
5627
5628	for (i = 0; i < 64; i++)
5629		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5630
5631	/* XXX support PHY-A??? */
5632	if (phy->rev == 1)
5633		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5634			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5635			    bwn_tab_noise_g1[i]);
5636	else
5637		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5638			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5639			    bwn_tab_noise_g2[i]);
5640
5641	/* XXX support PHY-A??? */
5642	if (phy->rev >= 6) {
5643		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5644		    BWN_PHY_ENCORE_EN)
5645			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5646		else
5647			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5648	} else
5649		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5650
5651	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5652		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5653		    bwn_tab_sigmasqr2[i]);
5654
5655	if (phy->rev == 1) {
5656		for (i = 0; i < 16; i++)
5657			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5658			    0x0020);
5659	} else {
5660		for (i = 0; i < 32; i++)
5661			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5662	}
5663
5664	bwn_wa_agc(mac);
5665
5666	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5667	if (ofdmrev > 2) {
5668		if (phy->type == BWN_PHYTYPE_A)
5669			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5670		else
5671			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5672	} else {
5673		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5674		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5675		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5676	}
5677
5678	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5679	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5680}
5681
5682static void
5683bwn_wa_init(struct bwn_mac *mac)
5684{
5685	struct bwn_phy *phy = &mac->mac_phy;
5686	struct bwn_softc *sc = mac->mac_sc;
5687
5688	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5689
5690	switch (phy->rev) {
5691	case 1:
5692		bwn_wa_grev1(mac);
5693		break;
5694	case 2:
5695	case 6:
5696	case 7:
5697	case 8:
5698	case 9:
5699		bwn_wa_grev26789(mac);
5700		break;
5701	default:
5702		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5703	}
5704
5705	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5706	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5707	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5708		if (phy->rev < 2) {
5709			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5710			    0x0002);
5711			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5712			    0x0001);
5713		} else {
5714			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5715			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5716			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5717			     BWN_BFL_EXTLNA) &&
5718			    (phy->rev >= 7)) {
5719				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5720				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5721				    0x0020, 0x0001);
5722				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723				    0x0021, 0x0001);
5724				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725				    0x0022, 0x0001);
5726				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727				    0x0023, 0x0000);
5728				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729				    0x0000, 0x0000);
5730				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5731				    0x0003, 0x0002);
5732			}
5733		}
5734	}
5735	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5736		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5737		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5738	}
5739
5740	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5741	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5742}
5743
5744static void
5745bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5746    uint16_t value)
5747{
5748	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5749	uint16_t addr;
5750
5751	addr = table + offset;
5752	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5753	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5754		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5755		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5756	}
5757	pg->pg_ofdmtab_addr = addr;
5758	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5759}
5760
5761static void
5762bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5763    uint32_t value)
5764{
5765	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5766	uint16_t addr;
5767
5768	addr = table + offset;
5769	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5770	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5771		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5772		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5773	}
5774	pg->pg_ofdmtab_addr = addr;
5775
5776	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5777	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5778}
5779
5780static void
5781bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5782    uint16_t value)
5783{
5784
5785	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5786	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5787}
5788
5789static void
5790bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5791{
5792	struct bwn_phy *phy = &mac->mac_phy;
5793	struct bwn_softc *sc = mac->mac_sc;
5794	unsigned int i, max_loop;
5795	uint16_t value;
5796	uint32_t buffer[5] = {
5797		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5798	};
5799
5800	if (ofdm) {
5801		max_loop = 0x1e;
5802		buffer[0] = 0x000201cc;
5803	} else {
5804		max_loop = 0xfa;
5805		buffer[0] = 0x000b846e;
5806	}
5807
5808	BWN_ASSERT_LOCKED(mac->mac_sc);
5809
5810	for (i = 0; i < 5; i++)
5811		bwn_ram_write(mac, i * 4, buffer[i]);
5812
5813	BWN_WRITE_2(mac, 0x0568, 0x0000);
5814	BWN_WRITE_2(mac, 0x07c0,
5815	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5816	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5817	BWN_WRITE_2(mac, 0x050c, value);
5818	if (phy->type == BWN_PHYTYPE_LP)
5819		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5820	BWN_WRITE_2(mac, 0x0508, 0x0000);
5821	BWN_WRITE_2(mac, 0x050a, 0x0000);
5822	BWN_WRITE_2(mac, 0x054c, 0x0000);
5823	BWN_WRITE_2(mac, 0x056a, 0x0014);
5824	BWN_WRITE_2(mac, 0x0568, 0x0826);
5825	BWN_WRITE_2(mac, 0x0500, 0x0000);
5826	if (phy->type == BWN_PHYTYPE_LP)
5827		BWN_WRITE_2(mac, 0x0502, 0x0050);
5828	else
5829		BWN_WRITE_2(mac, 0x0502, 0x0030);
5830
5831	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5832		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5833	for (i = 0x00; i < max_loop; i++) {
5834		value = BWN_READ_2(mac, 0x050e);
5835		if (value & 0x0080)
5836			break;
5837		DELAY(10);
5838	}
5839	for (i = 0x00; i < 0x0a; i++) {
5840		value = BWN_READ_2(mac, 0x050e);
5841		if (value & 0x0400)
5842			break;
5843		DELAY(10);
5844	}
5845	for (i = 0x00; i < 0x19; i++) {
5846		value = BWN_READ_2(mac, 0x0690);
5847		if (!(value & 0x0100))
5848			break;
5849		DELAY(10);
5850	}
5851	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5852		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5853}
5854
5855static void
5856bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5857{
5858	uint32_t macctl;
5859
5860	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5861
5862	macctl = BWN_READ_4(mac, BWN_MACCTL);
5863	if (macctl & BWN_MACCTL_BIGENDIAN)
5864		printf("TODO: need swap\n");
5865
5866	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5867	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5868	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5869}
5870
5871static void
5872bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5873{
5874	uint16_t value;
5875
5876	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5877	    ("%s:%d: fail", __func__, __LINE__));
5878
5879	value = (uint8_t) (ctl->q);
5880	value |= ((uint8_t) (ctl->i)) << 8;
5881	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5882}
5883
5884static uint16_t
5885bwn_lo_calcfeed(struct bwn_mac *mac,
5886    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5887{
5888	struct bwn_phy *phy = &mac->mac_phy;
5889	struct bwn_softc *sc = mac->mac_sc;
5890	uint16_t rfover;
5891	uint16_t feedthrough;
5892
5893	if (phy->gmode) {
5894		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5895		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5896
5897		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5898		    ("%s:%d: fail", __func__, __LINE__));
5899		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5900		    ("%s:%d: fail", __func__, __LINE__));
5901
5902		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5903
5904		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5905		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5906		    phy->rev > 6)
5907			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5908
5909		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5910		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5911		DELAY(10);
5912		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5913		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5914		DELAY(10);
5915		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5916		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5917		DELAY(10);
5918		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5919	} else {
5920		pga |= BWN_PHY_PGACTL_UNKNOWN;
5921		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5922		DELAY(10);
5923		pga |= BWN_PHY_PGACTL_LOWBANDW;
5924		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5925		DELAY(10);
5926		pga |= BWN_PHY_PGACTL_LPF;
5927		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5928	}
5929	DELAY(21);
5930	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5931
5932	return (feedthrough);
5933}
5934
5935static uint16_t
5936bwn_lo_txctl_regtable(struct bwn_mac *mac,
5937    uint16_t *value, uint16_t *pad_mix_gain)
5938{
5939	struct bwn_phy *phy = &mac->mac_phy;
5940	uint16_t reg, v, padmix;
5941
5942	if (phy->type == BWN_PHYTYPE_B) {
5943		v = 0x30;
5944		if (phy->rf_rev <= 5) {
5945			reg = 0x43;
5946			padmix = 0;
5947		} else {
5948			reg = 0x52;
5949			padmix = 5;
5950		}
5951	} else {
5952		if (phy->rev >= 2 && phy->rf_rev == 8) {
5953			reg = 0x43;
5954			v = 0x10;
5955			padmix = 2;
5956		} else {
5957			reg = 0x52;
5958			v = 0x30;
5959			padmix = 5;
5960		}
5961	}
5962	if (value)
5963		*value = v;
5964	if (pad_mix_gain)
5965		*pad_mix_gain = padmix;
5966
5967	return (reg);
5968}
5969
5970static void
5971bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5972{
5973	struct bwn_phy *phy = &mac->mac_phy;
5974	struct bwn_phy_g *pg = &phy->phy_g;
5975	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5976	uint16_t reg, mask;
5977	uint16_t trsw_rx, pga;
5978	uint16_t rf_pctl_reg;
5979
5980	static const uint8_t tx_bias_values[] = {
5981		0x09, 0x08, 0x0a, 0x01, 0x00,
5982		0x02, 0x05, 0x04, 0x06,
5983	};
5984	static const uint8_t tx_magn_values[] = {
5985		0x70, 0x40,
5986	};
5987
5988	if (!BWN_HAS_LOOPBACK(phy)) {
5989		rf_pctl_reg = 6;
5990		trsw_rx = 2;
5991		pga = 0;
5992	} else {
5993		int lb_gain;
5994
5995		trsw_rx = 0;
5996		lb_gain = pg->pg_max_lb_gain / 2;
5997		if (lb_gain > 10) {
5998			rf_pctl_reg = 0;
5999			pga = abs(10 - lb_gain) / 6;
6000			pga = MIN(MAX(pga, 0), 15);
6001		} else {
6002			int cmp_val;
6003			int tmp;
6004
6005			pga = 0;
6006			cmp_val = 0x24;
6007			if ((phy->rev >= 2) &&
6008			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6009				cmp_val = 0x3c;
6010			tmp = lb_gain;
6011			if ((10 - lb_gain) < cmp_val)
6012				tmp = (10 - lb_gain);
6013			if (tmp < 0)
6014				tmp += 6;
6015			else
6016				tmp += 3;
6017			cmp_val /= 4;
6018			tmp /= 4;
6019			if (tmp >= cmp_val)
6020				rf_pctl_reg = cmp_val;
6021			else
6022				rf_pctl_reg = tmp;
6023		}
6024	}
6025	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6026	bwn_phy_g_set_bbatt(mac, 2);
6027
6028	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6029	mask = ~mask;
6030	BWN_RF_MASK(mac, reg, mask);
6031
6032	if (BWN_HAS_TXMAG(phy)) {
6033		int i, j;
6034		int feedthrough;
6035		int min_feedth = 0xffff;
6036		uint8_t tx_magn, tx_bias;
6037
6038		for (i = 0; i < N(tx_magn_values); i++) {
6039			tx_magn = tx_magn_values[i];
6040			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6041			for (j = 0; j < N(tx_bias_values); j++) {
6042				tx_bias = tx_bias_values[j];
6043				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6044				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6045				    trsw_rx);
6046				if (feedthrough < min_feedth) {
6047					lo->tx_bias = tx_bias;
6048					lo->tx_magn = tx_magn;
6049					min_feedth = feedthrough;
6050				}
6051				if (lo->tx_bias == 0)
6052					break;
6053			}
6054			BWN_RF_WRITE(mac, 0x52,
6055					  (BWN_RF_READ(mac, 0x52)
6056					   & 0xff00) | lo->tx_bias | lo->
6057					  tx_magn);
6058		}
6059	} else {
6060		lo->tx_magn = 0;
6061		lo->tx_bias = 0;
6062		BWN_RF_MASK(mac, 0x52, 0xfff0);
6063	}
6064
6065	BWN_GETTIME(lo->txctl_measured_time);
6066}
6067
6068static void
6069bwn_lo_get_powervector(struct bwn_mac *mac)
6070{
6071	struct bwn_phy *phy = &mac->mac_phy;
6072	struct bwn_phy_g *pg = &phy->phy_g;
6073	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6074	int i;
6075	uint64_t tmp;
6076	uint64_t power_vector = 0;
6077
6078	for (i = 0; i < 8; i += 2) {
6079		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6080		power_vector |= (tmp << (i * 8));
6081		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6082	}
6083	if (power_vector)
6084		lo->power_vector = power_vector;
6085
6086	BWN_GETTIME(lo->pwr_vec_read_time);
6087}
6088
6089static void
6090bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6091    int use_trsw_rx)
6092{
6093	struct bwn_phy *phy = &mac->mac_phy;
6094	struct bwn_phy_g *pg = &phy->phy_g;
6095	uint16_t tmp;
6096
6097	if (max_rx_gain < 0)
6098		max_rx_gain = 0;
6099
6100	if (BWN_HAS_LOOPBACK(phy)) {
6101		int trsw_rx = 0;
6102		int trsw_rx_gain;
6103
6104		if (use_trsw_rx) {
6105			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6106			if (max_rx_gain >= trsw_rx_gain) {
6107				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6108				trsw_rx = 0x20;
6109			}
6110		} else
6111			trsw_rx_gain = max_rx_gain;
6112		if (trsw_rx_gain < 9) {
6113			pg->pg_lna_lod_gain = 0;
6114		} else {
6115			pg->pg_lna_lod_gain = 1;
6116			trsw_rx_gain -= 8;
6117		}
6118		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6119		pg->pg_pga_gain = trsw_rx_gain / 3;
6120		if (pg->pg_pga_gain >= 5) {
6121			pg->pg_pga_gain -= 5;
6122			pg->pg_lna_gain = 2;
6123		} else
6124			pg->pg_lna_gain = 0;
6125	} else {
6126		pg->pg_lna_gain = 0;
6127		pg->pg_trsw_rx_gain = 0x20;
6128		if (max_rx_gain >= 0x14) {
6129			pg->pg_lna_lod_gain = 1;
6130			pg->pg_pga_gain = 2;
6131		} else if (max_rx_gain >= 0x12) {
6132			pg->pg_lna_lod_gain = 1;
6133			pg->pg_pga_gain = 1;
6134		} else if (max_rx_gain >= 0xf) {
6135			pg->pg_lna_lod_gain = 1;
6136			pg->pg_pga_gain = 0;
6137		} else {
6138			pg->pg_lna_lod_gain = 0;
6139			pg->pg_pga_gain = 0;
6140		}
6141	}
6142
6143	tmp = BWN_RF_READ(mac, 0x7a);
6144	if (pg->pg_lna_lod_gain == 0)
6145		tmp &= ~0x0008;
6146	else
6147		tmp |= 0x0008;
6148	BWN_RF_WRITE(mac, 0x7a, tmp);
6149}
6150
6151static void
6152bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6153{
6154	struct bwn_phy *phy = &mac->mac_phy;
6155	struct bwn_phy_g *pg = &phy->phy_g;
6156	struct bwn_softc *sc = mac->mac_sc;
6157	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6158	struct timespec ts;
6159	uint16_t tmp;
6160
6161	if (bwn_has_hwpctl(mac)) {
6162		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6163		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6164		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6165		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6166		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6167
6168		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6169		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6170		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6171		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6172	}
6173	if (phy->type == BWN_PHYTYPE_B &&
6174	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6175		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6176		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6177	}
6178	if (phy->rev >= 2) {
6179		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6180		sav->phy_analogoverval =
6181		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6182		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6183		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6184		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6185		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6186		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6187
6188		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6189		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6190		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6191		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6192		if (phy->type == BWN_PHYTYPE_G) {
6193			if ((phy->rev >= 7) &&
6194			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6195			     BWN_BFL_EXTLNA)) {
6196				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6197			} else {
6198				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6199			}
6200		} else {
6201			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6202		}
6203		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6204	}
6205	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6206	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6207	sav->rf0 = BWN_RF_READ(mac, 0x43);
6208	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6209	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6210	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6211	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6212	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6213
6214	if (!BWN_HAS_TXMAG(phy)) {
6215		sav->rf2 = BWN_RF_READ(mac, 0x52);
6216		sav->rf2 &= 0x00f0;
6217	}
6218	if (phy->type == BWN_PHYTYPE_B) {
6219		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6220		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6221		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6222		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6223	} else {
6224		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6225			    | 0x8000);
6226	}
6227	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6228		    & 0xf000);
6229
6230	tmp =
6231	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6232	BWN_PHY_WRITE(mac, tmp, 0x007f);
6233
6234	tmp = sav->phy_syncctl;
6235	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6236	tmp = sav->rf1;
6237	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6238
6239	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6240	if (phy->type == BWN_PHYTYPE_G ||
6241	    (phy->type == BWN_PHYTYPE_B &&
6242	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6243		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6244	} else
6245		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6246	if (phy->rev >= 2)
6247		bwn_dummy_transmission(mac, 0, 1);
6248	bwn_phy_g_switch_chan(mac, 6, 0);
6249	BWN_RF_READ(mac, 0x51);
6250	if (phy->type == BWN_PHYTYPE_G)
6251		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6252
6253	nanouptime(&ts);
6254	if (time_before(lo->txctl_measured_time,
6255	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6256		bwn_lo_measure_txctl_values(mac);
6257
6258	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6259		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6260	else {
6261		if (phy->type == BWN_PHYTYPE_B)
6262			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6263		else
6264			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6265	}
6266}
6267
6268static void
6269bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6270{
6271	struct bwn_phy *phy = &mac->mac_phy;
6272	struct bwn_phy_g *pg = &phy->phy_g;
6273	uint16_t tmp;
6274
6275	if (phy->rev >= 2) {
6276		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6277		tmp = (pg->pg_pga_gain << 8);
6278		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6279		DELAY(5);
6280		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6281		DELAY(2);
6282		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6283	} else {
6284		tmp = (pg->pg_pga_gain | 0xefa0);
6285		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6286	}
6287	if (phy->type == BWN_PHYTYPE_G) {
6288		if (phy->rev >= 3)
6289			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6290		else
6291			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6292		if (phy->rev >= 2)
6293			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6294		else
6295			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6296	}
6297	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6298	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6299	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6300	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6301	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6302	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6303	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6304	if (!BWN_HAS_TXMAG(phy)) {
6305		tmp = sav->rf2;
6306		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6307	}
6308	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6309	if (phy->type == BWN_PHYTYPE_B &&
6310	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6311		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6312		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6313	}
6314	if (phy->rev >= 2) {
6315		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6316		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6317			      sav->phy_analogoverval);
6318		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6319		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6320		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6321		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6322		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6323	}
6324	if (bwn_has_hwpctl(mac)) {
6325		tmp = (sav->phy_lomask & 0xbfff);
6326		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6327		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6328		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6329		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6330		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6331	}
6332	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6333}
6334
6335static int
6336bwn_lo_probe_loctl(struct bwn_mac *mac,
6337    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6338{
6339	struct bwn_phy *phy = &mac->mac_phy;
6340	struct bwn_phy_g *pg = &phy->phy_g;
6341	struct bwn_loctl orig, test;
6342	struct bwn_loctl prev = { -100, -100 };
6343	static const struct bwn_loctl modifiers[] = {
6344		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6345		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6346	};
6347	int begin, end, lower = 0, i;
6348	uint16_t feedth;
6349
6350	if (d->curstate == 0) {
6351		begin = 1;
6352		end = 8;
6353	} else if (d->curstate % 2 == 0) {
6354		begin = d->curstate - 1;
6355		end = d->curstate + 1;
6356	} else {
6357		begin = d->curstate - 2;
6358		end = d->curstate + 2;
6359	}
6360	if (begin < 1)
6361		begin += 8;
6362	if (end > 8)
6363		end -= 8;
6364
6365	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6366	i = begin;
6367	d->curstate = i;
6368	while (1) {
6369		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6370		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6371		test.i += modifiers[i - 1].i * d->multipler;
6372		test.q += modifiers[i - 1].q * d->multipler;
6373		if ((test.i != prev.i || test.q != prev.q) &&
6374		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6375			bwn_lo_write(mac, &test);
6376			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6377			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6378			if (feedth < d->feedth) {
6379				memcpy(probe, &test,
6380				    sizeof(struct bwn_loctl));
6381				lower = 1;
6382				d->feedth = feedth;
6383				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6384					break;
6385			}
6386		}
6387		memcpy(&prev, &test, sizeof(prev));
6388		if (i == end)
6389			break;
6390		if (i == 8)
6391			i = 1;
6392		else
6393			i++;
6394		d->curstate = i;
6395	}
6396
6397	return (lower);
6398}
6399
6400static void
6401bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6402{
6403	struct bwn_phy *phy = &mac->mac_phy;
6404	struct bwn_phy_g *pg = &phy->phy_g;
6405	struct bwn_lo_g_sm d;
6406	struct bwn_loctl probe;
6407	int lower, repeat, cnt = 0;
6408	uint16_t feedth;
6409
6410	d.nmeasure = 0;
6411	d.multipler = 1;
6412	if (BWN_HAS_LOOPBACK(phy))
6413		d.multipler = 3;
6414
6415	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6416	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6417
6418	do {
6419		bwn_lo_write(mac, &d.loctl);
6420		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6421		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6422		if (feedth < 0x258) {
6423			if (feedth >= 0x12c)
6424				*rxgain += 6;
6425			else
6426				*rxgain += 3;
6427			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6428			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6429		}
6430		d.feedth = feedth;
6431		d.curstate = 0;
6432		do {
6433			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6434			    ("%s:%d: fail", __func__, __LINE__));
6435			memcpy(&probe, &d.loctl,
6436			       sizeof(struct bwn_loctl));
6437			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6438			if (!lower)
6439				break;
6440			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6441				break;
6442			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6443			d.nmeasure++;
6444		} while (d.nmeasure < 24);
6445		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6446
6447		if (BWN_HAS_LOOPBACK(phy)) {
6448			if (d.feedth > 0x1194)
6449				*rxgain -= 6;
6450			else if (d.feedth < 0x5dc)
6451				*rxgain += 3;
6452			if (cnt == 0) {
6453				if (d.feedth <= 0x5dc) {
6454					d.multipler = 1;
6455					cnt++;
6456				} else
6457					d.multipler = 2;
6458			} else if (cnt == 2)
6459				d.multipler = 1;
6460		}
6461		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6462	} while (++cnt < repeat);
6463}
6464
6465static struct bwn_lo_calib *
6466bwn_lo_calibset(struct bwn_mac *mac,
6467    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6468{
6469	struct bwn_phy *phy = &mac->mac_phy;
6470	struct bwn_phy_g *pg = &phy->phy_g;
6471	struct bwn_loctl loctl = { 0, 0 };
6472	struct bwn_lo_calib *cal;
6473	struct bwn_lo_g_value sval = { 0 };
6474	int rxgain;
6475	uint16_t pad, reg, value;
6476
6477	sval.old_channel = phy->chan;
6478	bwn_mac_suspend(mac);
6479	bwn_lo_save(mac, &sval);
6480
6481	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6482	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6483	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6484
6485	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6486	if (rfatt->padmix)
6487		rxgain -= pad;
6488	if (BWN_HAS_LOOPBACK(phy))
6489		rxgain += pg->pg_max_lb_gain;
6490	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6491	bwn_phy_g_set_bbatt(mac, bbatt->att);
6492	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6493
6494	bwn_lo_restore(mac, &sval);
6495	bwn_mac_enable(mac);
6496
6497	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6498	if (!cal) {
6499		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6500		return (NULL);
6501	}
6502	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6503	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6504	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6505
6506	BWN_GETTIME(cal->calib_time);
6507
6508	return (cal);
6509}
6510
6511static struct bwn_lo_calib *
6512bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6513    const struct bwn_rfatt *rfatt)
6514{
6515	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6516	struct bwn_lo_calib *c;
6517
6518	TAILQ_FOREACH(c, &lo->calib_list, list) {
6519		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6520			continue;
6521		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6522			continue;
6523		return (c);
6524	}
6525
6526	c = bwn_lo_calibset(mac, bbatt, rfatt);
6527	if (!c)
6528		return (NULL);
6529	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6530
6531	return (c);
6532}
6533
6534static void
6535bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6536{
6537	struct bwn_phy *phy = &mac->mac_phy;
6538	struct bwn_phy_g *pg = &phy->phy_g;
6539	struct bwn_softc *sc = mac->mac_sc;
6540	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6541	const struct bwn_rfatt *rfatt;
6542	const struct bwn_bbatt *bbatt;
6543	uint64_t pvector;
6544	int i;
6545	int rf_offset, bb_offset;
6546	uint8_t changed = 0;
6547
6548	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6549	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6550	    ("%s:%d: fail", __func__, __LINE__));
6551
6552	pvector = lo->power_vector;
6553	if (!update && !pvector)
6554		return;
6555
6556	bwn_mac_suspend(mac);
6557
6558	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6559		struct bwn_lo_calib *cal;
6560		int idx;
6561		uint16_t val;
6562
6563		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6564			continue;
6565		bb_offset = i / lo->rfatt.len;
6566		rf_offset = i % lo->rfatt.len;
6567		bbatt = &(lo->bbatt.array[bb_offset]);
6568		rfatt = &(lo->rfatt.array[rf_offset]);
6569
6570		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6571		if (!cal) {
6572			device_printf(sc->sc_dev, "LO: Could not "
6573			    "calibrate DC table entry\n");
6574			continue;
6575		}
6576		val = (uint8_t)(cal->ctl.q);
6577		val |= ((uint8_t)(cal->ctl.i)) << 4;
6578		free(cal, M_DEVBUF);
6579
6580		idx = i / 2;
6581		if (i % 2)
6582			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6583			    | ((val & 0x00ff) << 8);
6584		else
6585			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6586			    | (val & 0x00ff);
6587		changed = 1;
6588	}
6589	if (changed) {
6590		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6591			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6592	}
6593	bwn_mac_enable(mac);
6594}
6595
6596static void
6597bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6598{
6599
6600	if (!rf->padmix)
6601		return;
6602	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6603		rf->att = 4;
6604}
6605
6606static void
6607bwn_lo_g_adjust(struct bwn_mac *mac)
6608{
6609	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6610	struct bwn_lo_calib *cal;
6611	struct bwn_rfatt rf;
6612
6613	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6614	bwn_lo_fixup_rfatt(&rf);
6615
6616	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6617	if (!cal)
6618		return;
6619	bwn_lo_write(mac, &cal->ctl);
6620}
6621
6622static void
6623bwn_lo_g_init(struct bwn_mac *mac)
6624{
6625
6626	if (!bwn_has_hwpctl(mac))
6627		return;
6628
6629	bwn_lo_get_powervector(mac);
6630	bwn_phy_g_dc_lookup_init(mac, 1);
6631}
6632
6633static void
6634bwn_mac_suspend(struct bwn_mac *mac)
6635{
6636	struct bwn_softc *sc = mac->mac_sc;
6637	int i;
6638	uint32_t tmp;
6639
6640	KASSERT(mac->mac_suspended >= 0,
6641	    ("%s:%d: fail", __func__, __LINE__));
6642
6643	if (mac->mac_suspended == 0) {
6644		bwn_psctl(mac, BWN_PS_AWAKE);
6645		BWN_WRITE_4(mac, BWN_MACCTL,
6646			    BWN_READ_4(mac, BWN_MACCTL)
6647			    & ~BWN_MACCTL_ON);
6648		BWN_READ_4(mac, BWN_MACCTL);
6649		for (i = 35; i; i--) {
6650			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6651			if (tmp & BWN_INTR_MAC_SUSPENDED)
6652				goto out;
6653			DELAY(10);
6654		}
6655		for (i = 40; i; i--) {
6656			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6657			if (tmp & BWN_INTR_MAC_SUSPENDED)
6658				goto out;
6659			DELAY(1000);
6660		}
6661		device_printf(sc->sc_dev, "MAC suspend failed\n");
6662	}
6663out:
6664	mac->mac_suspended++;
6665}
6666
6667static void
6668bwn_mac_enable(struct bwn_mac *mac)
6669{
6670	struct bwn_softc *sc = mac->mac_sc;
6671	uint16_t state;
6672
6673	state = bwn_shm_read_2(mac, BWN_SHARED,
6674	    BWN_SHARED_UCODESTAT);
6675	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6676	    state != BWN_SHARED_UCODESTAT_SLEEP)
6677		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6678
6679	mac->mac_suspended--;
6680	KASSERT(mac->mac_suspended >= 0,
6681	    ("%s:%d: fail", __func__, __LINE__));
6682	if (mac->mac_suspended == 0) {
6683		BWN_WRITE_4(mac, BWN_MACCTL,
6684		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6685		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6686		BWN_READ_4(mac, BWN_MACCTL);
6687		BWN_READ_4(mac, BWN_INTR_REASON);
6688		bwn_psctl(mac, 0);
6689	}
6690}
6691
6692static void
6693bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6694{
6695	struct bwn_softc *sc = mac->mac_sc;
6696	int i;
6697	uint16_t ucstat;
6698
6699	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6700	    ("%s:%d: fail", __func__, __LINE__));
6701	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6702	    ("%s:%d: fail", __func__, __LINE__));
6703
6704	/* XXX forcibly awake and hwps-off */
6705
6706	BWN_WRITE_4(mac, BWN_MACCTL,
6707	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6708	    ~BWN_MACCTL_HWPS);
6709	BWN_READ_4(mac, BWN_MACCTL);
6710	if (siba_get_revid(sc->sc_dev) >= 5) {
6711		for (i = 0; i < 100; i++) {
6712			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6713			    BWN_SHARED_UCODESTAT);
6714			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6715				break;
6716			DELAY(10);
6717		}
6718	}
6719}
6720
6721static int16_t
6722bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6723{
6724
6725	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6726	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6727}
6728
6729static void
6730bwn_nrssi_threshold(struct bwn_mac *mac)
6731{
6732	struct bwn_phy *phy = &mac->mac_phy;
6733	struct bwn_phy_g *pg = &phy->phy_g;
6734	struct bwn_softc *sc = mac->mac_sc;
6735	int32_t a, b;
6736	int16_t tmp16;
6737	uint16_t tmpu16;
6738
6739	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6740
6741	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6742		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6743			a = 0x13;
6744			b = 0x12;
6745		} else {
6746			a = 0xe;
6747			b = 0x11;
6748		}
6749
6750		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6751		a += (pg->pg_nrssi[0] << 6);
6752		a += (a < 32) ? 31 : 32;
6753		a = a >> 6;
6754		a = MIN(MAX(a, -31), 31);
6755
6756		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6757		b += (pg->pg_nrssi[0] << 6);
6758		if (b < 32)
6759			b += 31;
6760		else
6761			b += 32;
6762		b = b >> 6;
6763		b = MIN(MAX(b, -31), 31);
6764
6765		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6766		tmpu16 |= ((uint32_t)b & 0x0000003f);
6767		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6768		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6769		return;
6770	}
6771
6772	tmp16 = bwn_nrssi_read(mac, 0x20);
6773	if (tmp16 >= 0x20)
6774		tmp16 -= 0x40;
6775	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6776}
6777
6778static void
6779bwn_nrssi_slope_11g(struct bwn_mac *mac)
6780{
6781#define	SAVE_RF_MAX		3
6782#define	SAVE_PHY_COMM_MAX	4
6783#define	SAVE_PHY3_MAX		8
6784	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6785		{ 0x7a, 0x52, 0x43 };
6786	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6787		{ 0x15, 0x5a, 0x59, 0x58 };
6788	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6789		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6790		0x0801, 0x0060, 0x0014, 0x0478
6791	};
6792	struct bwn_phy *phy = &mac->mac_phy;
6793	struct bwn_phy_g *pg = &phy->phy_g;
6794	int32_t i, tmp32, phy3_idx = 0;
6795	uint16_t delta, tmp;
6796	uint16_t save_rf[SAVE_RF_MAX];
6797	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6798	uint16_t save_phy3[SAVE_PHY3_MAX];
6799	uint16_t ant_div, phy0, chan_ex;
6800	int16_t nrssi0, nrssi1;
6801
6802	KASSERT(phy->type == BWN_PHYTYPE_G,
6803	    ("%s:%d: fail", __func__, __LINE__));
6804
6805	if (phy->rf_rev >= 9)
6806		return;
6807	if (phy->rf_rev == 8)
6808		bwn_nrssi_offset(mac);
6809
6810	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6811	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6812
6813	/*
6814	 * Save RF/PHY registers for later restoration
6815	 */
6816	ant_div = BWN_READ_2(mac, 0x03e2);
6817	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6818	for (i = 0; i < SAVE_RF_MAX; ++i)
6819		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6820	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6821		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6822
6823	phy0 = BWN_READ_2(mac, BWN_PHY0);
6824	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6825	if (phy->rev >= 3) {
6826		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6827			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6828		BWN_PHY_WRITE(mac, 0x002e, 0);
6829		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6830		switch (phy->rev) {
6831		case 4:
6832		case 6:
6833		case 7:
6834			BWN_PHY_SET(mac, 0x0478, 0x0100);
6835			BWN_PHY_SET(mac, 0x0801, 0x0040);
6836			break;
6837		case 3:
6838		case 5:
6839			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6840			break;
6841		}
6842		BWN_PHY_SET(mac, 0x0060, 0x0040);
6843		BWN_PHY_SET(mac, 0x0014, 0x0200);
6844	}
6845	/*
6846	 * Calculate nrssi0
6847	 */
6848	BWN_RF_SET(mac, 0x007a, 0x0070);
6849	bwn_set_all_gains(mac, 0, 8, 0);
6850	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6851	if (phy->rev >= 2) {
6852		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6853		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6854	}
6855	BWN_RF_SET(mac, 0x007a, 0x0080);
6856	DELAY(20);
6857
6858	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6859	if (nrssi0 >= 0x0020)
6860		nrssi0 -= 0x0040;
6861
6862	/*
6863	 * Calculate nrssi1
6864	 */
6865	BWN_RF_MASK(mac, 0x007a, 0x007f);
6866	if (phy->rev >= 2)
6867		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6868
6869	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6870	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6871	BWN_RF_SET(mac, 0x007a, 0x000f);
6872	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6873	if (phy->rev >= 2) {
6874		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6875		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6876	}
6877
6878	bwn_set_all_gains(mac, 3, 0, 1);
6879	if (phy->rf_rev == 8) {
6880		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6881	} else {
6882		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6883		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6884		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6885		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6886	}
6887	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6888	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6889	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6890	DELAY(20);
6891	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6892
6893	/*
6894	 * Install calculated narrow RSSI values
6895	 */
6896	if (nrssi1 >= 0x0020)
6897		nrssi1 -= 0x0040;
6898	if (nrssi0 == nrssi1)
6899		pg->pg_nrssi_slope = 0x00010000;
6900	else
6901		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6902	if (nrssi0 >= -4) {
6903		pg->pg_nrssi[0] = nrssi1;
6904		pg->pg_nrssi[1] = nrssi0;
6905	}
6906
6907	/*
6908	 * Restore saved RF/PHY registers
6909	 */
6910	if (phy->rev >= 3) {
6911		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6912			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6913			    save_phy3[phy3_idx]);
6914		}
6915	}
6916	if (phy->rev >= 2) {
6917		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6918		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6919	}
6920
6921	for (i = 0; i < SAVE_RF_MAX; ++i)
6922		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6923
6924	BWN_WRITE_2(mac, 0x03e2, ant_div);
6925	BWN_WRITE_2(mac, 0x03e6, phy0);
6926	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6927
6928	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6929		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6930
6931	bwn_spu_workaround(mac, phy->chan);
6932	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6933	bwn_set_original_gains(mac);
6934	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6935	if (phy->rev >= 3) {
6936		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6937			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6938			    save_phy3[phy3_idx]);
6939		}
6940	}
6941
6942	delta = 0x1f - pg->pg_nrssi[0];
6943	for (i = 0; i < 64; i++) {
6944		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6945		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6946		pg->pg_nrssi_lt[i] = tmp32;
6947	}
6948
6949	bwn_nrssi_threshold(mac);
6950#undef SAVE_RF_MAX
6951#undef SAVE_PHY_COMM_MAX
6952#undef SAVE_PHY3_MAX
6953}
6954
6955static void
6956bwn_nrssi_offset(struct bwn_mac *mac)
6957{
6958#define	SAVE_RF_MAX		2
6959#define	SAVE_PHY_COMM_MAX	10
6960#define	SAVE_PHY6_MAX		8
6961	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6962		{ 0x7a, 0x43 };
6963	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6964		0x0001, 0x0811, 0x0812, 0x0814,
6965		0x0815, 0x005a, 0x0059, 0x0058,
6966		0x000a, 0x0003
6967	};
6968	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6969		0x002e, 0x002f, 0x080f, 0x0810,
6970		0x0801, 0x0060, 0x0014, 0x0478
6971	};
6972	struct bwn_phy *phy = &mac->mac_phy;
6973	int i, phy6_idx = 0;
6974	uint16_t save_rf[SAVE_RF_MAX];
6975	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6976	uint16_t save_phy6[SAVE_PHY6_MAX];
6977	int16_t nrssi;
6978	uint16_t saved = 0xffff;
6979
6980	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6981		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6982	for (i = 0; i < SAVE_RF_MAX; ++i)
6983		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6984
6985	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6986	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6987	BWN_PHY_SET(mac, 0x0811, 0x000c);
6988	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6989	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6990	if (phy->rev >= 6) {
6991		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6992			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6993
6994		BWN_PHY_WRITE(mac, 0x002e, 0);
6995		BWN_PHY_WRITE(mac, 0x002f, 0);
6996		BWN_PHY_WRITE(mac, 0x080f, 0);
6997		BWN_PHY_WRITE(mac, 0x0810, 0);
6998		BWN_PHY_SET(mac, 0x0478, 0x0100);
6999		BWN_PHY_SET(mac, 0x0801, 0x0040);
7000		BWN_PHY_SET(mac, 0x0060, 0x0040);
7001		BWN_PHY_SET(mac, 0x0014, 0x0200);
7002	}
7003	BWN_RF_SET(mac, 0x007a, 0x0070);
7004	BWN_RF_SET(mac, 0x007a, 0x0080);
7005	DELAY(30);
7006
7007	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7008	if (nrssi >= 0x20)
7009		nrssi -= 0x40;
7010	if (nrssi == 31) {
7011		for (i = 7; i >= 4; i--) {
7012			BWN_RF_WRITE(mac, 0x007b, i);
7013			DELAY(20);
7014			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7015			    0x003f);
7016			if (nrssi >= 0x20)
7017				nrssi -= 0x40;
7018			if (nrssi < 31 && saved == 0xffff)
7019				saved = i;
7020		}
7021		if (saved == 0xffff)
7022			saved = 4;
7023	} else {
7024		BWN_RF_MASK(mac, 0x007a, 0x007f);
7025		if (phy->rev != 1) {
7026			BWN_PHY_SET(mac, 0x0814, 0x0001);
7027			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7028		}
7029		BWN_PHY_SET(mac, 0x0811, 0x000c);
7030		BWN_PHY_SET(mac, 0x0812, 0x000c);
7031		BWN_PHY_SET(mac, 0x0811, 0x0030);
7032		BWN_PHY_SET(mac, 0x0812, 0x0030);
7033		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7034		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7035		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7036		if (phy->rev == 0)
7037			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7038		else
7039			BWN_PHY_SET(mac, 0x000a, 0x2000);
7040		if (phy->rev != 1) {
7041			BWN_PHY_SET(mac, 0x0814, 0x0004);
7042			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7043		}
7044		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7045		BWN_RF_SET(mac, 0x007a, 0x000f);
7046		bwn_set_all_gains(mac, 3, 0, 1);
7047		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7048		DELAY(30);
7049		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7050		if (nrssi >= 0x20)
7051			nrssi -= 0x40;
7052		if (nrssi == -32) {
7053			for (i = 0; i < 4; i++) {
7054				BWN_RF_WRITE(mac, 0x007b, i);
7055				DELAY(20);
7056				nrssi = (int16_t)((BWN_PHY_READ(mac,
7057				    0x047f) >> 8) & 0x003f);
7058				if (nrssi >= 0x20)
7059					nrssi -= 0x40;
7060				if (nrssi > -31 && saved == 0xffff)
7061					saved = i;
7062			}
7063			if (saved == 0xffff)
7064				saved = 3;
7065		} else
7066			saved = 0;
7067	}
7068	BWN_RF_WRITE(mac, 0x007b, saved);
7069
7070	/*
7071	 * Restore saved RF/PHY registers
7072	 */
7073	if (phy->rev >= 6) {
7074		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7075			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7076			    save_phy6[phy6_idx]);
7077		}
7078	}
7079	if (phy->rev != 1) {
7080		for (i = 3; i < 5; i++)
7081			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7082			    save_phy_comm[i]);
7083	}
7084	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7085		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7086
7087	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7088		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7089
7090	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7091	BWN_PHY_SET(mac, 0x0429, 0x8000);
7092	bwn_set_original_gains(mac);
7093	if (phy->rev >= 6) {
7094		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7095			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7096			    save_phy6[phy6_idx]);
7097		}
7098	}
7099
7100	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7101	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7102	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7103}
7104
7105static void
7106bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7107    int16_t third)
7108{
7109	struct bwn_phy *phy = &mac->mac_phy;
7110	uint16_t i;
7111	uint16_t start = 0x08, end = 0x18;
7112	uint16_t tmp;
7113	uint16_t table;
7114
7115	if (phy->rev <= 1) {
7116		start = 0x10;
7117		end = 0x20;
7118	}
7119
7120	table = BWN_OFDMTAB_GAINX;
7121	if (phy->rev <= 1)
7122		table = BWN_OFDMTAB_GAINX_R1;
7123	for (i = 0; i < 4; i++)
7124		bwn_ofdmtab_write_2(mac, table, i, first);
7125
7126	for (i = start; i < end; i++)
7127		bwn_ofdmtab_write_2(mac, table, i, second);
7128
7129	if (third != -1) {
7130		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7131		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7132		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7133		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7134	}
7135	bwn_dummy_transmission(mac, 0, 1);
7136}
7137
7138static void
7139bwn_set_original_gains(struct bwn_mac *mac)
7140{
7141	struct bwn_phy *phy = &mac->mac_phy;
7142	uint16_t i, tmp;
7143	uint16_t table;
7144	uint16_t start = 0x0008, end = 0x0018;
7145
7146	if (phy->rev <= 1) {
7147		start = 0x0010;
7148		end = 0x0020;
7149	}
7150
7151	table = BWN_OFDMTAB_GAINX;
7152	if (phy->rev <= 1)
7153		table = BWN_OFDMTAB_GAINX_R1;
7154	for (i = 0; i < 4; i++) {
7155		tmp = (i & 0xfffc);
7156		tmp |= (i & 0x0001) << 1;
7157		tmp |= (i & 0x0002) >> 1;
7158
7159		bwn_ofdmtab_write_2(mac, table, i, tmp);
7160	}
7161
7162	for (i = start; i < end; i++)
7163		bwn_ofdmtab_write_2(mac, table, i, i - start);
7164
7165	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7166	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7167	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7168	bwn_dummy_transmission(mac, 0, 1);
7169}
7170
7171static void
7172bwn_phy_hwpctl_init(struct bwn_mac *mac)
7173{
7174	struct bwn_phy *phy = &mac->mac_phy;
7175	struct bwn_phy_g *pg = &phy->phy_g;
7176	struct bwn_rfatt old_rfatt, rfatt;
7177	struct bwn_bbatt old_bbatt, bbatt;
7178	struct bwn_softc *sc = mac->mac_sc;
7179	uint8_t old_txctl = 0;
7180
7181	KASSERT(phy->type == BWN_PHYTYPE_G,
7182	    ("%s:%d: fail", __func__, __LINE__));
7183
7184	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7185	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7186		return;
7187
7188	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7189
7190	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7191
7192	if (!phy->gmode)
7193		return;
7194	bwn_hwpctl_early_init(mac);
7195	if (pg->pg_curtssi == 0) {
7196		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7197			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7198		} else {
7199			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7200			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7201			old_txctl = pg->pg_txctl;
7202
7203			bbatt.att = 11;
7204			if (phy->rf_rev == 8) {
7205				rfatt.att = 15;
7206				rfatt.padmix = 1;
7207			} else {
7208				rfatt.att = 9;
7209				rfatt.padmix = 0;
7210			}
7211			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7212		}
7213		bwn_dummy_transmission(mac, 0, 1);
7214		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7215		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7216			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7217		else
7218			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7219			    &old_rfatt, old_txctl);
7220	}
7221	bwn_hwpctl_init_gphy(mac);
7222
7223	/* clear TSSI */
7224	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7225	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7226	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7227	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7228}
7229
7230static void
7231bwn_hwpctl_early_init(struct bwn_mac *mac)
7232{
7233	struct bwn_phy *phy = &mac->mac_phy;
7234
7235	if (!bwn_has_hwpctl(mac)) {
7236		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7237		return;
7238	}
7239
7240	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7241	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7242	BWN_PHY_SET(mac, 0x047c, 0x0002);
7243	BWN_PHY_SET(mac, 0x047a, 0xf000);
7244	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7245		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7246		BWN_PHY_SET(mac, 0x005d, 0x8000);
7247		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7248		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7249		BWN_PHY_SET(mac, 0x0036, 0x0400);
7250	} else {
7251		BWN_PHY_SET(mac, 0x0036, 0x0200);
7252		BWN_PHY_SET(mac, 0x0036, 0x0400);
7253		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7254		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7255		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7256		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7257		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7258	}
7259}
7260
7261static void
7262bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7263{
7264	struct bwn_phy *phy = &mac->mac_phy;
7265	struct bwn_phy_g *pg = &phy->phy_g;
7266	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7267	int i;
7268	uint16_t nr_written = 0, tmp, value;
7269	uint8_t rf, bb;
7270
7271	if (!bwn_has_hwpctl(mac)) {
7272		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7273		return;
7274	}
7275
7276	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7277	    (pg->pg_idletssi - pg->pg_curtssi));
7278	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7279	    (pg->pg_idletssi - pg->pg_curtssi));
7280
7281	for (i = 0; i < 32; i++)
7282		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7283	for (i = 32; i < 64; i++)
7284		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7285	for (i = 0; i < 64; i += 2) {
7286		value = (uint16_t) pg->pg_tssi2dbm[i];
7287		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7288		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7289	}
7290
7291	for (rf = 0; rf < lo->rfatt.len; rf++) {
7292		for (bb = 0; bb < lo->bbatt.len; bb++) {
7293			if (nr_written >= 0x40)
7294				return;
7295			tmp = lo->bbatt.array[bb].att;
7296			tmp <<= 8;
7297			if (phy->rf_rev == 8)
7298				tmp |= 0x50;
7299			else
7300				tmp |= 0x40;
7301			tmp |= lo->rfatt.array[rf].att;
7302			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7303			nr_written++;
7304		}
7305	}
7306
7307	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7308	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7309
7310	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7311	BWN_PHY_SET(mac, 0x0478, 0x0800);
7312	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7313	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7314
7315	bwn_phy_g_dc_lookup_init(mac, 1);
7316	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7317}
7318
7319static void
7320bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7321{
7322	struct bwn_softc *sc = mac->mac_sc;
7323
7324	if (spu != 0)
7325		bwn_spu_workaround(mac, channel);
7326
7327	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7328
7329	if (channel == 14) {
7330		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7331			bwn_hf_write(mac,
7332			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7333		else
7334			bwn_hf_write(mac,
7335			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7336		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7337		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7338		return;
7339	}
7340
7341	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7342	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7343}
7344
7345static uint16_t
7346bwn_phy_g_chan2freq(uint8_t channel)
7347{
7348	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7349
7350	KASSERT(channel >= 1 && channel <= 14,
7351	    ("%s:%d: fail", __func__, __LINE__));
7352
7353	return (bwn_phy_g_rf_channels[channel - 1]);
7354}
7355
7356static void
7357bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7358    const struct bwn_rfatt *rfatt, uint8_t txctl)
7359{
7360	struct bwn_phy *phy = &mac->mac_phy;
7361	struct bwn_phy_g *pg = &phy->phy_g;
7362	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7363	uint16_t bb, rf;
7364	uint16_t tx_bias, tx_magn;
7365
7366	bb = bbatt->att;
7367	rf = rfatt->att;
7368	tx_bias = lo->tx_bias;
7369	tx_magn = lo->tx_magn;
7370	if (tx_bias == 0xff)
7371		tx_bias = 0;
7372
7373	pg->pg_txctl = txctl;
7374	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7375	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7376	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7377	bwn_phy_g_set_bbatt(mac, bb);
7378	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7379	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7380		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7381	else {
7382		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7383		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7384	}
7385	if (BWN_HAS_TXMAG(phy))
7386		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7387	else
7388		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7389	bwn_lo_g_adjust(mac);
7390}
7391
7392static void
7393bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7394    uint16_t bbatt)
7395{
7396	struct bwn_phy *phy = &mac->mac_phy;
7397
7398	if (phy->analog == 0) {
7399		BWN_WRITE_2(mac, BWN_PHY0,
7400		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7401		return;
7402	}
7403	if (phy->analog > 1) {
7404		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7405		return;
7406	}
7407	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7408}
7409
7410static uint16_t
7411bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7412{
7413	struct bwn_phy *phy = &mac->mac_phy;
7414	struct bwn_phy_g *pg = &phy->phy_g;
7415	struct bwn_softc *sc = mac->mac_sc;
7416	int max_lb_gain;
7417	uint16_t extlna;
7418	uint16_t i;
7419
7420	if (phy->gmode == 0)
7421		return (0);
7422
7423	if (BWN_HAS_LOOPBACK(phy)) {
7424		max_lb_gain = pg->pg_max_lb_gain;
7425		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7426		if (max_lb_gain >= 0x46) {
7427			extlna = 0x3000;
7428			max_lb_gain -= 0x46;
7429		} else if (max_lb_gain >= 0x3a) {
7430			extlna = 0x1000;
7431			max_lb_gain -= 0x3a;
7432		} else if (max_lb_gain >= 0x2e) {
7433			extlna = 0x2000;
7434			max_lb_gain -= 0x2e;
7435		} else {
7436			extlna = 0;
7437			max_lb_gain -= 0x10;
7438		}
7439
7440		for (i = 0; i < 16; i++) {
7441			max_lb_gain -= (i * 6);
7442			if (max_lb_gain < 6)
7443				break;
7444		}
7445
7446		if ((phy->rev < 7) ||
7447		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7448			if (reg == BWN_PHY_RFOVER) {
7449				return (0x1b3);
7450			} else if (reg == BWN_PHY_RFOVERVAL) {
7451				extlna |= (i << 8);
7452				switch (lpd) {
7453				case BWN_LPD(0, 1, 1):
7454					return (0x0f92);
7455				case BWN_LPD(0, 0, 1):
7456				case BWN_LPD(1, 0, 1):
7457					return (0x0092 | extlna);
7458				case BWN_LPD(1, 0, 0):
7459					return (0x0093 | extlna);
7460				}
7461				KASSERT(0 == 1,
7462				    ("%s:%d: fail", __func__, __LINE__));
7463			}
7464			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7465		} else {
7466			if (reg == BWN_PHY_RFOVER)
7467				return (0x9b3);
7468			if (reg == BWN_PHY_RFOVERVAL) {
7469				if (extlna)
7470					extlna |= 0x8000;
7471				extlna |= (i << 8);
7472				switch (lpd) {
7473				case BWN_LPD(0, 1, 1):
7474					return (0x8f92);
7475				case BWN_LPD(0, 0, 1):
7476					return (0x8092 | extlna);
7477				case BWN_LPD(1, 0, 1):
7478					return (0x2092 | extlna);
7479				case BWN_LPD(1, 0, 0):
7480					return (0x2093 | extlna);
7481				}
7482				KASSERT(0 == 1,
7483				    ("%s:%d: fail", __func__, __LINE__));
7484			}
7485			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7486		}
7487		return (0);
7488	}
7489
7490	if ((phy->rev < 7) ||
7491	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7492		if (reg == BWN_PHY_RFOVER) {
7493			return (0x1b3);
7494		} else if (reg == BWN_PHY_RFOVERVAL) {
7495			switch (lpd) {
7496			case BWN_LPD(0, 1, 1):
7497				return (0x0fb2);
7498			case BWN_LPD(0, 0, 1):
7499				return (0x00b2);
7500			case BWN_LPD(1, 0, 1):
7501				return (0x30b2);
7502			case BWN_LPD(1, 0, 0):
7503				return (0x30b3);
7504			}
7505			KASSERT(0 == 1,
7506			    ("%s:%d: fail", __func__, __LINE__));
7507		}
7508		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7509	} else {
7510		if (reg == BWN_PHY_RFOVER) {
7511			return (0x9b3);
7512		} else if (reg == BWN_PHY_RFOVERVAL) {
7513			switch (lpd) {
7514			case BWN_LPD(0, 1, 1):
7515				return (0x8fb2);
7516			case BWN_LPD(0, 0, 1):
7517				return (0x80b2);
7518			case BWN_LPD(1, 0, 1):
7519				return (0x20b2);
7520			case BWN_LPD(1, 0, 0):
7521				return (0x20b3);
7522			}
7523			KASSERT(0 == 1,
7524			    ("%s:%d: fail", __func__, __LINE__));
7525		}
7526		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7527	}
7528	return (0);
7529}
7530
7531static void
7532bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7533{
7534
7535	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7536		return;
7537	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7538	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7539	DELAY(1000);
7540	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7541}
7542
7543static int
7544bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7545{
7546	struct bwn_softc *sc = mac->mac_sc;
7547	struct bwn_fw *fw = &mac->mac_fw;
7548	const uint8_t rev = siba_get_revid(sc->sc_dev);
7549	const char *filename;
7550	uint32_t high;
7551	int error;
7552
7553	/* microcode */
7554	if (rev >= 5 && rev <= 10)
7555		filename = "ucode5";
7556	else if (rev >= 11 && rev <= 12)
7557		filename = "ucode11";
7558	else if (rev == 13)
7559		filename = "ucode13";
7560	else if (rev == 14)
7561		filename = "ucode14";
7562	else if (rev >= 15)
7563		filename = "ucode15";
7564	else {
7565		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7566		bwn_release_firmware(mac);
7567		return (EOPNOTSUPP);
7568	}
7569	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7570	if (error) {
7571		bwn_release_firmware(mac);
7572		return (error);
7573	}
7574
7575	/* PCM */
7576	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7577	if (rev >= 5 && rev <= 10) {
7578		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7579		if (error == ENOENT)
7580			fw->no_pcmfile = 1;
7581		else if (error) {
7582			bwn_release_firmware(mac);
7583			return (error);
7584		}
7585	} else if (rev < 11) {
7586		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7587		return (EOPNOTSUPP);
7588	}
7589
7590	/* initvals */
7591	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7592	switch (mac->mac_phy.type) {
7593	case BWN_PHYTYPE_A:
7594		if (rev < 5 || rev > 10)
7595			goto fail1;
7596		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7597			filename = "a0g1initvals5";
7598		else
7599			filename = "a0g0initvals5";
7600		break;
7601	case BWN_PHYTYPE_G:
7602		if (rev >= 5 && rev <= 10)
7603			filename = "b0g0initvals5";
7604		else if (rev >= 13)
7605			filename = "b0g0initvals13";
7606		else
7607			goto fail1;
7608		break;
7609	case BWN_PHYTYPE_LP:
7610		if (rev == 13)
7611			filename = "lp0initvals13";
7612		else if (rev == 14)
7613			filename = "lp0initvals14";
7614		else if (rev >= 15)
7615			filename = "lp0initvals15";
7616		else
7617			goto fail1;
7618		break;
7619	case BWN_PHYTYPE_N:
7620		if (rev >= 11 && rev <= 12)
7621			filename = "n0initvals11";
7622		else
7623			goto fail1;
7624		break;
7625	default:
7626		goto fail1;
7627	}
7628	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7629	if (error) {
7630		bwn_release_firmware(mac);
7631		return (error);
7632	}
7633
7634	/* bandswitch initvals */
7635	switch (mac->mac_phy.type) {
7636	case BWN_PHYTYPE_A:
7637		if (rev >= 5 && rev <= 10) {
7638			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7639				filename = "a0g1bsinitvals5";
7640			else
7641				filename = "a0g0bsinitvals5";
7642		} else if (rev >= 11)
7643			filename = NULL;
7644		else
7645			goto fail1;
7646		break;
7647	case BWN_PHYTYPE_G:
7648		if (rev >= 5 && rev <= 10)
7649			filename = "b0g0bsinitvals5";
7650		else if (rev >= 11)
7651			filename = NULL;
7652		else
7653			goto fail1;
7654		break;
7655	case BWN_PHYTYPE_LP:
7656		if (rev == 13)
7657			filename = "lp0bsinitvals13";
7658		else if (rev == 14)
7659			filename = "lp0bsinitvals14";
7660		else if (rev >= 15)
7661			filename = "lp0bsinitvals15";
7662		else
7663			goto fail1;
7664		break;
7665	case BWN_PHYTYPE_N:
7666		if (rev >= 11 && rev <= 12)
7667			filename = "n0bsinitvals11";
7668		else
7669			goto fail1;
7670		break;
7671	default:
7672		goto fail1;
7673	}
7674	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7675	if (error) {
7676		bwn_release_firmware(mac);
7677		return (error);
7678	}
7679	return (0);
7680fail1:
7681	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7682	bwn_release_firmware(mac);
7683	return (EOPNOTSUPP);
7684}
7685
7686static int
7687bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7688    const char *name, struct bwn_fwfile *bfw)
7689{
7690	const struct bwn_fwhdr *hdr;
7691	struct bwn_softc *sc = mac->mac_sc;
7692	const struct firmware *fw;
7693	char namebuf[64];
7694
7695	if (name == NULL) {
7696		bwn_do_release_fw(bfw);
7697		return (0);
7698	}
7699	if (bfw->filename != NULL) {
7700		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7701			return (0);
7702		bwn_do_release_fw(bfw);
7703	}
7704
7705	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7706	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7707	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7708	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7709	fw = firmware_get(namebuf);
7710	if (fw == NULL) {
7711		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7712		    namebuf);
7713		return (ENOENT);
7714	}
7715	if (fw->datasize < sizeof(struct bwn_fwhdr))
7716		goto fail;
7717	hdr = (const struct bwn_fwhdr *)(fw->data);
7718	switch (hdr->type) {
7719	case BWN_FWTYPE_UCODE:
7720	case BWN_FWTYPE_PCM:
7721		if (be32toh(hdr->size) !=
7722		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7723			goto fail;
7724		/* FALLTHROUGH */
7725	case BWN_FWTYPE_IV:
7726		if (hdr->ver != 1)
7727			goto fail;
7728		break;
7729	default:
7730		goto fail;
7731	}
7732	bfw->filename = name;
7733	bfw->fw = fw;
7734	bfw->type = type;
7735	return (0);
7736fail:
7737	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7738	if (fw != NULL)
7739		firmware_put(fw, FIRMWARE_UNLOAD);
7740	return (EPROTO);
7741}
7742
7743static void
7744bwn_release_firmware(struct bwn_mac *mac)
7745{
7746
7747	bwn_do_release_fw(&mac->mac_fw.ucode);
7748	bwn_do_release_fw(&mac->mac_fw.pcm);
7749	bwn_do_release_fw(&mac->mac_fw.initvals);
7750	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7751}
7752
7753static void
7754bwn_do_release_fw(struct bwn_fwfile *bfw)
7755{
7756
7757	if (bfw->fw != NULL)
7758		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7759	bfw->fw = NULL;
7760	bfw->filename = NULL;
7761}
7762
7763static int
7764bwn_fw_loaducode(struct bwn_mac *mac)
7765{
7766#define	GETFWOFFSET(fwp, offset)	\
7767	((const uint32_t *)((const char *)fwp.fw->data + offset))
7768#define	GETFWSIZE(fwp, offset)	\
7769	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7770	struct bwn_softc *sc = mac->mac_sc;
7771	const uint32_t *data;
7772	unsigned int i;
7773	uint32_t ctl;
7774	uint16_t date, fwcaps, time;
7775	int error = 0;
7776
7777	ctl = BWN_READ_4(mac, BWN_MACCTL);
7778	ctl |= BWN_MACCTL_MCODE_JMP0;
7779	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7780	    __LINE__));
7781	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7782	for (i = 0; i < 64; i++)
7783		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7784	for (i = 0; i < 4096; i += 2)
7785		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7786
7787	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7788	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7789	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7790	     i++) {
7791		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7792		DELAY(10);
7793	}
7794
7795	if (mac->mac_fw.pcm.fw) {
7796		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7797		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7798		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7799		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7800		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7801		    sizeof(struct bwn_fwhdr)); i++) {
7802			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7803			DELAY(10);
7804		}
7805	}
7806
7807	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7808	BWN_WRITE_4(mac, BWN_MACCTL,
7809	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7810	    BWN_MACCTL_MCODE_RUN);
7811
7812	for (i = 0; i < 21; i++) {
7813		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7814			break;
7815		if (i >= 20) {
7816			device_printf(sc->sc_dev, "ucode timeout\n");
7817			error = ENXIO;
7818			goto error;
7819		}
7820		DELAY(50000);
7821	}
7822	BWN_READ_4(mac, BWN_INTR_REASON);
7823
7824	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7825	if (mac->mac_fw.rev <= 0x128) {
7826		device_printf(sc->sc_dev, "the firmware is too old\n");
7827		error = EOPNOTSUPP;
7828		goto error;
7829	}
7830	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7831	    BWN_SHARED_UCODE_PATCH);
7832	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7833	mac->mac_fw.opensource = (date == 0xffff);
7834	if (bwn_wme != 0)
7835		mac->mac_flags |= BWN_MAC_FLAG_WME;
7836	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7837
7838	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7839	if (mac->mac_fw.opensource == 0) {
7840		device_printf(sc->sc_dev,
7841		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7842		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7843		if (mac->mac_fw.no_pcmfile)
7844			device_printf(sc->sc_dev,
7845			    "no HW crypto acceleration due to pcm5\n");
7846	} else {
7847		mac->mac_fw.patch = time;
7848		fwcaps = bwn_fwcaps_read(mac);
7849		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7850			device_printf(sc->sc_dev,
7851			    "disabling HW crypto acceleration\n");
7852			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7853		}
7854		if (!(fwcaps & BWN_FWCAPS_WME)) {
7855			device_printf(sc->sc_dev, "disabling WME support\n");
7856			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7857		}
7858	}
7859
7860	if (BWN_ISOLDFMT(mac))
7861		device_printf(sc->sc_dev, "using old firmware image\n");
7862
7863	return (0);
7864
7865error:
7866	BWN_WRITE_4(mac, BWN_MACCTL,
7867	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7868	    BWN_MACCTL_MCODE_JMP0);
7869
7870	return (error);
7871#undef GETFWSIZE
7872#undef GETFWOFFSET
7873}
7874
7875/* OpenFirmware only */
7876static uint16_t
7877bwn_fwcaps_read(struct bwn_mac *mac)
7878{
7879
7880	KASSERT(mac->mac_fw.opensource == 1,
7881	    ("%s:%d: fail", __func__, __LINE__));
7882	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7883}
7884
7885static int
7886bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7887    size_t count, size_t array_size)
7888{
7889#define	GET_NEXTIV16(iv)						\
7890	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7891	    sizeof(uint16_t) + sizeof(uint16_t)))
7892#define	GET_NEXTIV32(iv)						\
7893	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7894	    sizeof(uint16_t) + sizeof(uint32_t)))
7895	struct bwn_softc *sc = mac->mac_sc;
7896	const struct bwn_fwinitvals *iv;
7897	uint16_t offset;
7898	size_t i;
7899	uint8_t bit32;
7900
7901	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7902	    ("%s:%d: fail", __func__, __LINE__));
7903	iv = ivals;
7904	for (i = 0; i < count; i++) {
7905		if (array_size < sizeof(iv->offset_size))
7906			goto fail;
7907		array_size -= sizeof(iv->offset_size);
7908		offset = be16toh(iv->offset_size);
7909		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7910		offset &= BWN_FWINITVALS_OFFSET_MASK;
7911		if (offset >= 0x1000)
7912			goto fail;
7913		if (bit32) {
7914			if (array_size < sizeof(iv->data.d32))
7915				goto fail;
7916			array_size -= sizeof(iv->data.d32);
7917			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7918			iv = GET_NEXTIV32(iv);
7919		} else {
7920
7921			if (array_size < sizeof(iv->data.d16))
7922				goto fail;
7923			array_size -= sizeof(iv->data.d16);
7924			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7925
7926			iv = GET_NEXTIV16(iv);
7927		}
7928	}
7929	if (array_size != 0)
7930		goto fail;
7931	return (0);
7932fail:
7933	device_printf(sc->sc_dev, "initvals: invalid format\n");
7934	return (EPROTO);
7935#undef GET_NEXTIV16
7936#undef GET_NEXTIV32
7937}
7938
7939static int
7940bwn_switch_channel(struct bwn_mac *mac, int chan)
7941{
7942	struct bwn_phy *phy = &(mac->mac_phy);
7943	struct bwn_softc *sc = mac->mac_sc;
7944	struct ifnet *ifp = sc->sc_ifp;
7945	struct ieee80211com *ic = ifp->if_l2com;
7946	uint16_t channelcookie, savedcookie;
7947	int error;
7948
7949	if (chan == 0xffff)
7950		chan = phy->get_default_chan(mac);
7951
7952	channelcookie = chan;
7953	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7954		channelcookie |= 0x100;
7955	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7956	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7957	error = phy->switch_channel(mac, chan);
7958	if (error)
7959		goto fail;
7960
7961	mac->mac_phy.chan = chan;
7962	DELAY(8000);
7963	return (0);
7964fail:
7965	device_printf(sc->sc_dev, "failed to switch channel\n");
7966	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7967	return (error);
7968}
7969
7970static uint16_t
7971bwn_ant2phy(int antenna)
7972{
7973
7974	switch (antenna) {
7975	case BWN_ANT0:
7976		return (BWN_TX_PHY_ANT0);
7977	case BWN_ANT1:
7978		return (BWN_TX_PHY_ANT1);
7979	case BWN_ANT2:
7980		return (BWN_TX_PHY_ANT2);
7981	case BWN_ANT3:
7982		return (BWN_TX_PHY_ANT3);
7983	case BWN_ANTAUTO:
7984		return (BWN_TX_PHY_ANT01AUTO);
7985	}
7986	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7987	return (0);
7988}
7989
7990static void
7991bwn_wme_load(struct bwn_mac *mac)
7992{
7993	struct bwn_softc *sc = mac->mac_sc;
7994	int i;
7995
7996	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7997	    ("%s:%d: fail", __func__, __LINE__));
7998
7999	bwn_mac_suspend(mac);
8000	for (i = 0; i < N(sc->sc_wmeParams); i++)
8001		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8002		    bwn_wme_shm_offsets[i]);
8003	bwn_mac_enable(mac);
8004}
8005
8006static void
8007bwn_wme_loadparams(struct bwn_mac *mac,
8008    const struct wmeParams *p, uint16_t shm_offset)
8009{
8010#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8011	struct bwn_softc *sc = mac->mac_sc;
8012	uint16_t params[BWN_NR_WMEPARAMS];
8013	int slot, tmp;
8014	unsigned int i;
8015
8016	slot = BWN_READ_2(mac, BWN_RNG) &
8017	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8018
8019	memset(&params, 0, sizeof(params));
8020
8021	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8022	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8023	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8024
8025	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8026	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8027	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8028	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8029	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8030	params[BWN_WMEPARAM_BSLOTS] = slot;
8031	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8032
8033	for (i = 0; i < N(params); i++) {
8034		if (i == BWN_WMEPARAM_STATUS) {
8035			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8036			    shm_offset + (i * 2));
8037			tmp |= 0x100;
8038			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8039			    tmp);
8040		} else {
8041			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8042			    params[i]);
8043		}
8044	}
8045}
8046
8047static void
8048bwn_mac_write_bssid(struct bwn_mac *mac)
8049{
8050	struct bwn_softc *sc = mac->mac_sc;
8051	uint32_t tmp;
8052	int i;
8053	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8054
8055	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8056	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8057	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8058	    IEEE80211_ADDR_LEN);
8059
8060	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8061		tmp = (uint32_t) (mac_bssid[i + 0]);
8062		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8063		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8064		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8065		bwn_ram_write(mac, 0x20 + i, tmp);
8066	}
8067}
8068
8069static void
8070bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8071    const uint8_t *macaddr)
8072{
8073	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8074	uint16_t data;
8075
8076	if (!mac)
8077		macaddr = zero;
8078
8079	offset |= 0x0020;
8080	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8081
8082	data = macaddr[0];
8083	data |= macaddr[1] << 8;
8084	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8085	data = macaddr[2];
8086	data |= macaddr[3] << 8;
8087	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8088	data = macaddr[4];
8089	data |= macaddr[5] << 8;
8090	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8091}
8092
8093static void
8094bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8095    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8096{
8097	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8098	uint8_t per_sta_keys_start = 8;
8099
8100	if (BWN_SEC_NEWAPI(mac))
8101		per_sta_keys_start = 4;
8102
8103	KASSERT(index < mac->mac_max_nr_keys,
8104	    ("%s:%d: fail", __func__, __LINE__));
8105	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8106	    ("%s:%d: fail", __func__, __LINE__));
8107
8108	if (index >= per_sta_keys_start)
8109		bwn_key_macwrite(mac, index, NULL);
8110	if (key)
8111		memcpy(buf, key, key_len);
8112	bwn_key_write(mac, index, algorithm, buf);
8113	if (index >= per_sta_keys_start)
8114		bwn_key_macwrite(mac, index, mac_addr);
8115
8116	mac->mac_key[index].algorithm = algorithm;
8117}
8118
8119static void
8120bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8121{
8122	struct bwn_softc *sc = mac->mac_sc;
8123	uint32_t addrtmp[2] = { 0, 0 };
8124	uint8_t start = 8;
8125
8126	if (BWN_SEC_NEWAPI(mac))
8127		start = 4;
8128
8129	KASSERT(index >= start,
8130	    ("%s:%d: fail", __func__, __LINE__));
8131	index -= start;
8132
8133	if (addr) {
8134		addrtmp[0] = addr[0];
8135		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8136		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8137		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8138		addrtmp[1] = addr[4];
8139		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8140	}
8141
8142	if (siba_get_revid(sc->sc_dev) >= 5) {
8143		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8144		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8145	} else {
8146		if (index >= 8) {
8147			bwn_shm_write_4(mac, BWN_SHARED,
8148			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8149			bwn_shm_write_2(mac, BWN_SHARED,
8150			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8151		}
8152	}
8153}
8154
8155static void
8156bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8157    const uint8_t *key)
8158{
8159	unsigned int i;
8160	uint32_t offset;
8161	uint16_t kidx, value;
8162
8163	kidx = BWN_SEC_KEY2FW(mac, index);
8164	bwn_shm_write_2(mac, BWN_SHARED,
8165	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8166
8167	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8168	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8169		value = key[i];
8170		value |= (uint16_t)(key[i + 1]) << 8;
8171		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8172	}
8173}
8174
8175static void
8176bwn_phy_exit(struct bwn_mac *mac)
8177{
8178
8179	mac->mac_phy.rf_onoff(mac, 0);
8180	if (mac->mac_phy.exit != NULL)
8181		mac->mac_phy.exit(mac);
8182}
8183
8184static void
8185bwn_dma_free(struct bwn_mac *mac)
8186{
8187	struct bwn_dma *dma;
8188
8189	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8190		return;
8191	dma = &mac->mac_method.dma;
8192
8193	bwn_dma_ringfree(&dma->rx);
8194	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8195	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8196	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8197	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8198	bwn_dma_ringfree(&dma->mcast);
8199}
8200
8201static void
8202bwn_core_stop(struct bwn_mac *mac)
8203{
8204	struct bwn_softc *sc = mac->mac_sc;
8205
8206	BWN_ASSERT_LOCKED(sc);
8207
8208	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8209		return;
8210
8211	callout_stop(&sc->sc_rfswitch_ch);
8212	callout_stop(&sc->sc_task_ch);
8213	callout_stop(&sc->sc_watchdog_ch);
8214	sc->sc_watchdog_timer = 0;
8215	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8216	BWN_READ_4(mac, BWN_INTR_MASK);
8217	bwn_mac_suspend(mac);
8218
8219	mac->mac_status = BWN_MAC_STATUS_INITED;
8220}
8221
8222static int
8223bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8224{
8225	struct bwn_mac *up_dev = NULL;
8226	struct bwn_mac *down_dev;
8227	struct bwn_mac *mac;
8228	int err, status;
8229	uint8_t gmode;
8230
8231	BWN_ASSERT_LOCKED(sc);
8232
8233	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8234		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8235		    mac->mac_phy.supports_2ghz) {
8236			up_dev = mac;
8237			gmode = 1;
8238		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8239		    mac->mac_phy.supports_5ghz) {
8240			up_dev = mac;
8241			gmode = 0;
8242		} else {
8243			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8244			return (EINVAL);
8245		}
8246		if (up_dev != NULL)
8247			break;
8248	}
8249	if (up_dev == NULL) {
8250		device_printf(sc->sc_dev, "Could not find a device\n");
8251		return (ENODEV);
8252	}
8253	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8254		return (0);
8255
8256	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8257	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8258
8259	down_dev = sc->sc_curmac;
8260	status = down_dev->mac_status;
8261	if (status >= BWN_MAC_STATUS_STARTED)
8262		bwn_core_stop(down_dev);
8263	if (status >= BWN_MAC_STATUS_INITED)
8264		bwn_core_exit(down_dev);
8265
8266	if (down_dev != up_dev)
8267		bwn_phy_reset(down_dev);
8268
8269	up_dev->mac_phy.gmode = gmode;
8270	if (status >= BWN_MAC_STATUS_INITED) {
8271		err = bwn_core_init(up_dev);
8272		if (err) {
8273			device_printf(sc->sc_dev,
8274			    "fatal: failed to initialize for %s-GHz\n",
8275			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8276			goto fail;
8277		}
8278	}
8279	if (status >= BWN_MAC_STATUS_STARTED)
8280		bwn_core_start(up_dev);
8281	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8282	sc->sc_curmac = up_dev;
8283
8284	return (0);
8285fail:
8286	sc->sc_curmac = NULL;
8287	return (err);
8288}
8289
8290static void
8291bwn_rf_turnon(struct bwn_mac *mac)
8292{
8293
8294	bwn_mac_suspend(mac);
8295	mac->mac_phy.rf_onoff(mac, 1);
8296	mac->mac_phy.rf_on = 1;
8297	bwn_mac_enable(mac);
8298}
8299
8300static void
8301bwn_rf_turnoff(struct bwn_mac *mac)
8302{
8303
8304	bwn_mac_suspend(mac);
8305	mac->mac_phy.rf_onoff(mac, 0);
8306	mac->mac_phy.rf_on = 0;
8307	bwn_mac_enable(mac);
8308}
8309
8310static void
8311bwn_phy_reset(struct bwn_mac *mac)
8312{
8313	struct bwn_softc *sc = mac->mac_sc;
8314
8315	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8316	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8317	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8318	DELAY(1000);
8319	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8320	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8321	    BWN_TGSLOW_PHYRESET);
8322	DELAY(1000);
8323}
8324
8325static int
8326bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8327{
8328	struct bwn_vap *bvp = BWN_VAP(vap);
8329	struct ieee80211com *ic= vap->iv_ic;
8330	struct ifnet *ifp = ic->ic_ifp;
8331	enum ieee80211_state ostate = vap->iv_state;
8332	struct bwn_softc *sc = ifp->if_softc;
8333	struct bwn_mac *mac = sc->sc_curmac;
8334	int error;
8335
8336	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8337	    ieee80211_state_name[vap->iv_state],
8338	    ieee80211_state_name[nstate]);
8339
8340	error = bvp->bv_newstate(vap, nstate, arg);
8341	if (error != 0)
8342		return (error);
8343
8344	BWN_LOCK(sc);
8345
8346	bwn_led_newstate(mac, nstate);
8347
8348	/*
8349	 * Clear the BSSID when we stop a STA
8350	 */
8351	if (vap->iv_opmode == IEEE80211_M_STA) {
8352		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8353			/*
8354			 * Clear out the BSSID.  If we reassociate to
8355			 * the same AP, this will reinialize things
8356			 * correctly...
8357			 */
8358			if (ic->ic_opmode == IEEE80211_M_STA &&
8359			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8360				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8361				bwn_set_macaddr(mac);
8362			}
8363		}
8364	}
8365
8366	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8367	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8368		/* XXX nothing to do? */
8369	} else if (nstate == IEEE80211_S_RUN) {
8370		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8371		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8372		bwn_set_opmode(mac);
8373		bwn_set_pretbtt(mac);
8374		bwn_spu_setdelay(mac, 0);
8375		bwn_set_macaddr(mac);
8376	}
8377
8378	BWN_UNLOCK(sc);
8379
8380	return (error);
8381}
8382
8383static void
8384bwn_set_pretbtt(struct bwn_mac *mac)
8385{
8386	struct bwn_softc *sc = mac->mac_sc;
8387	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8388	uint16_t pretbtt;
8389
8390	if (ic->ic_opmode == IEEE80211_M_IBSS)
8391		pretbtt = 2;
8392	else
8393		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8394	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8395	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8396}
8397
8398static int
8399bwn_intr(void *arg)
8400{
8401	struct bwn_mac *mac = arg;
8402	struct bwn_softc *sc = mac->mac_sc;
8403	uint32_t reason;
8404
8405	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8406	    (sc->sc_flags & BWN_FLAG_INVALID))
8407		return (FILTER_STRAY);
8408
8409	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8410	if (reason == 0xffffffff)	/* shared IRQ */
8411		return (FILTER_STRAY);
8412	reason &= mac->mac_intr_mask;
8413	if (reason == 0)
8414		return (FILTER_HANDLED);
8415
8416	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8417	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8418	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8419	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8420	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8421	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8422	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8423	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8424	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8425	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8426	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8427
8428	/* Disable interrupts. */
8429	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8430
8431	mac->mac_reason_intr = reason;
8432
8433	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8434	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8435
8436	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8437	return (FILTER_HANDLED);
8438}
8439
8440static void
8441bwn_intrtask(void *arg, int npending)
8442{
8443	struct bwn_mac *mac = arg;
8444	struct bwn_softc *sc = mac->mac_sc;
8445	struct ifnet *ifp = sc->sc_ifp;
8446	uint32_t merged = 0;
8447	int i, tx = 0, rx = 0;
8448
8449	BWN_LOCK(sc);
8450	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8451	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8452		BWN_UNLOCK(sc);
8453		return;
8454	}
8455
8456	for (i = 0; i < N(mac->mac_reason); i++)
8457		merged |= mac->mac_reason[i];
8458
8459	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8460		device_printf(sc->sc_dev, "MAC trans error\n");
8461
8462	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8463		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8464		mac->mac_phy.txerrors--;
8465		if (mac->mac_phy.txerrors == 0) {
8466			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8467			bwn_restart(mac, "PHY TX errors");
8468		}
8469	}
8470
8471	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8472		if (merged & BWN_DMAINTR_FATALMASK) {
8473			device_printf(sc->sc_dev,
8474			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8475			    mac->mac_reason[0], mac->mac_reason[1],
8476			    mac->mac_reason[2], mac->mac_reason[3],
8477			    mac->mac_reason[4], mac->mac_reason[5]);
8478			bwn_restart(mac, "DMA error");
8479			BWN_UNLOCK(sc);
8480			return;
8481		}
8482		if (merged & BWN_DMAINTR_NONFATALMASK) {
8483			device_printf(sc->sc_dev,
8484			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8485			    mac->mac_reason[0], mac->mac_reason[1],
8486			    mac->mac_reason[2], mac->mac_reason[3],
8487			    mac->mac_reason[4], mac->mac_reason[5]);
8488		}
8489	}
8490
8491	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8492		bwn_intr_ucode_debug(mac);
8493	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8494		bwn_intr_tbtt_indication(mac);
8495	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8496		bwn_intr_atim_end(mac);
8497	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8498		bwn_intr_beacon(mac);
8499	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8500		bwn_intr_pmq(mac);
8501	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8502		bwn_intr_noise(mac);
8503
8504	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8505		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8506			bwn_dma_rx(mac->mac_method.dma.rx);
8507			rx = 1;
8508		}
8509	} else
8510		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8511
8512	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8513	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517
8518	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8519		bwn_intr_txeof(mac);
8520		tx = 1;
8521	}
8522
8523	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8524
8525	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8526		int evt = BWN_LED_EVENT_NONE;
8527
8528		if (tx && rx) {
8529			if (sc->sc_rx_rate > sc->sc_tx_rate)
8530				evt = BWN_LED_EVENT_RX;
8531			else
8532				evt = BWN_LED_EVENT_TX;
8533		} else if (tx) {
8534			evt = BWN_LED_EVENT_TX;
8535		} else if (rx) {
8536			evt = BWN_LED_EVENT_RX;
8537		} else if (rx == 0) {
8538			evt = BWN_LED_EVENT_POLL;
8539		}
8540
8541		if (evt != BWN_LED_EVENT_NONE)
8542			bwn_led_event(mac, evt);
8543       }
8544
8545	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8546		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8547			bwn_start_locked(ifp);
8548	}
8549
8550	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8551	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8552
8553	BWN_UNLOCK(sc);
8554}
8555
8556static void
8557bwn_restart(struct bwn_mac *mac, const char *msg)
8558{
8559	struct bwn_softc *sc = mac->mac_sc;
8560	struct ifnet *ifp = sc->sc_ifp;
8561	struct ieee80211com *ic = ifp->if_l2com;
8562
8563	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8564		return;
8565
8566	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8567	ieee80211_runtask(ic, &mac->mac_hwreset);
8568}
8569
8570static void
8571bwn_intr_ucode_debug(struct bwn_mac *mac)
8572{
8573	struct bwn_softc *sc = mac->mac_sc;
8574	uint16_t reason;
8575
8576	if (mac->mac_fw.opensource == 0)
8577		return;
8578
8579	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8580	switch (reason) {
8581	case BWN_DEBUGINTR_PANIC:
8582		bwn_handle_fwpanic(mac);
8583		break;
8584	case BWN_DEBUGINTR_DUMP_SHM:
8585		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8586		break;
8587	case BWN_DEBUGINTR_DUMP_REGS:
8588		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8589		break;
8590	case BWN_DEBUGINTR_MARKER:
8591		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8592		break;
8593	default:
8594		device_printf(sc->sc_dev,
8595		    "ucode debug unknown reason: %#x\n", reason);
8596	}
8597
8598	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8599	    BWN_DEBUGINTR_ACK);
8600}
8601
8602static void
8603bwn_intr_tbtt_indication(struct bwn_mac *mac)
8604{
8605	struct bwn_softc *sc = mac->mac_sc;
8606	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8607
8608	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8609		bwn_psctl(mac, 0);
8610	if (ic->ic_opmode == IEEE80211_M_IBSS)
8611		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8612}
8613
8614static void
8615bwn_intr_atim_end(struct bwn_mac *mac)
8616{
8617
8618	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8619		BWN_WRITE_4(mac, BWN_MACCMD,
8620		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8621		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8622	}
8623}
8624
8625static void
8626bwn_intr_beacon(struct bwn_mac *mac)
8627{
8628	struct bwn_softc *sc = mac->mac_sc;
8629	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8630	uint32_t cmd, beacon0, beacon1;
8631
8632	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8633	    ic->ic_opmode == IEEE80211_M_MBSS)
8634		return;
8635
8636	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8637
8638	cmd = BWN_READ_4(mac, BWN_MACCMD);
8639	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8640	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8641
8642	if (beacon0 && beacon1) {
8643		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8644		mac->mac_intr_mask |= BWN_INTR_BEACON;
8645		return;
8646	}
8647
8648	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8649		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8650		bwn_load_beacon0(mac);
8651		bwn_load_beacon1(mac);
8652		cmd = BWN_READ_4(mac, BWN_MACCMD);
8653		cmd |= BWN_MACCMD_BEACON0_VALID;
8654		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8655	} else {
8656		if (!beacon0) {
8657			bwn_load_beacon0(mac);
8658			cmd = BWN_READ_4(mac, BWN_MACCMD);
8659			cmd |= BWN_MACCMD_BEACON0_VALID;
8660			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8661		} else if (!beacon1) {
8662			bwn_load_beacon1(mac);
8663			cmd = BWN_READ_4(mac, BWN_MACCMD);
8664			cmd |= BWN_MACCMD_BEACON1_VALID;
8665			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8666		}
8667	}
8668}
8669
8670static void
8671bwn_intr_pmq(struct bwn_mac *mac)
8672{
8673	uint32_t tmp;
8674
8675	while (1) {
8676		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8677		if (!(tmp & 0x00000008))
8678			break;
8679	}
8680	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8681}
8682
8683static void
8684bwn_intr_noise(struct bwn_mac *mac)
8685{
8686	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8687	uint16_t tmp;
8688	uint8_t noise[4];
8689	uint8_t i, j;
8690	int32_t average;
8691
8692	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8693		return;
8694
8695	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8696	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8697	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8698	    noise[3] == 0x7f)
8699		goto new;
8700
8701	KASSERT(mac->mac_noise.noi_nsamples < 8,
8702	    ("%s:%d: fail", __func__, __LINE__));
8703	i = mac->mac_noise.noi_nsamples;
8704	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8705	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8706	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8707	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8708	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8709	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8710	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8711	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8712	mac->mac_noise.noi_nsamples++;
8713	if (mac->mac_noise.noi_nsamples == 8) {
8714		average = 0;
8715		for (i = 0; i < 8; i++) {
8716			for (j = 0; j < 4; j++)
8717				average += mac->mac_noise.noi_samples[i][j];
8718		}
8719		average = (((average / 32) * 125) + 64) / 128;
8720		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8721		if (tmp >= 8)
8722			average += 2;
8723		else
8724			average -= 25;
8725		average -= (tmp == 8) ? 72 : 48;
8726
8727		mac->mac_stats.link_noise = average;
8728		mac->mac_noise.noi_running = 0;
8729		return;
8730	}
8731new:
8732	bwn_noise_gensample(mac);
8733}
8734
8735static int
8736bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8737{
8738	struct bwn_mac *mac = prq->prq_mac;
8739	struct bwn_softc *sc = mac->mac_sc;
8740	unsigned int i;
8741
8742	BWN_ASSERT_LOCKED(sc);
8743
8744	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8745		return (0);
8746
8747	for (i = 0; i < 5000; i++) {
8748		if (bwn_pio_rxeof(prq) == 0)
8749			break;
8750	}
8751	if (i >= 5000)
8752		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8753	return ((i > 0) ? 1 : 0);
8754}
8755
8756static void
8757bwn_dma_rx(struct bwn_dma_ring *dr)
8758{
8759	int slot, curslot;
8760
8761	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8762	curslot = dr->get_curslot(dr);
8763	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8764	    ("%s:%d: fail", __func__, __LINE__));
8765
8766	slot = dr->dr_curslot;
8767	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8768		bwn_dma_rxeof(dr, &slot);
8769
8770	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8771	    BUS_DMASYNC_PREWRITE);
8772
8773	dr->set_curslot(dr, slot);
8774	dr->dr_curslot = slot;
8775}
8776
8777static void
8778bwn_intr_txeof(struct bwn_mac *mac)
8779{
8780	struct bwn_txstatus stat;
8781	uint32_t stat0, stat1;
8782	uint16_t tmp;
8783
8784	BWN_ASSERT_LOCKED(mac->mac_sc);
8785
8786	while (1) {
8787		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8788		if (!(stat0 & 0x00000001))
8789			break;
8790		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8791
8792		stat.cookie = (stat0 >> 16);
8793		stat.seq = (stat1 & 0x0000ffff);
8794		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8795		tmp = (stat0 & 0x0000ffff);
8796		stat.framecnt = ((tmp & 0xf000) >> 12);
8797		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8798		stat.sreason = ((tmp & 0x001c) >> 2);
8799		stat.pm = (tmp & 0x0080) ? 1 : 0;
8800		stat.im = (tmp & 0x0040) ? 1 : 0;
8801		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8802		stat.ack = (tmp & 0x0002) ? 1 : 0;
8803
8804		bwn_handle_txeof(mac, &stat);
8805	}
8806}
8807
8808static void
8809bwn_hwreset(void *arg, int npending)
8810{
8811	struct bwn_mac *mac = arg;
8812	struct bwn_softc *sc = mac->mac_sc;
8813	int error = 0;
8814	int prev_status;
8815
8816	BWN_LOCK(sc);
8817
8818	prev_status = mac->mac_status;
8819	if (prev_status >= BWN_MAC_STATUS_STARTED)
8820		bwn_core_stop(mac);
8821	if (prev_status >= BWN_MAC_STATUS_INITED)
8822		bwn_core_exit(mac);
8823
8824	if (prev_status >= BWN_MAC_STATUS_INITED) {
8825		error = bwn_core_init(mac);
8826		if (error)
8827			goto out;
8828	}
8829	if (prev_status >= BWN_MAC_STATUS_STARTED)
8830		bwn_core_start(mac);
8831out:
8832	if (error) {
8833		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8834		sc->sc_curmac = NULL;
8835	}
8836	BWN_UNLOCK(sc);
8837}
8838
8839static void
8840bwn_handle_fwpanic(struct bwn_mac *mac)
8841{
8842	struct bwn_softc *sc = mac->mac_sc;
8843	uint16_t reason;
8844
8845	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8846	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8847
8848	if (reason == BWN_FWPANIC_RESTART)
8849		bwn_restart(mac, "ucode panic");
8850}
8851
8852static void
8853bwn_load_beacon0(struct bwn_mac *mac)
8854{
8855
8856	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8857}
8858
8859static void
8860bwn_load_beacon1(struct bwn_mac *mac)
8861{
8862
8863	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8864}
8865
8866static uint32_t
8867bwn_jssi_read(struct bwn_mac *mac)
8868{
8869	uint32_t val = 0;
8870
8871	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8872	val <<= 16;
8873	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8874
8875	return (val);
8876}
8877
8878static void
8879bwn_noise_gensample(struct bwn_mac *mac)
8880{
8881	uint32_t jssi = 0x7f7f7f7f;
8882
8883	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8884	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8885	BWN_WRITE_4(mac, BWN_MACCMD,
8886	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8887}
8888
8889static int
8890bwn_dma_freeslot(struct bwn_dma_ring *dr)
8891{
8892	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8893
8894	return (dr->dr_numslots - dr->dr_usedslot);
8895}
8896
8897static int
8898bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8899{
8900	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8901
8902	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8903	    ("%s:%d: fail", __func__, __LINE__));
8904	if (slot == dr->dr_numslots - 1)
8905		return (0);
8906	return (slot + 1);
8907}
8908
8909static void
8910bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8911{
8912	struct bwn_mac *mac = dr->dr_mac;
8913	struct bwn_softc *sc = mac->mac_sc;
8914	struct bwn_dma *dma = &mac->mac_method.dma;
8915	struct bwn_dmadesc_generic *desc;
8916	struct bwn_dmadesc_meta *meta;
8917	struct bwn_rxhdr4 *rxhdr;
8918	struct ifnet *ifp = sc->sc_ifp;
8919	struct mbuf *m;
8920	uint32_t macstat;
8921	int32_t tmp;
8922	int cnt = 0;
8923	uint16_t len;
8924
8925	dr->getdesc(dr, *slot, &desc, &meta);
8926
8927	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8928	m = meta->mt_m;
8929
8930	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8931		ifp->if_ierrors++;
8932		return;
8933	}
8934
8935	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8936	len = le16toh(rxhdr->frame_len);
8937	if (len <= 0) {
8938		ifp->if_ierrors++;
8939		return;
8940	}
8941	if (bwn_dma_check_redzone(dr, m)) {
8942		device_printf(sc->sc_dev, "redzone error.\n");
8943		bwn_dma_set_redzone(dr, m);
8944		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8945		    BUS_DMASYNC_PREWRITE);
8946		return;
8947	}
8948	if (len > dr->dr_rx_bufsize) {
8949		tmp = len;
8950		while (1) {
8951			dr->getdesc(dr, *slot, &desc, &meta);
8952			bwn_dma_set_redzone(dr, meta->mt_m);
8953			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8954			    BUS_DMASYNC_PREWRITE);
8955			*slot = bwn_dma_nextslot(dr, *slot);
8956			cnt++;
8957			tmp -= dr->dr_rx_bufsize;
8958			if (tmp <= 0)
8959				break;
8960		}
8961		device_printf(sc->sc_dev, "too small buffer "
8962		       "(len %u buffer %u dropped %d)\n",
8963		       len, dr->dr_rx_bufsize, cnt);
8964		return;
8965	}
8966	macstat = le32toh(rxhdr->mac_status);
8967	if (macstat & BWN_RX_MAC_FCSERR) {
8968		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8969			device_printf(sc->sc_dev, "RX drop\n");
8970			return;
8971		}
8972	}
8973
8974	m->m_pkthdr.rcvif = ifp;
8975	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8976	m_adj(m, dr->dr_frameoffset);
8977
8978	bwn_rxeof(dr->dr_mac, m, rxhdr);
8979}
8980
8981static void
8982bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8983{
8984	struct bwn_dma_ring *dr;
8985	struct bwn_dmadesc_generic *desc;
8986	struct bwn_dmadesc_meta *meta;
8987	struct bwn_pio_txqueue *tq;
8988	struct bwn_pio_txpkt *tp = NULL;
8989	struct bwn_softc *sc = mac->mac_sc;
8990	struct bwn_stats *stats = &mac->mac_stats;
8991	struct ieee80211_node *ni;
8992	struct ieee80211vap *vap;
8993	int retrycnt = 0, slot;
8994
8995	BWN_ASSERT_LOCKED(mac->mac_sc);
8996
8997	if (status->im)
8998		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8999	if (status->ampdu)
9000		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9001	if (status->rtscnt) {
9002		if (status->rtscnt == 0xf)
9003			stats->rtsfail++;
9004		else
9005			stats->rts++;
9006	}
9007
9008	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9009		if (status->ack) {
9010			dr = bwn_dma_parse_cookie(mac, status,
9011			    status->cookie, &slot);
9012			if (dr == NULL) {
9013				device_printf(sc->sc_dev,
9014				    "failed to parse cookie\n");
9015				return;
9016			}
9017			while (1) {
9018				dr->getdesc(dr, slot, &desc, &meta);
9019				if (meta->mt_islast) {
9020					ni = meta->mt_ni;
9021					vap = ni->ni_vap;
9022					ieee80211_ratectl_tx_complete(vap, ni,
9023					    status->ack ?
9024					      IEEE80211_RATECTL_TX_SUCCESS :
9025					      IEEE80211_RATECTL_TX_FAILURE,
9026					    &retrycnt, 0);
9027					break;
9028				}
9029				slot = bwn_dma_nextslot(dr, slot);
9030			}
9031		}
9032		bwn_dma_handle_txeof(mac, status);
9033	} else {
9034		if (status->ack) {
9035			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9036			if (tq == NULL) {
9037				device_printf(sc->sc_dev,
9038				    "failed to parse cookie\n");
9039				return;
9040			}
9041			ni = tp->tp_ni;
9042			vap = ni->ni_vap;
9043			ieee80211_ratectl_tx_complete(vap, ni,
9044			    status->ack ?
9045			      IEEE80211_RATECTL_TX_SUCCESS :
9046			      IEEE80211_RATECTL_TX_FAILURE,
9047			    &retrycnt, 0);
9048		}
9049		bwn_pio_handle_txeof(mac, status);
9050	}
9051
9052	bwn_phy_txpower_check(mac, 0);
9053}
9054
9055static uint8_t
9056bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9057{
9058	struct bwn_mac *mac = prq->prq_mac;
9059	struct bwn_softc *sc = mac->mac_sc;
9060	struct bwn_rxhdr4 rxhdr;
9061	struct ifnet *ifp = sc->sc_ifp;
9062	struct mbuf *m;
9063	uint32_t ctl32, macstat, v32;
9064	unsigned int i, padding;
9065	uint16_t ctl16, len, totlen, v16;
9066	unsigned char *mp;
9067	char *data;
9068
9069	memset(&rxhdr, 0, sizeof(rxhdr));
9070
9071	if (prq->prq_rev >= 8) {
9072		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9073		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9074			return (0);
9075		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9076		    BWN_PIO8_RXCTL_FRAMEREADY);
9077		for (i = 0; i < 10; i++) {
9078			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9079			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9080				goto ready;
9081			DELAY(10);
9082		}
9083	} else {
9084		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9085		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9086			return (0);
9087		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9088		    BWN_PIO_RXCTL_FRAMEREADY);
9089		for (i = 0; i < 10; i++) {
9090			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9091			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9092				goto ready;
9093			DELAY(10);
9094		}
9095	}
9096	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9097	return (1);
9098ready:
9099	if (prq->prq_rev >= 8)
9100		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9101		    prq->prq_base + BWN_PIO8_RXDATA);
9102	else
9103		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9104		    prq->prq_base + BWN_PIO_RXDATA);
9105	len = le16toh(rxhdr.frame_len);
9106	if (len > 0x700) {
9107		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9108		goto error;
9109	}
9110	if (len == 0) {
9111		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9112		goto error;
9113	}
9114
9115	macstat = le32toh(rxhdr.mac_status);
9116	if (macstat & BWN_RX_MAC_FCSERR) {
9117		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9118			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9119			goto error;
9120		}
9121	}
9122
9123	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9124	totlen = len + padding;
9125	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9126	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9127	if (m == NULL) {
9128		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9129		goto error;
9130	}
9131	mp = mtod(m, unsigned char *);
9132	if (prq->prq_rev >= 8) {
9133		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9134		    prq->prq_base + BWN_PIO8_RXDATA);
9135		if (totlen & 3) {
9136			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9137			data = &(mp[totlen - 1]);
9138			switch (totlen & 3) {
9139			case 3:
9140				*data = (v32 >> 16);
9141				data--;
9142			case 2:
9143				*data = (v32 >> 8);
9144				data--;
9145			case 1:
9146				*data = v32;
9147			}
9148		}
9149	} else {
9150		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9151		    prq->prq_base + BWN_PIO_RXDATA);
9152		if (totlen & 1) {
9153			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9154			mp[totlen - 1] = v16;
9155		}
9156	}
9157
9158	m->m_pkthdr.rcvif = ifp;
9159	m->m_len = m->m_pkthdr.len = totlen;
9160
9161	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9162
9163	return (1);
9164error:
9165	if (prq->prq_rev >= 8)
9166		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9167		    BWN_PIO8_RXCTL_DATAREADY);
9168	else
9169		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9170	return (1);
9171}
9172
9173static int
9174bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9175    struct bwn_dmadesc_meta *meta, int init)
9176{
9177	struct bwn_mac *mac = dr->dr_mac;
9178	struct bwn_dma *dma = &mac->mac_method.dma;
9179	struct bwn_rxhdr4 *hdr;
9180	bus_dmamap_t map;
9181	bus_addr_t paddr;
9182	struct mbuf *m;
9183	int error;
9184
9185	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9186	if (m == NULL) {
9187		error = ENOBUFS;
9188
9189		/*
9190		 * If the NIC is up and running, we need to:
9191		 * - Clear RX buffer's header.
9192		 * - Restore RX descriptor settings.
9193		 */
9194		if (init)
9195			return (error);
9196		else
9197			goto back;
9198	}
9199	m->m_len = m->m_pkthdr.len = MCLBYTES;
9200
9201	bwn_dma_set_redzone(dr, m);
9202
9203	/*
9204	 * Try to load RX buf into temporary DMA map
9205	 */
9206	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9207	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9208	if (error) {
9209		m_freem(m);
9210
9211		/*
9212		 * See the comment above
9213		 */
9214		if (init)
9215			return (error);
9216		else
9217			goto back;
9218	}
9219
9220	if (!init)
9221		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9222	meta->mt_m = m;
9223	meta->mt_paddr = paddr;
9224
9225	/*
9226	 * Swap RX buf's DMA map with the loaded temporary one
9227	 */
9228	map = meta->mt_dmap;
9229	meta->mt_dmap = dr->dr_spare_dmap;
9230	dr->dr_spare_dmap = map;
9231
9232back:
9233	/*
9234	 * Clear RX buf header
9235	 */
9236	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9237	bzero(hdr, sizeof(*hdr));
9238	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9239	    BUS_DMASYNC_PREWRITE);
9240
9241	/*
9242	 * Setup RX buf descriptor
9243	 */
9244	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9245	    sizeof(*hdr), 0, 0, 0);
9246	return (error);
9247}
9248
9249static void
9250bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9251		 bus_size_t mapsz __unused, int error)
9252{
9253
9254	if (!error) {
9255		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9256		*((bus_addr_t *)arg) = seg->ds_addr;
9257	}
9258}
9259
9260static int
9261bwn_hwrate2ieeerate(int rate)
9262{
9263
9264	switch (rate) {
9265	case BWN_CCK_RATE_1MB:
9266		return (2);
9267	case BWN_CCK_RATE_2MB:
9268		return (4);
9269	case BWN_CCK_RATE_5MB:
9270		return (11);
9271	case BWN_CCK_RATE_11MB:
9272		return (22);
9273	case BWN_OFDM_RATE_6MB:
9274		return (12);
9275	case BWN_OFDM_RATE_9MB:
9276		return (18);
9277	case BWN_OFDM_RATE_12MB:
9278		return (24);
9279	case BWN_OFDM_RATE_18MB:
9280		return (36);
9281	case BWN_OFDM_RATE_24MB:
9282		return (48);
9283	case BWN_OFDM_RATE_36MB:
9284		return (72);
9285	case BWN_OFDM_RATE_48MB:
9286		return (96);
9287	case BWN_OFDM_RATE_54MB:
9288		return (108);
9289	default:
9290		printf("Ooops\n");
9291		return (0);
9292	}
9293}
9294
9295static void
9296bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9297{
9298	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9299	struct bwn_plcp6 *plcp;
9300	struct bwn_softc *sc = mac->mac_sc;
9301	struct ieee80211_frame_min *wh;
9302	struct ieee80211_node *ni;
9303	struct ifnet *ifp = sc->sc_ifp;
9304	struct ieee80211com *ic = ifp->if_l2com;
9305	uint32_t macstat;
9306	int padding, rate, rssi = 0, noise = 0, type;
9307	uint16_t phytype, phystat0, phystat3, chanstat;
9308	unsigned char *mp = mtod(m, unsigned char *);
9309	static int rx_mac_dec_rpt = 0;
9310
9311	BWN_ASSERT_LOCKED(sc);
9312
9313	phystat0 = le16toh(rxhdr->phy_status0);
9314	phystat3 = le16toh(rxhdr->phy_status3);
9315	macstat = le32toh(rxhdr->mac_status);
9316	chanstat = le16toh(rxhdr->channel);
9317	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9318
9319	if (macstat & BWN_RX_MAC_FCSERR)
9320		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9321	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9322		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9323	if (macstat & BWN_RX_MAC_DECERR)
9324		goto drop;
9325
9326	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9327	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9328		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9329		    m->m_pkthdr.len);
9330		goto drop;
9331	}
9332	plcp = (struct bwn_plcp6 *)(mp + padding);
9333	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9334	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9335		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9336		    m->m_pkthdr.len);
9337		goto drop;
9338	}
9339	wh = mtod(m, struct ieee80211_frame_min *);
9340
9341	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9342		device_printf(sc->sc_dev,
9343		    "RX decryption attempted (old %d keyidx %#x)\n",
9344		    BWN_ISOLDFMT(mac),
9345		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9346
9347	/* XXX calculating RSSI & noise & antenna */
9348
9349	if (phystat0 & BWN_RX_PHYST0_OFDM)
9350		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9351		    phytype == BWN_PHYTYPE_A);
9352	else
9353		rate = bwn_plcp_get_cckrate(mac, plcp);
9354	if (rate == -1) {
9355		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9356			goto drop;
9357	}
9358	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9359
9360	/* RX radio tap */
9361	if (ieee80211_radiotap_active(ic))
9362		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9363	m_adj(m, -IEEE80211_CRC_LEN);
9364
9365	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9366	noise = mac->mac_stats.link_noise;
9367
9368	ifp->if_ipackets++;
9369
9370	BWN_UNLOCK(sc);
9371
9372	ni = ieee80211_find_rxnode(ic, wh);
9373	if (ni != NULL) {
9374		type = ieee80211_input(ni, m, rssi, noise);
9375		ieee80211_free_node(ni);
9376	} else
9377		type = ieee80211_input_all(ic, m, rssi, noise);
9378
9379	BWN_LOCK(sc);
9380	return;
9381drop:
9382	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9383}
9384
9385static void
9386bwn_dma_handle_txeof(struct bwn_mac *mac,
9387    const struct bwn_txstatus *status)
9388{
9389	struct bwn_dma *dma = &mac->mac_method.dma;
9390	struct bwn_dma_ring *dr;
9391	struct bwn_dmadesc_generic *desc;
9392	struct bwn_dmadesc_meta *meta;
9393	struct bwn_softc *sc = mac->mac_sc;
9394	struct ieee80211_node *ni;
9395	struct ifnet *ifp = sc->sc_ifp;
9396	struct mbuf *m;
9397	int slot;
9398
9399	BWN_ASSERT_LOCKED(sc);
9400
9401	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9402	if (dr == NULL) {
9403		device_printf(sc->sc_dev, "failed to parse cookie\n");
9404		return;
9405	}
9406	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9407
9408	while (1) {
9409		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9410		    ("%s:%d: fail", __func__, __LINE__));
9411		dr->getdesc(dr, slot, &desc, &meta);
9412
9413		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9414			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9415		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9416			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9417
9418		if (meta->mt_islast) {
9419			KASSERT(meta->mt_m != NULL,
9420			    ("%s:%d: fail", __func__, __LINE__));
9421
9422			ni = meta->mt_ni;
9423			m = meta->mt_m;
9424			if (ni != NULL) {
9425				/*
9426				 * Do any tx complete callback. Note this must
9427				 * be done before releasing the node reference.
9428				 */
9429				if (m->m_flags & M_TXCB)
9430					ieee80211_process_callback(ni, m, 0);
9431				ieee80211_free_node(ni);
9432				meta->mt_ni = NULL;
9433			}
9434			m_freem(m);
9435			meta->mt_m = NULL;
9436		} else {
9437			KASSERT(meta->mt_m == NULL,
9438			    ("%s:%d: fail", __func__, __LINE__));
9439		}
9440
9441		dr->dr_usedslot--;
9442		if (meta->mt_islast) {
9443			ifp->if_opackets++;
9444			break;
9445		}
9446		slot = bwn_dma_nextslot(dr, slot);
9447	}
9448	sc->sc_watchdog_timer = 0;
9449	if (dr->dr_stop) {
9450		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9451		    ("%s:%d: fail", __func__, __LINE__));
9452		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9453		dr->dr_stop = 0;
9454	}
9455}
9456
9457static void
9458bwn_pio_handle_txeof(struct bwn_mac *mac,
9459    const struct bwn_txstatus *status)
9460{
9461	struct bwn_pio_txqueue *tq;
9462	struct bwn_pio_txpkt *tp = NULL;
9463	struct bwn_softc *sc = mac->mac_sc;
9464	struct ifnet *ifp = sc->sc_ifp;
9465
9466	BWN_ASSERT_LOCKED(sc);
9467
9468	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9469	if (tq == NULL)
9470		return;
9471
9472	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9473	tq->tq_free++;
9474
9475	if (tp->tp_ni != NULL) {
9476		/*
9477		 * Do any tx complete callback.  Note this must
9478		 * be done before releasing the node reference.
9479		 */
9480		if (tp->tp_m->m_flags & M_TXCB)
9481			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9482		ieee80211_free_node(tp->tp_ni);
9483		tp->tp_ni = NULL;
9484	}
9485	m_freem(tp->tp_m);
9486	tp->tp_m = NULL;
9487	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9488
9489	ifp->if_opackets++;
9490
9491	sc->sc_watchdog_timer = 0;
9492	if (tq->tq_stop) {
9493		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9494		tq->tq_stop = 0;
9495	}
9496}
9497
9498static void
9499bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9500{
9501	struct bwn_softc *sc = mac->mac_sc;
9502	struct bwn_phy *phy = &mac->mac_phy;
9503	struct ifnet *ifp = sc->sc_ifp;
9504	struct ieee80211com *ic = ifp->if_l2com;
9505	unsigned long now;
9506	int result;
9507
9508	BWN_GETTIME(now);
9509
9510	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9511		return;
9512	phy->nexttime = now + 2 * 1000;
9513
9514	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9515	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9516		return;
9517
9518	if (phy->recalc_txpwr != NULL) {
9519		result = phy->recalc_txpwr(mac,
9520		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9521		if (result == BWN_TXPWR_RES_DONE)
9522			return;
9523		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9524		    ("%s: fail", __func__));
9525		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9526
9527		ieee80211_runtask(ic, &mac->mac_txpower);
9528	}
9529}
9530
9531static uint16_t
9532bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9533{
9534
9535	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9536}
9537
9538static uint32_t
9539bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9540{
9541
9542	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9543}
9544
9545static void
9546bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9547{
9548
9549	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9550}
9551
9552static void
9553bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9554{
9555
9556	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9557}
9558
9559static int
9560bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9561{
9562
9563	switch (rate) {
9564	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9565	case 12:
9566		return (BWN_OFDM_RATE_6MB);
9567	case 18:
9568		return (BWN_OFDM_RATE_9MB);
9569	case 24:
9570		return (BWN_OFDM_RATE_12MB);
9571	case 36:
9572		return (BWN_OFDM_RATE_18MB);
9573	case 48:
9574		return (BWN_OFDM_RATE_24MB);
9575	case 72:
9576		return (BWN_OFDM_RATE_36MB);
9577	case 96:
9578		return (BWN_OFDM_RATE_48MB);
9579	case 108:
9580		return (BWN_OFDM_RATE_54MB);
9581	/* CCK rates (NB: not IEEE std, device-specific) */
9582	case 2:
9583		return (BWN_CCK_RATE_1MB);
9584	case 4:
9585		return (BWN_CCK_RATE_2MB);
9586	case 11:
9587		return (BWN_CCK_RATE_5MB);
9588	case 22:
9589		return (BWN_CCK_RATE_11MB);
9590	}
9591
9592	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9593	return (BWN_CCK_RATE_1MB);
9594}
9595
9596static int
9597bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9598    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9599{
9600	const struct bwn_phy *phy = &mac->mac_phy;
9601	struct bwn_softc *sc = mac->mac_sc;
9602	struct ieee80211_frame *wh;
9603	struct ieee80211_frame *protwh;
9604	struct ieee80211_frame_cts *cts;
9605	struct ieee80211_frame_rts *rts;
9606	const struct ieee80211_txparam *tp;
9607	struct ieee80211vap *vap = ni->ni_vap;
9608	struct ifnet *ifp = sc->sc_ifp;
9609	struct ieee80211com *ic = ifp->if_l2com;
9610	struct mbuf *mprot;
9611	unsigned int len;
9612	uint32_t macctl = 0;
9613	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9614	uint16_t phyctl = 0;
9615	uint8_t rate, rate_fb;
9616
9617	wh = mtod(m, struct ieee80211_frame *);
9618	memset(txhdr, 0, sizeof(*txhdr));
9619
9620	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9621	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9622	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9623
9624	/*
9625	 * Find TX rate
9626	 */
9627	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9628	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9629		rate = rate_fb = tp->mgmtrate;
9630	else if (ismcast)
9631		rate = rate_fb = tp->mcastrate;
9632	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9633		rate = rate_fb = tp->ucastrate;
9634	else {
9635		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9636		rate = ni->ni_txrate;
9637
9638		if (rix > 0)
9639			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9640			    IEEE80211_RATE_VAL;
9641		else
9642			rate_fb = rate;
9643	}
9644
9645	sc->sc_tx_rate = rate;
9646
9647	rate = bwn_ieeerate2hwrate(sc, rate);
9648	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9649
9650	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9651	    bwn_plcp_getcck(rate);
9652	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9653	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9654
9655	if ((rate_fb == rate) ||
9656	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9657	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9658		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9659	else
9660		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9661		    m->m_pkthdr.len, rate, isshort);
9662
9663	/* XXX TX encryption */
9664	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9665	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9666	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9667	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9668	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9669	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9670
9671	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9672	    BWN_TX_EFT_FB_CCK;
9673	txhdr->chan = phy->chan;
9674	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9675	    BWN_TX_PHY_ENC_CCK;
9676	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9677	     rate == BWN_CCK_RATE_11MB))
9678		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9679
9680	/* XXX TX antenna selection */
9681
9682	switch (bwn_antenna_sanitize(mac, 0)) {
9683	case 0:
9684		phyctl |= BWN_TX_PHY_ANT01AUTO;
9685		break;
9686	case 1:
9687		phyctl |= BWN_TX_PHY_ANT0;
9688		break;
9689	case 2:
9690		phyctl |= BWN_TX_PHY_ANT1;
9691		break;
9692	case 3:
9693		phyctl |= BWN_TX_PHY_ANT2;
9694		break;
9695	case 4:
9696		phyctl |= BWN_TX_PHY_ANT3;
9697		break;
9698	default:
9699		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9700	}
9701
9702	if (!ismcast)
9703		macctl |= BWN_TX_MAC_ACK;
9704
9705	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9706	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9707	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9708		macctl |= BWN_TX_MAC_LONGFRAME;
9709
9710	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9711		/* XXX RTS rate is always 1MB??? */
9712		rts_rate = BWN_CCK_RATE_1MB;
9713		rts_rate_fb = bwn_get_fbrate(rts_rate);
9714
9715		protdur = ieee80211_compute_duration(ic->ic_rt,
9716		    m->m_pkthdr.len, rate, isshort) +
9717		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9718
9719		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9720			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9721			    (txhdr->body.old.rts_frame) :
9722			    (txhdr->body.new.rts_frame));
9723			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9724			    protdur);
9725			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9726			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9727			    mprot->m_pkthdr.len);
9728			m_freem(mprot);
9729			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9730			len = sizeof(struct ieee80211_frame_cts);
9731		} else {
9732			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9733			    (txhdr->body.old.rts_frame) :
9734			    (txhdr->body.new.rts_frame));
9735			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9736			    isshort);
9737			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9738			    wh->i_addr2, protdur);
9739			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9740			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9741			    mprot->m_pkthdr.len);
9742			m_freem(mprot);
9743			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9744			len = sizeof(struct ieee80211_frame_rts);
9745		}
9746		len += IEEE80211_CRC_LEN;
9747		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9748		    &txhdr->body.old.rts_plcp :
9749		    &txhdr->body.new.rts_plcp), len, rts_rate);
9750		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9751		    rts_rate_fb);
9752
9753		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9754		    (&txhdr->body.old.rts_frame) :
9755		    (&txhdr->body.new.rts_frame));
9756		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9757
9758		if (BWN_ISOFDMRATE(rts_rate)) {
9759			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9760			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9761		} else {
9762			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9763			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9764		}
9765		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9766		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9767	}
9768
9769	if (BWN_ISOLDFMT(mac))
9770		txhdr->body.old.cookie = htole16(cookie);
9771	else
9772		txhdr->body.new.cookie = htole16(cookie);
9773
9774	txhdr->macctl = htole32(macctl);
9775	txhdr->phyctl = htole16(phyctl);
9776
9777	/*
9778	 * TX radio tap
9779	 */
9780	if (ieee80211_radiotap_active_vap(vap)) {
9781		sc->sc_tx_th.wt_flags = 0;
9782		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9783			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9784		if (isshort &&
9785		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9786		     rate == BWN_CCK_RATE_11MB))
9787			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9788		sc->sc_tx_th.wt_rate = rate;
9789
9790		ieee80211_radiotap_tx(vap, m);
9791	}
9792
9793	return (0);
9794}
9795
9796static void
9797bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9798    const uint8_t rate)
9799{
9800	uint32_t d, plen;
9801	uint8_t *raw = plcp->o.raw;
9802
9803	if (BWN_ISOFDMRATE(rate)) {
9804		d = bwn_plcp_getofdm(rate);
9805		KASSERT(!(octets & 0xf000),
9806		    ("%s:%d: fail", __func__, __LINE__));
9807		d |= (octets << 5);
9808		plcp->o.data = htole32(d);
9809	} else {
9810		plen = octets * 16 / rate;
9811		if ((octets * 16 % rate) > 0) {
9812			plen++;
9813			if ((rate == BWN_CCK_RATE_11MB)
9814			    && ((octets * 8 % 11) < 4)) {
9815				raw[1] = 0x84;
9816			} else
9817				raw[1] = 0x04;
9818		} else
9819			raw[1] = 0x04;
9820		plcp->o.data |= htole32(plen << 16);
9821		raw[0] = bwn_plcp_getcck(rate);
9822	}
9823}
9824
9825static uint8_t
9826bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9827{
9828	struct bwn_softc *sc = mac->mac_sc;
9829	uint8_t mask;
9830
9831	if (n == 0)
9832		return (0);
9833	if (mac->mac_phy.gmode)
9834		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9835	else
9836		mask = siba_sprom_get_ant_a(sc->sc_dev);
9837	if (!(mask & (1 << (n - 1))))
9838		return (0);
9839	return (n);
9840}
9841
9842static uint8_t
9843bwn_get_fbrate(uint8_t bitrate)
9844{
9845	switch (bitrate) {
9846	case BWN_CCK_RATE_1MB:
9847		return (BWN_CCK_RATE_1MB);
9848	case BWN_CCK_RATE_2MB:
9849		return (BWN_CCK_RATE_1MB);
9850	case BWN_CCK_RATE_5MB:
9851		return (BWN_CCK_RATE_2MB);
9852	case BWN_CCK_RATE_11MB:
9853		return (BWN_CCK_RATE_5MB);
9854	case BWN_OFDM_RATE_6MB:
9855		return (BWN_CCK_RATE_5MB);
9856	case BWN_OFDM_RATE_9MB:
9857		return (BWN_OFDM_RATE_6MB);
9858	case BWN_OFDM_RATE_12MB:
9859		return (BWN_OFDM_RATE_9MB);
9860	case BWN_OFDM_RATE_18MB:
9861		return (BWN_OFDM_RATE_12MB);
9862	case BWN_OFDM_RATE_24MB:
9863		return (BWN_OFDM_RATE_18MB);
9864	case BWN_OFDM_RATE_36MB:
9865		return (BWN_OFDM_RATE_24MB);
9866	case BWN_OFDM_RATE_48MB:
9867		return (BWN_OFDM_RATE_36MB);
9868	case BWN_OFDM_RATE_54MB:
9869		return (BWN_OFDM_RATE_48MB);
9870	}
9871	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9872	return (0);
9873}
9874
9875static uint32_t
9876bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9877    uint32_t ctl, const void *_data, int len)
9878{
9879	struct bwn_softc *sc = mac->mac_sc;
9880	uint32_t value = 0;
9881	const uint8_t *data = _data;
9882
9883	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9884	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9885	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9886
9887	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9888	    tq->tq_base + BWN_PIO8_TXDATA);
9889	if (len & 3) {
9890		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9891		    BWN_PIO8_TXCTL_24_31);
9892		data = &(data[len - 1]);
9893		switch (len & 3) {
9894		case 3:
9895			ctl |= BWN_PIO8_TXCTL_16_23;
9896			value |= (uint32_t)(*data) << 16;
9897			data--;
9898		case 2:
9899			ctl |= BWN_PIO8_TXCTL_8_15;
9900			value |= (uint32_t)(*data) << 8;
9901			data--;
9902		case 1:
9903			value |= (uint32_t)(*data);
9904		}
9905		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9906		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9907	}
9908
9909	return (ctl);
9910}
9911
9912static void
9913bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9914    uint16_t offset, uint32_t value)
9915{
9916
9917	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9918}
9919
9920static uint16_t
9921bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9922    uint16_t ctl, const void *_data, int len)
9923{
9924	struct bwn_softc *sc = mac->mac_sc;
9925	const uint8_t *data = _data;
9926
9927	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9928	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9929
9930	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9931	    tq->tq_base + BWN_PIO_TXDATA);
9932	if (len & 1) {
9933		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9934		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9935		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9936	}
9937
9938	return (ctl);
9939}
9940
9941static uint16_t
9942bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9943    uint16_t ctl, struct mbuf *m0)
9944{
9945	int i, j = 0;
9946	uint16_t data = 0;
9947	const uint8_t *buf;
9948	struct mbuf *m = m0;
9949
9950	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9951	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9952
9953	for (; m != NULL; m = m->m_next) {
9954		buf = mtod(m, const uint8_t *);
9955		for (i = 0; i < m->m_len; i++) {
9956			if (!((j++) % 2))
9957				data |= buf[i];
9958			else {
9959				data |= (buf[i] << 8);
9960				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9961				data = 0;
9962			}
9963		}
9964	}
9965	if (m0->m_pkthdr.len % 2) {
9966		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9967		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9968		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9969	}
9970
9971	return (ctl);
9972}
9973
9974static void
9975bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9976{
9977
9978	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9979		return;
9980	BWN_WRITE_2(mac, 0x684, 510 + time);
9981	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9982}
9983
9984static struct bwn_dma_ring *
9985bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9986{
9987
9988	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9989		return (mac->mac_method.dma.wme[WME_AC_BE]);
9990
9991	switch (prio) {
9992	case 3:
9993		return (mac->mac_method.dma.wme[WME_AC_VO]);
9994	case 2:
9995		return (mac->mac_method.dma.wme[WME_AC_VI]);
9996	case 0:
9997		return (mac->mac_method.dma.wme[WME_AC_BE]);
9998	case 1:
9999		return (mac->mac_method.dma.wme[WME_AC_BK]);
10000	}
10001	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10002	return (NULL);
10003}
10004
10005static int
10006bwn_dma_getslot(struct bwn_dma_ring *dr)
10007{
10008	int slot;
10009
10010	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10011
10012	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10013	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10014	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10015
10016	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10017	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10018	dr->dr_curslot = slot;
10019	dr->dr_usedslot++;
10020
10021	return (slot);
10022}
10023
10024static int
10025bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10026{
10027	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10028	unsigned int a, b, c, d;
10029	unsigned int avg;
10030	uint32_t tmp;
10031
10032	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10033	a = tmp & 0xff;
10034	b = (tmp >> 8) & 0xff;
10035	c = (tmp >> 16) & 0xff;
10036	d = (tmp >> 24) & 0xff;
10037	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10038	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10039		return (ENOENT);
10040	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10041	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10042	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10043
10044	if (ofdm) {
10045		a = (a + 32) & 0x3f;
10046		b = (b + 32) & 0x3f;
10047		c = (c + 32) & 0x3f;
10048		d = (d + 32) & 0x3f;
10049	}
10050
10051	avg = (a + b + c + d + 2) / 4;
10052	if (ofdm) {
10053		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10054		    & BWN_HF_4DB_CCK_POWERBOOST)
10055			avg = (avg >= 13) ? (avg - 13) : 0;
10056	}
10057	return (avg);
10058}
10059
10060static void
10061bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10062{
10063	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10064	int rfatt = *rfattp;
10065	int bbatt = *bbattp;
10066
10067	while (1) {
10068		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10069			break;
10070		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10071			break;
10072		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10073			break;
10074		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10075			break;
10076		if (bbatt > lo->bbatt.max) {
10077			bbatt -= 4;
10078			rfatt += 1;
10079			continue;
10080		}
10081		if (bbatt < lo->bbatt.min) {
10082			bbatt += 4;
10083			rfatt -= 1;
10084			continue;
10085		}
10086		if (rfatt > lo->rfatt.max) {
10087			rfatt -= 1;
10088			bbatt += 4;
10089			continue;
10090		}
10091		if (rfatt < lo->rfatt.min) {
10092			rfatt += 1;
10093			bbatt -= 4;
10094			continue;
10095		}
10096		break;
10097	}
10098
10099	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10100	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10101}
10102
10103static void
10104bwn_phy_lock(struct bwn_mac *mac)
10105{
10106	struct bwn_softc *sc = mac->mac_sc;
10107	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10108
10109	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10110	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10111
10112	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10113		bwn_psctl(mac, BWN_PS_AWAKE);
10114}
10115
10116static void
10117bwn_phy_unlock(struct bwn_mac *mac)
10118{
10119	struct bwn_softc *sc = mac->mac_sc;
10120	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10121
10122	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10123	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10124
10125	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10126		bwn_psctl(mac, 0);
10127}
10128
10129static void
10130bwn_rf_lock(struct bwn_mac *mac)
10131{
10132
10133	BWN_WRITE_4(mac, BWN_MACCTL,
10134	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10135	BWN_READ_4(mac, BWN_MACCTL);
10136	DELAY(10);
10137}
10138
10139static void
10140bwn_rf_unlock(struct bwn_mac *mac)
10141{
10142
10143	BWN_READ_2(mac, BWN_PHYVER);
10144	BWN_WRITE_4(mac, BWN_MACCTL,
10145	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10146}
10147
10148static struct bwn_pio_txqueue *
10149bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10150    struct bwn_pio_txpkt **pack)
10151{
10152	struct bwn_pio *pio = &mac->mac_method.pio;
10153	struct bwn_pio_txqueue *tq = NULL;
10154	unsigned int index;
10155
10156	switch (cookie & 0xf000) {
10157	case 0x1000:
10158		tq = &pio->wme[WME_AC_BK];
10159		break;
10160	case 0x2000:
10161		tq = &pio->wme[WME_AC_BE];
10162		break;
10163	case 0x3000:
10164		tq = &pio->wme[WME_AC_VI];
10165		break;
10166	case 0x4000:
10167		tq = &pio->wme[WME_AC_VO];
10168		break;
10169	case 0x5000:
10170		tq = &pio->mcast;
10171		break;
10172	}
10173	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10174	if (tq == NULL)
10175		return (NULL);
10176	index = (cookie & 0x0fff);
10177	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10178	if (index >= N(tq->tq_pkts))
10179		return (NULL);
10180	*pack = &tq->tq_pkts[index];
10181	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10182	return (tq);
10183}
10184
10185static void
10186bwn_txpwr(void *arg, int npending)
10187{
10188	struct bwn_mac *mac = arg;
10189	struct bwn_softc *sc = mac->mac_sc;
10190
10191	BWN_LOCK(sc);
10192	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10193	    mac->mac_phy.set_txpwr != NULL)
10194		mac->mac_phy.set_txpwr(mac);
10195	BWN_UNLOCK(sc);
10196}
10197
10198static void
10199bwn_task_15s(struct bwn_mac *mac)
10200{
10201	uint16_t reg;
10202
10203	if (mac->mac_fw.opensource) {
10204		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10205		if (reg) {
10206			bwn_restart(mac, "fw watchdog");
10207			return;
10208		}
10209		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10210	}
10211	if (mac->mac_phy.task_15s)
10212		mac->mac_phy.task_15s(mac);
10213
10214	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10215}
10216
10217static void
10218bwn_task_30s(struct bwn_mac *mac)
10219{
10220
10221	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10222		return;
10223	mac->mac_noise.noi_running = 1;
10224	mac->mac_noise.noi_nsamples = 0;
10225
10226	bwn_noise_gensample(mac);
10227}
10228
10229static void
10230bwn_task_60s(struct bwn_mac *mac)
10231{
10232
10233	if (mac->mac_phy.task_60s)
10234		mac->mac_phy.task_60s(mac);
10235	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10236}
10237
10238static void
10239bwn_tasks(void *arg)
10240{
10241	struct bwn_mac *mac = arg;
10242	struct bwn_softc *sc = mac->mac_sc;
10243
10244	BWN_ASSERT_LOCKED(sc);
10245	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10246		return;
10247
10248	if (mac->mac_task_state % 4 == 0)
10249		bwn_task_60s(mac);
10250	if (mac->mac_task_state % 2 == 0)
10251		bwn_task_30s(mac);
10252	bwn_task_15s(mac);
10253
10254	mac->mac_task_state++;
10255	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10256}
10257
10258static int
10259bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10260{
10261	struct bwn_softc *sc = mac->mac_sc;
10262
10263	KASSERT(a == 0, ("not support APHY\n"));
10264
10265	switch (plcp->o.raw[0] & 0xf) {
10266	case 0xb:
10267		return (BWN_OFDM_RATE_6MB);
10268	case 0xf:
10269		return (BWN_OFDM_RATE_9MB);
10270	case 0xa:
10271		return (BWN_OFDM_RATE_12MB);
10272	case 0xe:
10273		return (BWN_OFDM_RATE_18MB);
10274	case 0x9:
10275		return (BWN_OFDM_RATE_24MB);
10276	case 0xd:
10277		return (BWN_OFDM_RATE_36MB);
10278	case 0x8:
10279		return (BWN_OFDM_RATE_48MB);
10280	case 0xc:
10281		return (BWN_OFDM_RATE_54MB);
10282	}
10283	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10284	    plcp->o.raw[0] & 0xf);
10285	return (-1);
10286}
10287
10288static int
10289bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10290{
10291	struct bwn_softc *sc = mac->mac_sc;
10292
10293	switch (plcp->o.raw[0]) {
10294	case 0x0a:
10295		return (BWN_CCK_RATE_1MB);
10296	case 0x14:
10297		return (BWN_CCK_RATE_2MB);
10298	case 0x37:
10299		return (BWN_CCK_RATE_5MB);
10300	case 0x6e:
10301		return (BWN_CCK_RATE_11MB);
10302	}
10303	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10304	return (-1);
10305}
10306
10307static void
10308bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10309    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10310    int rssi, int noise)
10311{
10312	struct bwn_softc *sc = mac->mac_sc;
10313	const struct ieee80211_frame_min *wh;
10314	uint64_t tsf;
10315	uint16_t low_mactime_now;
10316
10317	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10318		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10319
10320	wh = mtod(m, const struct ieee80211_frame_min *);
10321	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10322		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10323
10324	bwn_tsf_read(mac, &tsf);
10325	low_mactime_now = tsf;
10326	tsf = tsf & ~0xffffULL;
10327	tsf += le16toh(rxhdr->mac_time);
10328	if (low_mactime_now < le16toh(rxhdr->mac_time))
10329		tsf -= 0x10000;
10330
10331	sc->sc_rx_th.wr_tsf = tsf;
10332	sc->sc_rx_th.wr_rate = rate;
10333	sc->sc_rx_th.wr_antsignal = rssi;
10334	sc->sc_rx_th.wr_antnoise = noise;
10335}
10336
10337static void
10338bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10339{
10340	uint32_t low, high;
10341
10342	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10343	    ("%s:%d: fail", __func__, __LINE__));
10344
10345	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10346	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10347	*tsf = high;
10348	*tsf <<= 32;
10349	*tsf |= low;
10350}
10351
10352static int
10353bwn_dma_attach(struct bwn_mac *mac)
10354{
10355	struct bwn_dma *dma = &mac->mac_method.dma;
10356	struct bwn_softc *sc = mac->mac_sc;
10357	bus_addr_t lowaddr = 0;
10358	int error;
10359
10360	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10361		return (0);
10362
10363	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10364
10365	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10366
10367	dma->dmatype = bwn_dma_gettype(mac);
10368	if (dma->dmatype == BWN_DMA_30BIT)
10369		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10370	else if (dma->dmatype == BWN_DMA_32BIT)
10371		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10372	else
10373		lowaddr = BUS_SPACE_MAXADDR;
10374
10375	/*
10376	 * Create top level DMA tag
10377	 */
10378	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10379			       BWN_ALIGN, 0,		/* alignment, bounds */
10380			       lowaddr,			/* lowaddr */
10381			       BUS_SPACE_MAXADDR,	/* highaddr */
10382			       NULL, NULL,		/* filter, filterarg */
10383			       MAXBSIZE,		/* maxsize */
10384			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10385			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10386			       0,			/* flags */
10387			       NULL, NULL,		/* lockfunc, lockarg */
10388			       &dma->parent_dtag);
10389	if (error) {
10390		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10391		return (error);
10392	}
10393
10394	/*
10395	 * Create TX/RX mbuf DMA tag
10396	 */
10397	error = bus_dma_tag_create(dma->parent_dtag,
10398				1,
10399				0,
10400				BUS_SPACE_MAXADDR,
10401				BUS_SPACE_MAXADDR,
10402				NULL, NULL,
10403				MCLBYTES,
10404				1,
10405				BUS_SPACE_MAXSIZE_32BIT,
10406				0,
10407				NULL, NULL,
10408				&dma->rxbuf_dtag);
10409	if (error) {
10410		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10411		goto fail0;
10412	}
10413	error = bus_dma_tag_create(dma->parent_dtag,
10414				1,
10415				0,
10416				BUS_SPACE_MAXADDR,
10417				BUS_SPACE_MAXADDR,
10418				NULL, NULL,
10419				MCLBYTES,
10420				1,
10421				BUS_SPACE_MAXSIZE_32BIT,
10422				0,
10423				NULL, NULL,
10424				&dma->txbuf_dtag);
10425	if (error) {
10426		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10427		goto fail1;
10428	}
10429
10430	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10431	if (!dma->wme[WME_AC_BK])
10432		goto fail2;
10433
10434	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10435	if (!dma->wme[WME_AC_BE])
10436		goto fail3;
10437
10438	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10439	if (!dma->wme[WME_AC_VI])
10440		goto fail4;
10441
10442	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10443	if (!dma->wme[WME_AC_VO])
10444		goto fail5;
10445
10446	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10447	if (!dma->mcast)
10448		goto fail6;
10449	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10450	if (!dma->rx)
10451		goto fail7;
10452
10453	return (error);
10454
10455fail7:	bwn_dma_ringfree(&dma->mcast);
10456fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10457fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10458fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10459fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10460fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10461fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10462fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10463	return (error);
10464}
10465
10466static struct bwn_dma_ring *
10467bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10468    uint16_t cookie, int *slot)
10469{
10470	struct bwn_dma *dma = &mac->mac_method.dma;
10471	struct bwn_dma_ring *dr;
10472	struct bwn_softc *sc = mac->mac_sc;
10473
10474	BWN_ASSERT_LOCKED(mac->mac_sc);
10475
10476	switch (cookie & 0xf000) {
10477	case 0x1000:
10478		dr = dma->wme[WME_AC_BK];
10479		break;
10480	case 0x2000:
10481		dr = dma->wme[WME_AC_BE];
10482		break;
10483	case 0x3000:
10484		dr = dma->wme[WME_AC_VI];
10485		break;
10486	case 0x4000:
10487		dr = dma->wme[WME_AC_VO];
10488		break;
10489	case 0x5000:
10490		dr = dma->mcast;
10491		break;
10492	default:
10493		dr = NULL;
10494		KASSERT(0 == 1,
10495		    ("invalid cookie value %d", cookie & 0xf000));
10496	}
10497	*slot = (cookie & 0x0fff);
10498	if (*slot < 0 || *slot >= dr->dr_numslots) {
10499		/*
10500		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10501		 * that it occurs events which have same H/W sequence numbers.
10502		 * When it's occurred just prints a WARNING msgs and ignores.
10503		 */
10504		KASSERT(status->seq == dma->lastseq,
10505		    ("%s:%d: fail", __func__, __LINE__));
10506		device_printf(sc->sc_dev,
10507		    "out of slot ranges (0 < %d < %d)\n", *slot,
10508		    dr->dr_numslots);
10509		return (NULL);
10510	}
10511	dma->lastseq = status->seq;
10512	return (dr);
10513}
10514
10515static void
10516bwn_dma_stop(struct bwn_mac *mac)
10517{
10518	struct bwn_dma *dma;
10519
10520	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10521		return;
10522	dma = &mac->mac_method.dma;
10523
10524	bwn_dma_ringstop(&dma->rx);
10525	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10526	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10527	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10528	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10529	bwn_dma_ringstop(&dma->mcast);
10530}
10531
10532static void
10533bwn_dma_ringstop(struct bwn_dma_ring **dr)
10534{
10535
10536	if (dr == NULL)
10537		return;
10538
10539	bwn_dma_cleanup(*dr);
10540}
10541
10542static void
10543bwn_pio_stop(struct bwn_mac *mac)
10544{
10545	struct bwn_pio *pio;
10546
10547	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10548		return;
10549	pio = &mac->mac_method.pio;
10550
10551	bwn_destroy_queue_tx(&pio->mcast);
10552	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10553	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10554	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10555	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10556}
10557
10558static void
10559bwn_led_attach(struct bwn_mac *mac)
10560{
10561	struct bwn_softc *sc = mac->mac_sc;
10562	const uint8_t *led_act = NULL;
10563	uint16_t val[BWN_LED_MAX];
10564	int i;
10565
10566	sc->sc_led_idle = (2350 * hz) / 1000;
10567	sc->sc_led_blink = 1;
10568
10569	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10570		if (siba_get_pci_subvendor(sc->sc_dev) ==
10571		    bwn_vendor_led_act[i].vid) {
10572			led_act = bwn_vendor_led_act[i].led_act;
10573			break;
10574		}
10575	}
10576	if (led_act == NULL)
10577		led_act = bwn_default_led_act;
10578
10579	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10580	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10581	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10582	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10583
10584	for (i = 0; i < BWN_LED_MAX; ++i) {
10585		struct bwn_led *led = &sc->sc_leds[i];
10586
10587		if (val[i] == 0xff) {
10588			led->led_act = led_act[i];
10589		} else {
10590			if (val[i] & BWN_LED_ACT_LOW)
10591				led->led_flags |= BWN_LED_F_ACTLOW;
10592			led->led_act = val[i] & BWN_LED_ACT_MASK;
10593		}
10594		led->led_mask = (1 << i);
10595
10596		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10597		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10598		    led->led_act == BWN_LED_ACT_BLINK) {
10599			led->led_flags |= BWN_LED_F_BLINK;
10600			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10601				led->led_flags |= BWN_LED_F_POLLABLE;
10602			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10603				led->led_flags |= BWN_LED_F_SLOW;
10604
10605			if (sc->sc_blink_led == NULL) {
10606				sc->sc_blink_led = led;
10607				if (led->led_flags & BWN_LED_F_SLOW)
10608					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10609			}
10610		}
10611
10612		DPRINTF(sc, BWN_DEBUG_LED,
10613		    "%dth led, act %d, lowact %d\n", i,
10614		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10615	}
10616	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10617}
10618
10619static __inline uint16_t
10620bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10621{
10622
10623	if (led->led_flags & BWN_LED_F_ACTLOW)
10624		on = !on;
10625	if (on)
10626		val |= led->led_mask;
10627	else
10628		val &= ~led->led_mask;
10629	return val;
10630}
10631
10632static void
10633bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10634{
10635	struct bwn_softc *sc = mac->mac_sc;
10636	struct ifnet *ifp = sc->sc_ifp;
10637	struct ieee80211com *ic = ifp->if_l2com;
10638	uint16_t val;
10639	int i;
10640
10641	if (nstate == IEEE80211_S_INIT) {
10642		callout_stop(&sc->sc_led_blink_ch);
10643		sc->sc_led_blinking = 0;
10644	}
10645
10646	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10647		return;
10648
10649	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10650	for (i = 0; i < BWN_LED_MAX; ++i) {
10651		struct bwn_led *led = &sc->sc_leds[i];
10652		int on;
10653
10654		if (led->led_act == BWN_LED_ACT_UNKN ||
10655		    led->led_act == BWN_LED_ACT_NULL)
10656			continue;
10657
10658		if ((led->led_flags & BWN_LED_F_BLINK) &&
10659		    nstate != IEEE80211_S_INIT)
10660			continue;
10661
10662		switch (led->led_act) {
10663		case BWN_LED_ACT_ON:    /* Always on */
10664			on = 1;
10665			break;
10666		case BWN_LED_ACT_OFF:   /* Always off */
10667		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10668			on = 0;
10669			break;
10670		default:
10671			on = 1;
10672			switch (nstate) {
10673			case IEEE80211_S_INIT:
10674				on = 0;
10675				break;
10676			case IEEE80211_S_RUN:
10677				if (led->led_act == BWN_LED_ACT_11G &&
10678				    ic->ic_curmode != IEEE80211_MODE_11G)
10679					on = 0;
10680				break;
10681			default:
10682				if (led->led_act == BWN_LED_ACT_ASSOC)
10683					on = 0;
10684				break;
10685			}
10686			break;
10687		}
10688
10689		val = bwn_led_onoff(led, val, on);
10690	}
10691	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10692}
10693
10694static void
10695bwn_led_event(struct bwn_mac *mac, int event)
10696{
10697	struct bwn_softc *sc = mac->mac_sc;
10698	struct bwn_led *led = sc->sc_blink_led;
10699	int rate;
10700
10701	if (event == BWN_LED_EVENT_POLL) {
10702		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10703			return;
10704		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10705			return;
10706	}
10707
10708	sc->sc_led_ticks = ticks;
10709	if (sc->sc_led_blinking)
10710		return;
10711
10712	switch (event) {
10713	case BWN_LED_EVENT_RX:
10714		rate = sc->sc_rx_rate;
10715		break;
10716	case BWN_LED_EVENT_TX:
10717		rate = sc->sc_tx_rate;
10718		break;
10719	case BWN_LED_EVENT_POLL:
10720		rate = 0;
10721		break;
10722	default:
10723		panic("unknown LED event %d\n", event);
10724		break;
10725	}
10726	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10727	    bwn_led_duration[rate].off_dur);
10728}
10729
10730static void
10731bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10732{
10733	struct bwn_softc *sc = mac->mac_sc;
10734	struct bwn_led *led = sc->sc_blink_led;
10735	uint16_t val;
10736
10737	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10738	val = bwn_led_onoff(led, val, 1);
10739	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10740
10741	if (led->led_flags & BWN_LED_F_SLOW) {
10742		BWN_LED_SLOWDOWN(on_dur);
10743		BWN_LED_SLOWDOWN(off_dur);
10744	}
10745
10746	sc->sc_led_blinking = 1;
10747	sc->sc_led_blink_offdur = off_dur;
10748
10749	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10750}
10751
10752static void
10753bwn_led_blink_next(void *arg)
10754{
10755	struct bwn_mac *mac = arg;
10756	struct bwn_softc *sc = mac->mac_sc;
10757	uint16_t val;
10758
10759	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10760	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10761	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10762
10763	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10764	    bwn_led_blink_end, mac);
10765}
10766
10767static void
10768bwn_led_blink_end(void *arg)
10769{
10770	struct bwn_mac *mac = arg;
10771	struct bwn_softc *sc = mac->mac_sc;
10772
10773	sc->sc_led_blinking = 0;
10774}
10775
10776static int
10777bwn_suspend(device_t dev)
10778{
10779	struct bwn_softc *sc = device_get_softc(dev);
10780
10781	bwn_stop(sc, 1);
10782	return (0);
10783}
10784
10785static int
10786bwn_resume(device_t dev)
10787{
10788	struct bwn_softc *sc = device_get_softc(dev);
10789	struct ifnet *ifp = sc->sc_ifp;
10790
10791	if (ifp->if_flags & IFF_UP)
10792		bwn_init(sc);
10793	return (0);
10794}
10795
10796static void
10797bwn_rfswitch(void *arg)
10798{
10799	struct bwn_softc *sc = arg;
10800	struct bwn_mac *mac = sc->sc_curmac;
10801	int cur = 0, prev = 0;
10802
10803	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10804	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10805
10806	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10807		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10808			& BWN_RF_HWENABLED_HI_MASK))
10809			cur = 1;
10810	} else {
10811		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10812		    & BWN_RF_HWENABLED_LO_MASK)
10813			cur = 1;
10814	}
10815
10816	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10817		prev = 1;
10818
10819	if (cur != prev) {
10820		if (cur)
10821			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10822		else
10823			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10824
10825		device_printf(sc->sc_dev,
10826		    "status of RF switch is changed to %s\n",
10827		    cur ? "ON" : "OFF");
10828		if (cur != mac->mac_phy.rf_on) {
10829			if (cur)
10830				bwn_rf_turnon(mac);
10831			else
10832				bwn_rf_turnoff(mac);
10833		}
10834	}
10835
10836	callout_schedule(&sc->sc_rfswitch_ch, hz);
10837}
10838
10839static void
10840bwn_phy_lp_init_pre(struct bwn_mac *mac)
10841{
10842	struct bwn_phy *phy = &mac->mac_phy;
10843	struct bwn_phy_lp *plp = &phy->phy_lp;
10844
10845	plp->plp_antenna = BWN_ANT_DEFAULT;
10846}
10847
10848static int
10849bwn_phy_lp_init(struct bwn_mac *mac)
10850{
10851	static const struct bwn_stxtable tables[] = {
10852		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10853		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10854		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10855		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10856		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10857		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10858		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10859		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10860		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10861		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10862		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10863		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10864		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10865		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10866		{ 2, 11, 0x40, 0, 0x0f }
10867	};
10868	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10869	struct bwn_softc *sc = mac->mac_sc;
10870	const struct bwn_stxtable *st;
10871	struct ifnet *ifp = sc->sc_ifp;
10872	struct ieee80211com *ic = ifp->if_l2com;
10873	int i, error;
10874	uint16_t tmp;
10875
10876	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10877	bwn_phy_lp_bbinit(mac);
10878
10879	/* initialize RF */
10880	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10881	DELAY(1);
10882	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10883	DELAY(1);
10884
10885	if (mac->mac_phy.rf_ver == 0x2062)
10886		bwn_phy_lp_b2062_init(mac);
10887	else {
10888		bwn_phy_lp_b2063_init(mac);
10889
10890		/* synchronize stx table. */
10891		for (i = 0; i < N(tables); i++) {
10892			st = &tables[i];
10893			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10894			tmp >>= st->st_rfshift;
10895			tmp <<= st->st_physhift;
10896			BWN_PHY_SETMASK(mac,
10897			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10898			    ~(st->st_mask << st->st_physhift), tmp);
10899		}
10900
10901		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10902		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10903	}
10904
10905	/* calibrate RC */
10906	if (mac->mac_phy.rev >= 2)
10907		bwn_phy_lp_rxcal_r2(mac);
10908	else if (!plp->plp_rccap) {
10909		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10910			bwn_phy_lp_rccal_r12(mac);
10911	} else
10912		bwn_phy_lp_set_rccap(mac);
10913
10914	error = bwn_phy_lp_switch_channel(mac, 7);
10915	if (error)
10916		device_printf(sc->sc_dev,
10917		    "failed to change channel 7 (%d)\n", error);
10918	bwn_phy_lp_txpctl_init(mac);
10919	bwn_phy_lp_calib(mac);
10920	return (0);
10921}
10922
10923static uint16_t
10924bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10925{
10926
10927	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10928	return (BWN_READ_2(mac, BWN_PHYDATA));
10929}
10930
10931static void
10932bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10933{
10934
10935	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10936	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10937}
10938
10939static void
10940bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10941    uint16_t set)
10942{
10943
10944	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10945	BWN_WRITE_2(mac, BWN_PHYDATA,
10946	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10947}
10948
10949static uint16_t
10950bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10951{
10952
10953	KASSERT(reg != 1, ("unaccessible register %d", reg));
10954	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10955		reg |= 0x100;
10956	if (mac->mac_phy.rev >= 2)
10957		reg |= 0x200;
10958	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10959	return BWN_READ_2(mac, BWN_RFDATALO);
10960}
10961
10962static void
10963bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10964{
10965
10966	KASSERT(reg != 1, ("unaccessible register %d", reg));
10967	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10968	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10969}
10970
10971static void
10972bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10973{
10974
10975	if (on) {
10976		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10977		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10978		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10979		return;
10980	}
10981
10982	if (mac->mac_phy.rev >= 2) {
10983		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10984		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10985		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10986		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10987		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10988		return;
10989	}
10990
10991	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10992	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10993	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10994	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10995}
10996
10997static int
10998bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10999{
11000	struct bwn_phy *phy = &mac->mac_phy;
11001	struct bwn_phy_lp *plp = &phy->phy_lp;
11002	int error;
11003
11004	if (phy->rf_ver == 0x2063) {
11005		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11006		if (error)
11007			return (error);
11008	} else {
11009		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11010		if (error)
11011			return (error);
11012		bwn_phy_lp_set_anafilter(mac, chan);
11013		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11014	}
11015
11016	plp->plp_chan = chan;
11017	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11018	return (0);
11019}
11020
11021static uint32_t
11022bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11023{
11024	struct bwn_softc *sc = mac->mac_sc;
11025	struct ifnet *ifp = sc->sc_ifp;
11026	struct ieee80211com *ic = ifp->if_l2com;
11027
11028	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11029}
11030
11031static void
11032bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11033{
11034	struct bwn_phy *phy = &mac->mac_phy;
11035	struct bwn_phy_lp *plp = &phy->phy_lp;
11036
11037	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11038		return;
11039
11040	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11041	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11042	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11043	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11044	plp->plp_antenna = antenna;
11045}
11046
11047static void
11048bwn_phy_lp_task_60s(struct bwn_mac *mac)
11049{
11050
11051	bwn_phy_lp_calib(mac);
11052}
11053
11054static void
11055bwn_phy_lp_readsprom(struct bwn_mac *mac)
11056{
11057	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11058	struct bwn_softc *sc = mac->mac_sc;
11059	struct ifnet *ifp = sc->sc_ifp;
11060	struct ieee80211com *ic = ifp->if_l2com;
11061
11062	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11063		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11064		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11065		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11066		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11067		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11068		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11069		return;
11070	}
11071
11072	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11073	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11074	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11075	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11076	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11077	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11078	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11079	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11080}
11081
11082static void
11083bwn_phy_lp_bbinit(struct bwn_mac *mac)
11084{
11085
11086	bwn_phy_lp_tblinit(mac);
11087	if (mac->mac_phy.rev >= 2)
11088		bwn_phy_lp_bbinit_r2(mac);
11089	else
11090		bwn_phy_lp_bbinit_r01(mac);
11091}
11092
11093static void
11094bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11095{
11096	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11097	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11098	struct bwn_softc *sc = mac->mac_sc;
11099	struct ifnet *ifp = sc->sc_ifp;
11100	struct ieee80211com *ic = ifp->if_l2com;
11101
11102	bwn_phy_lp_set_txgain(mac,
11103	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11104	bwn_phy_lp_set_bbmult(mac, 150);
11105}
11106
11107static void
11108bwn_phy_lp_calib(struct bwn_mac *mac)
11109{
11110	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11111	struct bwn_softc *sc = mac->mac_sc;
11112	struct ifnet *ifp = sc->sc_ifp;
11113	struct ieee80211com *ic = ifp->if_l2com;
11114	const struct bwn_rxcompco *rc = NULL;
11115	struct bwn_txgain ogain;
11116	int i, omode, oafeovr, orf, obbmult;
11117	uint8_t mode, fc = 0;
11118
11119	if (plp->plp_chanfullcal != plp->plp_chan) {
11120		plp->plp_chanfullcal = plp->plp_chan;
11121		fc = 1;
11122	}
11123
11124	bwn_mac_suspend(mac);
11125
11126	/* BlueTooth Coexistance Override */
11127	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11128	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11129
11130	if (mac->mac_phy.rev >= 2)
11131		bwn_phy_lp_digflt_save(mac);
11132	bwn_phy_lp_get_txpctlmode(mac);
11133	mode = plp->plp_txpctlmode;
11134	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11135	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11136		bwn_phy_lp_bugfix(mac);
11137	if (mac->mac_phy.rev >= 2 && fc == 1) {
11138		bwn_phy_lp_get_txpctlmode(mac);
11139		omode = plp->plp_txpctlmode;
11140		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11141		if (oafeovr)
11142			ogain = bwn_phy_lp_get_txgain(mac);
11143		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11144		obbmult = bwn_phy_lp_get_bbmult(mac);
11145		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11146		if (oafeovr)
11147			bwn_phy_lp_set_txgain(mac, &ogain);
11148		bwn_phy_lp_set_bbmult(mac, obbmult);
11149		bwn_phy_lp_set_txpctlmode(mac, omode);
11150		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11151	}
11152	bwn_phy_lp_set_txpctlmode(mac, mode);
11153	if (mac->mac_phy.rev >= 2)
11154		bwn_phy_lp_digflt_restore(mac);
11155
11156	/* do RX IQ Calculation; assumes that noise is true. */
11157	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11158		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11159			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11160				rc = &bwn_rxcompco_5354[i];
11161		}
11162	} else if (mac->mac_phy.rev >= 2)
11163		rc = &bwn_rxcompco_r2;
11164	else {
11165		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11166			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11167				rc = &bwn_rxcompco_r12[i];
11168		}
11169	}
11170	if (rc == NULL)
11171		goto fail;
11172
11173	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11174	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11175
11176	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11177
11178	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11179		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11180		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11181	} else {
11182		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11183		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11184	}
11185
11186	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11187	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11188	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11189	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11190	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11191	bwn_phy_lp_set_deaf(mac, 0);
11192	/* XXX no checking return value? */
11193	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11194	bwn_phy_lp_clear_deaf(mac, 0);
11195	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11196	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11197	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11198
11199	/* disable RX GAIN override. */
11200	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11201	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11202	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11203	if (mac->mac_phy.rev >= 2) {
11204		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11205		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11206			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11207			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11208		}
11209	} else {
11210		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11211	}
11212
11213	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11214	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11215fail:
11216	bwn_mac_enable(mac);
11217}
11218
11219static void
11220bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11221{
11222
11223	if (on) {
11224		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11225		return;
11226	}
11227
11228	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11229	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11230}
11231
11232static int
11233bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11234{
11235	static const struct bwn_b206x_chan *bc = NULL;
11236	struct bwn_softc *sc = mac->mac_sc;
11237	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11238	    tmp[6];
11239	uint16_t old, scale, tmp16;
11240	int i, div;
11241
11242	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11243		if (bwn_b2063_chantable[i].bc_chan == chan) {
11244			bc = &bwn_b2063_chantable[i];
11245			break;
11246		}
11247	}
11248	if (bc == NULL)
11249		return (EINVAL);
11250
11251	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11252	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11253	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11254	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11255	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11256	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11257	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11258	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11259	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11260	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11261	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11262	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11263
11264	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11265	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11266
11267	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11268	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11269	freqref = freqxtal * 3;
11270	div = (freqxtal <= 26000000 ? 1 : 2);
11271	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11272	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11273		999999) / 1000000) + 1;
11274
11275	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11276	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11277	    0xfff8, timeout >> 2);
11278	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11279	    0xff9f,timeout << 5);
11280	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11281
11282	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11283	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11284	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11285
11286	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11287	    (timeoutref + 1)) - 1;
11288	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11289	    0xf0, count >> 8);
11290	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11291
11292	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11293	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11294	while (tmp[1] >= freqref) {
11295		tmp[0]++;
11296		tmp[1] -= freqref;
11297	}
11298	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11299	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11300	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11301	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11302	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11303
11304	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11305	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11306	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11307	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11308
11309	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11310	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11311
11312	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11313		scale = 1;
11314		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11315	} else {
11316		scale = 0;
11317		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11318	}
11319	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11320	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11321
11322	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11323	    (scale + 1);
11324	if (tmp[5] > 150)
11325		tmp[5] = 0;
11326
11327	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11328	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11329
11330	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11331	if (freqxtal > 26000000)
11332		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11333	else
11334		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11335
11336	if (val[0] == 45)
11337		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11338	else
11339		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11340
11341	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11342	DELAY(1);
11343	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11344
11345	/* VCO Calibration */
11346	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11347	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11348	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11349	DELAY(1);
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11351	DELAY(1);
11352	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11353	DELAY(1);
11354	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11355	DELAY(300);
11356	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11357
11358	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11359	return (0);
11360}
11361
11362static int
11363bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11364{
11365	struct bwn_softc *sc = mac->mac_sc;
11366	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11367	const struct bwn_b206x_chan *bc = NULL;
11368	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11369	uint32_t tmp[9];
11370	int i;
11371
11372	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11373		if (bwn_b2062_chantable[i].bc_chan == chan) {
11374			bc = &bwn_b2062_chantable[i];
11375			break;
11376		}
11377	}
11378
11379	if (bc == NULL)
11380		return (EINVAL);
11381
11382	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11383	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11384	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11385	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11386	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11387	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11388	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11389	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11390	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11391	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11392
11393	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11394	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11395	bwn_phy_lp_b2062_reset_pllbias(mac);
11396	tmp[0] = freqxtal / 1000;
11397	tmp[1] = plp->plp_div * 1000;
11398	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11399	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11400		tmp[2] *= 2;
11401	tmp[3] = 48 * tmp[0];
11402	tmp[5] = tmp[2] / tmp[3];
11403	tmp[6] = tmp[2] % tmp[3];
11404	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11405	tmp[4] = tmp[6] * 0x100;
11406	tmp[5] = tmp[4] / tmp[3];
11407	tmp[6] = tmp[4] % tmp[3];
11408	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11409	tmp[4] = tmp[6] * 0x100;
11410	tmp[5] = tmp[4] / tmp[3];
11411	tmp[6] = tmp[4] % tmp[3];
11412	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11413	tmp[4] = tmp[6] * 0x100;
11414	tmp[5] = tmp[4] / tmp[3];
11415	tmp[6] = tmp[4] % tmp[3];
11416	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11417	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11418	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11419	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11420	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11421	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11422
11423	bwn_phy_lp_b2062_vco_calib(mac);
11424	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11425		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11426		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11427		bwn_phy_lp_b2062_reset_pllbias(mac);
11428		bwn_phy_lp_b2062_vco_calib(mac);
11429		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11430			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11431			return (EIO);
11432		}
11433	}
11434	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11435	return (0);
11436}
11437
11438static void
11439bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11440{
11441	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11442	uint16_t tmp = (channel == 14);
11443
11444	if (mac->mac_phy.rev < 2) {
11445		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11446		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11447			bwn_phy_lp_set_rccap(mac);
11448		return;
11449	}
11450
11451	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11452}
11453
11454static void
11455bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11456{
11457	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11458	struct bwn_softc *sc = mac->mac_sc;
11459	struct ifnet *ifp = sc->sc_ifp;
11460	struct ieee80211com *ic = ifp->if_l2com;
11461	uint16_t iso, tmp[3];
11462
11463	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11464
11465	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11466		iso = plp->plp_txisoband_m;
11467	else if (freq <= 5320)
11468		iso = plp->plp_txisoband_l;
11469	else if (freq <= 5700)
11470		iso = plp->plp_txisoband_m;
11471	else
11472		iso = plp->plp_txisoband_h;
11473
11474	tmp[0] = ((iso - 26) / 12) << 12;
11475	tmp[1] = tmp[0] + 0x1000;
11476	tmp[2] = tmp[0] + 0x2000;
11477
11478	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11479	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11480}
11481
11482static void
11483bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11484{
11485	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11486	int i;
11487	static const uint16_t addr[] = {
11488		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11489		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11490		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11491		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11492		BWN_PHY_OFDM(0xcf),
11493	};
11494	static const uint16_t val[] = {
11495		0xde5e, 0xe832, 0xe331, 0x4d26,
11496		0x0026, 0x1420, 0x0020, 0xfe08,
11497		0x0008,
11498	};
11499
11500	for (i = 0; i < N(addr); i++) {
11501		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11502		BWN_PHY_WRITE(mac, addr[i], val[i]);
11503	}
11504}
11505
11506static void
11507bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11508{
11509	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11510	struct bwn_softc *sc = mac->mac_sc;
11511	uint16_t ctl;
11512
11513	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11514	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11515	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11516		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11517		break;
11518	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11519		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11520		break;
11521	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11522		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11523		break;
11524	default:
11525		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11526		device_printf(sc->sc_dev, "unknown command mode\n");
11527		break;
11528	}
11529}
11530
11531static void
11532bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11533{
11534	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11535	uint16_t ctl;
11536	uint8_t old;
11537
11538	bwn_phy_lp_get_txpctlmode(mac);
11539	old = plp->plp_txpctlmode;
11540	if (old == mode)
11541		return;
11542	plp->plp_txpctlmode = mode;
11543
11544	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11545		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11546		    plp->plp_tssiidx);
11547		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11548		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11549
11550		/* disable TX GAIN override */
11551		if (mac->mac_phy.rev < 2)
11552			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11553		else {
11554			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11555			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11556		}
11557		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11558
11559		plp->plp_txpwridx = -1;
11560	}
11561	if (mac->mac_phy.rev >= 2) {
11562		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11563			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11564		else
11565			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11566	}
11567
11568	/* writes TX Power Control mode */
11569	switch (plp->plp_txpctlmode) {
11570	case BWN_PHYLP_TXPCTL_OFF:
11571		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11572		break;
11573	case BWN_PHYLP_TXPCTL_ON_HW:
11574		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11575		break;
11576	case BWN_PHYLP_TXPCTL_ON_SW:
11577		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11578		break;
11579	default:
11580		ctl = 0;
11581		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11582	}
11583	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11584	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11585}
11586
11587static void
11588bwn_phy_lp_bugfix(struct bwn_mac *mac)
11589{
11590	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11591	struct bwn_softc *sc = mac->mac_sc;
11592	const unsigned int size = 256;
11593	struct bwn_txgain tg;
11594	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11595	uint16_t tssinpt, tssiidx, value[2];
11596	uint8_t mode;
11597	int8_t txpwridx;
11598
11599	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11600	    M_NOWAIT | M_ZERO);
11601	if (tabs == NULL) {
11602		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11603		return;
11604	}
11605
11606	bwn_phy_lp_get_txpctlmode(mac);
11607	mode = plp->plp_txpctlmode;
11608	txpwridx = plp->plp_txpwridx;
11609	tssinpt = plp->plp_tssinpt;
11610	tssiidx = plp->plp_tssiidx;
11611
11612	bwn_tab_read_multi(mac,
11613	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11614	    BWN_TAB_4(7, 0x140), size, tabs);
11615
11616	bwn_phy_lp_tblinit(mac);
11617	bwn_phy_lp_bbinit(mac);
11618	bwn_phy_lp_txpctl_init(mac);
11619	bwn_phy_lp_rf_onoff(mac, 1);
11620	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11621
11622	bwn_tab_write_multi(mac,
11623	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11624	    BWN_TAB_4(7, 0x140), size, tabs);
11625
11626	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11627	plp->plp_tssinpt = tssinpt;
11628	plp->plp_tssiidx = tssiidx;
11629	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11630	if (txpwridx != -1) {
11631		/* set TX power by index */
11632		plp->plp_txpwridx = txpwridx;
11633		bwn_phy_lp_get_txpctlmode(mac);
11634		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11635			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11636		if (mac->mac_phy.rev >= 2) {
11637			rxcomp = bwn_tab_read(mac,
11638			    BWN_TAB_4(7, txpwridx + 320));
11639			txgain = bwn_tab_read(mac,
11640			    BWN_TAB_4(7, txpwridx + 192));
11641			tg.tg_pad = (txgain >> 16) & 0xff;
11642			tg.tg_gm = txgain & 0xff;
11643			tg.tg_pga = (txgain >> 8) & 0xff;
11644			tg.tg_dac = (rxcomp >> 28) & 0xff;
11645			bwn_phy_lp_set_txgain(mac, &tg);
11646		} else {
11647			rxcomp = bwn_tab_read(mac,
11648			    BWN_TAB_4(10, txpwridx + 320));
11649			txgain = bwn_tab_read(mac,
11650			    BWN_TAB_4(10, txpwridx + 192));
11651			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11652			    0xf800, (txgain >> 4) & 0x7fff);
11653			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11654			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11655		}
11656		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11657
11658		/* set TX IQCC */
11659		value[0] = (rxcomp >> 10) & 0x3ff;
11660		value[1] = rxcomp & 0x3ff;
11661		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11662
11663		coeff = bwn_tab_read(mac,
11664		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11665		    BWN_TAB_4(10, txpwridx + 448));
11666		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11667		if (mac->mac_phy.rev >= 2) {
11668			rfpwr = bwn_tab_read(mac,
11669			    BWN_TAB_4(7, txpwridx + 576));
11670			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11671			    rfpwr & 0xffff);
11672		}
11673		bwn_phy_lp_set_txgain_override(mac);
11674	}
11675	if (plp->plp_rccap)
11676		bwn_phy_lp_set_rccap(mac);
11677	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11678	bwn_phy_lp_set_txpctlmode(mac, mode);
11679	free(tabs, M_DEVBUF);
11680}
11681
11682static void
11683bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11684{
11685	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11686	int i;
11687	static const uint16_t addr[] = {
11688		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11689		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11690		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11691		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11692		BWN_PHY_OFDM(0xcf),
11693	};
11694
11695	for (i = 0; i < N(addr); i++)
11696		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11697}
11698
11699static void
11700bwn_phy_lp_tblinit(struct bwn_mac *mac)
11701{
11702	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11703
11704	if (mac->mac_phy.rev < 2) {
11705		bwn_phy_lp_tblinit_r01(mac);
11706		bwn_phy_lp_tblinit_txgain(mac);
11707		bwn_phy_lp_set_gaintbl(mac, freq);
11708		return;
11709	}
11710
11711	bwn_phy_lp_tblinit_r2(mac);
11712	bwn_phy_lp_tblinit_txgain(mac);
11713}
11714
11715struct bwn_wpair {
11716	uint16_t		reg;
11717	uint16_t		value;
11718};
11719
11720struct bwn_smpair {
11721	uint16_t		offset;
11722	uint16_t		mask;
11723	uint16_t		set;
11724};
11725
11726static void
11727bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11728{
11729	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11730	struct bwn_softc *sc = mac->mac_sc;
11731	struct ifnet *ifp = sc->sc_ifp;
11732	struct ieee80211com *ic = ifp->if_l2com;
11733	static const struct bwn_wpair v1[] = {
11734		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11735		{ BWN_PHY_AFE_CTL, 0x8800 },
11736		{ BWN_PHY_AFE_CTL_OVR, 0 },
11737		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11738		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11739		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11740		{ BWN_PHY_OFDM(0xf9), 0 },
11741		{ BWN_PHY_TR_LOOKUP_1, 0 }
11742	};
11743	static const struct bwn_smpair v2[] = {
11744		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11745		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11746		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11747		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11748		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11749	};
11750	static const struct bwn_smpair v3[] = {
11751		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11752		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11753		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11754		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11755		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11756		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11757		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11758		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11759		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11760		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11761
11762	};
11763	int i;
11764
11765	for (i = 0; i < N(v1); i++)
11766		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11767	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11768	for (i = 0; i < N(v2); i++)
11769		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11770
11771	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11772	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11773	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11774	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11775		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11776		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11777	} else {
11778		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11779	}
11780	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11781	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11782	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11783	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11784	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11785	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11786	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11787	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11788	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11789	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11790	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11791	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11792	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11793		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11794		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11795	} else {
11796		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11797		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11798	}
11799	for (i = 0; i < N(v3); i++)
11800		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11801	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11802	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11803		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11804		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11805	}
11806
11807	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11808		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11809		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11810		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11811		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11812		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11813		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11814	} else
11815		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11816
11817	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11818	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11819	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11820	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11821	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11822	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11823	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11824	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11825	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11826
11827	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11828	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11829		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11830		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11831		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11832	}
11833
11834	bwn_phy_lp_digflt_save(mac);
11835}
11836
11837static void
11838bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11839{
11840	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11841	struct bwn_softc *sc = mac->mac_sc;
11842	struct ifnet *ifp = sc->sc_ifp;
11843	struct ieee80211com *ic = ifp->if_l2com;
11844	static const struct bwn_smpair v1[] = {
11845		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11846		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11847		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11848		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11849		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11850		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11851		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11852	};
11853	static const struct bwn_smpair v2[] = {
11854		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11855		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11856		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11857		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11858		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11859		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11860		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11861		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11862		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11863		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11864		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11865		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11866		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11867		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11868		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11869		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11870	};
11871	static const struct bwn_smpair v3[] = {
11872		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11873		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11874		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11875		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11876		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11877		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11878		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11879		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11880	};
11881	static const struct bwn_smpair v4[] = {
11882		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11883		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11884		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11885		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11886		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11887		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11888		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11889		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11890	};
11891	static const struct bwn_smpair v5[] = {
11892		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11893		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11894		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11895		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11896		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11897		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11898		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11899		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11900	};
11901	int i;
11902	uint16_t tmp, tmp2;
11903
11904	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11905	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11906	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11907	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11908	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11909	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11910	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11911	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11912	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11913	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11914	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11915	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11916	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11917	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11918	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11919	for (i = 0; i < N(v1); i++)
11920		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11921	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11922	    0xff00, plp->plp_rxpwroffset);
11923	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11924	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11925	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11926		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11927		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11928		if (mac->mac_phy.rev == 0)
11929			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11930			    0xffcf, 0x0010);
11931		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11932	} else {
11933		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11934		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11935		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11936	}
11937	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11938	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11939	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11940		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11941	else
11942		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11943	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11944	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11945	    0xfff9, (plp->plp_bxarch << 1));
11946	if (mac->mac_phy.rev == 1 &&
11947	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11948		for (i = 0; i < N(v2); i++)
11949			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11950			    v2[i].set);
11951	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11952	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11953	    ((mac->mac_phy.rev == 0) &&
11954	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11955		for (i = 0; i < N(v3); i++)
11956			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11957			    v3[i].set);
11958	} else if (mac->mac_phy.rev == 1 ||
11959		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11960		for (i = 0; i < N(v4); i++)
11961			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11962			    v4[i].set);
11963	} else {
11964		for (i = 0; i < N(v5); i++)
11965			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11966			    v5[i].set);
11967	}
11968	if (mac->mac_phy.rev == 1 &&
11969	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11970		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11971		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11972		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11973		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11974	}
11975	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11976	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11977	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11978		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11979		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11980		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11981		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11982	}
11983	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11984		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11985		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11986		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11987		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11988		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11989		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11990		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11991		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11992	} else {
11993		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11994		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11995	}
11996	if (mac->mac_phy.rev == 1) {
11997		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11998		tmp2 = (tmp & 0x03e0) >> 5;
11999		tmp2 |= tmp2 << 5;
12000		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12001		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12002		tmp2 = (tmp & 0x1f00) >> 8;
12003		tmp2 |= tmp2 << 5;
12004		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12005		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12006		tmp2 = tmp & 0x00ff;
12007		tmp2 |= tmp << 8;
12008		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12009	}
12010}
12011
12012struct bwn_b2062_freq {
12013	uint16_t		freq;
12014	uint8_t			value[6];
12015};
12016
12017static void
12018bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12019{
12020#define	CALC_CTL7(freq, div)						\
12021	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12022#define	CALC_CTL18(freq, div)						\
12023	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12024#define	CALC_CTL19(freq, div)						\
12025	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12026	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12027	struct bwn_softc *sc = mac->mac_sc;
12028	struct ifnet *ifp = sc->sc_ifp;
12029	struct ieee80211com *ic = ifp->if_l2com;
12030	static const struct bwn_b2062_freq freqdata_tab[] = {
12031		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12032		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12033		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12034		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12035		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12036		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12037	};
12038	static const struct bwn_wpair v1[] = {
12039		{ BWN_B2062_N_TXCTL3, 0 },
12040		{ BWN_B2062_N_TXCTL4, 0 },
12041		{ BWN_B2062_N_TXCTL5, 0 },
12042		{ BWN_B2062_N_TXCTL6, 0 },
12043		{ BWN_B2062_N_PDNCTL0, 0x40 },
12044		{ BWN_B2062_N_PDNCTL0, 0 },
12045		{ BWN_B2062_N_CALIB_TS, 0x10 },
12046		{ BWN_B2062_N_CALIB_TS, 0 }
12047	};
12048	const struct bwn_b2062_freq *f = NULL;
12049	uint32_t xtalfreq, ref;
12050	unsigned int i;
12051
12052	bwn_phy_lp_b2062_tblinit(mac);
12053
12054	for (i = 0; i < N(v1); i++)
12055		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12056	if (mac->mac_phy.rev > 0)
12057		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12058		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12059	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12060		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12061	else
12062		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12063
12064	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12065	    ("%s:%d: fail", __func__, __LINE__));
12066	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12067	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12068
12069	if (xtalfreq <= 30000000) {
12070		plp->plp_div = 1;
12071		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12072	} else {
12073		plp->plp_div = 2;
12074		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12075	}
12076
12077	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12078	    CALC_CTL7(xtalfreq, plp->plp_div));
12079	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12080	    CALC_CTL18(xtalfreq, plp->plp_div));
12081	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12082	    CALC_CTL19(xtalfreq, plp->plp_div));
12083
12084	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12085	ref &= 0xffff;
12086	for (i = 0; i < N(freqdata_tab); i++) {
12087		if (ref < freqdata_tab[i].freq) {
12088			f = &freqdata_tab[i];
12089			break;
12090		}
12091	}
12092	if (f == NULL)
12093		f = &freqdata_tab[N(freqdata_tab) - 1];
12094	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12095	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12096	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12097	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12098	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12099	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12100#undef CALC_CTL7
12101#undef CALC_CTL18
12102#undef CALC_CTL19
12103}
12104
12105static void
12106bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12107{
12108
12109	bwn_phy_lp_b2063_tblinit(mac);
12110	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12111	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12112	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12113	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12114	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12115	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12116	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12117	if (mac->mac_phy.rev == 2) {
12118		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12119		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12120		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12121	} else {
12122		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12123		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12124	}
12125}
12126
12127static void
12128bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12129{
12130	struct bwn_softc *sc = mac->mac_sc;
12131	static const struct bwn_wpair v1[] = {
12132		{ BWN_B2063_RX_BB_SP8, 0x0 },
12133		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12134		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12135		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12136		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12137		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12138		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12139		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12140	};
12141	static const struct bwn_wpair v2[] = {
12142		{ BWN_B2063_TX_BB_SP3, 0x0 },
12143		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12144		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12145		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12146		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12147	};
12148	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12149	int i;
12150	uint8_t tmp;
12151
12152	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12153
12154	for (i = 0; i < 2; i++)
12155		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12156	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12157	for (i = 2; i < N(v1); i++)
12158		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12159	for (i = 0; i < 10000; i++) {
12160		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12161			break;
12162		DELAY(1000);
12163	}
12164
12165	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12166		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12167
12168	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12169
12170	for (i = 0; i < N(v2); i++)
12171		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12172	if (freqxtal == 24000000) {
12173		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12174		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12175	} else {
12176		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12177		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12178	}
12179	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12180	for (i = 0; i < 10000; i++) {
12181		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12182			break;
12183		DELAY(1000);
12184	}
12185	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12186		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12187	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12188}
12189
12190static void
12191bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12192{
12193	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12194	struct bwn_softc *sc = mac->mac_sc;
12195	struct bwn_phy_lp_iq_est ie;
12196	struct bwn_txgain tx_gains;
12197	static const uint32_t pwrtbl[21] = {
12198		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12199		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12200		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12201		0x0004c, 0x0002c, 0x0001a,
12202	};
12203	uint32_t npwr, ipwr, sqpwr, tmp;
12204	int loopback, i, j, sum, error;
12205	uint16_t save[7];
12206	uint8_t txo, bbmult, txpctlmode;
12207
12208	error = bwn_phy_lp_switch_channel(mac, 7);
12209	if (error)
12210		device_printf(sc->sc_dev,
12211		    "failed to change channel to 7 (%d)\n", error);
12212	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12213	bbmult = bwn_phy_lp_get_bbmult(mac);
12214	if (txo)
12215		tx_gains = bwn_phy_lp_get_txgain(mac);
12216
12217	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12218	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12219	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12220	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12221	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12222	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12223	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12224
12225	bwn_phy_lp_get_txpctlmode(mac);
12226	txpctlmode = plp->plp_txpctlmode;
12227	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12228
12229	/* disable CRS */
12230	bwn_phy_lp_set_deaf(mac, 1);
12231	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12232	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12233	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12234	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12235	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12236	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12237	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12238	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12239	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12240	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12241	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12242	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12243	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12244	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12245	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12246	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12247	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12248	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12249	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12250	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12251	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12252	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12253	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12254	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12255
12256	loopback = bwn_phy_lp_loopback(mac);
12257	if (loopback == -1)
12258		goto done;
12259	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12260	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12261	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12262	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12263	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12264
12265	tmp = 0;
12266	memset(&ie, 0, sizeof(ie));
12267	for (i = 128; i <= 159; i++) {
12268		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12269		sum = 0;
12270		for (j = 5; j <= 25; j++) {
12271			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12272			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12273				goto done;
12274			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12275			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12276			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12277			    12);
12278			sum += ((ipwr - npwr) * (ipwr - npwr));
12279			if ((i == 128) || (sum < tmp)) {
12280				plp->plp_rccap = i;
12281				tmp = sum;
12282			}
12283		}
12284	}
12285	bwn_phy_lp_ddfs_turnoff(mac);
12286done:
12287	/* restore CRS */
12288	bwn_phy_lp_clear_deaf(mac, 1);
12289	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12290	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12291
12292	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12293	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12294	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12295	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12296	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12297	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12298	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12299
12300	bwn_phy_lp_set_bbmult(mac, bbmult);
12301	if (txo)
12302		bwn_phy_lp_set_txgain(mac, &tx_gains);
12303	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12304	if (plp->plp_rccap)
12305		bwn_phy_lp_set_rccap(mac);
12306}
12307
12308static void
12309bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12310{
12311	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12312	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12313
12314	if (mac->mac_phy.rev == 1)
12315		rc_cap = MIN(rc_cap + 5, 15);
12316
12317	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12318	    MAX(plp->plp_rccap - 4, 0x80));
12319	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12320	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12321	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12322}
12323
12324static uint32_t
12325bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12326{
12327	uint32_t i, q, r;
12328
12329	if (div == 0)
12330		return (0);
12331
12332	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12333		q <<= 1;
12334		if (r << 1 >= div) {
12335			q++;
12336			r = (r << 1) - div;
12337		}
12338	}
12339	if (r << 1 >= div)
12340		q++;
12341	return (q);
12342}
12343
12344static void
12345bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12346{
12347	struct bwn_softc *sc = mac->mac_sc;
12348
12349	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12350	DELAY(20);
12351	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12352		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12353		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12354	} else {
12355		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12356	}
12357	DELAY(5);
12358}
12359
12360static void
12361bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12362{
12363
12364	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12365	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12366	DELAY(200);
12367}
12368
12369static void
12370bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12371{
12372#define	FLAG_A	0x01
12373#define	FLAG_G	0x02
12374	struct bwn_softc *sc = mac->mac_sc;
12375	struct ifnet *ifp = sc->sc_ifp;
12376	struct ieee80211com *ic = ifp->if_l2com;
12377	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12378		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12379		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12380		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12381		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12382		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12383		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12384		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12385		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12386		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12387		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12388		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12389		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12390		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12391		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12392		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12393		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12394		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12399		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12400		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12425	};
12426	const struct bwn_b206x_rfinit_entry *br;
12427	unsigned int i;
12428
12429	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12430		br = &bwn_b2062_init_tab[i];
12431		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12432			if (br->br_flags & FLAG_G)
12433				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12434		} else {
12435			if (br->br_flags & FLAG_A)
12436				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12437		}
12438	}
12439#undef FLAG_A
12440#undef FLAG_B
12441}
12442
12443static void
12444bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12445{
12446#define	FLAG_A	0x01
12447#define	FLAG_G	0x02
12448	struct bwn_softc *sc = mac->mac_sc;
12449	struct ifnet *ifp = sc->sc_ifp;
12450	struct ieee80211com *ic = ifp->if_l2com;
12451	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12452		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12453		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12454		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12455		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12456		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12457		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12458		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12459		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12460		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12461		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12462		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12463		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12464		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12465		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12466		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12467		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12468		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12469		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12470		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12471		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12472		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12473		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12474		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12475		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12476		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12477		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12478		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12479		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12480		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12482		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12483		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12484		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12485		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12487		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12488		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12491		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12492		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12493		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12494	};
12495	const struct bwn_b206x_rfinit_entry *br;
12496	unsigned int i;
12497
12498	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12499		br = &bwn_b2063_init_tab[i];
12500		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12501			if (br->br_flags & FLAG_G)
12502				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12503		} else {
12504			if (br->br_flags & FLAG_A)
12505				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12506		}
12507	}
12508#undef FLAG_A
12509#undef FLAG_B
12510}
12511
12512static void
12513bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12514    int count, void *_data)
12515{
12516	unsigned int i;
12517	uint32_t offset, type;
12518	uint8_t *data = _data;
12519
12520	type = BWN_TAB_GETTYPE(typenoffset);
12521	offset = BWN_TAB_GETOFFSET(typenoffset);
12522	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12523
12524	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12525
12526	for (i = 0; i < count; i++) {
12527		switch (type) {
12528		case BWN_TAB_8BIT:
12529			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12530			data++;
12531			break;
12532		case BWN_TAB_16BIT:
12533			*((uint16_t *)data) = BWN_PHY_READ(mac,
12534			    BWN_PHY_TABLEDATALO);
12535			data += 2;
12536			break;
12537		case BWN_TAB_32BIT:
12538			*((uint32_t *)data) = BWN_PHY_READ(mac,
12539			    BWN_PHY_TABLEDATAHI);
12540			*((uint32_t *)data) <<= 16;
12541			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12542			    BWN_PHY_TABLEDATALO);
12543			data += 4;
12544			break;
12545		default:
12546			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12547		}
12548	}
12549}
12550
12551static void
12552bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12553    int count, const void *_data)
12554{
12555	uint32_t offset, type, value;
12556	const uint8_t *data = _data;
12557	unsigned int i;
12558
12559	type = BWN_TAB_GETTYPE(typenoffset);
12560	offset = BWN_TAB_GETOFFSET(typenoffset);
12561	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12562
12563	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12564
12565	for (i = 0; i < count; i++) {
12566		switch (type) {
12567		case BWN_TAB_8BIT:
12568			value = *data;
12569			data++;
12570			KASSERT(!(value & ~0xff),
12571			    ("%s:%d: fail", __func__, __LINE__));
12572			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12573			break;
12574		case BWN_TAB_16BIT:
12575			value = *((const uint16_t *)data);
12576			data += 2;
12577			KASSERT(!(value & ~0xffff),
12578			    ("%s:%d: fail", __func__, __LINE__));
12579			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12580			break;
12581		case BWN_TAB_32BIT:
12582			value = *((const uint32_t *)data);
12583			data += 4;
12584			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12585			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12586			break;
12587		default:
12588			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12589		}
12590	}
12591}
12592
12593static struct bwn_txgain
12594bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12595{
12596	struct bwn_txgain tg;
12597	uint16_t tmp;
12598
12599	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12600	if (mac->mac_phy.rev < 2) {
12601		tmp = BWN_PHY_READ(mac,
12602		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12603		tg.tg_gm = tmp & 0x0007;
12604		tg.tg_pga = (tmp & 0x0078) >> 3;
12605		tg.tg_pad = (tmp & 0x780) >> 7;
12606		return (tg);
12607	}
12608
12609	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12610	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12611	tg.tg_gm = tmp & 0xff;
12612	tg.tg_pga = (tmp >> 8) & 0xff;
12613	return (tg);
12614}
12615
12616static uint8_t
12617bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12618{
12619
12620	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12621}
12622
12623static void
12624bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12625{
12626	uint16_t pa;
12627
12628	if (mac->mac_phy.rev < 2) {
12629		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12630		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12631		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12632		bwn_phy_lp_set_txgain_override(mac);
12633		return;
12634	}
12635
12636	pa = bwn_phy_lp_get_pa_gain(mac);
12637	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12638	    (tg->tg_pga << 8) | tg->tg_gm);
12639	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12640	    tg->tg_pad | (pa << 6));
12641	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12642	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12643	    tg->tg_pad | (pa << 8));
12644	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12645	bwn_phy_lp_set_txgain_override(mac);
12646}
12647
12648static void
12649bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12650{
12651
12652	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12653}
12654
12655static void
12656bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12657{
12658	uint16_t trsw = (tx << 1) | rx;
12659
12660	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12661	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12662}
12663
12664static void
12665bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12666{
12667	struct bwn_softc *sc = mac->mac_sc;
12668	struct ifnet *ifp = sc->sc_ifp;
12669	struct ieee80211com *ic = ifp->if_l2com;
12670	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12671
12672	if (mac->mac_phy.rev < 2) {
12673		trsw = gain & 0x1;
12674		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12675		ext_lna = (gain & 2) >> 1;
12676
12677		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12678		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12679		    0xfbff, ext_lna << 10);
12680		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12681		    0xf7ff, ext_lna << 11);
12682		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12683	} else {
12684		low_gain = gain & 0xffff;
12685		high_gain = (gain >> 16) & 0xf;
12686		ext_lna = (gain >> 21) & 0x1;
12687		trsw = ~(gain >> 20) & 0x1;
12688
12689		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12690		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12691		    0xfdff, ext_lna << 9);
12692		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12693		    0xfbff, ext_lna << 10);
12694		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12695		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12696		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12697			tmp = (gain >> 2) & 0x3;
12698			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12699			    0xe7ff, tmp<<11);
12700			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12701			    tmp << 3);
12702		}
12703	}
12704
12705	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12706	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12707	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12708	if (mac->mac_phy.rev >= 2) {
12709		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12710		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12711			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12712			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12713		}
12714		return;
12715	}
12716	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12717}
12718
12719static void
12720bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12721{
12722	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12723
12724	if (user)
12725		plp->plp_crsusr_off = 1;
12726	else
12727		plp->plp_crssys_off = 1;
12728
12729	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12730}
12731
12732static void
12733bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12734{
12735	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12736	struct bwn_softc *sc = mac->mac_sc;
12737	struct ifnet *ifp = sc->sc_ifp;
12738	struct ieee80211com *ic = ifp->if_l2com;
12739
12740	if (user)
12741		plp->plp_crsusr_off = 0;
12742	else
12743		plp->plp_crssys_off = 0;
12744
12745	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12746		return;
12747
12748	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12749		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12750	else
12751		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12752}
12753
12754static unsigned int
12755bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12756{
12757	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12758	static uint8_t sqrt_table[256] = {
12759		10, 14, 17, 20, 22, 24, 26, 28,
12760		30, 31, 33, 34, 36, 37, 38, 40,
12761		41, 42, 43, 44, 45, 46, 47, 48,
12762		50, 50, 51, 52, 53, 54, 55, 56,
12763		57, 58, 59, 60, 60, 61, 62, 63,
12764		64, 64, 65, 66, 67, 67, 68, 69,
12765		70, 70, 71, 72, 72, 73, 74, 74,
12766		75, 76, 76, 77, 78, 78, 79, 80,
12767		80, 81, 81, 82, 83, 83, 84, 84,
12768		85, 86, 86, 87, 87, 88, 88, 89,
12769		90, 90, 91, 91, 92, 92, 93, 93,
12770		94, 94, 95, 95, 96, 96, 97, 97,
12771		98, 98, 99, 100, 100, 100, 101, 101,
12772		102, 102, 103, 103, 104, 104, 105, 105,
12773		106, 106, 107, 107, 108, 108, 109, 109,
12774		110, 110, 110, 111, 111, 112, 112, 113,
12775		113, 114, 114, 114, 115, 115, 116, 116,
12776		117, 117, 117, 118, 118, 119, 119, 120,
12777		120, 120, 121, 121, 122, 122, 122, 123,
12778		123, 124, 124, 124, 125, 125, 126, 126,
12779		126, 127, 127, 128, 128, 128, 129, 129,
12780		130, 130, 130, 131, 131, 131, 132, 132,
12781		133, 133, 133, 134, 134, 134, 135, 135,
12782		136, 136, 136, 137, 137, 137, 138, 138,
12783		138, 139, 139, 140, 140, 140, 141, 141,
12784		141, 142, 142, 142, 143, 143, 143, 144,
12785		144, 144, 145, 145, 145, 146, 146, 146,
12786		147, 147, 147, 148, 148, 148, 149, 149,
12787		150, 150, 150, 150, 151, 151, 151, 152,
12788		152, 152, 153, 153, 153, 154, 154, 154,
12789		155, 155, 155, 156, 156, 156, 157, 157,
12790		157, 158, 158, 158, 159, 159, 159, 160
12791	};
12792
12793	if (x == 0)
12794		return (0);
12795	if (x >= 256) {
12796		unsigned int tmp;
12797
12798		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12799			/* do nothing */ ;
12800		return (tmp);
12801	}
12802	return (sqrt_table[x - 1] / 10);
12803}
12804
12805static int
12806bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12807{
12808#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12809	int _t;								\
12810	_t = _x - 20;							\
12811	if (_t >= 0) {							\
12812		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12813	} else {							\
12814		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12815	}								\
12816} while (0)
12817#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12818	int _t;								\
12819	_t = _x - 11;							\
12820	if (_t >= 0)							\
12821		_v = (_y << (31 - _x)) / (_z >> _t);			\
12822	else								\
12823		_v = (_y << (31 - _x)) / (_z << -_t);			\
12824} while (0)
12825	struct bwn_phy_lp_iq_est ie;
12826	uint16_t v0, v1;
12827	int tmp[2], ret;
12828
12829	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12830	v0 = v1 >> 8;
12831	v1 |= 0xff;
12832
12833	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12834	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12835
12836	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12837	if (ret == 0)
12838		goto done;
12839
12840	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12841		ret = 0;
12842		goto done;
12843	}
12844
12845	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12846	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12847
12848	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12849	v0 = tmp[0] >> 3;
12850	v1 = tmp[1] >> 4;
12851done:
12852	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12853	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12854	return ret;
12855#undef CALC_COEFF
12856#undef CALC_COEFF2
12857}
12858
12859static void
12860bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12861{
12862	static const uint16_t noisescale[] = {
12863		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12864		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12865		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12866		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12867		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12868	};
12869	static const uint16_t crsgainnft[] = {
12870		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12871		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12872		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12873		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12874		0x013d,
12875	};
12876	static const uint16_t filterctl[] = {
12877		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12878		0xff53, 0x0127,
12879	};
12880	static const uint32_t psctl[] = {
12881		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12882		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12883		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12884		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12885		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12886		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12887		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12888		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12889	};
12890	static const uint16_t ofdmcckgain_r0[] = {
12891		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12892		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12893		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12894		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12895		0x755d,
12896	};
12897	static const uint16_t ofdmcckgain_r1[] = {
12898		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12899		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12900		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12901		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12902		0x755d,
12903	};
12904	static const uint16_t gaindelta[] = {
12905		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12906		0x0000,
12907	};
12908	static const uint32_t txpwrctl[] = {
12909		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12910		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12911		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12912		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12913		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12914		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12915		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12916		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12917		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12918		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12919		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12920		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12921		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12922		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12923		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12924		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
12948		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12949		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12950		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12951		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12952		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12953		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12954		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12955		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12956		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12957		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12958		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12959		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12960		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12961		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12962		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12963		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12964		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12965		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12966		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12967		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12968		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12969		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12970		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12971		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12972		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12973		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12974		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12975		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12976		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12977		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12978		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12979		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12980		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12981		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12982		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12983		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12984		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12985		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12986		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12987		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12988		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12989		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12990		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12991		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12992		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12993		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12994		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12995		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12996		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12997		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12998		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12999		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13000		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13001		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13002		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13003		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13004		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13005		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13006		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13007		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13008		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13009		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13010		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13011		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13012		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13013		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13014		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13015		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13016		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13017		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13018		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13019		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13020		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13021		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13022		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13023		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13024		0x00000702,
13025	};
13026
13027	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13028
13029	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13030	    bwn_tab_sigsq_tbl);
13031	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13032	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13033	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13034	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13035	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13036	    bwn_tab_pllfrac_tbl);
13037	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13038	    bwn_tabl_iqlocal_tbl);
13039	if (mac->mac_phy.rev == 0) {
13040		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13041		    ofdmcckgain_r0);
13042		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13043		    ofdmcckgain_r0);
13044	} else {
13045		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13046		    ofdmcckgain_r1);
13047		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13048		    ofdmcckgain_r1);
13049	}
13050	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13051	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13052}
13053
13054static void
13055bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13056{
13057	struct bwn_softc *sc = mac->mac_sc;
13058	int i;
13059	static const uint16_t noisescale[] = {
13060		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13061		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13067	};
13068	static const uint32_t filterctl[] = {
13069		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13070		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13071	};
13072	static const uint32_t psctl[] = {
13073		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13074		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13075		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13076		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13077	};
13078	static const uint32_t gainidx[] = {
13079		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13080		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13081		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13083		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13084		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13085		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13086		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13087		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13088		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13089		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13090		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13091		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13092		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13093		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13094		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13095		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13096		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13098		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13099		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13100		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13101		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13102		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13103		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13104		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13105		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13106		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13107		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13108		0x0000001a, 0x64ca55ad, 0x0000001a
13109	};
13110	static const uint16_t auxgainidx[] = {
13111		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13112		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13113		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13114		0x0004, 0x0016
13115	};
13116	static const uint16_t swctl[] = {
13117		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13118		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13119		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13120		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13121		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13122		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13123		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13124		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13125	};
13126	static const uint8_t hf[] = {
13127		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13128		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13129	};
13130	static const uint32_t gainval[] = {
13131		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13132		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13133		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13134		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13135		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13136		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13137		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13138		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13141		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13142		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13143		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13144		0x000000f1, 0x00000000, 0x00000000
13145	};
13146	static const uint16_t gain[] = {
13147		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13148		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13149		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13150		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13151		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13152		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13153		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13154		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13159	};
13160	static const uint32_t papdeps[] = {
13161		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13162		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13163		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13164		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13165		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13166		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13167		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13168		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13169		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13170		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13171		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13172		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13173		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13174	};
13175	static const uint32_t papdmult[] = {
13176		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13177		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13178		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13179		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13180		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13181		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13182		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13183		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13184		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13185		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13186		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13187		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13188		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13189	};
13190	static const uint32_t gainidx_a0[] = {
13191		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13192		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13193		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13194		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13195		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13196		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13197		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13198		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13199		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13200		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13201		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13202		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13203		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13204	};
13205	static const uint16_t auxgainidx_a0[] = {
13206		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13207		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13208		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13209		0x0002, 0x0014
13210	};
13211	static const uint32_t gainval_a0[] = {
13212		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13213		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13214		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13215		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13216		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13217		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13218		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13219		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13220		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13221		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13222		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13223		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13224		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13225		0x000000f7, 0x00000000, 0x00000000
13226	};
13227	static const uint16_t gain_a0[] = {
13228		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13229		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13230		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13231		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13232		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13233		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13234		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13235		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13240	};
13241
13242	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13243
13244	for (i = 0; i < 704; i++)
13245		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13246
13247	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13248	    bwn_tab_sigsq_tbl);
13249	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13250	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13251	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13252	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13253	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13254	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13255	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13256	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13257	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13258	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13259	    bwn_tab_pllfrac_tbl);
13260	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13261	    bwn_tabl_iqlocal_tbl);
13262	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13263	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13264
13265	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13266	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13267		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13268		    gainidx_a0);
13269		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13270		    auxgainidx_a0);
13271		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13272		    gainval_a0);
13273		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13274	}
13275}
13276
13277static void
13278bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13279{
13280	struct bwn_softc *sc = mac->mac_sc;
13281	struct ifnet *ifp = sc->sc_ifp;
13282	struct ieee80211com *ic = ifp->if_l2com;
13283	static struct bwn_txgain_entry txgain_r2[] = {
13284		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13285		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13286		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13287		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13288		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13289		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13290		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13291		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13292		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13293		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13294		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13295		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13296		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13297		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13298		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13299		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13300		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13301		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13302		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13303		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13304		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13305		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13306		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13307		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13308		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13309		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13310		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13311		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13312		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13313		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13314		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13315		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13316		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13317		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13318		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13319		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13320		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13321		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13322		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13323		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13324		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13325		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13326		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13327		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13328		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13329		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13330		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13331		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13332		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13333		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13334		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13335		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13336		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13337		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13338		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13339		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13340		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13341		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13342		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13343		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13344		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13345		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13346		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13347		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13348	};
13349	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13350		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13351		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13352		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13353		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13354		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13355		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13356		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13357		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13358		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13359		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13360		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13361		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13362		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13363		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13364		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13365		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13366		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13367		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13368		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13369		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13370		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13371		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13372		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13373		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13374		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13375		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13376		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13377		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13378		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13379		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13380		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13381		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13382		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13383		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13384		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13385		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13386		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13387		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13388		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13389		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13390		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13391		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13392		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13393		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13394		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13395		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13396		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13397		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13398		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13399		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13400		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13401		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13402		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13403		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13404		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13405		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13406		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13407		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13408		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13409		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13410		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13411		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13412		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13413		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13414	};
13415	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13416		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13417		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13418		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13419		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13420		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13421		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13422		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13423		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13424		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13425		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13426		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13427		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13428		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13429		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13430		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13431		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13432		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13433		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13434		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13435		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13436		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13437		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13438		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13439		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13440		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13441		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13442		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13443		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13444		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13445		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13446		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13447		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13448		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13449		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13450		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13451		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13452		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13453		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13454		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13455		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13456		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13457		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13458		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13459		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13460		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13461		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13462		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13463		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13464		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13465		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13466		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13467		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13468		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13469		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13470		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13471		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13472		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13473		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13474		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13475		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13476		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13477		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13478		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13479		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13480	};
13481	static struct bwn_txgain_entry txgain_r0[] = {
13482		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13483		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13484		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13485		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13486		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13487		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13488		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13489		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13490		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13491		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13492		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13493		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13494		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13495		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13496		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13497		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13498		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13499		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13500		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13501		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13502		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13503		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13504		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13505		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13506		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13507		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13508		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13509		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13510		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13511		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13512		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13513		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13514		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13515		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13516		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13517		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13518		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13519		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13520		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13521		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13522		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13523		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13524		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13525		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13526		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13527		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13528		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13529		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13530		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13531		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13532		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13533		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13534		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13535		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13536		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13537		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13538		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13539		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13540		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13541		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13542		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13543		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13544		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13545		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13546	};
13547	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13548		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13549		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13550		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13551		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13552		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13553		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13554		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13555		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13556		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13557		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13558		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13559		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13560		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13561		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13562		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13563		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13564		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13565		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13566		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13567		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13568		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13569		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13570		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13571		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13572		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13573		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13574		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13575		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13576		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13577		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13578		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13579		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13580		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13581		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13582		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13583		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13584		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13585		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13586		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13587		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13588		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13589		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13590		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13591		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13592		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13593		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13594		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13595		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13596		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13597		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13598		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13599		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13600		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13601		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13602		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13603		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13604		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13605		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13606		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13607		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13608		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13609		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13610		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13611		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13612	};
13613	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13614		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13615		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13616		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13617		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13618		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13619		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13620		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13621		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13622		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13623		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13624		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13625		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13626		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13627		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13628		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13629		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13630		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13631		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13632		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13633		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13634		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13635		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13636		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13637		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13638		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13639		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13640		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13641		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13642		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13643		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13644		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13645		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13646		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13647		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13648		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13649		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13650		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13651		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13652		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13653		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13654		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13655		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13656		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13657		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13658		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13659		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13660		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13661		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13662		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13663		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13664		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13665		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13666		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13667		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13668		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13669		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13670		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13671		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13672		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13673		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13674		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13675		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13676		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13677		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13678	};
13679	static struct bwn_txgain_entry txgain_r1[] = {
13680		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13681		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13682		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13683		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13684		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13685		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13686		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13687		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13688		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13689		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13690		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13691		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13692		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13693		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13694		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13695		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13696		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13697		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13698		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13699		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13700		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13701		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13702		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13703		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13704		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13705		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13706		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13707		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13708		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13709		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13710		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13711		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13712		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13713		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13714		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13715		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13716		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13717		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13718		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13719		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13720		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13721		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13722		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13723		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13724		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13725		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13726		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13727		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13728		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13729		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13730		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13731		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13732		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13733		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13734		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13735		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13736		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13737		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13738		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13739		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13740		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13741		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13742		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13743		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13744		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13745		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13746		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13747		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13748		{ 7, 11, 6, 0, 71 }
13749	};
13750	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13751		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13752		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13753		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13754		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13755		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13756		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13757		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13758		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13759		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13760		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13761		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13762		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13763		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13764		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13765		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13766		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13767		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13768		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13769		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13770		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13771		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13772		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13773		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13774		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13775		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13776		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13777		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13778		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13779		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13780		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13781		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13782		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13783		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13784		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13785		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13786		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13787		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13788		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13789		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13790		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13791		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13792		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13793		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13794		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13795		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13796		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13797		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13798		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13799		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13800		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13801		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13802		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13803		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13804		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13805		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13806		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13807		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13808		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13809		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13810		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13811		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13812		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13813		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13814		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13815	};
13816	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13817		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13818		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13819		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13820		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13821		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13822		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13823		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13824		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13825		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13826		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13827		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13828		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13829		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13830		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13831		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13832		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13833		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13834		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13835		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13836		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13837		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13838		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13839		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13840		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13841		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13842		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13843		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13844		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13845		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13846		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13847		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13848		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13849		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13850		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13851		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13852		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13853		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13854		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13855		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13856		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13857		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13858		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13859		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13860		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13861		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13862		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13863		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13864		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13865		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13866		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13867		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13868		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13869		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13870		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13871		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13872		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13873		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13874		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13875		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13876		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13877		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13878		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13879		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13880		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13881	};
13882
13883	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13884		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13885			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13886		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13887			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13888			    txgain_2ghz_r2);
13889		else
13890			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13891			    txgain_5ghz_r2);
13892		return;
13893	}
13894
13895	if (mac->mac_phy.rev == 0) {
13896		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13897		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13898			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13899		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13900			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13901			    txgain_2ghz_r0);
13902		else
13903			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13904			    txgain_5ghz_r0);
13905		return;
13906	}
13907
13908	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13909	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13910		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13911	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13912		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13913	else
13914		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13915}
13916
13917static void
13918bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13919{
13920	uint32_t offset, type;
13921
13922	type = BWN_TAB_GETTYPE(typeoffset);
13923	offset = BWN_TAB_GETOFFSET(typeoffset);
13924	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13925
13926	switch (type) {
13927	case BWN_TAB_8BIT:
13928		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13929		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13930		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13931		break;
13932	case BWN_TAB_16BIT:
13933		KASSERT(!(value & ~0xffff),
13934		    ("%s:%d: fail", __func__, __LINE__));
13935		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13936		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13937		break;
13938	case BWN_TAB_32BIT:
13939		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13940		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13941		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13942		break;
13943	default:
13944		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13945	}
13946}
13947
13948static int
13949bwn_phy_lp_loopback(struct bwn_mac *mac)
13950{
13951	struct bwn_phy_lp_iq_est ie;
13952	int i, index = -1;
13953	uint32_t tmp;
13954
13955	memset(&ie, 0, sizeof(ie));
13956
13957	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13958	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13959	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13960	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13961	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13962	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13963	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13964	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13965	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13966	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13967	for (i = 0; i < 32; i++) {
13968		bwn_phy_lp_set_rxgain_idx(mac, i);
13969		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13970		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13971			continue;
13972		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13973		if ((tmp > 4000) && (tmp < 10000)) {
13974			index = i;
13975			break;
13976		}
13977	}
13978	bwn_phy_lp_ddfs_turnoff(mac);
13979	return (index);
13980}
13981
13982static void
13983bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13984{
13985
13986	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13987}
13988
13989static void
13990bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13991    int incr1, int incr2, int scale_idx)
13992{
13993
13994	bwn_phy_lp_ddfs_turnoff(mac);
13995	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13996	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13997	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13998	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13999	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14000	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14001	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14002	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14003	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14004	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14005}
14006
14007static uint8_t
14008bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14009    struct bwn_phy_lp_iq_est *ie)
14010{
14011	int i;
14012
14013	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14014	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14015	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14016	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14017	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14018
14019	for (i = 0; i < 500; i++) {
14020		if (!(BWN_PHY_READ(mac,
14021		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14022			break;
14023		DELAY(1000);
14024	}
14025	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14026		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14027		return 0;
14028	}
14029
14030	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14031	ie->ie_iqprod <<= 16;
14032	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14033	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14034	ie->ie_ipwr <<= 16;
14035	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14036	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14037	ie->ie_qpwr <<= 16;
14038	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14039
14040	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14041	return 1;
14042}
14043
14044static uint32_t
14045bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14046{
14047	uint32_t offset, type, value;
14048
14049	type = BWN_TAB_GETTYPE(typeoffset);
14050	offset = BWN_TAB_GETOFFSET(typeoffset);
14051	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14052
14053	switch (type) {
14054	case BWN_TAB_8BIT:
14055		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14056		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14057		break;
14058	case BWN_TAB_16BIT:
14059		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14060		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14061		break;
14062	case BWN_TAB_32BIT:
14063		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14064		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14065		value <<= 16;
14066		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14067		break;
14068	default:
14069		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14070		value = 0;
14071	}
14072
14073	return (value);
14074}
14075
14076static void
14077bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14078{
14079
14080	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14081	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14082}
14083
14084static void
14085bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14086{
14087	uint16_t ctl;
14088
14089	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14090	ctl |= dac << 7;
14091	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14092}
14093
14094static void
14095bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14096{
14097
14098	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14099	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14100}
14101
14102static void
14103bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14104{
14105
14106	if (mac->mac_phy.rev < 2)
14107		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14108	else {
14109		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14110		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14111	}
14112	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14113}
14114
14115static uint16_t
14116bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14117{
14118
14119	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14120}
14121
14122static uint8_t
14123bwn_nbits(int32_t val)
14124{
14125	uint32_t tmp;
14126	uint8_t nbits = 0;
14127
14128	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14129		nbits++;
14130	return (nbits);
14131}
14132
14133static void
14134bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14135    struct bwn_txgain_entry *table)
14136{
14137	int i;
14138
14139	for (i = offset; i < count; i++)
14140		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14141}
14142
14143static void
14144bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14145    struct bwn_txgain_entry data)
14146{
14147
14148	if (mac->mac_phy.rev >= 2)
14149		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14150	else
14151		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14152}
14153
14154static void
14155bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14156    struct bwn_txgain_entry te)
14157{
14158	struct bwn_softc *sc = mac->mac_sc;
14159	struct ifnet *ifp = sc->sc_ifp;
14160	struct ieee80211com *ic = ifp->if_l2com;
14161	uint32_t tmp;
14162
14163	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14164
14165	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14166	if (mac->mac_phy.rev >= 3) {
14167		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14168		    (0x10 << 24) : (0x70 << 24));
14169	} else {
14170		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14171		    (0x14 << 24) : (0x7f << 24));
14172	}
14173	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14174	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14175	    te.te_bbmult << 20 | te.te_dac << 28);
14176}
14177
14178static void
14179bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14180    struct bwn_txgain_entry te)
14181{
14182
14183	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14184
14185	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14186	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14187	    te.te_dac);
14188	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14189}
14190
14191static void
14192bwn_sysctl_node(struct bwn_softc *sc)
14193{
14194	device_t dev = sc->sc_dev;
14195	struct bwn_mac *mac;
14196	struct bwn_stats *stats;
14197
14198	/* XXX assume that count of MAC is only 1. */
14199
14200	if ((mac = sc->sc_curmac) == NULL)
14201		return;
14202	stats = &mac->mac_stats;
14203
14204	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14205	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14206	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14207	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14208	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14209	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14210	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14211	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14212	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14213
14214#ifdef BWN_DEBUG
14215	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14216	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14217	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14218#endif
14219}
14220
14221static device_method_t bwn_methods[] = {
14222	/* Device interface */
14223	DEVMETHOD(device_probe,		bwn_probe),
14224	DEVMETHOD(device_attach,	bwn_attach),
14225	DEVMETHOD(device_detach,	bwn_detach),
14226	DEVMETHOD(device_suspend,	bwn_suspend),
14227	DEVMETHOD(device_resume,	bwn_resume),
14228	KOBJMETHOD_END
14229};
14230static driver_t bwn_driver = {
14231	"bwn",
14232	bwn_methods,
14233	sizeof(struct bwn_softc)
14234};
14235static devclass_t bwn_devclass;
14236DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14237MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14238MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14239MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14240MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14241