if_bwn.c revision 286865
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 286865 2015-08-17 23:44:38Z adrian $");
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_var.h>
56#include <net/if_arp.h>
57#include <net/if_dl.h>
58#include <net/if_llc.h>
59#include <net/if_media.h>
60#include <net/if_types.h>
61
62#include <dev/pci/pcivar.h>
63#include <dev/pci/pcireg.h>
64#include <dev/siba/siba_ids.h>
65#include <dev/siba/sibareg.h>
66#include <dev/siba/sibavar.h>
67
68#include <net80211/ieee80211_var.h>
69#include <net80211/ieee80211_radiotap.h>
70#include <net80211/ieee80211_regdomain.h>
71#include <net80211/ieee80211_phy.h>
72#include <net80211/ieee80211_ratectl.h>
73
74#include <dev/bwn/if_bwnreg.h>
75#include <dev/bwn/if_bwnvar.h>
76
77static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
78    "Broadcom driver parameters");
79
80/*
81 * Tunable & sysctl variables.
82 */
83
84#ifdef BWN_DEBUG
85static	int bwn_debug = 0;
86SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
87    "Broadcom debugging printfs");
88enum {
89	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107	BWN_DEBUG_ANY		= 0xffffffff
108};
109#define	DPRINTF(sc, m, fmt, ...) do {			\
110	if (sc->sc_debug & (m))				\
111		printf(fmt, __VA_ARGS__);		\
112} while (0)
113#else
114#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115#endif
116
117static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119    "uses Bad Frames Preemption");
120static int	bwn_bluetooth = 1;
121SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122    "turns on Bluetooth Coexistence");
123static int	bwn_hwpctl = 0;
124SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125    "uses H/W power control");
126static int	bwn_msi_disable = 0;		/* MSI disabled  */
127TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128static int	bwn_usedma = 1;
129SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130    "uses DMA");
131TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132static int	bwn_wme = 1;
133SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134    "uses WME support");
135
136static int	bwn_attach_pre(struct bwn_softc *);
137static int	bwn_attach_post(struct bwn_softc *);
138static void	bwn_sprom_bugfixes(device_t);
139static void	bwn_init(void *);
140static int	bwn_init_locked(struct bwn_softc *);
141static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
142static void	bwn_start(struct ifnet *);
143static int	bwn_attach_core(struct bwn_mac *);
144static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145static int	bwn_phy_getinfo(struct bwn_mac *, int);
146static int	bwn_chiptest(struct bwn_mac *);
147static int	bwn_setup_channels(struct bwn_mac *, int, int);
148static int	bwn_phy_g_attach(struct bwn_mac *);
149static void	bwn_phy_g_detach(struct bwn_mac *);
150static void	bwn_phy_g_init_pre(struct bwn_mac *);
151static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152static int	bwn_phy_g_init(struct bwn_mac *);
153static void	bwn_phy_g_exit(struct bwn_mac *);
154static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156		    uint16_t);
157static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159		    uint16_t);
160static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165static int	bwn_phy_g_im(struct bwn_mac *, int);
166static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168static void	bwn_phy_g_task_15s(struct bwn_mac *);
169static void	bwn_phy_g_task_60s(struct bwn_mac *);
170static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174		    uint16_t);
175static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177		    uint32_t);
178static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179		    uint16_t);
180static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181		    const struct bwn_channelinfo *, int);
182static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183		    const struct ieee80211_bpf_params *);
184static void	bwn_updateslot(struct ieee80211com *);
185static void	bwn_update_promisc(struct ieee80211com *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static void	bwn_wme_clear(struct bwn_softc *);
189static void	bwn_wme_load(struct bwn_mac *);
190static void	bwn_wme_loadparams(struct bwn_mac *,
191		    const struct wmeParams *, uint16_t);
192static void	bwn_scan_start(struct ieee80211com *);
193static void	bwn_scan_end(struct ieee80211com *);
194static void	bwn_set_channel(struct ieee80211com *);
195static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197		    const uint8_t [IEEE80211_ADDR_LEN],
198		    const uint8_t [IEEE80211_ADDR_LEN]);
199static void	bwn_vap_delete(struct ieee80211vap *);
200static void	bwn_stop(struct bwn_softc *, int);
201static void	bwn_stop_locked(struct bwn_softc *, int);
202static int	bwn_core_init(struct bwn_mac *);
203static void	bwn_core_start(struct bwn_mac *);
204static void	bwn_core_exit(struct bwn_mac *);
205static void	bwn_bt_disable(struct bwn_mac *);
206static int	bwn_chip_init(struct bwn_mac *);
207static uint64_t	bwn_hf_read(struct bwn_mac *);
208static void	bwn_hf_write(struct bwn_mac *, uint64_t);
209static void	bwn_set_txretry(struct bwn_mac *, int, int);
210static void	bwn_rate_init(struct bwn_mac *);
211static void	bwn_set_phytxctl(struct bwn_mac *);
212static void	bwn_spu_setdelay(struct bwn_mac *, int);
213static void	bwn_bt_enable(struct bwn_mac *);
214static void	bwn_set_macaddr(struct bwn_mac *);
215static void	bwn_crypt_init(struct bwn_mac *);
216static void	bwn_chip_exit(struct bwn_mac *);
217static int	bwn_fw_fillinfo(struct bwn_mac *);
218static int	bwn_fw_loaducode(struct bwn_mac *);
219static int	bwn_gpio_init(struct bwn_mac *);
220static int	bwn_fw_loadinitvals(struct bwn_mac *);
221static int	bwn_phy_init(struct bwn_mac *);
222static void	bwn_set_txantenna(struct bwn_mac *, int);
223static void	bwn_set_opmode(struct bwn_mac *);
224static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
225static uint8_t	bwn_plcp_getcck(const uint8_t);
226static uint8_t	bwn_plcp_getofdm(const uint8_t);
227static void	bwn_pio_init(struct bwn_mac *);
228static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
229static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230		    int);
231static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
232		    struct bwn_pio_rxqueue *, int);
233static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    uint16_t);
236static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
238static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239static void	bwn_pio_handle_txeof(struct bwn_mac *,
240		    const struct bwn_txstatus *);
241static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244		    uint16_t);
245static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246		    uint32_t);
247static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248		    struct mbuf *);
249static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
251		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
252static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253		    uint16_t, uint32_t);
254static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
255		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
256static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
257		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259		    uint16_t, struct bwn_pio_txpkt **);
260static void	bwn_dma_init(struct bwn_mac *);
261static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262static int	bwn_dma_mask2type(uint64_t);
263static uint64_t	bwn_dma_mask(struct bwn_mac *);
264static uint16_t	bwn_dma_base(int, int);
265static void	bwn_dma_ringfree(struct bwn_dma_ring **);
266static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
267		    int, struct bwn_dmadesc_generic **,
268		    struct bwn_dmadesc_meta **);
269static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
270		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271		    int, int);
272static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
274static void	bwn_dma_32_resume(struct bwn_dma_ring *);
275static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
278		    int, struct bwn_dmadesc_generic **,
279		    struct bwn_dmadesc_meta **);
280static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
281		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282		    int, int);
283static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
285static void	bwn_dma_64_resume(struct bwn_dma_ring *);
286static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
289static void	bwn_dma_setup(struct bwn_dma_ring *);
290static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291static void	bwn_dma_cleanup(struct bwn_dma_ring *);
292static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
293static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294static void	bwn_dma_rx(struct bwn_dma_ring *);
295static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
297		    struct bwn_dmadesc_meta *);
298static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299static int	bwn_dma_gettype(struct bwn_mac *);
300static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301static int	bwn_dma_freeslot(struct bwn_dma_ring *);
302static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
303static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304static int	bwn_dma_newbuf(struct bwn_dma_ring *,
305		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306		    int);
307static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308		    bus_size_t, int);
309static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310static void	bwn_dma_handle_txeof(struct bwn_mac *,
311		    const struct bwn_txstatus *);
312static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313		    struct mbuf *);
314static int	bwn_dma_getslot(struct bwn_dma_ring *);
315static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316		    uint8_t);
317static int	bwn_dma_attach(struct bwn_mac *);
318static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319		    int, int, int);
320static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321		    const struct bwn_txstatus *, uint16_t, int *);
322static void	bwn_dma_free(struct bwn_mac *);
323static void	bwn_phy_g_init_sub(struct bwn_mac *);
324static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
325static void	bwn_phy_init_b5(struct bwn_mac *);
326static void	bwn_phy_init_b6(struct bwn_mac *);
327static void	bwn_phy_init_a(struct bwn_mac *);
328static void	bwn_loopback_calcgain(struct bwn_mac *);
329static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
330static void	bwn_lo_g_init(struct bwn_mac *);
331static void	bwn_lo_g_adjust(struct bwn_mac *);
332static void	bwn_lo_get_powervector(struct bwn_mac *);
333static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334		    const struct bwn_bbatt *, const struct bwn_rfatt *);
335static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336static void	bwn_phy_hwpctl_init(struct bwn_mac *);
337static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *,
340		    uint8_t);
341static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
344static void	bwn_wa_init(struct bwn_mac *);
345static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346		    uint16_t);
347static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
348static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349		    uint32_t);
350static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353static void	bwn_mac_suspend(struct bwn_mac *);
354static void	bwn_mac_enable(struct bwn_mac *);
355static void	bwn_psctl(struct bwn_mac *, uint32_t);
356static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
357static void	bwn_nrssi_offset(struct bwn_mac *);
358static void	bwn_nrssi_threshold(struct bwn_mac *);
359static void	bwn_nrssi_slope_11g(struct bwn_mac *);
360static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361		    int16_t);
362static void	bwn_set_original_gains(struct bwn_mac *);
363static void	bwn_hwpctl_early_init(struct bwn_mac *);
364static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
365static uint16_t	bwn_phy_g_chan2freq(uint8_t);
366static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368		    const char *, struct bwn_fwfile *);
369static void	bwn_release_firmware(struct bwn_mac *);
370static void	bwn_do_release_fw(struct bwn_fwfile *);
371static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
372static int	bwn_fwinitvals_write(struct bwn_mac *,
373		    const struct bwn_fwinitvals *, size_t, size_t);
374static int	bwn_switch_channel(struct bwn_mac *, int);
375static uint16_t	bwn_ant2phy(int);
376static void	bwn_mac_write_bssid(struct bwn_mac *);
377static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378		    const uint8_t *);
379static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380		    const uint8_t *, size_t, const uint8_t *);
381static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
382		    const uint8_t *);
383static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384		    const uint8_t *);
385static void	bwn_phy_exit(struct bwn_mac *);
386static void	bwn_core_stop(struct bwn_mac *);
387static int	bwn_switch_band(struct bwn_softc *,
388		    struct ieee80211_channel *);
389static void	bwn_phy_reset(struct bwn_mac *);
390static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391static void	bwn_set_pretbtt(struct bwn_mac *);
392static int	bwn_intr(void *);
393static void	bwn_intrtask(void *, int);
394static void	bwn_restart(struct bwn_mac *, const char *);
395static void	bwn_intr_ucode_debug(struct bwn_mac *);
396static void	bwn_intr_tbtt_indication(struct bwn_mac *);
397static void	bwn_intr_atim_end(struct bwn_mac *);
398static void	bwn_intr_beacon(struct bwn_mac *);
399static void	bwn_intr_pmq(struct bwn_mac *);
400static void	bwn_intr_noise(struct bwn_mac *);
401static void	bwn_intr_txeof(struct bwn_mac *);
402static void	bwn_hwreset(void *, int);
403static void	bwn_handle_fwpanic(struct bwn_mac *);
404static void	bwn_load_beacon0(struct bwn_mac *);
405static void	bwn_load_beacon1(struct bwn_mac *);
406static uint32_t	bwn_jssi_read(struct bwn_mac *);
407static void	bwn_noise_gensample(struct bwn_mac *);
408static void	bwn_handle_txeof(struct bwn_mac *,
409		    const struct bwn_txstatus *);
410static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
412static void	bwn_start_locked(struct ifnet *);
413static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414		    struct mbuf *);
415static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416static int	bwn_set_txhdr(struct bwn_mac *,
417		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418		    uint16_t);
419static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420		    const uint8_t);
421static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422static uint8_t	bwn_get_fbrate(uint8_t);
423static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425static void	bwn_phy_lock(struct bwn_mac *);
426static void	bwn_phy_unlock(struct bwn_mac *);
427static void	bwn_rf_lock(struct bwn_mac *);
428static void	bwn_rf_unlock(struct bwn_mac *);
429static void	bwn_txpwr(void *, int);
430static void	bwn_tasks(void *);
431static void	bwn_task_15s(struct bwn_mac *);
432static void	bwn_task_30s(struct bwn_mac *);
433static void	bwn_task_60s(struct bwn_mac *);
434static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435		    uint8_t);
436static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439		    int, int);
440static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
441static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
443static void	bwn_watchdog(void *);
444static void	bwn_dma_stop(struct bwn_mac *);
445static void	bwn_pio_stop(struct bwn_mac *);
446static void	bwn_dma_ringstop(struct bwn_dma_ring **);
447static void	bwn_led_attach(struct bwn_mac *);
448static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449static void	bwn_led_event(struct bwn_mac *, int);
450static void	bwn_led_blink_start(struct bwn_mac *, int, int);
451static void	bwn_led_blink_next(void *);
452static void	bwn_led_blink_end(void *);
453static void	bwn_rfswitch(void *);
454static void	bwn_rf_turnon(struct bwn_mac *);
455static void	bwn_rf_turnoff(struct bwn_mac *);
456static void	bwn_phy_lp_init_pre(struct bwn_mac *);
457static int	bwn_phy_lp_init(struct bwn_mac *);
458static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461		    uint16_t);
462static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
467static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468static void	bwn_phy_lp_task_60s(struct bwn_mac *);
469static void	bwn_phy_lp_readsprom(struct bwn_mac *);
470static void	bwn_phy_lp_bbinit(struct bwn_mac *);
471static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
472static void	bwn_phy_lp_calib(struct bwn_mac *);
473static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
479static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_bugfix(struct bwn_mac *);
482static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
483static void	bwn_phy_lp_tblinit(struct bwn_mac *);
484static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
487static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
488static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
490static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
491static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495		    const void *);
496static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497static struct bwn_txgain
498		bwn_phy_lp_get_txgain(struct bwn_mac *);
499static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
500static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513static int	bwn_phy_lp_loopback(struct bwn_mac *);
514static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516		    int);
517static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518		    struct bwn_phy_lp_iq_est *);
519static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
521static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525static uint8_t	bwn_nbits(int32_t);
526static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527		    struct bwn_txgain_entry *);
528static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529		    struct bwn_txgain_entry);
530static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531		    struct bwn_txgain_entry);
532static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533		    struct bwn_txgain_entry);
534static void	bwn_sysctl_node(struct bwn_softc *);
535
536static struct resource_spec bwn_res_spec_legacy[] = {
537	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
538	{ -1,			0,		0 }
539};
540
541static struct resource_spec bwn_res_spec_msi[] = {
542	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
543	{ -1,			0,		0 }
544};
545
546static const struct bwn_channelinfo bwn_chantable_bg = {
547	.channels = {
548		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
549		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
550		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
551		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552		{ 2472, 13, 30 }, { 2484, 14, 30 } },
553	.nchannels = 14
554};
555
556static const struct bwn_channelinfo bwn_chantable_a = {
557	.channels = {
558		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
559		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
560		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
561		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
562		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570		{ 6080, 216, 30 } },
571	.nchannels = 37
572};
573
574static const struct bwn_channelinfo bwn_chantable_n = {
575	.channels = {
576		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
577		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
578		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
579		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
580		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
581		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
582		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
583		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
584		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
585		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
586		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
587		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612		{ 6130, 226, 30 }, { 6140, 228, 30 } },
613	.nchannels = 110
614};
615
616static const uint8_t bwn_b2063_chantable_data[33][12] = {
617	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650};
651
652static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653	{ 1, 2412, bwn_b2063_chantable_data[0] },
654	{ 2, 2417, bwn_b2063_chantable_data[0] },
655	{ 3, 2422, bwn_b2063_chantable_data[0] },
656	{ 4, 2427, bwn_b2063_chantable_data[1] },
657	{ 5, 2432, bwn_b2063_chantable_data[1] },
658	{ 6, 2437, bwn_b2063_chantable_data[1] },
659	{ 7, 2442, bwn_b2063_chantable_data[1] },
660	{ 8, 2447, bwn_b2063_chantable_data[1] },
661	{ 9, 2452, bwn_b2063_chantable_data[2] },
662	{ 10, 2457, bwn_b2063_chantable_data[2] },
663	{ 11, 2462, bwn_b2063_chantable_data[3] },
664	{ 12, 2467, bwn_b2063_chantable_data[3] },
665	{ 13, 2472, bwn_b2063_chantable_data[3] },
666	{ 14, 2484, bwn_b2063_chantable_data[4] },
667	{ 34, 5170, bwn_b2063_chantable_data[5] },
668	{ 36, 5180, bwn_b2063_chantable_data[6] },
669	{ 38, 5190, bwn_b2063_chantable_data[7] },
670	{ 40, 5200, bwn_b2063_chantable_data[8] },
671	{ 42, 5210, bwn_b2063_chantable_data[9] },
672	{ 44, 5220, bwn_b2063_chantable_data[10] },
673	{ 46, 5230, bwn_b2063_chantable_data[11] },
674	{ 48, 5240, bwn_b2063_chantable_data[12] },
675	{ 52, 5260, bwn_b2063_chantable_data[13] },
676	{ 56, 5280, bwn_b2063_chantable_data[14] },
677	{ 60, 5300, bwn_b2063_chantable_data[14] },
678	{ 64, 5320, bwn_b2063_chantable_data[15] },
679	{ 100, 5500, bwn_b2063_chantable_data[16] },
680	{ 104, 5520, bwn_b2063_chantable_data[17] },
681	{ 108, 5540, bwn_b2063_chantable_data[18] },
682	{ 112, 5560, bwn_b2063_chantable_data[19] },
683	{ 116, 5580, bwn_b2063_chantable_data[20] },
684	{ 120, 5600, bwn_b2063_chantable_data[21] },
685	{ 124, 5620, bwn_b2063_chantable_data[21] },
686	{ 128, 5640, bwn_b2063_chantable_data[22] },
687	{ 132, 5660, bwn_b2063_chantable_data[22] },
688	{ 136, 5680, bwn_b2063_chantable_data[22] },
689	{ 140, 5700, bwn_b2063_chantable_data[23] },
690	{ 149, 5745, bwn_b2063_chantable_data[23] },
691	{ 153, 5765, bwn_b2063_chantable_data[23] },
692	{ 157, 5785, bwn_b2063_chantable_data[23] },
693	{ 161, 5805, bwn_b2063_chantable_data[23] },
694	{ 165, 5825, bwn_b2063_chantable_data[23] },
695	{ 184, 4920, bwn_b2063_chantable_data[24] },
696	{ 188, 4940, bwn_b2063_chantable_data[25] },
697	{ 192, 4960, bwn_b2063_chantable_data[26] },
698	{ 196, 4980, bwn_b2063_chantable_data[27] },
699	{ 200, 5000, bwn_b2063_chantable_data[28] },
700	{ 204, 5020, bwn_b2063_chantable_data[29] },
701	{ 208, 5040, bwn_b2063_chantable_data[30] },
702	{ 212, 5060, bwn_b2063_chantable_data[31] },
703	{ 216, 5080, bwn_b2063_chantable_data[32] }
704};
705
706static const uint8_t bwn_b2062_chantable_data[22][12] = {
707	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729};
730
731static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732	{ 1, 2412, bwn_b2062_chantable_data[0] },
733	{ 2, 2417, bwn_b2062_chantable_data[0] },
734	{ 3, 2422, bwn_b2062_chantable_data[0] },
735	{ 4, 2427, bwn_b2062_chantable_data[0] },
736	{ 5, 2432, bwn_b2062_chantable_data[0] },
737	{ 6, 2437, bwn_b2062_chantable_data[0] },
738	{ 7, 2442, bwn_b2062_chantable_data[0] },
739	{ 8, 2447, bwn_b2062_chantable_data[0] },
740	{ 9, 2452, bwn_b2062_chantable_data[0] },
741	{ 10, 2457, bwn_b2062_chantable_data[0] },
742	{ 11, 2462, bwn_b2062_chantable_data[0] },
743	{ 12, 2467, bwn_b2062_chantable_data[0] },
744	{ 13, 2472, bwn_b2062_chantable_data[0] },
745	{ 14, 2484, bwn_b2062_chantable_data[0] },
746	{ 34, 5170, bwn_b2062_chantable_data[1] },
747	{ 38, 5190, bwn_b2062_chantable_data[2] },
748	{ 42, 5210, bwn_b2062_chantable_data[2] },
749	{ 46, 5230, bwn_b2062_chantable_data[3] },
750	{ 36, 5180, bwn_b2062_chantable_data[4] },
751	{ 40, 5200, bwn_b2062_chantable_data[5] },
752	{ 44, 5220, bwn_b2062_chantable_data[6] },
753	{ 48, 5240, bwn_b2062_chantable_data[3] },
754	{ 52, 5260, bwn_b2062_chantable_data[3] },
755	{ 56, 5280, bwn_b2062_chantable_data[3] },
756	{ 60, 5300, bwn_b2062_chantable_data[7] },
757	{ 64, 5320, bwn_b2062_chantable_data[8] },
758	{ 100, 5500, bwn_b2062_chantable_data[9] },
759	{ 104, 5520, bwn_b2062_chantable_data[10] },
760	{ 108, 5540, bwn_b2062_chantable_data[10] },
761	{ 112, 5560, bwn_b2062_chantable_data[10] },
762	{ 116, 5580, bwn_b2062_chantable_data[11] },
763	{ 120, 5600, bwn_b2062_chantable_data[12] },
764	{ 124, 5620, bwn_b2062_chantable_data[12] },
765	{ 128, 5640, bwn_b2062_chantable_data[12] },
766	{ 132, 5660, bwn_b2062_chantable_data[12] },
767	{ 136, 5680, bwn_b2062_chantable_data[12] },
768	{ 140, 5700, bwn_b2062_chantable_data[12] },
769	{ 149, 5745, bwn_b2062_chantable_data[12] },
770	{ 153, 5765, bwn_b2062_chantable_data[12] },
771	{ 157, 5785, bwn_b2062_chantable_data[12] },
772	{ 161, 5805, bwn_b2062_chantable_data[12] },
773	{ 165, 5825, bwn_b2062_chantable_data[12] },
774	{ 184, 4920, bwn_b2062_chantable_data[13] },
775	{ 188, 4940, bwn_b2062_chantable_data[14] },
776	{ 192, 4960, bwn_b2062_chantable_data[15] },
777	{ 196, 4980, bwn_b2062_chantable_data[16] },
778	{ 200, 5000, bwn_b2062_chantable_data[17] },
779	{ 204, 5020, bwn_b2062_chantable_data[18] },
780	{ 208, 5040, bwn_b2062_chantable_data[19] },
781	{ 212, 5060, bwn_b2062_chantable_data[20] },
782	{ 216, 5080, bwn_b2062_chantable_data[21] }
783};
784
785/* for LP PHY */
786static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
788	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
789	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790	{ 13, -66, 13 }, { 14, -66, 13 },
791};
792
793/* for LP PHY */
794static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
796	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
797	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
798	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
799	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
800	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
801	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
805	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
806	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808};
809
810static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811
812static const uint8_t bwn_tab_sigsq_tbl[] = {
813	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819};
820
821static const uint8_t bwn_tab_pllfrac_tbl[] = {
822	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824};
825
826static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 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, 0x0000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839};
840
841static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847
848#define	VENDOR_LED_ACT(vendor)				\
849{							\
850	.vid = PCI_VENDOR_##vendor,			\
851	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
852}
853
854static const struct {
855	uint16_t	vid;
856	uint8_t		led_act[BWN_LED_MAX];
857} bwn_vendor_led_act[] = {
858	VENDOR_LED_ACT(COMPAQ),
859	VENDOR_LED_ACT(ASUSTEK)
860};
861
862static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863	{ BWN_VENDOR_LED_ACT_DEFAULT };
864
865#undef VENDOR_LED_ACT
866
867static const struct {
868	int		on_dur;
869	int		off_dur;
870} bwn_led_duration[109] = {
871	[0]	= { 400, 100 },
872	[2]	= { 150, 75 },
873	[4]	= { 90, 45 },
874	[11]	= { 66, 34 },
875	[12]	= { 53, 26 },
876	[18]	= { 42, 21 },
877	[22]	= { 35, 17 },
878	[24]	= { 32, 16 },
879	[36]	= { 21, 10 },
880	[48]	= { 16, 8 },
881	[72]	= { 11, 5 },
882	[96]	= { 9, 4 },
883	[108]	= { 7, 3 }
884};
885
886static const uint16_t bwn_wme_shm_offsets[] = {
887	[0] = BWN_WME_BESTEFFORT,
888	[1] = BWN_WME_BACKGROUND,
889	[2] = BWN_WME_VOICE,
890	[3] = BWN_WME_VIDEO,
891};
892
893static const struct siba_devid bwn_devs[] = {
894	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903};
904
905static int
906bwn_probe(device_t dev)
907{
908	int i;
909
910	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912		    siba_get_device(dev) == bwn_devs[i].sd_device &&
913		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
914			return (BUS_PROBE_DEFAULT);
915	}
916
917	return (ENXIO);
918}
919
920static int
921bwn_attach(device_t dev)
922{
923	struct bwn_mac *mac;
924	struct bwn_softc *sc = device_get_softc(dev);
925	int error, i, msic, reg;
926
927	sc->sc_dev = dev;
928#ifdef BWN_DEBUG
929	sc->sc_debug = bwn_debug;
930#endif
931
932	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933		error = bwn_attach_pre(sc);
934		if (error != 0)
935			return (error);
936		bwn_sprom_bugfixes(dev);
937		sc->sc_flags |= BWN_FLAG_ATTACHED;
938	}
939
940	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941		if (siba_get_pci_device(dev) != 0x4313 &&
942		    siba_get_pci_device(dev) != 0x431a &&
943		    siba_get_pci_device(dev) != 0x4321) {
944			device_printf(sc->sc_dev,
945			    "skip 802.11 cores\n");
946			return (ENODEV);
947		}
948	}
949
950	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951	    M_NOWAIT | M_ZERO);
952	if (mac == NULL)
953		return (ENOMEM);
954	mac->mac_sc = sc;
955	mac->mac_status = BWN_MAC_STATUS_UNINIT;
956	if (bwn_bfp != 0)
957		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958
959	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962
963	error = bwn_attach_core(mac);
964	if (error)
965		goto fail0;
966	bwn_led_attach(mac);
967
968	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973	    mac->mac_phy.rf_rev);
974	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975		device_printf(sc->sc_dev, "DMA (%d bits)\n",
976		    mac->mac_method.dma.dmatype);
977	else
978		device_printf(sc->sc_dev, "PIO\n");
979
980	/*
981	 * setup PCI resources and interrupt.
982	 */
983	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
984		msic = pci_msi_count(dev);
985		if (bootverbose)
986			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987	} else
988		msic = 0;
989
990	mac->mac_intr_spec = bwn_res_spec_legacy;
991	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992		if (pci_alloc_msi(dev, &msic) == 0) {
993			device_printf(sc->sc_dev,
994			    "Using %d MSI messages\n", msic);
995			mac->mac_intr_spec = bwn_res_spec_msi;
996			mac->mac_msi = 1;
997		}
998	}
999
1000	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001	    mac->mac_res_irq);
1002	if (error) {
1003		device_printf(sc->sc_dev,
1004		    "couldn't allocate IRQ resources (%d)\n", error);
1005		goto fail1;
1006	}
1007
1008	if (mac->mac_msi == 0)
1009		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011		    &mac->mac_intrhand[0]);
1012	else {
1013		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016			    &mac->mac_intrhand[i]);
1017			if (error != 0) {
1018				device_printf(sc->sc_dev,
1019				    "couldn't setup interrupt (%d)\n", error);
1020				break;
1021			}
1022		}
1023	}
1024
1025	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026
1027	/*
1028	 * calls attach-post routine
1029	 */
1030	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031		bwn_attach_post(sc);
1032
1033	return (0);
1034fail1:
1035	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036		pci_release_msi(dev);
1037fail0:
1038	free(mac, M_DEVBUF);
1039	return (error);
1040}
1041
1042static int
1043bwn_is_valid_ether_addr(uint8_t *addr)
1044{
1045	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046
1047	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048		return (FALSE);
1049
1050	return (TRUE);
1051}
1052
1053static int
1054bwn_attach_post(struct bwn_softc *sc)
1055{
1056	struct ieee80211com *ic;
1057	struct ifnet *ifp = sc->sc_ifp;
1058
1059	ic = ifp->if_l2com;
1060	ic->ic_ifp = ifp;
1061	ic->ic_softc = sc;
1062	ic->ic_name = device_get_nameunit(sc->sc_dev);
1063	/* XXX not right but it's not used anywhere important */
1064	ic->ic_phytype = IEEE80211_T_OFDM;
1065	ic->ic_opmode = IEEE80211_M_STA;
1066	ic->ic_caps =
1067		  IEEE80211_C_STA		/* station mode supported */
1068		| IEEE80211_C_MONITOR		/* monitor mode */
1069		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1070		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1071		| IEEE80211_C_SHSLOT		/* short slot time supported */
1072		| IEEE80211_C_WME		/* WME/WMM supported */
1073		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1074		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1075		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1076		;
1077
1078	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1079
1080	/* call MI attach routine. */
1081	ieee80211_ifattach(ic,
1082	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1083	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1084	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1085
1086	ic->ic_headroom = sizeof(struct bwn_txhdr);
1087
1088	/* override default methods */
1089	ic->ic_raw_xmit = bwn_raw_xmit;
1090	ic->ic_updateslot = bwn_updateslot;
1091	ic->ic_update_promisc = bwn_update_promisc;
1092	ic->ic_wme.wme_update = bwn_wme_update;
1093
1094	ic->ic_scan_start = bwn_scan_start;
1095	ic->ic_scan_end = bwn_scan_end;
1096	ic->ic_set_channel = bwn_set_channel;
1097
1098	ic->ic_vap_create = bwn_vap_create;
1099	ic->ic_vap_delete = bwn_vap_delete;
1100
1101	ieee80211_radiotap_attach(ic,
1102	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1103	    BWN_TX_RADIOTAP_PRESENT,
1104	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1105	    BWN_RX_RADIOTAP_PRESENT);
1106
1107	bwn_sysctl_node(sc);
1108
1109	if (bootverbose)
1110		ieee80211_announce(ic);
1111	return (0);
1112}
1113
1114static void
1115bwn_phy_detach(struct bwn_mac *mac)
1116{
1117
1118	if (mac->mac_phy.detach != NULL)
1119		mac->mac_phy.detach(mac);
1120}
1121
1122static int
1123bwn_detach(device_t dev)
1124{
1125	struct bwn_softc *sc = device_get_softc(dev);
1126	struct bwn_mac *mac = sc->sc_curmac;
1127	struct ifnet *ifp = sc->sc_ifp;
1128	struct ieee80211com *ic = ifp->if_l2com;
1129	int i;
1130
1131	sc->sc_flags |= BWN_FLAG_INVALID;
1132
1133	if (device_is_attached(sc->sc_dev)) {
1134		bwn_stop(sc, 1);
1135		bwn_dma_free(mac);
1136		callout_drain(&sc->sc_led_blink_ch);
1137		callout_drain(&sc->sc_rfswitch_ch);
1138		callout_drain(&sc->sc_task_ch);
1139		callout_drain(&sc->sc_watchdog_ch);
1140		bwn_phy_detach(mac);
1141		if (ifp != NULL) {
1142			ieee80211_draintask(ic, &mac->mac_hwreset);
1143			ieee80211_draintask(ic, &mac->mac_txpower);
1144			ieee80211_ifdetach(ic);
1145			if_free(ifp);
1146		}
1147	}
1148	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1149	taskqueue_free(sc->sc_tq);
1150
1151	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1152		if (mac->mac_intrhand[i] != NULL) {
1153			bus_teardown_intr(dev, mac->mac_res_irq[i],
1154			    mac->mac_intrhand[i]);
1155			mac->mac_intrhand[i] = NULL;
1156		}
1157	}
1158	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1159	if (mac->mac_msi != 0)
1160		pci_release_msi(dev);
1161
1162	BWN_LOCK_DESTROY(sc);
1163	return (0);
1164}
1165
1166static int
1167bwn_attach_pre(struct bwn_softc *sc)
1168{
1169	struct ifnet *ifp;
1170	int error = 0;
1171
1172	BWN_LOCK_INIT(sc);
1173	TAILQ_INIT(&sc->sc_maclist);
1174	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1175	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1176	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1177
1178	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1179		taskqueue_thread_enqueue, &sc->sc_tq);
1180	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1181		"%s taskq", device_get_nameunit(sc->sc_dev));
1182
1183	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1184	if (ifp == NULL) {
1185		device_printf(sc->sc_dev, "can not if_alloc()\n");
1186		error = ENOSPC;
1187		goto fail;
1188	}
1189
1190	/* set these up early for if_printf use */
1191	if_initname(ifp, device_get_name(sc->sc_dev),
1192	    device_get_unit(sc->sc_dev));
1193
1194	ifp->if_softc = sc;
1195	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1196	ifp->if_init = bwn_init;
1197	ifp->if_ioctl = bwn_ioctl;
1198	ifp->if_start = bwn_start;
1199	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1200	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1201	IFQ_SET_READY(&ifp->if_snd);
1202
1203	return (0);
1204
1205fail:	BWN_LOCK_DESTROY(sc);
1206	return (error);
1207}
1208
1209static void
1210bwn_sprom_bugfixes(device_t dev)
1211{
1212#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1213	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1214	 (siba_get_pci_device(dev) == _device) &&			\
1215	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1216	 (siba_get_pci_subdevice(dev) == _subdevice))
1217
1218	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1219	    siba_get_pci_subdevice(dev) == 0x4e &&
1220	    siba_get_pci_revid(dev) > 0x40)
1221		siba_sprom_set_bf_lo(dev,
1222		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1223	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1224	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1225		siba_sprom_set_bf_lo(dev,
1226		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1227	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1228		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1232		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1233		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1234		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1235			siba_sprom_set_bf_lo(dev,
1236			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1237	}
1238#undef	BWN_ISDEV
1239}
1240
1241static int
1242bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1243{
1244#define	IS_RUNNING(ifp) \
1245	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1246	struct bwn_softc *sc = ifp->if_softc;
1247	struct ieee80211com *ic = ifp->if_l2com;
1248	struct ifreq *ifr = (struct ifreq *)data;
1249	int error = 0, startall;
1250
1251	switch (cmd) {
1252	case SIOCSIFFLAGS:
1253		startall = 0;
1254		if (IS_RUNNING(ifp)) {
1255			bwn_update_promisc(ic);
1256		} else if (ifp->if_flags & IFF_UP) {
1257			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1258				bwn_init(sc);
1259				startall = 1;
1260			}
1261		} else
1262			bwn_stop(sc, 1);
1263		if (startall)
1264			ieee80211_start_all(ic);
1265		break;
1266	case SIOCGIFMEDIA:
1267		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1268		break;
1269	case SIOCGIFADDR:
1270		error = ether_ioctl(ifp, cmd, data);
1271		break;
1272	default:
1273		error = EINVAL;
1274		break;
1275	}
1276	return (error);
1277}
1278
1279static void
1280bwn_start(struct ifnet *ifp)
1281{
1282	struct bwn_softc *sc = ifp->if_softc;
1283
1284	BWN_LOCK(sc);
1285	bwn_start_locked(ifp);
1286	BWN_UNLOCK(sc);
1287}
1288
1289static void
1290bwn_start_locked(struct ifnet *ifp)
1291{
1292	struct bwn_softc *sc = ifp->if_softc;
1293	struct bwn_mac *mac = sc->sc_curmac;
1294	struct ieee80211_frame *wh;
1295	struct ieee80211_node *ni;
1296	struct ieee80211_key *k;
1297	struct mbuf *m;
1298
1299	BWN_ASSERT_LOCKED(sc);
1300
1301	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1302	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1303		return;
1304
1305	for (;;) {
1306		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1307		if (m == NULL)
1308			break;
1309
1310		if (bwn_tx_isfull(sc, m))
1311			break;
1312		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1313		if (ni == NULL) {
1314			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1315			m_freem(m);
1316			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1317			continue;
1318		}
1319		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1320		wh = mtod(m, struct ieee80211_frame *);
1321		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1322			k = ieee80211_crypto_encap(ni, m);
1323			if (k == NULL) {
1324				ieee80211_free_node(ni);
1325				m_freem(m);
1326				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1327				continue;
1328			}
1329		}
1330		wh = NULL;	/* Catch any invalid use */
1331
1332		if (bwn_tx_start(sc, ni, m) != 0) {
1333			if (ni != NULL)
1334				ieee80211_free_node(ni);
1335			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1336			continue;
1337		}
1338
1339		sc->sc_watchdog_timer = 5;
1340	}
1341}
1342
1343static int
1344bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1345{
1346	struct bwn_dma_ring *dr;
1347	struct bwn_mac *mac = sc->sc_curmac;
1348	struct bwn_pio_txqueue *tq;
1349	struct ifnet *ifp = sc->sc_ifp;
1350	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1351
1352	BWN_ASSERT_LOCKED(sc);
1353
1354	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1355		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1356		if (dr->dr_stop == 1 ||
1357		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1358			dr->dr_stop = 1;
1359			goto full;
1360		}
1361	} else {
1362		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1363		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1364		    pktlen > (tq->tq_size - tq->tq_used)) {
1365			tq->tq_stop = 1;
1366			goto full;
1367		}
1368	}
1369	return (0);
1370full:
1371	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1372	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1373	return (1);
1374}
1375
1376static int
1377bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1378{
1379	struct bwn_mac *mac = sc->sc_curmac;
1380	int error;
1381
1382	BWN_ASSERT_LOCKED(sc);
1383
1384	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1385		m_freem(m);
1386		return (ENXIO);
1387	}
1388
1389	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1390	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1391	if (error) {
1392		m_freem(m);
1393		return (error);
1394	}
1395	return (0);
1396}
1397
1398static int
1399bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1400{
1401	struct bwn_pio_txpkt *tp;
1402	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1403	struct bwn_softc *sc = mac->mac_sc;
1404	struct bwn_txhdr txhdr;
1405	struct mbuf *m_new;
1406	uint32_t ctl32;
1407	int error;
1408	uint16_t ctl16;
1409
1410	BWN_ASSERT_LOCKED(sc);
1411
1412	/* XXX TODO send packets after DTIM */
1413
1414	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1415	tp = TAILQ_FIRST(&tq->tq_pktlist);
1416	tp->tp_ni = ni;
1417	tp->tp_m = m;
1418
1419	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1420	if (error) {
1421		device_printf(sc->sc_dev, "tx fail\n");
1422		return (error);
1423	}
1424
1425	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1426	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1427	tq->tq_free--;
1428
1429	if (siba_get_revid(sc->sc_dev) >= 8) {
1430		/*
1431		 * XXX please removes m_defrag(9)
1432		 */
1433		m_new = m_defrag(m, M_NOWAIT);
1434		if (m_new == NULL) {
1435			device_printf(sc->sc_dev,
1436			    "%s: can't defrag TX buffer\n",
1437			    __func__);
1438			return (ENOBUFS);
1439		}
1440		if (m_new->m_next != NULL)
1441			device_printf(sc->sc_dev,
1442			    "TODO: fragmented packets for PIO\n");
1443		tp->tp_m = m_new;
1444
1445		/* send HEADER */
1446		ctl32 = bwn_pio_write_multi_4(mac, tq,
1447		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1448			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1449		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1450		/* send BODY */
1451		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1452		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1453		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1454		    ctl32 | BWN_PIO8_TXCTL_EOF);
1455	} else {
1456		ctl16 = bwn_pio_write_multi_2(mac, tq,
1457		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1458			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1459		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1460		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1461		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1462		    ctl16 | BWN_PIO_TXCTL_EOF);
1463	}
1464
1465	return (0);
1466}
1467
1468static struct bwn_pio_txqueue *
1469bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1470{
1471
1472	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1473		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1474
1475	switch (prio) {
1476	case 0:
1477		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478	case 1:
1479		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1480	case 2:
1481		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1482	case 3:
1483		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1484	}
1485	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1486	return (NULL);
1487}
1488
1489static int
1490bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1491{
1492#define	BWN_GET_TXHDRCACHE(slot)					\
1493	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1494	struct bwn_dma *dma = &mac->mac_method.dma;
1495	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1496	struct bwn_dmadesc_generic *desc;
1497	struct bwn_dmadesc_meta *mt;
1498	struct bwn_softc *sc = mac->mac_sc;
1499	struct ifnet *ifp = sc->sc_ifp;
1500	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1501	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1502
1503	BWN_ASSERT_LOCKED(sc);
1504	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1505
1506	/* XXX send after DTIM */
1507
1508	slot = bwn_dma_getslot(dr);
1509	dr->getdesc(dr, slot, &desc, &mt);
1510	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1511	    ("%s:%d: fail", __func__, __LINE__));
1512
1513	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1514	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1515	    BWN_DMA_COOKIE(dr, slot));
1516	if (error)
1517		goto fail;
1518	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1519	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1520	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1521	if (error) {
1522		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1523		    __func__, error);
1524		goto fail;
1525	}
1526	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1527	    BUS_DMASYNC_PREWRITE);
1528	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1529	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1530	    BUS_DMASYNC_PREWRITE);
1531
1532	slot = bwn_dma_getslot(dr);
1533	dr->getdesc(dr, slot, &desc, &mt);
1534	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1535	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1536	mt->mt_m = m;
1537	mt->mt_ni = ni;
1538
1539	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1540	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1541	if (error && error != EFBIG) {
1542		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1543		    __func__, error);
1544		goto fail;
1545	}
1546	if (error) {    /* error == EFBIG */
1547		struct mbuf *m_new;
1548
1549		m_new = m_defrag(m, M_NOWAIT);
1550		if (m_new == NULL) {
1551			if_printf(ifp, "%s: can't defrag TX buffer\n",
1552			    __func__);
1553			error = ENOBUFS;
1554			goto fail;
1555		} else {
1556			m = m_new;
1557		}
1558
1559		mt->mt_m = m;
1560		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1561		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1562		if (error) {
1563			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1564			    __func__, error);
1565			goto fail;
1566		}
1567	}
1568	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1569	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1570	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1571	    BUS_DMASYNC_PREWRITE);
1572
1573	/* XXX send after DTIM */
1574
1575	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1576	return (0);
1577fail:
1578	dr->dr_curslot = backup[0];
1579	dr->dr_usedslot = backup[1];
1580	return (error);
1581#undef BWN_GET_TXHDRCACHE
1582}
1583
1584static void
1585bwn_watchdog(void *arg)
1586{
1587	struct bwn_softc *sc = arg;
1588	struct ifnet *ifp = sc->sc_ifp;
1589
1590	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1591		if_printf(ifp, "device timeout\n");
1592		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1593	}
1594	callout_schedule(&sc->sc_watchdog_ch, hz);
1595}
1596
1597static int
1598bwn_attach_core(struct bwn_mac *mac)
1599{
1600	struct bwn_softc *sc = mac->mac_sc;
1601	int error, have_bg = 0, have_a = 0;
1602	uint32_t high;
1603
1604	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1605	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1606
1607	siba_powerup(sc->sc_dev, 0);
1608
1609	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1610	bwn_reset_core(mac,
1611	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1612	error = bwn_phy_getinfo(mac, high);
1613	if (error)
1614		goto fail;
1615
1616	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1617	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1618	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1619	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1620	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1621		have_a = have_bg = 0;
1622		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1623			have_a = 1;
1624		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1625		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1626		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1627			have_bg = 1;
1628		else
1629			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1630			    mac->mac_phy.type));
1631	}
1632	/* XXX turns off PHY A because it's not supported */
1633	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1634	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1635		have_a = 0;
1636		have_bg = 1;
1637	}
1638
1639	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1640		mac->mac_phy.attach = bwn_phy_g_attach;
1641		mac->mac_phy.detach = bwn_phy_g_detach;
1642		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1643		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1644		mac->mac_phy.init = bwn_phy_g_init;
1645		mac->mac_phy.exit = bwn_phy_g_exit;
1646		mac->mac_phy.phy_read = bwn_phy_g_read;
1647		mac->mac_phy.phy_write = bwn_phy_g_write;
1648		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1649		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1650		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1651		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1652		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1653		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1654		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1655		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1656		mac->mac_phy.set_im = bwn_phy_g_im;
1657		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1658		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1659		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1660		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1661	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1662		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1663		mac->mac_phy.init = bwn_phy_lp_init;
1664		mac->mac_phy.phy_read = bwn_phy_lp_read;
1665		mac->mac_phy.phy_write = bwn_phy_lp_write;
1666		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1667		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1668		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1669		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1670		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1671		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1672		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1673		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1674		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1675	} else {
1676		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1677		    mac->mac_phy.type);
1678		error = ENXIO;
1679		goto fail;
1680	}
1681
1682	mac->mac_phy.gmode = have_bg;
1683	if (mac->mac_phy.attach != NULL) {
1684		error = mac->mac_phy.attach(mac);
1685		if (error) {
1686			device_printf(sc->sc_dev, "failed\n");
1687			goto fail;
1688		}
1689	}
1690
1691	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1692
1693	error = bwn_chiptest(mac);
1694	if (error)
1695		goto fail;
1696	error = bwn_setup_channels(mac, have_bg, have_a);
1697	if (error) {
1698		device_printf(sc->sc_dev, "failed to setup channels\n");
1699		goto fail;
1700	}
1701
1702	if (sc->sc_curmac == NULL)
1703		sc->sc_curmac = mac;
1704
1705	error = bwn_dma_attach(mac);
1706	if (error != 0) {
1707		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1708		goto fail;
1709	}
1710
1711	mac->mac_phy.switch_analog(mac, 0);
1712
1713	siba_dev_down(sc->sc_dev, 0);
1714fail:
1715	siba_powerdown(sc->sc_dev);
1716	return (error);
1717}
1718
1719static void
1720bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1721{
1722	struct bwn_softc *sc = mac->mac_sc;
1723	uint32_t low, ctl;
1724
1725	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1726
1727	siba_dev_up(sc->sc_dev, flags);
1728	DELAY(2000);
1729
1730	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1731	    ~BWN_TGSLOW_PHYRESET;
1732	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1733	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734	DELAY(1000);
1735	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1736	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1737	DELAY(1000);
1738
1739	if (mac->mac_phy.switch_analog != NULL)
1740		mac->mac_phy.switch_analog(mac, 1);
1741
1742	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1743	if (flags & BWN_TGSLOW_SUPPORT_G)
1744		ctl |= BWN_MACCTL_GMODE;
1745	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1746}
1747
1748static int
1749bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1750{
1751	struct bwn_phy *phy = &mac->mac_phy;
1752	struct bwn_softc *sc = mac->mac_sc;
1753	uint32_t tmp;
1754
1755	/* PHY */
1756	tmp = BWN_READ_2(mac, BWN_PHYVER);
1757	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1758	phy->rf_on = 1;
1759	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1760	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1761	phy->rev = (tmp & BWN_PHYVER_VERSION);
1762	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1763	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1764		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1765	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1766	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1767	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1768		goto unsupphy;
1769
1770	/* RADIO */
1771	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1772		if (siba_get_chiprev(sc->sc_dev) == 0)
1773			tmp = 0x3205017f;
1774		else if (siba_get_chiprev(sc->sc_dev) == 1)
1775			tmp = 0x4205017f;
1776		else
1777			tmp = 0x5205017f;
1778	} else {
1779		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1781		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1782		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1783	}
1784	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1785	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1786	phy->rf_manuf = (tmp & 0x00000fff);
1787	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1788		goto unsupradio;
1789	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1790	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1791	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1792	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1793	    (phy->type == BWN_PHYTYPE_N &&
1794	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1795	    (phy->type == BWN_PHYTYPE_LP &&
1796	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1797		goto unsupradio;
1798
1799	return (0);
1800unsupphy:
1801	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1802	    "analog %#x)\n",
1803	    phy->type, phy->rev, phy->analog);
1804	return (ENXIO);
1805unsupradio:
1806	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1807	    "rev %#x)\n",
1808	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1809	return (ENXIO);
1810}
1811
1812static int
1813bwn_chiptest(struct bwn_mac *mac)
1814{
1815#define	TESTVAL0	0x55aaaa55
1816#define	TESTVAL1	0xaa5555aa
1817	struct bwn_softc *sc = mac->mac_sc;
1818	uint32_t v, backup;
1819
1820	BWN_LOCK(sc);
1821
1822	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1823
1824	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1825	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1826		goto error;
1827	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1828	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1829		goto error;
1830
1831	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1832
1833	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1834	    (siba_get_revid(sc->sc_dev) <= 10)) {
1835		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1836		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1837		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1838			goto error;
1839		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1840			goto error;
1841	}
1842	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1843
1844	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1845	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1846		goto error;
1847
1848	BWN_UNLOCK(sc);
1849	return (0);
1850error:
1851	BWN_UNLOCK(sc);
1852	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1853	return (ENODEV);
1854}
1855
1856#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1857#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1858
1859static int
1860bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1861{
1862	struct bwn_softc *sc = mac->mac_sc;
1863	struct ifnet *ifp = sc->sc_ifp;
1864	struct ieee80211com *ic = ifp->if_l2com;
1865
1866	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1867	ic->ic_nchans = 0;
1868
1869	if (have_bg)
1870		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1871		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1872	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1873		if (have_a)
1874			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875			    &ic->ic_nchans, &bwn_chantable_n,
1876			    IEEE80211_CHAN_HTA);
1877	} else {
1878		if (have_a)
1879			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1880			    &ic->ic_nchans, &bwn_chantable_a,
1881			    IEEE80211_CHAN_A);
1882	}
1883
1884	mac->mac_phy.supports_2ghz = have_bg;
1885	mac->mac_phy.supports_5ghz = have_a;
1886
1887	return (ic->ic_nchans == 0 ? ENXIO : 0);
1888}
1889
1890static uint32_t
1891bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1892{
1893	uint32_t ret;
1894
1895	BWN_ASSERT_LOCKED(mac->mac_sc);
1896
1897	if (way == BWN_SHARED) {
1898		KASSERT((offset & 0x0001) == 0,
1899		    ("%s:%d warn", __func__, __LINE__));
1900		if (offset & 0x0003) {
1901			bwn_shm_ctlword(mac, way, offset >> 2);
1902			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1903			ret <<= 16;
1904			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1905			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1906			goto out;
1907		}
1908		offset >>= 2;
1909	}
1910	bwn_shm_ctlword(mac, way, offset);
1911	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1912out:
1913	return (ret);
1914}
1915
1916static uint16_t
1917bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1918{
1919	uint16_t ret;
1920
1921	BWN_ASSERT_LOCKED(mac->mac_sc);
1922
1923	if (way == BWN_SHARED) {
1924		KASSERT((offset & 0x0001) == 0,
1925		    ("%s:%d warn", __func__, __LINE__));
1926		if (offset & 0x0003) {
1927			bwn_shm_ctlword(mac, way, offset >> 2);
1928			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1929			goto out;
1930		}
1931		offset >>= 2;
1932	}
1933	bwn_shm_ctlword(mac, way, offset);
1934	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1935out:
1936
1937	return (ret);
1938}
1939
1940static void
1941bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1942    uint16_t offset)
1943{
1944	uint32_t control;
1945
1946	control = way;
1947	control <<= 16;
1948	control |= offset;
1949	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1950}
1951
1952static void
1953bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1954    uint32_t value)
1955{
1956	BWN_ASSERT_LOCKED(mac->mac_sc);
1957
1958	if (way == BWN_SHARED) {
1959		KASSERT((offset & 0x0001) == 0,
1960		    ("%s:%d warn", __func__, __LINE__));
1961		if (offset & 0x0003) {
1962			bwn_shm_ctlword(mac, way, offset >> 2);
1963			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1964				    (value >> 16) & 0xffff);
1965			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1966			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1967			return;
1968		}
1969		offset >>= 2;
1970	}
1971	bwn_shm_ctlword(mac, way, offset);
1972	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1973}
1974
1975static void
1976bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1977    uint16_t value)
1978{
1979	BWN_ASSERT_LOCKED(mac->mac_sc);
1980
1981	if (way == BWN_SHARED) {
1982		KASSERT((offset & 0x0001) == 0,
1983		    ("%s:%d warn", __func__, __LINE__));
1984		if (offset & 0x0003) {
1985			bwn_shm_ctlword(mac, way, offset >> 2);
1986			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1987			return;
1988		}
1989		offset >>= 2;
1990	}
1991	bwn_shm_ctlword(mac, way, offset);
1992	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1993}
1994
1995static void
1996bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1997    int txpow)
1998{
1999
2000	c->ic_freq = freq;
2001	c->ic_flags = flags;
2002	c->ic_ieee = ieee;
2003	c->ic_minpower = 0;
2004	c->ic_maxpower = 2 * txpow;
2005	c->ic_maxregpower = txpow;
2006}
2007
2008static void
2009bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2010    const struct bwn_channelinfo *ci, int flags)
2011{
2012	struct ieee80211_channel *c;
2013	int i;
2014
2015	c = &chans[*nchans];
2016
2017	for (i = 0; i < ci->nchannels; i++) {
2018		const struct bwn_channel *hc;
2019
2020		hc = &ci->channels[i];
2021		if (*nchans >= maxchans)
2022			break;
2023		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2024		c++, (*nchans)++;
2025		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2026			/* g channel have a separate b-only entry */
2027			if (*nchans >= maxchans)
2028				break;
2029			c[0] = c[-1];
2030			c[-1].ic_flags = IEEE80211_CHAN_B;
2031			c++, (*nchans)++;
2032		}
2033		if (flags == IEEE80211_CHAN_HTG) {
2034			/* HT g channel have a separate g-only entry */
2035			if (*nchans >= maxchans)
2036				break;
2037			c[-1].ic_flags = IEEE80211_CHAN_G;
2038			c[0] = c[-1];
2039			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2040			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2041			c++, (*nchans)++;
2042		}
2043		if (flags == IEEE80211_CHAN_HTA) {
2044			/* HT a channel have a separate a-only entry */
2045			if (*nchans >= maxchans)
2046				break;
2047			c[-1].ic_flags = IEEE80211_CHAN_A;
2048			c[0] = c[-1];
2049			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2050			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2051			c++, (*nchans)++;
2052		}
2053	}
2054}
2055
2056static int
2057bwn_phy_g_attach(struct bwn_mac *mac)
2058{
2059	struct bwn_softc *sc = mac->mac_sc;
2060	struct bwn_phy *phy = &mac->mac_phy;
2061	struct bwn_phy_g *pg = &phy->phy_g;
2062	unsigned int i;
2063	int16_t pab0, pab1, pab2;
2064	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2065	int8_t bg;
2066
2067	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2068	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2069	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2070	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2071
2072	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2073		device_printf(sc->sc_dev, "not supported anymore\n");
2074
2075	pg->pg_flags = 0;
2076	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2077	    pab2 == -1) {
2078		pg->pg_idletssi = 52;
2079		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2080		return (0);
2081	}
2082
2083	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2084	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2085	if (pg->pg_tssi2dbm == NULL) {
2086		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2087		return (ENOMEM);
2088	}
2089	for (i = 0; i < 64; i++) {
2090		int32_t m1, m2, f, q, delta;
2091		int8_t j = 0;
2092
2093		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2094		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2095		f = 256;
2096
2097		do {
2098			if (j > 15) {
2099				device_printf(sc->sc_dev,
2100				    "failed to generate tssi2dBm\n");
2101				free(pg->pg_tssi2dbm, M_DEVBUF);
2102				return (ENOMEM);
2103			}
2104			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2105			    f, 2048);
2106			delta = abs(q - f);
2107			f = q;
2108			j++;
2109		} while (delta >= 2);
2110
2111		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2112		    128);
2113	}
2114
2115	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2116	return (0);
2117}
2118
2119static void
2120bwn_phy_g_detach(struct bwn_mac *mac)
2121{
2122	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2123
2124	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2125		free(pg->pg_tssi2dbm, M_DEVBUF);
2126		pg->pg_tssi2dbm = NULL;
2127	}
2128	pg->pg_flags = 0;
2129}
2130
2131static void
2132bwn_phy_g_init_pre(struct bwn_mac *mac)
2133{
2134	struct bwn_phy *phy = &mac->mac_phy;
2135	struct bwn_phy_g *pg = &phy->phy_g;
2136	void *tssi2dbm;
2137	int idletssi;
2138	unsigned int i;
2139
2140	tssi2dbm = pg->pg_tssi2dbm;
2141	idletssi = pg->pg_idletssi;
2142
2143	memset(pg, 0, sizeof(*pg));
2144
2145	pg->pg_tssi2dbm = tssi2dbm;
2146	pg->pg_idletssi = idletssi;
2147
2148	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2149
2150	for (i = 0; i < N(pg->pg_nrssi); i++)
2151		pg->pg_nrssi[i] = -1000;
2152	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2153		pg->pg_nrssi_lt[i] = i;
2154	pg->pg_lofcal = 0xffff;
2155	pg->pg_initval = 0xffff;
2156	pg->pg_immode = BWN_IMMODE_NONE;
2157	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2158	pg->pg_avgtssi = 0xff;
2159
2160	pg->pg_loctl.tx_bias = 0xff;
2161	TAILQ_INIT(&pg->pg_loctl.calib_list);
2162}
2163
2164static int
2165bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2166{
2167	struct bwn_phy *phy = &mac->mac_phy;
2168	struct bwn_phy_g *pg = &phy->phy_g;
2169	struct bwn_softc *sc = mac->mac_sc;
2170	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2171	static const struct bwn_rfatt rfatt0[] = {
2172		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2173		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2174		{ 3, 1 }, { 4, 1 }
2175	};
2176	static const struct bwn_rfatt rfatt1[] = {
2177		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2178		{ 14, 1 }
2179	};
2180	static const struct bwn_rfatt rfatt2[] = {
2181		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2182		{ 9, 1 }
2183	};
2184	static const struct bwn_bbatt bbatt_0[] = {
2185		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2186	};
2187
2188	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2189
2190	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2191		pg->pg_bbatt.att = 0;
2192	else
2193		pg->pg_bbatt.att = 2;
2194
2195	/* prepare Radio Attenuation */
2196	pg->pg_rfatt.padmix = 0;
2197
2198	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2199	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2200		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2201			pg->pg_rfatt.att = 2;
2202			goto done;
2203		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2204			pg->pg_rfatt.att = 3;
2205			goto done;
2206		}
2207	}
2208
2209	if (phy->type == BWN_PHYTYPE_A) {
2210		pg->pg_rfatt.att = 0x60;
2211		goto done;
2212	}
2213
2214	switch (phy->rf_ver) {
2215	case 0x2050:
2216		switch (phy->rf_rev) {
2217		case 0:
2218			pg->pg_rfatt.att = 5;
2219			goto done;
2220		case 1:
2221			if (phy->type == BWN_PHYTYPE_G) {
2222				if (siba_get_pci_subvendor(sc->sc_dev) ==
2223				    SIBA_BOARDVENDOR_BCM &&
2224				    siba_get_pci_subdevice(sc->sc_dev) ==
2225				    SIBA_BOARD_BCM4309G &&
2226				    siba_get_pci_revid(sc->sc_dev) >= 30)
2227					pg->pg_rfatt.att = 3;
2228				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2229				    SIBA_BOARDVENDOR_BCM &&
2230				    siba_get_pci_subdevice(sc->sc_dev) ==
2231				    SIBA_BOARD_BU4306)
2232					pg->pg_rfatt.att = 3;
2233				else
2234					pg->pg_rfatt.att = 1;
2235			} else {
2236				if (siba_get_pci_subvendor(sc->sc_dev) ==
2237				    SIBA_BOARDVENDOR_BCM &&
2238				    siba_get_pci_subdevice(sc->sc_dev) ==
2239				    SIBA_BOARD_BCM4309G &&
2240				    siba_get_pci_revid(sc->sc_dev) >= 30)
2241					pg->pg_rfatt.att = 7;
2242				else
2243					pg->pg_rfatt.att = 6;
2244			}
2245			goto done;
2246		case 2:
2247			if (phy->type == BWN_PHYTYPE_G) {
2248				if (siba_get_pci_subvendor(sc->sc_dev) ==
2249				    SIBA_BOARDVENDOR_BCM &&
2250				    siba_get_pci_subdevice(sc->sc_dev) ==
2251				    SIBA_BOARD_BCM4309G &&
2252				    siba_get_pci_revid(sc->sc_dev) >= 30)
2253					pg->pg_rfatt.att = 3;
2254				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2255				    SIBA_BOARDVENDOR_BCM &&
2256				    siba_get_pci_subdevice(sc->sc_dev) ==
2257				    SIBA_BOARD_BU4306)
2258					pg->pg_rfatt.att = 5;
2259				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2260					pg->pg_rfatt.att = 4;
2261				else
2262					pg->pg_rfatt.att = 3;
2263			} else
2264				pg->pg_rfatt.att = 6;
2265			goto done;
2266		case 3:
2267			pg->pg_rfatt.att = 5;
2268			goto done;
2269		case 4:
2270		case 5:
2271			pg->pg_rfatt.att = 1;
2272			goto done;
2273		case 6:
2274		case 7:
2275			pg->pg_rfatt.att = 5;
2276			goto done;
2277		case 8:
2278			pg->pg_rfatt.att = 0xa;
2279			pg->pg_rfatt.padmix = 1;
2280			goto done;
2281		case 9:
2282		default:
2283			pg->pg_rfatt.att = 5;
2284			goto done;
2285		}
2286		break;
2287	case 0x2053:
2288		switch (phy->rf_rev) {
2289		case 1:
2290			pg->pg_rfatt.att = 6;
2291			goto done;
2292		}
2293		break;
2294	}
2295	pg->pg_rfatt.att = 5;
2296done:
2297	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2298
2299	if (!bwn_has_hwpctl(mac)) {
2300		lo->rfatt.array = rfatt0;
2301		lo->rfatt.len = N(rfatt0);
2302		lo->rfatt.min = 0;
2303		lo->rfatt.max = 9;
2304		goto genbbatt;
2305	}
2306	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2307		lo->rfatt.array = rfatt1;
2308		lo->rfatt.len = N(rfatt1);
2309		lo->rfatt.min = 0;
2310		lo->rfatt.max = 14;
2311		goto genbbatt;
2312	}
2313	lo->rfatt.array = rfatt2;
2314	lo->rfatt.len = N(rfatt2);
2315	lo->rfatt.min = 0;
2316	lo->rfatt.max = 9;
2317genbbatt:
2318	lo->bbatt.array = bbatt_0;
2319	lo->bbatt.len = N(bbatt_0);
2320	lo->bbatt.min = 0;
2321	lo->bbatt.max = 8;
2322
2323	BWN_READ_4(mac, BWN_MACCTL);
2324	if (phy->rev == 1) {
2325		phy->gmode = 0;
2326		bwn_reset_core(mac, 0);
2327		bwn_phy_g_init_sub(mac);
2328		phy->gmode = 1;
2329		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2330	}
2331	return (0);
2332}
2333
2334static uint16_t
2335bwn_phy_g_txctl(struct bwn_mac *mac)
2336{
2337	struct bwn_phy *phy = &mac->mac_phy;
2338
2339	if (phy->rf_ver != 0x2050)
2340		return (0);
2341	if (phy->rf_rev == 1)
2342		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2343	if (phy->rf_rev < 6)
2344		return (BWN_TXCTL_PA2DB);
2345	if (phy->rf_rev == 8)
2346		return (BWN_TXCTL_TXMIX);
2347	return (0);
2348}
2349
2350static int
2351bwn_phy_g_init(struct bwn_mac *mac)
2352{
2353
2354	bwn_phy_g_init_sub(mac);
2355	return (0);
2356}
2357
2358static void
2359bwn_phy_g_exit(struct bwn_mac *mac)
2360{
2361	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2362	struct bwn_lo_calib *cal, *tmp;
2363
2364	if (lo == NULL)
2365		return;
2366	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2367		TAILQ_REMOVE(&lo->calib_list, cal, list);
2368		free(cal, M_DEVBUF);
2369	}
2370}
2371
2372static uint16_t
2373bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2374{
2375
2376	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2377	return (BWN_READ_2(mac, BWN_PHYDATA));
2378}
2379
2380static void
2381bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2382{
2383
2384	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2385	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2386}
2387
2388static uint16_t
2389bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2390{
2391
2392	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2393	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2394	return (BWN_READ_2(mac, BWN_RFDATALO));
2395}
2396
2397static void
2398bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2399{
2400
2401	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2402	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2403	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2404}
2405
2406static int
2407bwn_phy_g_hwpctl(struct bwn_mac *mac)
2408{
2409
2410	return (mac->mac_phy.rev >= 6);
2411}
2412
2413static void
2414bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2415{
2416	struct bwn_phy *phy = &mac->mac_phy;
2417	struct bwn_phy_g *pg = &phy->phy_g;
2418	unsigned int channel;
2419	uint16_t rfover, rfoverval;
2420
2421	if (on) {
2422		if (phy->rf_on)
2423			return;
2424
2425		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2426		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2427		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2428		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2429			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2430			    pg->pg_radioctx_over);
2431			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2432			    pg->pg_radioctx_overval);
2433			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2434		}
2435		channel = phy->chan;
2436		bwn_phy_g_switch_chan(mac, 6, 1);
2437		bwn_phy_g_switch_chan(mac, channel, 0);
2438		return;
2439	}
2440
2441	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2442	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2443	pg->pg_radioctx_over = rfover;
2444	pg->pg_radioctx_overval = rfoverval;
2445	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2446	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2447	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2448}
2449
2450static int
2451bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2452{
2453
2454	if ((newchan < 1) || (newchan > 14))
2455		return (EINVAL);
2456	bwn_phy_g_switch_chan(mac, newchan, 0);
2457
2458	return (0);
2459}
2460
2461static uint32_t
2462bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2463{
2464
2465	return (1);
2466}
2467
2468static void
2469bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2470{
2471	struct bwn_phy *phy = &mac->mac_phy;
2472	uint64_t hf;
2473	int autodiv = 0;
2474	uint16_t tmp;
2475
2476	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2477		autodiv = 1;
2478
2479	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2480	bwn_hf_write(mac, hf);
2481
2482	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2483	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2484	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2485		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2486
2487	if (autodiv) {
2488		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2489		if (antenna == BWN_ANTAUTO1)
2490			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2491		else
2492			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2493		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2494	}
2495	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2496	if (autodiv)
2497		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2498	else
2499		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2500	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2501	if (phy->rev >= 2) {
2502		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2503		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2504		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2505		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2506		    0x15);
2507		if (phy->rev == 2)
2508			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2509		else
2510			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2511			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2512			    8);
2513	}
2514	if (phy->rev >= 6)
2515		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2516
2517	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2518	bwn_hf_write(mac, hf);
2519}
2520
2521static int
2522bwn_phy_g_im(struct bwn_mac *mac, int mode)
2523{
2524	struct bwn_phy *phy = &mac->mac_phy;
2525	struct bwn_phy_g *pg = &phy->phy_g;
2526
2527	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2528	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2529
2530	if (phy->rev == 0 || !phy->gmode)
2531		return (ENODEV);
2532
2533	pg->pg_aci_wlan_automatic = 0;
2534	return (0);
2535}
2536
2537static int
2538bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2539{
2540	struct bwn_phy *phy = &mac->mac_phy;
2541	struct bwn_phy_g *pg = &phy->phy_g;
2542	struct bwn_softc *sc = mac->mac_sc;
2543	unsigned int tssi;
2544	int cck, ofdm;
2545	int power;
2546	int rfatt, bbatt;
2547	unsigned int max;
2548
2549	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2550
2551	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2552	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2553	if (cck < 0 && ofdm < 0) {
2554		if (ignore_tssi == 0)
2555			return (BWN_TXPWR_RES_DONE);
2556		cck = 0;
2557		ofdm = 0;
2558	}
2559	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2560	if (pg->pg_avgtssi != 0xff)
2561		tssi = (tssi + pg->pg_avgtssi) / 2;
2562	pg->pg_avgtssi = tssi;
2563	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2564
2565	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2566	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2567		max -= 3;
2568	if (max >= 120) {
2569		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2570		max = 80;
2571		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2572	}
2573
2574	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2575	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2576	     tssi, 0x00), 0x3f)]);
2577	if (power == 0)
2578		return (BWN_TXPWR_RES_DONE);
2579
2580	rfatt = -((power + 7) / 8);
2581	bbatt = (-(power / 2)) - (4 * rfatt);
2582	if ((rfatt == 0) && (bbatt == 0))
2583		return (BWN_TXPWR_RES_DONE);
2584	pg->pg_bbatt_delta = bbatt;
2585	pg->pg_rfatt_delta = rfatt;
2586	return (BWN_TXPWR_RES_NEED_ADJUST);
2587}
2588
2589static void
2590bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2591{
2592	struct bwn_phy *phy = &mac->mac_phy;
2593	struct bwn_phy_g *pg = &phy->phy_g;
2594	struct bwn_softc *sc = mac->mac_sc;
2595	int rfatt, bbatt;
2596	uint8_t txctl;
2597
2598	bwn_mac_suspend(mac);
2599
2600	BWN_ASSERT_LOCKED(sc);
2601
2602	bbatt = pg->pg_bbatt.att;
2603	bbatt += pg->pg_bbatt_delta;
2604	rfatt = pg->pg_rfatt.att;
2605	rfatt += pg->pg_rfatt_delta;
2606
2607	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2608	txctl = pg->pg_txctl;
2609	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2610		if (rfatt <= 1) {
2611			if (txctl == 0) {
2612				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2613				rfatt += 2;
2614				bbatt += 2;
2615			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2616			    BWN_BFL_PACTRL) {
2617				bbatt += 4 * (rfatt - 2);
2618				rfatt = 2;
2619			}
2620		} else if (rfatt > 4 && txctl) {
2621			txctl = 0;
2622			if (bbatt < 3) {
2623				rfatt -= 3;
2624				bbatt += 2;
2625			} else {
2626				rfatt -= 2;
2627				bbatt -= 2;
2628			}
2629		}
2630	}
2631	pg->pg_txctl = txctl;
2632	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2633	pg->pg_rfatt.att = rfatt;
2634	pg->pg_bbatt.att = bbatt;
2635
2636	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2637
2638	bwn_phy_lock(mac);
2639	bwn_rf_lock(mac);
2640	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2641	    pg->pg_txctl);
2642	bwn_rf_unlock(mac);
2643	bwn_phy_unlock(mac);
2644
2645	bwn_mac_enable(mac);
2646}
2647
2648static void
2649bwn_phy_g_task_15s(struct bwn_mac *mac)
2650{
2651	struct bwn_phy *phy = &mac->mac_phy;
2652	struct bwn_phy_g *pg = &phy->phy_g;
2653	struct bwn_softc *sc = mac->mac_sc;
2654	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2655	unsigned long expire, now;
2656	struct bwn_lo_calib *cal, *tmp;
2657	uint8_t expired = 0;
2658
2659	bwn_mac_suspend(mac);
2660
2661	if (lo == NULL)
2662		goto fail;
2663
2664	BWN_GETTIME(now);
2665	if (bwn_has_hwpctl(mac)) {
2666		expire = now - BWN_LO_PWRVEC_EXPIRE;
2667		if (time_before(lo->pwr_vec_read_time, expire)) {
2668			bwn_lo_get_powervector(mac);
2669			bwn_phy_g_dc_lookup_init(mac, 0);
2670		}
2671		goto fail;
2672	}
2673
2674	expire = now - BWN_LO_CALIB_EXPIRE;
2675	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2676		if (!time_before(cal->calib_time, expire))
2677			continue;
2678		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2679		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2680			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2681			expired = 1;
2682		}
2683
2684		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2685		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2686		    cal->ctl.i, cal->ctl.q);
2687
2688		TAILQ_REMOVE(&lo->calib_list, cal, list);
2689		free(cal, M_DEVBUF);
2690	}
2691	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2692		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2693		    &pg->pg_rfatt);
2694		if (cal == NULL) {
2695			device_printf(sc->sc_dev,
2696			    "failed to recalibrate LO\n");
2697			goto fail;
2698		}
2699		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2700		bwn_lo_write(mac, &cal->ctl);
2701	}
2702
2703fail:
2704	bwn_mac_enable(mac);
2705}
2706
2707static void
2708bwn_phy_g_task_60s(struct bwn_mac *mac)
2709{
2710	struct bwn_phy *phy = &mac->mac_phy;
2711	struct bwn_softc *sc = mac->mac_sc;
2712	uint8_t old = phy->chan;
2713
2714	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2715		return;
2716
2717	bwn_mac_suspend(mac);
2718	bwn_nrssi_slope_11g(mac);
2719	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2720		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2721		bwn_switch_channel(mac, old);
2722	}
2723	bwn_mac_enable(mac);
2724}
2725
2726static void
2727bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2728{
2729
2730	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2731}
2732
2733static int
2734bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2735	const struct ieee80211_bpf_params *params)
2736{
2737	struct ieee80211com *ic = ni->ni_ic;
2738	struct ifnet *ifp = ic->ic_ifp;
2739	struct bwn_softc *sc = ic->ic_softc;
2740	struct bwn_mac *mac = sc->sc_curmac;
2741
2742	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2743	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2744		ieee80211_free_node(ni);
2745		m_freem(m);
2746		return (ENETDOWN);
2747	}
2748
2749	BWN_LOCK(sc);
2750	if (bwn_tx_isfull(sc, m)) {
2751		ieee80211_free_node(ni);
2752		m_freem(m);
2753		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2754		BWN_UNLOCK(sc);
2755		return (ENOBUFS);
2756	}
2757
2758	if (bwn_tx_start(sc, ni, m) != 0) {
2759		if (ni != NULL)
2760			ieee80211_free_node(ni);
2761		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2762	}
2763	sc->sc_watchdog_timer = 5;
2764	BWN_UNLOCK(sc);
2765	return (0);
2766}
2767
2768/*
2769 * Callback from the 802.11 layer to update the slot time
2770 * based on the current setting.  We use it to notify the
2771 * firmware of ERP changes and the f/w takes care of things
2772 * like slot time and preamble.
2773 */
2774static void
2775bwn_updateslot(struct ieee80211com *ic)
2776{
2777	struct bwn_softc *sc = ic->ic_softc;
2778	struct bwn_mac *mac;
2779
2780	BWN_LOCK(sc);
2781	if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
2782		mac = (struct bwn_mac *)sc->sc_curmac;
2783		bwn_set_slot_time(mac,
2784		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2785	}
2786	BWN_UNLOCK(sc);
2787}
2788
2789/*
2790 * Callback from the 802.11 layer after a promiscuous mode change.
2791 * Note this interface does not check the operating mode as this
2792 * is an internal callback and we are expected to honor the current
2793 * state (e.g. this is used for setting the interface in promiscuous
2794 * mode when operating in hostap mode to do ACS).
2795 */
2796static void
2797bwn_update_promisc(struct ieee80211com *ic)
2798{
2799	struct bwn_softc *sc = ic->ic_softc;
2800	struct bwn_mac *mac = sc->sc_curmac;
2801
2802	BWN_LOCK(sc);
2803	mac = sc->sc_curmac;
2804	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2805		if (ic->ic_ifp->if_flags & IFF_PROMISC)
2806			sc->sc_filters |= BWN_MACCTL_PROMISC;
2807		else
2808			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2809		bwn_set_opmode(mac);
2810	}
2811	BWN_UNLOCK(sc);
2812}
2813
2814/*
2815 * Callback from the 802.11 layer to update WME parameters.
2816 */
2817static int
2818bwn_wme_update(struct ieee80211com *ic)
2819{
2820	struct bwn_softc *sc = ic->ic_softc;
2821	struct bwn_mac *mac = sc->sc_curmac;
2822	struct wmeParams *wmep;
2823	int i;
2824
2825	BWN_LOCK(sc);
2826	mac = sc->sc_curmac;
2827	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2828		bwn_mac_suspend(mac);
2829		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2830			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2831			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2832		}
2833		bwn_mac_enable(mac);
2834	}
2835	BWN_UNLOCK(sc);
2836	return (0);
2837}
2838
2839static void
2840bwn_scan_start(struct ieee80211com *ic)
2841{
2842	struct bwn_softc *sc = ic->ic_softc;
2843	struct bwn_mac *mac;
2844
2845	BWN_LOCK(sc);
2846	mac = sc->sc_curmac;
2847	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849		bwn_set_opmode(mac);
2850		/* disable CFP update during scan */
2851		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852	}
2853	BWN_UNLOCK(sc);
2854}
2855
2856static void
2857bwn_scan_end(struct ieee80211com *ic)
2858{
2859	struct bwn_softc *sc = ic->ic_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 bwn_softc *sc = ic->ic_softc;
2876	struct bwn_mac *mac = sc->sc_curmac;
2877	struct bwn_phy *phy = &mac->mac_phy;
2878	int chan, error;
2879
2880	BWN_LOCK(sc);
2881
2882	error = bwn_switch_band(sc, ic->ic_curchan);
2883	if (error)
2884		goto fail;
2885	bwn_mac_suspend(mac);
2886	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2887	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2888	if (chan != phy->chan)
2889		bwn_switch_channel(mac, chan);
2890
2891	/* TX power level */
2892	if (ic->ic_curchan->ic_maxpower != 0 &&
2893	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2894		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2895		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2896		    BWN_TXPWR_IGNORE_TSSI);
2897	}
2898
2899	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2900	if (phy->set_antenna)
2901		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2902
2903	if (sc->sc_rf_enabled != phy->rf_on) {
2904		if (sc->sc_rf_enabled) {
2905			bwn_rf_turnon(mac);
2906			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2907				device_printf(sc->sc_dev,
2908				    "please turn on the RF switch\n");
2909		} else
2910			bwn_rf_turnoff(mac);
2911	}
2912
2913	bwn_mac_enable(mac);
2914
2915fail:
2916	/*
2917	 * Setup radio tap channel freq and flags
2918	 */
2919	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2920		htole16(ic->ic_curchan->ic_freq);
2921	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2922		htole16(ic->ic_curchan->ic_flags & 0xffff);
2923
2924	BWN_UNLOCK(sc);
2925}
2926
2927static struct ieee80211vap *
2928bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2929    enum ieee80211_opmode opmode, int flags,
2930    const uint8_t bssid[IEEE80211_ADDR_LEN],
2931    const uint8_t mac0[IEEE80211_ADDR_LEN])
2932{
2933	struct bwn_softc *sc = ic->ic_softc;
2934	struct ieee80211vap *vap;
2935	struct bwn_vap *bvp;
2936	uint8_t mac[IEEE80211_ADDR_LEN];
2937
2938	IEEE80211_ADDR_COPY(mac, mac0);
2939	switch (opmode) {
2940	case IEEE80211_M_HOSTAP:
2941	case IEEE80211_M_MBSS:
2942	case IEEE80211_M_STA:
2943	case IEEE80211_M_WDS:
2944	case IEEE80211_M_MONITOR:
2945	case IEEE80211_M_IBSS:
2946	case IEEE80211_M_AHDEMO:
2947		break;
2948	default:
2949		return (NULL);
2950	}
2951
2952	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2953
2954	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2955	    M_80211_VAP, M_NOWAIT | M_ZERO);
2956	if (bvp == NULL) {
2957		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2958		return (NULL);
2959	}
2960	vap = &bvp->bv_vap;
2961	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2962	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2963	/* override with driver methods */
2964	bvp->bv_newstate = vap->iv_newstate;
2965	vap->iv_newstate = bwn_newstate;
2966
2967	/* override max aid so sta's cannot assoc when we're out of sta id's */
2968	vap->iv_max_aid = BWN_STAID_MAX;
2969
2970	ieee80211_ratectl_init(vap);
2971
2972	/* complete setup */
2973	ieee80211_vap_attach(vap, ieee80211_media_change,
2974	    ieee80211_media_status);
2975	return (vap);
2976}
2977
2978static void
2979bwn_vap_delete(struct ieee80211vap *vap)
2980{
2981	struct bwn_vap *bvp = BWN_VAP(vap);
2982
2983	ieee80211_ratectl_deinit(vap);
2984	ieee80211_vap_detach(vap);
2985	free(bvp, M_80211_VAP);
2986}
2987
2988static void
2989bwn_init(void *arg)
2990{
2991	struct bwn_softc *sc = arg;
2992	struct ifnet *ifp = sc->sc_ifp;
2993	struct ieee80211com *ic = ifp->if_l2com;
2994	int error = 0;
2995
2996	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2997		__func__, ifp->if_flags);
2998
2999	BWN_LOCK(sc);
3000	error = bwn_init_locked(sc);
3001	BWN_UNLOCK(sc);
3002
3003	if (error == 0)
3004		ieee80211_start_all(ic);	/* start all vap's */
3005}
3006
3007static int
3008bwn_init_locked(struct bwn_softc *sc)
3009{
3010	struct bwn_mac *mac;
3011	struct ifnet *ifp = sc->sc_ifp;
3012	int error;
3013
3014	BWN_ASSERT_LOCKED(sc);
3015
3016	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3017	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3018	sc->sc_filters = 0;
3019	bwn_wme_clear(sc);
3020	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3021	sc->sc_rf_enabled = 1;
3022
3023	mac = sc->sc_curmac;
3024	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3025		error = bwn_core_init(mac);
3026		if (error != 0)
3027			return (error);
3028	}
3029	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3030		bwn_core_start(mac);
3031
3032	bwn_set_opmode(mac);
3033	bwn_set_pretbtt(mac);
3034	bwn_spu_setdelay(mac, 0);
3035	bwn_set_macaddr(mac);
3036
3037	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3038	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3039	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3040
3041	return (0);
3042}
3043
3044static void
3045bwn_stop(struct bwn_softc *sc, int statechg)
3046{
3047
3048	BWN_LOCK(sc);
3049	bwn_stop_locked(sc, statechg);
3050	BWN_UNLOCK(sc);
3051}
3052
3053static void
3054bwn_stop_locked(struct bwn_softc *sc, int statechg)
3055{
3056	struct bwn_mac *mac = sc->sc_curmac;
3057	struct ifnet *ifp = sc->sc_ifp;
3058
3059	BWN_ASSERT_LOCKED(sc);
3060
3061	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3062		/* XXX FIXME opmode not based on VAP */
3063		bwn_set_opmode(mac);
3064		bwn_set_macaddr(mac);
3065	}
3066
3067	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3068		bwn_core_stop(mac);
3069
3070	callout_stop(&sc->sc_led_blink_ch);
3071	sc->sc_led_blinking = 0;
3072
3073	bwn_core_exit(mac);
3074	sc->sc_rf_enabled = 0;
3075
3076	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3077}
3078
3079static void
3080bwn_wme_clear(struct bwn_softc *sc)
3081{
3082#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3083	struct wmeParams *p;
3084	unsigned int i;
3085
3086	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3087	    ("%s:%d: fail", __func__, __LINE__));
3088
3089	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3090		p = &(sc->sc_wmeParams[i]);
3091
3092		switch (bwn_wme_shm_offsets[i]) {
3093		case BWN_WME_VOICE:
3094			p->wmep_txopLimit = 0;
3095			p->wmep_aifsn = 2;
3096			/* XXX FIXME: log2(cwmin) */
3097			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3098			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3099			break;
3100		case BWN_WME_VIDEO:
3101			p->wmep_txopLimit = 0;
3102			p->wmep_aifsn = 2;
3103			/* XXX FIXME: log2(cwmin) */
3104			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3105			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3106			break;
3107		case BWN_WME_BESTEFFORT:
3108			p->wmep_txopLimit = 0;
3109			p->wmep_aifsn = 3;
3110			/* XXX FIXME: log2(cwmin) */
3111			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3112			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3113			break;
3114		case BWN_WME_BACKGROUND:
3115			p->wmep_txopLimit = 0;
3116			p->wmep_aifsn = 7;
3117			/* XXX FIXME: log2(cwmin) */
3118			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3119			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3120			break;
3121		default:
3122			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3123		}
3124	}
3125}
3126
3127static int
3128bwn_core_init(struct bwn_mac *mac)
3129{
3130	struct bwn_softc *sc = mac->mac_sc;
3131	uint64_t hf;
3132	int error;
3133
3134	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3135	    ("%s:%d: fail", __func__, __LINE__));
3136
3137	siba_powerup(sc->sc_dev, 0);
3138	if (!siba_dev_isup(sc->sc_dev))
3139		bwn_reset_core(mac,
3140		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3141
3142	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3143	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3144	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3145	BWN_GETTIME(mac->mac_phy.nexttime);
3146	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3147	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3148	mac->mac_stats.link_noise = -95;
3149	mac->mac_reason_intr = 0;
3150	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3151	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3152#ifdef BWN_DEBUG
3153	if (sc->sc_debug & BWN_DEBUG_XMIT)
3154		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3155#endif
3156	mac->mac_suspended = 1;
3157	mac->mac_task_state = 0;
3158	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3159
3160	mac->mac_phy.init_pre(mac);
3161
3162	siba_pcicore_intr(sc->sc_dev);
3163
3164	siba_fix_imcfglobug(sc->sc_dev);
3165	bwn_bt_disable(mac);
3166	if (mac->mac_phy.prepare_hw) {
3167		error = mac->mac_phy.prepare_hw(mac);
3168		if (error)
3169			goto fail0;
3170	}
3171	error = bwn_chip_init(mac);
3172	if (error)
3173		goto fail0;
3174	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3175	    siba_get_revid(sc->sc_dev));
3176	hf = bwn_hf_read(mac);
3177	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3178		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3179		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3180			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3181		if (mac->mac_phy.rev == 1)
3182			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3183	}
3184	if (mac->mac_phy.rf_ver == 0x2050) {
3185		if (mac->mac_phy.rf_rev < 6)
3186			hf |= BWN_HF_FORCE_VCO_RECALC;
3187		if (mac->mac_phy.rf_rev == 6)
3188			hf |= BWN_HF_4318_TSSI;
3189	}
3190	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3191		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3192	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3193	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3194		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3195	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3196	bwn_hf_write(mac, hf);
3197
3198	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3199	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3200	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3201	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3202
3203	bwn_rate_init(mac);
3204	bwn_set_phytxctl(mac);
3205
3206	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3207	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3208	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3209
3210	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3211		bwn_pio_init(mac);
3212	else
3213		bwn_dma_init(mac);
3214	bwn_wme_init(mac);
3215	bwn_spu_setdelay(mac, 1);
3216	bwn_bt_enable(mac);
3217
3218	siba_powerup(sc->sc_dev,
3219	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3220	bwn_set_macaddr(mac);
3221	bwn_crypt_init(mac);
3222
3223	/* XXX LED initializatin */
3224
3225	mac->mac_status = BWN_MAC_STATUS_INITED;
3226
3227	return (error);
3228
3229fail0:
3230	siba_powerdown(sc->sc_dev);
3231	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3232	    ("%s:%d: fail", __func__, __LINE__));
3233	return (error);
3234}
3235
3236static void
3237bwn_core_start(struct bwn_mac *mac)
3238{
3239	struct bwn_softc *sc = mac->mac_sc;
3240	uint32_t tmp;
3241
3242	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3243	    ("%s:%d: fail", __func__, __LINE__));
3244
3245	if (siba_get_revid(sc->sc_dev) < 5)
3246		return;
3247
3248	while (1) {
3249		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3250		if (!(tmp & 0x00000001))
3251			break;
3252		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3253	}
3254
3255	bwn_mac_enable(mac);
3256	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3257	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3258
3259	mac->mac_status = BWN_MAC_STATUS_STARTED;
3260}
3261
3262static void
3263bwn_core_exit(struct bwn_mac *mac)
3264{
3265	struct bwn_softc *sc = mac->mac_sc;
3266	uint32_t macctl;
3267
3268	BWN_ASSERT_LOCKED(mac->mac_sc);
3269
3270	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3271	    ("%s:%d: fail", __func__, __LINE__));
3272
3273	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3274		return;
3275	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3276
3277	macctl = BWN_READ_4(mac, BWN_MACCTL);
3278	macctl &= ~BWN_MACCTL_MCODE_RUN;
3279	macctl |= BWN_MACCTL_MCODE_JMP0;
3280	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3281
3282	bwn_dma_stop(mac);
3283	bwn_pio_stop(mac);
3284	bwn_chip_exit(mac);
3285	mac->mac_phy.switch_analog(mac, 0);
3286	siba_dev_down(sc->sc_dev, 0);
3287	siba_powerdown(sc->sc_dev);
3288}
3289
3290static void
3291bwn_bt_disable(struct bwn_mac *mac)
3292{
3293	struct bwn_softc *sc = mac->mac_sc;
3294
3295	(void)sc;
3296	/* XXX do nothing yet */
3297}
3298
3299static int
3300bwn_chip_init(struct bwn_mac *mac)
3301{
3302	struct bwn_softc *sc = mac->mac_sc;
3303	struct bwn_phy *phy = &mac->mac_phy;
3304	uint32_t macctl;
3305	int error;
3306
3307	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3308	if (phy->gmode)
3309		macctl |= BWN_MACCTL_GMODE;
3310	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3311
3312	error = bwn_fw_fillinfo(mac);
3313	if (error)
3314		return (error);
3315	error = bwn_fw_loaducode(mac);
3316	if (error)
3317		return (error);
3318
3319	error = bwn_gpio_init(mac);
3320	if (error)
3321		return (error);
3322
3323	error = bwn_fw_loadinitvals(mac);
3324	if (error) {
3325		siba_gpio_set(sc->sc_dev, 0);
3326		return (error);
3327	}
3328	phy->switch_analog(mac, 1);
3329	error = bwn_phy_init(mac);
3330	if (error) {
3331		siba_gpio_set(sc->sc_dev, 0);
3332		return (error);
3333	}
3334	if (phy->set_im)
3335		phy->set_im(mac, BWN_IMMODE_NONE);
3336	if (phy->set_antenna)
3337		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3338	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3339
3340	if (phy->type == BWN_PHYTYPE_B)
3341		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3342	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3343	if (siba_get_revid(sc->sc_dev) < 5)
3344		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3345
3346	BWN_WRITE_4(mac, BWN_MACCTL,
3347	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3348	BWN_WRITE_4(mac, BWN_MACCTL,
3349	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3350	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3351
3352	bwn_set_opmode(mac);
3353	if (siba_get_revid(sc->sc_dev) < 3) {
3354		BWN_WRITE_2(mac, 0x060e, 0x0000);
3355		BWN_WRITE_2(mac, 0x0610, 0x8000);
3356		BWN_WRITE_2(mac, 0x0604, 0x0000);
3357		BWN_WRITE_2(mac, 0x0606, 0x0200);
3358	} else {
3359		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3360		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3361	}
3362	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3363	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3364	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3365	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3366	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3367	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3368	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3369	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3370	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3371	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3372	return (error);
3373}
3374
3375/* read hostflags */
3376static uint64_t
3377bwn_hf_read(struct bwn_mac *mac)
3378{
3379	uint64_t ret;
3380
3381	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3382	ret <<= 16;
3383	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3384	ret <<= 16;
3385	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3386	return (ret);
3387}
3388
3389static void
3390bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3391{
3392
3393	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3394	    (value & 0x00000000ffffull));
3395	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3396	    (value & 0x0000ffff0000ull) >> 16);
3397	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3398	    (value & 0xffff00000000ULL) >> 32);
3399}
3400
3401static void
3402bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3403{
3404
3405	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3406	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3407}
3408
3409static void
3410bwn_rate_init(struct bwn_mac *mac)
3411{
3412
3413	switch (mac->mac_phy.type) {
3414	case BWN_PHYTYPE_A:
3415	case BWN_PHYTYPE_G:
3416	case BWN_PHYTYPE_LP:
3417	case BWN_PHYTYPE_N:
3418		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3419		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3420		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3421		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3422		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3423		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3424		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3425		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3426			break;
3427		/* FALLTHROUGH */
3428	case BWN_PHYTYPE_B:
3429		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3430		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3431		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3432		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3433		break;
3434	default:
3435		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3436	}
3437}
3438
3439static void
3440bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3441{
3442	uint16_t offset;
3443
3444	if (ofdm) {
3445		offset = 0x480;
3446		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3447	} else {
3448		offset = 0x4c0;
3449		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3450	}
3451	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3452	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3453}
3454
3455static uint8_t
3456bwn_plcp_getcck(const uint8_t bitrate)
3457{
3458
3459	switch (bitrate) {
3460	case BWN_CCK_RATE_1MB:
3461		return (0x0a);
3462	case BWN_CCK_RATE_2MB:
3463		return (0x14);
3464	case BWN_CCK_RATE_5MB:
3465		return (0x37);
3466	case BWN_CCK_RATE_11MB:
3467		return (0x6e);
3468	}
3469	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3470	return (0);
3471}
3472
3473static uint8_t
3474bwn_plcp_getofdm(const uint8_t bitrate)
3475{
3476
3477	switch (bitrate) {
3478	case BWN_OFDM_RATE_6MB:
3479		return (0xb);
3480	case BWN_OFDM_RATE_9MB:
3481		return (0xf);
3482	case BWN_OFDM_RATE_12MB:
3483		return (0xa);
3484	case BWN_OFDM_RATE_18MB:
3485		return (0xe);
3486	case BWN_OFDM_RATE_24MB:
3487		return (0x9);
3488	case BWN_OFDM_RATE_36MB:
3489		return (0xd);
3490	case BWN_OFDM_RATE_48MB:
3491		return (0x8);
3492	case BWN_OFDM_RATE_54MB:
3493		return (0xc);
3494	}
3495	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3496	return (0);
3497}
3498
3499static void
3500bwn_set_phytxctl(struct bwn_mac *mac)
3501{
3502	uint16_t ctl;
3503
3504	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3505	    BWN_TX_PHY_TXPWR);
3506	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3507	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3508	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3509}
3510
3511static void
3512bwn_pio_init(struct bwn_mac *mac)
3513{
3514	struct bwn_pio *pio = &mac->mac_method.pio;
3515
3516	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3517	    & ~BWN_MACCTL_BIGENDIAN);
3518	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3519
3520	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3521	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3522	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3523	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3524	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3525	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3526}
3527
3528static void
3529bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3530    int index)
3531{
3532	struct bwn_pio_txpkt *tp;
3533	struct bwn_softc *sc = mac->mac_sc;
3534	unsigned int i;
3535
3536	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3537	tq->tq_index = index;
3538
3539	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3540	if (siba_get_revid(sc->sc_dev) >= 8)
3541		tq->tq_size = 1920;
3542	else {
3543		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3544		tq->tq_size -= 80;
3545	}
3546
3547	TAILQ_INIT(&tq->tq_pktlist);
3548	for (i = 0; i < N(tq->tq_pkts); i++) {
3549		tp = &(tq->tq_pkts[i]);
3550		tp->tp_index = i;
3551		tp->tp_queue = tq;
3552		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3553	}
3554}
3555
3556static uint16_t
3557bwn_pio_idx2base(struct bwn_mac *mac, int index)
3558{
3559	struct bwn_softc *sc = mac->mac_sc;
3560	static const uint16_t bases[] = {
3561		BWN_PIO_BASE0,
3562		BWN_PIO_BASE1,
3563		BWN_PIO_BASE2,
3564		BWN_PIO_BASE3,
3565		BWN_PIO_BASE4,
3566		BWN_PIO_BASE5,
3567		BWN_PIO_BASE6,
3568		BWN_PIO_BASE7,
3569	};
3570	static const uint16_t bases_rev11[] = {
3571		BWN_PIO11_BASE0,
3572		BWN_PIO11_BASE1,
3573		BWN_PIO11_BASE2,
3574		BWN_PIO11_BASE3,
3575		BWN_PIO11_BASE4,
3576		BWN_PIO11_BASE5,
3577	};
3578
3579	if (siba_get_revid(sc->sc_dev) >= 11) {
3580		if (index >= N(bases_rev11))
3581			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3582		return (bases_rev11[index]);
3583	}
3584	if (index >= N(bases))
3585		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3586	return (bases[index]);
3587}
3588
3589static void
3590bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3591    int index)
3592{
3593	struct bwn_softc *sc = mac->mac_sc;
3594
3595	prq->prq_mac = mac;
3596	prq->prq_rev = siba_get_revid(sc->sc_dev);
3597	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3598	bwn_dma_rxdirectfifo(mac, index, 1);
3599}
3600
3601static void
3602bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3603{
3604	if (tq == NULL)
3605		return;
3606	bwn_pio_cancel_tx_packets(tq);
3607}
3608
3609static void
3610bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3611{
3612
3613	bwn_destroy_pioqueue_tx(pio);
3614}
3615
3616static uint16_t
3617bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3618    uint16_t offset)
3619{
3620
3621	return (BWN_READ_2(mac, tq->tq_base + offset));
3622}
3623
3624static void
3625bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3626{
3627	uint32_t ctl;
3628	int type;
3629	uint16_t base;
3630
3631	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3632	base = bwn_dma_base(type, idx);
3633	if (type == BWN_DMA_64BIT) {
3634		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3635		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3636		if (enable)
3637			ctl |= BWN_DMA64_RXDIRECTFIFO;
3638		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3639	} else {
3640		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3641		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3642		if (enable)
3643			ctl |= BWN_DMA32_RXDIRECTFIFO;
3644		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3645	}
3646}
3647
3648static uint64_t
3649bwn_dma_mask(struct bwn_mac *mac)
3650{
3651	uint32_t tmp;
3652	uint16_t base;
3653
3654	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3655	if (tmp & SIBA_TGSHIGH_DMA64)
3656		return (BWN_DMA_BIT_MASK(64));
3657	base = bwn_dma_base(0, 0);
3658	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3659	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3660	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3661		return (BWN_DMA_BIT_MASK(32));
3662
3663	return (BWN_DMA_BIT_MASK(30));
3664}
3665
3666static int
3667bwn_dma_mask2type(uint64_t dmamask)
3668{
3669
3670	if (dmamask == BWN_DMA_BIT_MASK(30))
3671		return (BWN_DMA_30BIT);
3672	if (dmamask == BWN_DMA_BIT_MASK(32))
3673		return (BWN_DMA_32BIT);
3674	if (dmamask == BWN_DMA_BIT_MASK(64))
3675		return (BWN_DMA_64BIT);
3676	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3677	return (BWN_DMA_30BIT);
3678}
3679
3680static void
3681bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3682{
3683	struct bwn_pio_txpkt *tp;
3684	unsigned int i;
3685
3686	for (i = 0; i < N(tq->tq_pkts); i++) {
3687		tp = &(tq->tq_pkts[i]);
3688		if (tp->tp_m) {
3689			m_freem(tp->tp_m);
3690			tp->tp_m = NULL;
3691		}
3692	}
3693}
3694
3695static uint16_t
3696bwn_dma_base(int type, int controller_idx)
3697{
3698	static const uint16_t map64[] = {
3699		BWN_DMA64_BASE0,
3700		BWN_DMA64_BASE1,
3701		BWN_DMA64_BASE2,
3702		BWN_DMA64_BASE3,
3703		BWN_DMA64_BASE4,
3704		BWN_DMA64_BASE5,
3705	};
3706	static const uint16_t map32[] = {
3707		BWN_DMA32_BASE0,
3708		BWN_DMA32_BASE1,
3709		BWN_DMA32_BASE2,
3710		BWN_DMA32_BASE3,
3711		BWN_DMA32_BASE4,
3712		BWN_DMA32_BASE5,
3713	};
3714
3715	if (type == BWN_DMA_64BIT) {
3716		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3717		    ("%s:%d: fail", __func__, __LINE__));
3718		return (map64[controller_idx]);
3719	}
3720	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3721	    ("%s:%d: fail", __func__, __LINE__));
3722	return (map32[controller_idx]);
3723}
3724
3725static void
3726bwn_dma_init(struct bwn_mac *mac)
3727{
3728	struct bwn_dma *dma = &mac->mac_method.dma;
3729
3730	/* setup TX DMA channels. */
3731	bwn_dma_setup(dma->wme[WME_AC_BK]);
3732	bwn_dma_setup(dma->wme[WME_AC_BE]);
3733	bwn_dma_setup(dma->wme[WME_AC_VI]);
3734	bwn_dma_setup(dma->wme[WME_AC_VO]);
3735	bwn_dma_setup(dma->mcast);
3736	/* setup RX DMA channel. */
3737	bwn_dma_setup(dma->rx);
3738}
3739
3740static struct bwn_dma_ring *
3741bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3742    int for_tx, int type)
3743{
3744	struct bwn_dma *dma = &mac->mac_method.dma;
3745	struct bwn_dma_ring *dr;
3746	struct bwn_dmadesc_generic *desc;
3747	struct bwn_dmadesc_meta *mt;
3748	struct bwn_softc *sc = mac->mac_sc;
3749	int error, i;
3750
3751	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3752	if (dr == NULL)
3753		goto out;
3754	dr->dr_numslots = BWN_RXRING_SLOTS;
3755	if (for_tx)
3756		dr->dr_numslots = BWN_TXRING_SLOTS;
3757
3758	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3759	    M_DEVBUF, M_NOWAIT | M_ZERO);
3760	if (dr->dr_meta == NULL)
3761		goto fail0;
3762
3763	dr->dr_type = type;
3764	dr->dr_mac = mac;
3765	dr->dr_base = bwn_dma_base(type, controller_index);
3766	dr->dr_index = controller_index;
3767	if (type == BWN_DMA_64BIT) {
3768		dr->getdesc = bwn_dma_64_getdesc;
3769		dr->setdesc = bwn_dma_64_setdesc;
3770		dr->start_transfer = bwn_dma_64_start_transfer;
3771		dr->suspend = bwn_dma_64_suspend;
3772		dr->resume = bwn_dma_64_resume;
3773		dr->get_curslot = bwn_dma_64_get_curslot;
3774		dr->set_curslot = bwn_dma_64_set_curslot;
3775	} else {
3776		dr->getdesc = bwn_dma_32_getdesc;
3777		dr->setdesc = bwn_dma_32_setdesc;
3778		dr->start_transfer = bwn_dma_32_start_transfer;
3779		dr->suspend = bwn_dma_32_suspend;
3780		dr->resume = bwn_dma_32_resume;
3781		dr->get_curslot = bwn_dma_32_get_curslot;
3782		dr->set_curslot = bwn_dma_32_set_curslot;
3783	}
3784	if (for_tx) {
3785		dr->dr_tx = 1;
3786		dr->dr_curslot = -1;
3787	} else {
3788		if (dr->dr_index == 0) {
3789			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3790			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3791		} else
3792			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3793	}
3794
3795	error = bwn_dma_allocringmemory(dr);
3796	if (error)
3797		goto fail2;
3798
3799	if (for_tx) {
3800		/*
3801		 * Assumption: BWN_TXRING_SLOTS can be divided by
3802		 * BWN_TX_SLOTS_PER_FRAME
3803		 */
3804		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3805		    ("%s:%d: fail", __func__, __LINE__));
3806
3807		dr->dr_txhdr_cache =
3808		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3809			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3810		KASSERT(dr->dr_txhdr_cache != NULL,
3811		    ("%s:%d: fail", __func__, __LINE__));
3812
3813		/*
3814		 * Create TX ring DMA stuffs
3815		 */
3816		error = bus_dma_tag_create(dma->parent_dtag,
3817				    BWN_ALIGN, 0,
3818				    BUS_SPACE_MAXADDR,
3819				    BUS_SPACE_MAXADDR,
3820				    NULL, NULL,
3821				    BWN_HDRSIZE(mac),
3822				    1,
3823				    BUS_SPACE_MAXSIZE_32BIT,
3824				    0,
3825				    NULL, NULL,
3826				    &dr->dr_txring_dtag);
3827		if (error) {
3828			device_printf(sc->sc_dev,
3829			    "can't create TX ring DMA tag: TODO frees\n");
3830			goto fail1;
3831		}
3832
3833		for (i = 0; i < dr->dr_numslots; i += 2) {
3834			dr->getdesc(dr, i, &desc, &mt);
3835
3836			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3837			mt->mt_m = NULL;
3838			mt->mt_ni = NULL;
3839			mt->mt_islast = 0;
3840			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3841			    &mt->mt_dmap);
3842			if (error) {
3843				device_printf(sc->sc_dev,
3844				     "can't create RX buf DMA map\n");
3845				goto fail1;
3846			}
3847
3848			dr->getdesc(dr, i + 1, &desc, &mt);
3849
3850			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3851			mt->mt_m = NULL;
3852			mt->mt_ni = NULL;
3853			mt->mt_islast = 1;
3854			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3855			    &mt->mt_dmap);
3856			if (error) {
3857				device_printf(sc->sc_dev,
3858				     "can't create RX buf DMA map\n");
3859				goto fail1;
3860			}
3861		}
3862	} else {
3863		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3864		    &dr->dr_spare_dmap);
3865		if (error) {
3866			device_printf(sc->sc_dev,
3867			    "can't create RX buf DMA map\n");
3868			goto out;		/* XXX wrong! */
3869		}
3870
3871		for (i = 0; i < dr->dr_numslots; i++) {
3872			dr->getdesc(dr, i, &desc, &mt);
3873
3874			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3875			    &mt->mt_dmap);
3876			if (error) {
3877				device_printf(sc->sc_dev,
3878				    "can't create RX buf DMA map\n");
3879				goto out;	/* XXX wrong! */
3880			}
3881			error = bwn_dma_newbuf(dr, desc, mt, 1);
3882			if (error) {
3883				device_printf(sc->sc_dev,
3884				    "failed to allocate RX buf\n");
3885				goto out;	/* XXX wrong! */
3886			}
3887		}
3888
3889		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3890		    BUS_DMASYNC_PREWRITE);
3891
3892		dr->dr_usedslot = dr->dr_numslots;
3893	}
3894
3895      out:
3896	return (dr);
3897
3898fail2:
3899	free(dr->dr_txhdr_cache, M_DEVBUF);
3900fail1:
3901	free(dr->dr_meta, M_DEVBUF);
3902fail0:
3903	free(dr, M_DEVBUF);
3904	return (NULL);
3905}
3906
3907static void
3908bwn_dma_ringfree(struct bwn_dma_ring **dr)
3909{
3910
3911	if (dr == NULL)
3912		return;
3913
3914	bwn_dma_free_descbufs(*dr);
3915	bwn_dma_free_ringmemory(*dr);
3916
3917	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3918	free((*dr)->dr_meta, M_DEVBUF);
3919	free(*dr, M_DEVBUF);
3920
3921	*dr = NULL;
3922}
3923
3924static void
3925bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3926    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3927{
3928	struct bwn_dmadesc32 *desc;
3929
3930	*meta = &(dr->dr_meta[slot]);
3931	desc = dr->dr_ring_descbase;
3932	desc = &(desc[slot]);
3933
3934	*gdesc = (struct bwn_dmadesc_generic *)desc;
3935}
3936
3937static void
3938bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3939    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3940    int start, int end, int irq)
3941{
3942	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3943	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3944	uint32_t addr, addrext, ctl;
3945	int slot;
3946
3947	slot = (int)(&(desc->dma.dma32) - descbase);
3948	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3949	    ("%s:%d: fail", __func__, __LINE__));
3950
3951	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3952	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3953	addr |= siba_dma_translation(sc->sc_dev);
3954	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3955	if (slot == dr->dr_numslots - 1)
3956		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3957	if (start)
3958		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3959	if (end)
3960		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3961	if (irq)
3962		ctl |= BWN_DMA32_DCTL_IRQ;
3963	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3964	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3965
3966	desc->dma.dma32.control = htole32(ctl);
3967	desc->dma.dma32.address = htole32(addr);
3968}
3969
3970static void
3971bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3972{
3973
3974	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3975	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3976}
3977
3978static void
3979bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3980{
3981
3982	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3983	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3984}
3985
3986static void
3987bwn_dma_32_resume(struct bwn_dma_ring *dr)
3988{
3989
3990	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3991	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3992}
3993
3994static int
3995bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3996{
3997	uint32_t val;
3998
3999	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4000	val &= BWN_DMA32_RXDPTR;
4001
4002	return (val / sizeof(struct bwn_dmadesc32));
4003}
4004
4005static void
4006bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4007{
4008
4009	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4010	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4011}
4012
4013static void
4014bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4015    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4016{
4017	struct bwn_dmadesc64 *desc;
4018
4019	*meta = &(dr->dr_meta[slot]);
4020	desc = dr->dr_ring_descbase;
4021	desc = &(desc[slot]);
4022
4023	*gdesc = (struct bwn_dmadesc_generic *)desc;
4024}
4025
4026static void
4027bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4028    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4029    int start, int end, int irq)
4030{
4031	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4032	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4033	int slot;
4034	uint32_t ctl0 = 0, ctl1 = 0;
4035	uint32_t addrlo, addrhi;
4036	uint32_t addrext;
4037
4038	slot = (int)(&(desc->dma.dma64) - descbase);
4039	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4040	    ("%s:%d: fail", __func__, __LINE__));
4041
4042	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4043	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4044	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4045	    30;
4046	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4047	if (slot == dr->dr_numslots - 1)
4048		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4049	if (start)
4050		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4051	if (end)
4052		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4053	if (irq)
4054		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4055	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4056	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4057	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4058
4059	desc->dma.dma64.control0 = htole32(ctl0);
4060	desc->dma.dma64.control1 = htole32(ctl1);
4061	desc->dma.dma64.address_low = htole32(addrlo);
4062	desc->dma.dma64.address_high = htole32(addrhi);
4063}
4064
4065static void
4066bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4067{
4068
4069	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4070	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4071}
4072
4073static void
4074bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4075{
4076
4077	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4078	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4079}
4080
4081static void
4082bwn_dma_64_resume(struct bwn_dma_ring *dr)
4083{
4084
4085	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4086	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4087}
4088
4089static int
4090bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4091{
4092	uint32_t val;
4093
4094	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4095	val &= BWN_DMA64_RXSTATDPTR;
4096
4097	return (val / sizeof(struct bwn_dmadesc64));
4098}
4099
4100static void
4101bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4102{
4103
4104	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4105	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4106}
4107
4108static int
4109bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4110{
4111	struct bwn_mac *mac = dr->dr_mac;
4112	struct bwn_dma *dma = &mac->mac_method.dma;
4113	struct bwn_softc *sc = mac->mac_sc;
4114	int error;
4115
4116	error = bus_dma_tag_create(dma->parent_dtag,
4117			    BWN_ALIGN, 0,
4118			    BUS_SPACE_MAXADDR,
4119			    BUS_SPACE_MAXADDR,
4120			    NULL, NULL,
4121			    BWN_DMA_RINGMEMSIZE,
4122			    1,
4123			    BUS_SPACE_MAXSIZE_32BIT,
4124			    0,
4125			    NULL, NULL,
4126			    &dr->dr_ring_dtag);
4127	if (error) {
4128		device_printf(sc->sc_dev,
4129		    "can't create TX ring DMA tag: TODO frees\n");
4130		return (-1);
4131	}
4132
4133	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4134	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4135	    &dr->dr_ring_dmap);
4136	if (error) {
4137		device_printf(sc->sc_dev,
4138		    "can't allocate DMA mem: TODO frees\n");
4139		return (-1);
4140	}
4141	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4142	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4143	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4144	if (error) {
4145		device_printf(sc->sc_dev,
4146		    "can't load DMA mem: TODO free\n");
4147		return (-1);
4148	}
4149
4150	return (0);
4151}
4152
4153static void
4154bwn_dma_setup(struct bwn_dma_ring *dr)
4155{
4156	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4157	uint64_t ring64;
4158	uint32_t addrext, ring32, value;
4159	uint32_t trans = siba_dma_translation(sc->sc_dev);
4160
4161	if (dr->dr_tx) {
4162		dr->dr_curslot = -1;
4163
4164		if (dr->dr_type == BWN_DMA_64BIT) {
4165			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4166			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4167			    >> 30;
4168			value = BWN_DMA64_TXENABLE;
4169			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4170			    & BWN_DMA64_TXADDREXT_MASK;
4171			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4172			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4173			    (ring64 & 0xffffffff));
4174			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4175			    ((ring64 >> 32) &
4176			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4177		} else {
4178			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4179			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4180			value = BWN_DMA32_TXENABLE;
4181			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4182			    & BWN_DMA32_TXADDREXT_MASK;
4183			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4184			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4185			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4186		}
4187		return;
4188	}
4189
4190	/*
4191	 * set for RX
4192	 */
4193	dr->dr_usedslot = dr->dr_numslots;
4194
4195	if (dr->dr_type == BWN_DMA_64BIT) {
4196		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4197		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4198		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4199		value |= BWN_DMA64_RXENABLE;
4200		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4201		    & BWN_DMA64_RXADDREXT_MASK;
4202		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4203		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4204		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4205		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4206		    | (trans << 1));
4207		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4208		    sizeof(struct bwn_dmadesc64));
4209	} else {
4210		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4211		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4212		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4213		value |= BWN_DMA32_RXENABLE;
4214		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4215		    & BWN_DMA32_RXADDREXT_MASK;
4216		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4217		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4218		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4219		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4220		    sizeof(struct bwn_dmadesc32));
4221	}
4222}
4223
4224static void
4225bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4226{
4227
4228	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4229	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4230	    dr->dr_ring_dmap);
4231}
4232
4233static void
4234bwn_dma_cleanup(struct bwn_dma_ring *dr)
4235{
4236
4237	if (dr->dr_tx) {
4238		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4239		if (dr->dr_type == BWN_DMA_64BIT) {
4240			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4241			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4242		} else
4243			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4244	} else {
4245		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4246		if (dr->dr_type == BWN_DMA_64BIT) {
4247			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4248			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4249		} else
4250			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4251	}
4252}
4253
4254static void
4255bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4256{
4257	struct bwn_dmadesc_generic *desc;
4258	struct bwn_dmadesc_meta *meta;
4259	struct bwn_mac *mac = dr->dr_mac;
4260	struct bwn_dma *dma = &mac->mac_method.dma;
4261	struct bwn_softc *sc = mac->mac_sc;
4262	int i;
4263
4264	if (!dr->dr_usedslot)
4265		return;
4266	for (i = 0; i < dr->dr_numslots; i++) {
4267		dr->getdesc(dr, i, &desc, &meta);
4268
4269		if (meta->mt_m == NULL) {
4270			if (!dr->dr_tx)
4271				device_printf(sc->sc_dev, "%s: not TX?\n",
4272				    __func__);
4273			continue;
4274		}
4275		if (dr->dr_tx) {
4276			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4277				bus_dmamap_unload(dr->dr_txring_dtag,
4278				    meta->mt_dmap);
4279			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4280				bus_dmamap_unload(dma->txbuf_dtag,
4281				    meta->mt_dmap);
4282		} else
4283			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4284		bwn_dma_free_descbuf(dr, meta);
4285	}
4286}
4287
4288static int
4289bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4290    int type)
4291{
4292	struct bwn_softc *sc = mac->mac_sc;
4293	uint32_t value;
4294	int i;
4295	uint16_t offset;
4296
4297	for (i = 0; i < 10; i++) {
4298		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4299		    BWN_DMA32_TXSTATUS;
4300		value = BWN_READ_4(mac, base + offset);
4301		if (type == BWN_DMA_64BIT) {
4302			value &= BWN_DMA64_TXSTAT;
4303			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4304			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4305			    value == BWN_DMA64_TXSTAT_STOPPED)
4306				break;
4307		} else {
4308			value &= BWN_DMA32_TXSTATE;
4309			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4310			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4311			    value == BWN_DMA32_TXSTAT_STOPPED)
4312				break;
4313		}
4314		DELAY(1000);
4315	}
4316	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4317	BWN_WRITE_4(mac, base + offset, 0);
4318	for (i = 0; i < 10; i++) {
4319		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4320						   BWN_DMA32_TXSTATUS;
4321		value = BWN_READ_4(mac, base + offset);
4322		if (type == BWN_DMA_64BIT) {
4323			value &= BWN_DMA64_TXSTAT;
4324			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4325				i = -1;
4326				break;
4327			}
4328		} else {
4329			value &= BWN_DMA32_TXSTATE;
4330			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4331				i = -1;
4332				break;
4333			}
4334		}
4335		DELAY(1000);
4336	}
4337	if (i != -1) {
4338		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4339		return (ENODEV);
4340	}
4341	DELAY(1000);
4342
4343	return (0);
4344}
4345
4346static int
4347bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4348    int type)
4349{
4350	struct bwn_softc *sc = mac->mac_sc;
4351	uint32_t value;
4352	int i;
4353	uint16_t offset;
4354
4355	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4356	BWN_WRITE_4(mac, base + offset, 0);
4357	for (i = 0; i < 10; i++) {
4358		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4359		    BWN_DMA32_RXSTATUS;
4360		value = BWN_READ_4(mac, base + offset);
4361		if (type == BWN_DMA_64BIT) {
4362			value &= BWN_DMA64_RXSTAT;
4363			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4364				i = -1;
4365				break;
4366			}
4367		} else {
4368			value &= BWN_DMA32_RXSTATE;
4369			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4370				i = -1;
4371				break;
4372			}
4373		}
4374		DELAY(1000);
4375	}
4376	if (i != -1) {
4377		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4378		return (ENODEV);
4379	}
4380
4381	return (0);
4382}
4383
4384static void
4385bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4386    struct bwn_dmadesc_meta *meta)
4387{
4388
4389	if (meta->mt_m != NULL) {
4390		m_freem(meta->mt_m);
4391		meta->mt_m = NULL;
4392	}
4393	if (meta->mt_ni != NULL) {
4394		ieee80211_free_node(meta->mt_ni);
4395		meta->mt_ni = NULL;
4396	}
4397}
4398
4399static void
4400bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4401{
4402	struct bwn_rxhdr4 *rxhdr;
4403	unsigned char *frame;
4404
4405	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4406	rxhdr->frame_len = 0;
4407
4408	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4409	    sizeof(struct bwn_plcp6) + 2,
4410	    ("%s:%d: fail", __func__, __LINE__));
4411	frame = mtod(m, char *) + dr->dr_frameoffset;
4412	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4413}
4414
4415static uint8_t
4416bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4417{
4418	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4419
4420	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4421	    == 0xff);
4422}
4423
4424static void
4425bwn_wme_init(struct bwn_mac *mac)
4426{
4427
4428	bwn_wme_load(mac);
4429
4430	/* enable WME support. */
4431	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4432	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4433	    BWN_IFSCTL_USE_EDCF);
4434}
4435
4436static void
4437bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4438{
4439	struct bwn_softc *sc = mac->mac_sc;
4440	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4441	uint16_t delay;	/* microsec */
4442
4443	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4444	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4445		delay = 500;
4446	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4447		delay = max(delay, (uint16_t)2400);
4448
4449	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4450}
4451
4452static void
4453bwn_bt_enable(struct bwn_mac *mac)
4454{
4455	struct bwn_softc *sc = mac->mac_sc;
4456	uint64_t hf;
4457
4458	if (bwn_bluetooth == 0)
4459		return;
4460	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4461		return;
4462	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4463		return;
4464
4465	hf = bwn_hf_read(mac);
4466	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4467		hf |= BWN_HF_BT_COEXISTALT;
4468	else
4469		hf |= BWN_HF_BT_COEXIST;
4470	bwn_hf_write(mac, hf);
4471}
4472
4473static void
4474bwn_set_macaddr(struct bwn_mac *mac)
4475{
4476
4477	bwn_mac_write_bssid(mac);
4478	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4479}
4480
4481static void
4482bwn_clear_keys(struct bwn_mac *mac)
4483{
4484	int i;
4485
4486	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4487		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4488		    ("%s:%d: fail", __func__, __LINE__));
4489
4490		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4491		    NULL, BWN_SEC_KEYSIZE, NULL);
4492		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4493			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4494			    NULL, BWN_SEC_KEYSIZE, NULL);
4495		}
4496		mac->mac_key[i].keyconf = NULL;
4497	}
4498}
4499
4500static void
4501bwn_crypt_init(struct bwn_mac *mac)
4502{
4503	struct bwn_softc *sc = mac->mac_sc;
4504
4505	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4506	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4507	    ("%s:%d: fail", __func__, __LINE__));
4508	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4509	mac->mac_ktp *= 2;
4510	if (siba_get_revid(sc->sc_dev) >= 5)
4511		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4512	bwn_clear_keys(mac);
4513}
4514
4515static void
4516bwn_chip_exit(struct bwn_mac *mac)
4517{
4518	struct bwn_softc *sc = mac->mac_sc;
4519
4520	bwn_phy_exit(mac);
4521	siba_gpio_set(sc->sc_dev, 0);
4522}
4523
4524static int
4525bwn_fw_fillinfo(struct bwn_mac *mac)
4526{
4527	int error;
4528
4529	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4530	if (error == 0)
4531		return (0);
4532	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4533	if (error == 0)
4534		return (0);
4535	return (error);
4536}
4537
4538static int
4539bwn_gpio_init(struct bwn_mac *mac)
4540{
4541	struct bwn_softc *sc = mac->mac_sc;
4542	uint32_t mask = 0x1f, set = 0xf, value;
4543
4544	BWN_WRITE_4(mac, BWN_MACCTL,
4545	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4546	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4547	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4548
4549	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4550		mask |= 0x0060;
4551		set |= 0x0060;
4552	}
4553	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4554		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4555		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4556		mask |= 0x0200;
4557		set |= 0x0200;
4558	}
4559	if (siba_get_revid(sc->sc_dev) >= 2)
4560		mask |= 0x0010;
4561
4562	value = siba_gpio_get(sc->sc_dev);
4563	if (value == -1)
4564		return (0);
4565	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4566
4567	return (0);
4568}
4569
4570static int
4571bwn_fw_loadinitvals(struct bwn_mac *mac)
4572{
4573#define	GETFWOFFSET(fwp, offset)				\
4574	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4575	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4576	const struct bwn_fwhdr *hdr;
4577	struct bwn_fw *fw = &mac->mac_fw;
4578	int error;
4579
4580	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4581	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4582	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4583	if (error)
4584		return (error);
4585	if (fw->initvals_band.fw) {
4586		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4587		error = bwn_fwinitvals_write(mac,
4588		    GETFWOFFSET(fw->initvals_band, hdr_len),
4589		    be32toh(hdr->size),
4590		    fw->initvals_band.fw->datasize - hdr_len);
4591	}
4592	return (error);
4593#undef GETFWOFFSET
4594}
4595
4596static int
4597bwn_phy_init(struct bwn_mac *mac)
4598{
4599	struct bwn_softc *sc = mac->mac_sc;
4600	int error;
4601
4602	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4603	mac->mac_phy.rf_onoff(mac, 1);
4604	error = mac->mac_phy.init(mac);
4605	if (error) {
4606		device_printf(sc->sc_dev, "PHY init failed\n");
4607		goto fail0;
4608	}
4609	error = bwn_switch_channel(mac,
4610	    mac->mac_phy.get_default_chan(mac));
4611	if (error) {
4612		device_printf(sc->sc_dev,
4613		    "failed to switch default channel\n");
4614		goto fail1;
4615	}
4616	return (0);
4617fail1:
4618	if (mac->mac_phy.exit)
4619		mac->mac_phy.exit(mac);
4620fail0:
4621	mac->mac_phy.rf_onoff(mac, 0);
4622
4623	return (error);
4624}
4625
4626static void
4627bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4628{
4629	uint16_t ant;
4630	uint16_t tmp;
4631
4632	ant = bwn_ant2phy(antenna);
4633
4634	/* For ACK/CTS */
4635	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4636	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4637	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4638	/* For Probe Resposes */
4639	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4640	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4641	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4642}
4643
4644static void
4645bwn_set_opmode(struct bwn_mac *mac)
4646{
4647	struct bwn_softc *sc = mac->mac_sc;
4648	struct ifnet *ifp = sc->sc_ifp;
4649	struct ieee80211com *ic = ifp->if_l2com;
4650	uint32_t ctl;
4651	uint16_t cfp_pretbtt;
4652
4653	ctl = BWN_READ_4(mac, BWN_MACCTL);
4654	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4655	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4656	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4657	ctl |= BWN_MACCTL_STA;
4658
4659	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4660	    ic->ic_opmode == IEEE80211_M_MBSS)
4661		ctl |= BWN_MACCTL_HOSTAP;
4662	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4663		ctl &= ~BWN_MACCTL_STA;
4664	ctl |= sc->sc_filters;
4665
4666	if (siba_get_revid(sc->sc_dev) <= 4)
4667		ctl |= BWN_MACCTL_PROMISC;
4668
4669	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4670
4671	cfp_pretbtt = 2;
4672	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4673		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4674		    siba_get_chiprev(sc->sc_dev) == 3)
4675			cfp_pretbtt = 100;
4676		else
4677			cfp_pretbtt = 50;
4678	}
4679	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4680}
4681
4682static int
4683bwn_dma_gettype(struct bwn_mac *mac)
4684{
4685	uint32_t tmp;
4686	uint16_t base;
4687
4688	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4689	if (tmp & SIBA_TGSHIGH_DMA64)
4690		return (BWN_DMA_64BIT);
4691	base = bwn_dma_base(0, 0);
4692	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4693	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4694	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4695		return (BWN_DMA_32BIT);
4696
4697	return (BWN_DMA_30BIT);
4698}
4699
4700static void
4701bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4702{
4703	if (!error) {
4704		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4705		*((bus_addr_t *)arg) = seg->ds_addr;
4706	}
4707}
4708
4709static void
4710bwn_phy_g_init_sub(struct bwn_mac *mac)
4711{
4712	struct bwn_phy *phy = &mac->mac_phy;
4713	struct bwn_phy_g *pg = &phy->phy_g;
4714	struct bwn_softc *sc = mac->mac_sc;
4715	uint16_t i, tmp;
4716
4717	if (phy->rev == 1)
4718		bwn_phy_init_b5(mac);
4719	else
4720		bwn_phy_init_b6(mac);
4721
4722	if (phy->rev >= 2 || phy->gmode)
4723		bwn_phy_init_a(mac);
4724
4725	if (phy->rev >= 2) {
4726		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4727		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4728	}
4729	if (phy->rev == 2) {
4730		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4731		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4732	}
4733	if (phy->rev > 5) {
4734		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4735		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4736	}
4737	if (phy->gmode || phy->rev >= 2) {
4738		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4739		tmp &= BWN_PHYVER_VERSION;
4740		if (tmp == 3 || tmp == 5) {
4741			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4742			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4743		}
4744		if (tmp == 5) {
4745			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4746			    0x1f00);
4747		}
4748	}
4749	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4750		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4751	if (phy->rf_rev == 8) {
4752		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4753		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4754	}
4755	if (BWN_HAS_LOOPBACK(phy))
4756		bwn_loopback_calcgain(mac);
4757
4758	if (phy->rf_rev != 8) {
4759		if (pg->pg_initval == 0xffff)
4760			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4761		else
4762			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4763	}
4764	bwn_lo_g_init(mac);
4765	if (BWN_HAS_TXMAG(phy)) {
4766		BWN_RF_WRITE(mac, 0x52,
4767		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4768		    | pg->pg_loctl.tx_bias |
4769		    pg->pg_loctl.tx_magn);
4770	} else {
4771		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4772	}
4773	if (phy->rev >= 6) {
4774		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4775		    (pg->pg_loctl.tx_bias << 12));
4776	}
4777	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4778		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4779	else
4780		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4781	if (phy->rev < 2)
4782		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4783	else
4784		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4785	if (phy->gmode || phy->rev >= 2) {
4786		bwn_lo_g_adjust(mac);
4787		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4788	}
4789
4790	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4791		for (i = 0; i < 64; i++) {
4792			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4793			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4794			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4795			    -32), 31));
4796		}
4797		bwn_nrssi_threshold(mac);
4798	} else if (phy->gmode || phy->rev >= 2) {
4799		if (pg->pg_nrssi[0] == -1000) {
4800			KASSERT(pg->pg_nrssi[1] == -1000,
4801			    ("%s:%d: fail", __func__, __LINE__));
4802			bwn_nrssi_slope_11g(mac);
4803		} else
4804			bwn_nrssi_threshold(mac);
4805	}
4806	if (phy->rf_rev == 8)
4807		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4808	bwn_phy_hwpctl_init(mac);
4809	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4810	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4811		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4812		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4813	}
4814}
4815
4816static uint8_t
4817bwn_has_hwpctl(struct bwn_mac *mac)
4818{
4819
4820	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4821		return (0);
4822	return (mac->mac_phy.use_hwpctl(mac));
4823}
4824
4825static void
4826bwn_phy_init_b5(struct bwn_mac *mac)
4827{
4828	struct bwn_phy *phy = &mac->mac_phy;
4829	struct bwn_phy_g *pg = &phy->phy_g;
4830	struct bwn_softc *sc = mac->mac_sc;
4831	uint16_t offset, value;
4832	uint8_t old_channel;
4833
4834	if (phy->analog == 1)
4835		BWN_RF_SET(mac, 0x007a, 0x0050);
4836	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4837	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4838		value = 0x2120;
4839		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4840			BWN_PHY_WRITE(mac, offset, value);
4841			value += 0x202;
4842		}
4843	}
4844	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4845	if (phy->rf_ver == 0x2050)
4846		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4847
4848	if (phy->gmode || phy->rev >= 2) {
4849		if (phy->rf_ver == 0x2050) {
4850			BWN_RF_SET(mac, 0x007a, 0x0020);
4851			BWN_RF_SET(mac, 0x0051, 0x0004);
4852		}
4853		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4854
4855		BWN_PHY_SET(mac, 0x0802, 0x0100);
4856		BWN_PHY_SET(mac, 0x042b, 0x2000);
4857
4858		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4859
4860		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4861		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4862		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4863	}
4864
4865	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4866		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4867
4868	if (phy->analog == 1) {
4869		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4870		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4871		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4872		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4873		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4874	} else
4875		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4876	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4877	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4878
4879	if (phy->analog == 1)
4880		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4881	else
4882		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4883
4884	if (phy->analog == 0)
4885		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4886
4887	old_channel = phy->chan;
4888	bwn_phy_g_switch_chan(mac, 7, 0);
4889
4890	if (phy->rf_ver != 0x2050) {
4891		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4892		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4893	}
4894
4895	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4896	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4897
4898	if (phy->rf_ver == 0x2050) {
4899		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4900		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4901	}
4902
4903	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4904	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4905	BWN_RF_SET(mac, 0x007a, 0x0007);
4906
4907	bwn_phy_g_switch_chan(mac, old_channel, 0);
4908	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4909	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4910	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4911
4912	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4913	    pg->pg_txctl);
4914
4915	if (phy->rf_ver == 0x2050)
4916		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4917
4918	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4919}
4920
4921static void
4922bwn_loopback_calcgain(struct bwn_mac *mac)
4923{
4924	struct bwn_phy *phy = &mac->mac_phy;
4925	struct bwn_phy_g *pg = &phy->phy_g;
4926	struct bwn_softc *sc = mac->mac_sc;
4927	uint16_t backup_phy[16] = { 0 };
4928	uint16_t backup_radio[3];
4929	uint16_t backup_bband;
4930	uint16_t i, j, loop_i_max;
4931	uint16_t trsw_rx;
4932	uint16_t loop1_outer_done, loop1_inner_done;
4933
4934	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4935	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4936	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4937	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4938	if (phy->rev != 1) {
4939		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4940		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4941	}
4942	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4943	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4944	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4945	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4946	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4947	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4948	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4949	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4950	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4951	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4952	backup_bband = pg->pg_bbatt.att;
4953	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4954	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4955	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4956
4957	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4958	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4959	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4960	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4961	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4962	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4963	if (phy->rev != 1) {
4964		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4965		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4966		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4967		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4968	}
4969	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4970	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4971	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4972	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4973
4974	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4975	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4976	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4977
4978	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4979	if (phy->rev != 1) {
4980		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4981		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4982	}
4983	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4984
4985	if (phy->rf_rev == 8)
4986		BWN_RF_WRITE(mac, 0x43, 0x000f);
4987	else {
4988		BWN_RF_WRITE(mac, 0x52, 0);
4989		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4990	}
4991	bwn_phy_g_set_bbatt(mac, 11);
4992
4993	if (phy->rev >= 3)
4994		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4995	else
4996		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4997	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4998
4999	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5000	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5001
5002	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5003	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5004
5005	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5006		if (phy->rev >= 7) {
5007			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5008			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5009		}
5010	}
5011	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5012
5013	j = 0;
5014	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5015	for (i = 0; i < loop_i_max; i++) {
5016		for (j = 0; j < 16; j++) {
5017			BWN_RF_WRITE(mac, 0x43, i);
5018			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5019			    (j << 8));
5020			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5021			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5022			DELAY(20);
5023			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5024				goto done0;
5025		}
5026	}
5027done0:
5028	loop1_outer_done = i;
5029	loop1_inner_done = j;
5030	if (j >= 8) {
5031		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5032		trsw_rx = 0x1b;
5033		for (j = j - 8; j < 16; j++) {
5034			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5035			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5036			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5037			DELAY(20);
5038			trsw_rx -= 3;
5039			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5040				goto done1;
5041		}
5042	} else
5043		trsw_rx = 0x18;
5044done1:
5045
5046	if (phy->rev != 1) {
5047		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5048		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5049	}
5050	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5051	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5052	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5053	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5054	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5055	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5056	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5059
5060	bwn_phy_g_set_bbatt(mac, backup_bband);
5061
5062	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5063	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5064	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5065
5066	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5067	DELAY(10);
5068	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5069	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5070	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5071	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5072
5073	pg->pg_max_lb_gain =
5074	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5075	pg->pg_trsw_rx_gain = trsw_rx * 2;
5076}
5077
5078static uint16_t
5079bwn_rf_init_bcm2050(struct bwn_mac *mac)
5080{
5081	struct bwn_phy *phy = &mac->mac_phy;
5082	uint32_t tmp1 = 0, tmp2 = 0;
5083	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5084	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5085	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5086	static const uint8_t rcc_table[] = {
5087		0x02, 0x03, 0x01, 0x0f,
5088		0x06, 0x07, 0x05, 0x0f,
5089		0x0a, 0x0b, 0x09, 0x0f,
5090		0x0e, 0x0f, 0x0d, 0x0f,
5091	};
5092
5093	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5094	    rfoverval = rfover = cck3 = 0;
5095	radio0 = BWN_RF_READ(mac, 0x43);
5096	radio1 = BWN_RF_READ(mac, 0x51);
5097	radio2 = BWN_RF_READ(mac, 0x52);
5098	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5099	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5100	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5101	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5102
5103	if (phy->type == BWN_PHYTYPE_B) {
5104		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5105		reg0 = BWN_READ_2(mac, 0x3ec);
5106
5107		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5108		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5109	} else if (phy->gmode || phy->rev >= 2) {
5110		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5111		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5112		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5113		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5114		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5115		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5116
5117		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5118		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5119		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5120		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5121		if (BWN_HAS_LOOPBACK(phy)) {
5122			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5123			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5124			if (phy->rev >= 3)
5125				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5126			else
5127				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5128			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5129		}
5130
5131		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5132		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5133			BWN_LPD(0, 1, 1)));
5134		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5135		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5136	}
5137	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5138
5139	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5140	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5141	reg1 = BWN_READ_2(mac, 0x3e6);
5142	reg2 = BWN_READ_2(mac, 0x3f4);
5143
5144	if (phy->analog == 0)
5145		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5146	else {
5147		if (phy->analog >= 2)
5148			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5149		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5150		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5151	}
5152
5153	reg = BWN_RF_READ(mac, 0x60);
5154	index = (reg & 0x001e) >> 1;
5155	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5156
5157	if (phy->type == BWN_PHYTYPE_B)
5158		BWN_RF_WRITE(mac, 0x78, 0x26);
5159	if (phy->gmode || phy->rev >= 2) {
5160		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5161		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5162			BWN_LPD(0, 1, 1)));
5163	}
5164	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5165	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5166	if (phy->gmode || phy->rev >= 2) {
5167		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5168		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5169			BWN_LPD(0, 0, 1)));
5170	}
5171	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5172	BWN_RF_SET(mac, 0x51, 0x0004);
5173	if (phy->rf_rev == 8)
5174		BWN_RF_WRITE(mac, 0x43, 0x1f);
5175	else {
5176		BWN_RF_WRITE(mac, 0x52, 0);
5177		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5178	}
5179	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5180
5181	for (i = 0; i < 16; i++) {
5182		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5183		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5184		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5185		if (phy->gmode || phy->rev >= 2) {
5186			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5187			    bwn_rf_2050_rfoverval(mac,
5188				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5189		}
5190		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5191		DELAY(10);
5192		if (phy->gmode || phy->rev >= 2) {
5193			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5194			    bwn_rf_2050_rfoverval(mac,
5195				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5196		}
5197		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5198		DELAY(10);
5199		if (phy->gmode || phy->rev >= 2) {
5200			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5201			    bwn_rf_2050_rfoverval(mac,
5202				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5203		}
5204		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5205		DELAY(20);
5206		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5207		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5208		if (phy->gmode || phy->rev >= 2) {
5209			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5210			    bwn_rf_2050_rfoverval(mac,
5211				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5212		}
5213		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5214	}
5215	DELAY(10);
5216
5217	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5218	tmp1++;
5219	tmp1 >>= 9;
5220
5221	for (i = 0; i < 16; i++) {
5222		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5223		BWN_RF_WRITE(mac, 0x78, radio78);
5224		DELAY(10);
5225		for (j = 0; j < 16; j++) {
5226			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5227			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5228			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5229			if (phy->gmode || phy->rev >= 2) {
5230				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5231				    bwn_rf_2050_rfoverval(mac,
5232					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5233			}
5234			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5235			DELAY(10);
5236			if (phy->gmode || phy->rev >= 2) {
5237				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238				    bwn_rf_2050_rfoverval(mac,
5239					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5240			}
5241			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5242			DELAY(10);
5243			if (phy->gmode || phy->rev >= 2) {
5244				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245				    bwn_rf_2050_rfoverval(mac,
5246					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5247			}
5248			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5249			DELAY(10);
5250			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5251			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5252			if (phy->gmode || phy->rev >= 2) {
5253				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5254				    bwn_rf_2050_rfoverval(mac,
5255					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5256			}
5257			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5258		}
5259		tmp2++;
5260		tmp2 >>= 8;
5261		if (tmp1 < tmp2)
5262			break;
5263	}
5264
5265	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5266	BWN_RF_WRITE(mac, 0x51, radio1);
5267	BWN_RF_WRITE(mac, 0x52, radio2);
5268	BWN_RF_WRITE(mac, 0x43, radio0);
5269	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5270	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5271	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5272	BWN_WRITE_2(mac, 0x3e6, reg1);
5273	if (phy->analog != 0)
5274		BWN_WRITE_2(mac, 0x3f4, reg2);
5275	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5276	bwn_spu_workaround(mac, phy->chan);
5277	if (phy->type == BWN_PHYTYPE_B) {
5278		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5279		BWN_WRITE_2(mac, 0x3ec, reg0);
5280	} else if (phy->gmode) {
5281		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5282			    BWN_READ_2(mac, BWN_PHY_RADIO)
5283			    & 0x7fff);
5284		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5285		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5286		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5287		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5288			      analogoverval);
5289		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5290		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5291		if (BWN_HAS_LOOPBACK(phy)) {
5292			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5293			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5294		}
5295	}
5296
5297	return ((i > 15) ? radio78 : rcc);
5298}
5299
5300static void
5301bwn_phy_init_b6(struct bwn_mac *mac)
5302{
5303	struct bwn_phy *phy = &mac->mac_phy;
5304	struct bwn_phy_g *pg = &phy->phy_g;
5305	struct bwn_softc *sc = mac->mac_sc;
5306	uint16_t offset, val;
5307	uint8_t old_channel;
5308
5309	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5310	    ("%s:%d: fail", __func__, __LINE__));
5311
5312	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5313	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5314	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5315		BWN_RF_WRITE(mac, 0x51, 0x37);
5316		BWN_RF_WRITE(mac, 0x52, 0x70);
5317		BWN_RF_WRITE(mac, 0x53, 0xb3);
5318		BWN_RF_WRITE(mac, 0x54, 0x9b);
5319		BWN_RF_WRITE(mac, 0x5a, 0x88);
5320		BWN_RF_WRITE(mac, 0x5b, 0x88);
5321		BWN_RF_WRITE(mac, 0x5d, 0x88);
5322		BWN_RF_WRITE(mac, 0x5e, 0x88);
5323		BWN_RF_WRITE(mac, 0x7d, 0x88);
5324		bwn_hf_write(mac,
5325		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5326	}
5327	if (phy->rf_rev == 8) {
5328		BWN_RF_WRITE(mac, 0x51, 0);
5329		BWN_RF_WRITE(mac, 0x52, 0x40);
5330		BWN_RF_WRITE(mac, 0x53, 0xb7);
5331		BWN_RF_WRITE(mac, 0x54, 0x98);
5332		BWN_RF_WRITE(mac, 0x5a, 0x88);
5333		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5334		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5335		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5336			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5337			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5338		} else {
5339			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5340			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5341		}
5342		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5343		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5344		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5345		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5346	}
5347	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5348		BWN_PHY_WRITE(mac, offset, val);
5349		val -= 0x0202;
5350	}
5351	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5352		BWN_PHY_WRITE(mac, offset, val);
5353		val -= 0x0202;
5354	}
5355	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5356		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5357		val += 0x0202;
5358	}
5359	if (phy->type == BWN_PHYTYPE_G) {
5360		BWN_RF_SET(mac, 0x007a, 0x0020);
5361		BWN_RF_SET(mac, 0x0051, 0x0004);
5362		BWN_PHY_SET(mac, 0x0802, 0x0100);
5363		BWN_PHY_SET(mac, 0x042b, 0x2000);
5364		BWN_PHY_WRITE(mac, 0x5b, 0);
5365		BWN_PHY_WRITE(mac, 0x5c, 0);
5366	}
5367
5368	old_channel = phy->chan;
5369	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5370
5371	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5372	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5373	DELAY(40);
5374	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5375		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5376		BWN_RF_WRITE(mac, 0x50, 0x20);
5377	}
5378	if (phy->rf_rev <= 2) {
5379		BWN_RF_WRITE(mac, 0x7c, 0x20);
5380		BWN_RF_WRITE(mac, 0x5a, 0x70);
5381		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5382		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5383	}
5384	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5385
5386	bwn_phy_g_switch_chan(mac, old_channel, 0);
5387
5388	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5389	if (phy->rf_rev >= 6)
5390		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5391	else
5392		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5393	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5394	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5395	    pg->pg_txctl);
5396	if (phy->rf_rev <= 5)
5397		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5398	if (phy->rf_rev <= 2)
5399		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5400
5401	if (phy->analog == 4) {
5402		BWN_WRITE_2(mac, 0x3e4, 9);
5403		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5404	} else
5405		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5406	if (phy->type == BWN_PHYTYPE_B)
5407		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5408	else if (phy->type == BWN_PHYTYPE_G)
5409		BWN_WRITE_2(mac, 0x03e6, 0x0);
5410}
5411
5412static void
5413bwn_phy_init_a(struct bwn_mac *mac)
5414{
5415	struct bwn_phy *phy = &mac->mac_phy;
5416	struct bwn_softc *sc = mac->mac_sc;
5417
5418	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5419	    ("%s:%d: fail", __func__, __LINE__));
5420
5421	if (phy->rev >= 6) {
5422		if (phy->type == BWN_PHYTYPE_A)
5423			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5424		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5425			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5426		else
5427			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5428	}
5429
5430	bwn_wa_init(mac);
5431
5432	if (phy->type == BWN_PHYTYPE_G &&
5433	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5434		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5435}
5436
5437static void
5438bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5439{
5440	int i;
5441
5442	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5443		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5444}
5445
5446static void
5447bwn_wa_agc(struct bwn_mac *mac)
5448{
5449	struct bwn_phy *phy = &mac->mac_phy;
5450
5451	if (phy->rev == 1) {
5452		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5453		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5454		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5455		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5456		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5457		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5460		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5461	} else {
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5463		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5464		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5465		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5466	}
5467
5468	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5469	    0x5700);
5470	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5471	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5472	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5473	BWN_RF_SET(mac, 0x7a, 0x0008);
5474	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5475	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5476	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5478	if (phy->rev == 1)
5479		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5480	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5481	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5482	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5483	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5484	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5485	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5489	if (phy->rev == 1) {
5490		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5491		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5492	} else {
5493		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5494		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5495		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5496		if (phy->rev >= 6) {
5497			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5498			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5499			    (uint16_t)~0xf000, 0x3000);
5500		}
5501	}
5502	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5503	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5504	if (phy->rev == 1) {
5505		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5506		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5507		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5508		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5509		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5510		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5511		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5512		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5513	} else {
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5518	}
5519	if (phy->rev >= 6) {
5520		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5521		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5522	}
5523	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5524}
5525
5526static void
5527bwn_wa_grev1(struct bwn_mac *mac)
5528{
5529	struct bwn_phy *phy = &mac->mac_phy;
5530	int i;
5531	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5532	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5533	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5534
5535	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5536
5537	/* init CRSTHRES and ANTDWELL */
5538	if (phy->rev == 1) {
5539		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5540	} else if (phy->rev == 2) {
5541		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5542		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5543		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5544	} else {
5545		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5546		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5547		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5548		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5549	}
5550	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5551	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5552	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5553
5554	/* XXX support PHY-A??? */
5555	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5556		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5557		    bwn_tab_finefreqg[i]);
5558
5559	/* XXX support PHY-A??? */
5560	if (phy->rev == 1)
5561		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5562			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5563			    bwn_tab_noise_g1[i]);
5564	else
5565		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5566			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5567			    bwn_tab_noise_g2[i]);
5568
5569
5570	for (i = 0; i < N(bwn_tab_rotor); i++)
5571		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5572		    bwn_tab_rotor[i]);
5573
5574	/* XXX support PHY-A??? */
5575	if (phy->rev >= 6) {
5576		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5577		    BWN_PHY_ENCORE_EN)
5578			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5579		else
5580			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5581	} else
5582		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5583
5584	for (i = 0; i < N(bwn_tab_retard); i++)
5585		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5586		    bwn_tab_retard[i]);
5587
5588	if (phy->rev == 1) {
5589		for (i = 0; i < 16; i++)
5590			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5591			    i, 0x0020);
5592	} else {
5593		for (i = 0; i < 32; i++)
5594			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5595	}
5596
5597	bwn_wa_agc(mac);
5598}
5599
5600static void
5601bwn_wa_grev26789(struct bwn_mac *mac)
5602{
5603	struct bwn_phy *phy = &mac->mac_phy;
5604	int i;
5605	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5606	uint16_t ofdmrev;
5607
5608	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5609
5610	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5611
5612	/* init CRSTHRES and ANTDWELL */
5613	if (phy->rev == 1)
5614		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5615	else if (phy->rev == 2) {
5616		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5617		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5618		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5619	} else {
5620		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5621		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5622		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5623		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5624	}
5625
5626	for (i = 0; i < 64; i++)
5627		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5628
5629	/* XXX support PHY-A??? */
5630	if (phy->rev == 1)
5631		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5632			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5633			    bwn_tab_noise_g1[i]);
5634	else
5635		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5636			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5637			    bwn_tab_noise_g2[i]);
5638
5639	/* XXX support PHY-A??? */
5640	if (phy->rev >= 6) {
5641		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5642		    BWN_PHY_ENCORE_EN)
5643			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5644		else
5645			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5646	} else
5647		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5648
5649	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5650		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5651		    bwn_tab_sigmasqr2[i]);
5652
5653	if (phy->rev == 1) {
5654		for (i = 0; i < 16; i++)
5655			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5656			    0x0020);
5657	} else {
5658		for (i = 0; i < 32; i++)
5659			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5660	}
5661
5662	bwn_wa_agc(mac);
5663
5664	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5665	if (ofdmrev > 2) {
5666		if (phy->type == BWN_PHYTYPE_A)
5667			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5668		else
5669			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5670	} else {
5671		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5672		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5673		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5674	}
5675
5676	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5677	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5678}
5679
5680static void
5681bwn_wa_init(struct bwn_mac *mac)
5682{
5683	struct bwn_phy *phy = &mac->mac_phy;
5684	struct bwn_softc *sc = mac->mac_sc;
5685
5686	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5687
5688	switch (phy->rev) {
5689	case 1:
5690		bwn_wa_grev1(mac);
5691		break;
5692	case 2:
5693	case 6:
5694	case 7:
5695	case 8:
5696	case 9:
5697		bwn_wa_grev26789(mac);
5698		break;
5699	default:
5700		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5701	}
5702
5703	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5704	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5705	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5706		if (phy->rev < 2) {
5707			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5708			    0x0002);
5709			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5710			    0x0001);
5711		} else {
5712			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5713			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5714			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5715			     BWN_BFL_EXTLNA) &&
5716			    (phy->rev >= 7)) {
5717				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5718				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5719				    0x0020, 0x0001);
5720				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5721				    0x0021, 0x0001);
5722				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723				    0x0022, 0x0001);
5724				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725				    0x0023, 0x0000);
5726				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727				    0x0000, 0x0000);
5728				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729				    0x0003, 0x0002);
5730			}
5731		}
5732	}
5733	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5734		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5735		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5736	}
5737
5738	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5739	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5740}
5741
5742static void
5743bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5744    uint16_t value)
5745{
5746	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5747	uint16_t addr;
5748
5749	addr = table + offset;
5750	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5751	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5752		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5753		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5754	}
5755	pg->pg_ofdmtab_addr = addr;
5756	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5757}
5758
5759static void
5760bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5761    uint32_t value)
5762{
5763	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5764	uint16_t addr;
5765
5766	addr = table + offset;
5767	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5768	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5769		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5770		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5771	}
5772	pg->pg_ofdmtab_addr = addr;
5773
5774	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5775	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5776}
5777
5778static void
5779bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5780    uint16_t value)
5781{
5782
5783	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5784	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5785}
5786
5787static void
5788bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5789{
5790	struct bwn_phy *phy = &mac->mac_phy;
5791	struct bwn_softc *sc = mac->mac_sc;
5792	unsigned int i, max_loop;
5793	uint16_t value;
5794	uint32_t buffer[5] = {
5795		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5796	};
5797
5798	if (ofdm) {
5799		max_loop = 0x1e;
5800		buffer[0] = 0x000201cc;
5801	} else {
5802		max_loop = 0xfa;
5803		buffer[0] = 0x000b846e;
5804	}
5805
5806	BWN_ASSERT_LOCKED(mac->mac_sc);
5807
5808	for (i = 0; i < 5; i++)
5809		bwn_ram_write(mac, i * 4, buffer[i]);
5810
5811	BWN_WRITE_2(mac, 0x0568, 0x0000);
5812	BWN_WRITE_2(mac, 0x07c0,
5813	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5814	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5815	BWN_WRITE_2(mac, 0x050c, value);
5816	if (phy->type == BWN_PHYTYPE_LP)
5817		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5818	BWN_WRITE_2(mac, 0x0508, 0x0000);
5819	BWN_WRITE_2(mac, 0x050a, 0x0000);
5820	BWN_WRITE_2(mac, 0x054c, 0x0000);
5821	BWN_WRITE_2(mac, 0x056a, 0x0014);
5822	BWN_WRITE_2(mac, 0x0568, 0x0826);
5823	BWN_WRITE_2(mac, 0x0500, 0x0000);
5824	if (phy->type == BWN_PHYTYPE_LP)
5825		BWN_WRITE_2(mac, 0x0502, 0x0050);
5826	else
5827		BWN_WRITE_2(mac, 0x0502, 0x0030);
5828
5829	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5830		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5831	for (i = 0x00; i < max_loop; i++) {
5832		value = BWN_READ_2(mac, 0x050e);
5833		if (value & 0x0080)
5834			break;
5835		DELAY(10);
5836	}
5837	for (i = 0x00; i < 0x0a; i++) {
5838		value = BWN_READ_2(mac, 0x050e);
5839		if (value & 0x0400)
5840			break;
5841		DELAY(10);
5842	}
5843	for (i = 0x00; i < 0x19; i++) {
5844		value = BWN_READ_2(mac, 0x0690);
5845		if (!(value & 0x0100))
5846			break;
5847		DELAY(10);
5848	}
5849	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5850		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5851}
5852
5853static void
5854bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5855{
5856	uint32_t macctl;
5857
5858	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5859
5860	macctl = BWN_READ_4(mac, BWN_MACCTL);
5861	if (macctl & BWN_MACCTL_BIGENDIAN)
5862		printf("TODO: need swap\n");
5863
5864	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5865	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5866	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5867}
5868
5869static void
5870bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5871{
5872	uint16_t value;
5873
5874	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5875	    ("%s:%d: fail", __func__, __LINE__));
5876
5877	value = (uint8_t) (ctl->q);
5878	value |= ((uint8_t) (ctl->i)) << 8;
5879	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5880}
5881
5882static uint16_t
5883bwn_lo_calcfeed(struct bwn_mac *mac,
5884    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5885{
5886	struct bwn_phy *phy = &mac->mac_phy;
5887	struct bwn_softc *sc = mac->mac_sc;
5888	uint16_t rfover;
5889	uint16_t feedthrough;
5890
5891	if (phy->gmode) {
5892		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5893		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5894
5895		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5896		    ("%s:%d: fail", __func__, __LINE__));
5897		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5898		    ("%s:%d: fail", __func__, __LINE__));
5899
5900		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5901
5902		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5903		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5904		    phy->rev > 6)
5905			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5906
5907		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5908		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5909		DELAY(10);
5910		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5911		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912		DELAY(10);
5913		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5914		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915		DELAY(10);
5916		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5917	} else {
5918		pga |= BWN_PHY_PGACTL_UNKNOWN;
5919		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5920		DELAY(10);
5921		pga |= BWN_PHY_PGACTL_LOWBANDW;
5922		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923		DELAY(10);
5924		pga |= BWN_PHY_PGACTL_LPF;
5925		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926	}
5927	DELAY(21);
5928	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5929
5930	return (feedthrough);
5931}
5932
5933static uint16_t
5934bwn_lo_txctl_regtable(struct bwn_mac *mac,
5935    uint16_t *value, uint16_t *pad_mix_gain)
5936{
5937	struct bwn_phy *phy = &mac->mac_phy;
5938	uint16_t reg, v, padmix;
5939
5940	if (phy->type == BWN_PHYTYPE_B) {
5941		v = 0x30;
5942		if (phy->rf_rev <= 5) {
5943			reg = 0x43;
5944			padmix = 0;
5945		} else {
5946			reg = 0x52;
5947			padmix = 5;
5948		}
5949	} else {
5950		if (phy->rev >= 2 && phy->rf_rev == 8) {
5951			reg = 0x43;
5952			v = 0x10;
5953			padmix = 2;
5954		} else {
5955			reg = 0x52;
5956			v = 0x30;
5957			padmix = 5;
5958		}
5959	}
5960	if (value)
5961		*value = v;
5962	if (pad_mix_gain)
5963		*pad_mix_gain = padmix;
5964
5965	return (reg);
5966}
5967
5968static void
5969bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5970{
5971	struct bwn_phy *phy = &mac->mac_phy;
5972	struct bwn_phy_g *pg = &phy->phy_g;
5973	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5974	uint16_t reg, mask;
5975	uint16_t trsw_rx, pga;
5976	uint16_t rf_pctl_reg;
5977
5978	static const uint8_t tx_bias_values[] = {
5979		0x09, 0x08, 0x0a, 0x01, 0x00,
5980		0x02, 0x05, 0x04, 0x06,
5981	};
5982	static const uint8_t tx_magn_values[] = {
5983		0x70, 0x40,
5984	};
5985
5986	if (!BWN_HAS_LOOPBACK(phy)) {
5987		rf_pctl_reg = 6;
5988		trsw_rx = 2;
5989		pga = 0;
5990	} else {
5991		int lb_gain;
5992
5993		trsw_rx = 0;
5994		lb_gain = pg->pg_max_lb_gain / 2;
5995		if (lb_gain > 10) {
5996			rf_pctl_reg = 0;
5997			pga = abs(10 - lb_gain) / 6;
5998			pga = MIN(MAX(pga, 0), 15);
5999		} else {
6000			int cmp_val;
6001			int tmp;
6002
6003			pga = 0;
6004			cmp_val = 0x24;
6005			if ((phy->rev >= 2) &&
6006			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6007				cmp_val = 0x3c;
6008			tmp = lb_gain;
6009			if ((10 - lb_gain) < cmp_val)
6010				tmp = (10 - lb_gain);
6011			if (tmp < 0)
6012				tmp += 6;
6013			else
6014				tmp += 3;
6015			cmp_val /= 4;
6016			tmp /= 4;
6017			if (tmp >= cmp_val)
6018				rf_pctl_reg = cmp_val;
6019			else
6020				rf_pctl_reg = tmp;
6021		}
6022	}
6023	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6024	bwn_phy_g_set_bbatt(mac, 2);
6025
6026	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6027	mask = ~mask;
6028	BWN_RF_MASK(mac, reg, mask);
6029
6030	if (BWN_HAS_TXMAG(phy)) {
6031		int i, j;
6032		int feedthrough;
6033		int min_feedth = 0xffff;
6034		uint8_t tx_magn, tx_bias;
6035
6036		for (i = 0; i < N(tx_magn_values); i++) {
6037			tx_magn = tx_magn_values[i];
6038			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6039			for (j = 0; j < N(tx_bias_values); j++) {
6040				tx_bias = tx_bias_values[j];
6041				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6042				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6043				    trsw_rx);
6044				if (feedthrough < min_feedth) {
6045					lo->tx_bias = tx_bias;
6046					lo->tx_magn = tx_magn;
6047					min_feedth = feedthrough;
6048				}
6049				if (lo->tx_bias == 0)
6050					break;
6051			}
6052			BWN_RF_WRITE(mac, 0x52,
6053					  (BWN_RF_READ(mac, 0x52)
6054					   & 0xff00) | lo->tx_bias | lo->
6055					  tx_magn);
6056		}
6057	} else {
6058		lo->tx_magn = 0;
6059		lo->tx_bias = 0;
6060		BWN_RF_MASK(mac, 0x52, 0xfff0);
6061	}
6062
6063	BWN_GETTIME(lo->txctl_measured_time);
6064}
6065
6066static void
6067bwn_lo_get_powervector(struct bwn_mac *mac)
6068{
6069	struct bwn_phy *phy = &mac->mac_phy;
6070	struct bwn_phy_g *pg = &phy->phy_g;
6071	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6072	int i;
6073	uint64_t tmp;
6074	uint64_t power_vector = 0;
6075
6076	for (i = 0; i < 8; i += 2) {
6077		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6078		power_vector |= (tmp << (i * 8));
6079		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6080	}
6081	if (power_vector)
6082		lo->power_vector = power_vector;
6083
6084	BWN_GETTIME(lo->pwr_vec_read_time);
6085}
6086
6087static void
6088bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6089    int use_trsw_rx)
6090{
6091	struct bwn_phy *phy = &mac->mac_phy;
6092	struct bwn_phy_g *pg = &phy->phy_g;
6093	uint16_t tmp;
6094
6095	if (max_rx_gain < 0)
6096		max_rx_gain = 0;
6097
6098	if (BWN_HAS_LOOPBACK(phy)) {
6099		int trsw_rx = 0;
6100		int trsw_rx_gain;
6101
6102		if (use_trsw_rx) {
6103			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6104			if (max_rx_gain >= trsw_rx_gain) {
6105				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6106				trsw_rx = 0x20;
6107			}
6108		} else
6109			trsw_rx_gain = max_rx_gain;
6110		if (trsw_rx_gain < 9) {
6111			pg->pg_lna_lod_gain = 0;
6112		} else {
6113			pg->pg_lna_lod_gain = 1;
6114			trsw_rx_gain -= 8;
6115		}
6116		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6117		pg->pg_pga_gain = trsw_rx_gain / 3;
6118		if (pg->pg_pga_gain >= 5) {
6119			pg->pg_pga_gain -= 5;
6120			pg->pg_lna_gain = 2;
6121		} else
6122			pg->pg_lna_gain = 0;
6123	} else {
6124		pg->pg_lna_gain = 0;
6125		pg->pg_trsw_rx_gain = 0x20;
6126		if (max_rx_gain >= 0x14) {
6127			pg->pg_lna_lod_gain = 1;
6128			pg->pg_pga_gain = 2;
6129		} else if (max_rx_gain >= 0x12) {
6130			pg->pg_lna_lod_gain = 1;
6131			pg->pg_pga_gain = 1;
6132		} else if (max_rx_gain >= 0xf) {
6133			pg->pg_lna_lod_gain = 1;
6134			pg->pg_pga_gain = 0;
6135		} else {
6136			pg->pg_lna_lod_gain = 0;
6137			pg->pg_pga_gain = 0;
6138		}
6139	}
6140
6141	tmp = BWN_RF_READ(mac, 0x7a);
6142	if (pg->pg_lna_lod_gain == 0)
6143		tmp &= ~0x0008;
6144	else
6145		tmp |= 0x0008;
6146	BWN_RF_WRITE(mac, 0x7a, tmp);
6147}
6148
6149static void
6150bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6151{
6152	struct bwn_phy *phy = &mac->mac_phy;
6153	struct bwn_phy_g *pg = &phy->phy_g;
6154	struct bwn_softc *sc = mac->mac_sc;
6155	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6156	struct timespec ts;
6157	uint16_t tmp;
6158
6159	if (bwn_has_hwpctl(mac)) {
6160		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6161		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6162		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6163		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6164		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6165
6166		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6167		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6168		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6169		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6170	}
6171	if (phy->type == BWN_PHYTYPE_B &&
6172	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6173		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6174		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6175	}
6176	if (phy->rev >= 2) {
6177		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6178		sav->phy_analogoverval =
6179		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6180		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6181		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6182		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6183		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6184		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6185
6186		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6187		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6188		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6189		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6190		if (phy->type == BWN_PHYTYPE_G) {
6191			if ((phy->rev >= 7) &&
6192			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6193			     BWN_BFL_EXTLNA)) {
6194				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6195			} else {
6196				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6197			}
6198		} else {
6199			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6200		}
6201		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6202	}
6203	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6204	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6205	sav->rf0 = BWN_RF_READ(mac, 0x43);
6206	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6207	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6208	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6209	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6210	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6211
6212	if (!BWN_HAS_TXMAG(phy)) {
6213		sav->rf2 = BWN_RF_READ(mac, 0x52);
6214		sav->rf2 &= 0x00f0;
6215	}
6216	if (phy->type == BWN_PHYTYPE_B) {
6217		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6218		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6219		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6220		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6221	} else {
6222		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6223			    | 0x8000);
6224	}
6225	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6226		    & 0xf000);
6227
6228	tmp =
6229	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6230	BWN_PHY_WRITE(mac, tmp, 0x007f);
6231
6232	tmp = sav->phy_syncctl;
6233	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6234	tmp = sav->rf1;
6235	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6236
6237	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6238	if (phy->type == BWN_PHYTYPE_G ||
6239	    (phy->type == BWN_PHYTYPE_B &&
6240	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6241		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6242	} else
6243		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6244	if (phy->rev >= 2)
6245		bwn_dummy_transmission(mac, 0, 1);
6246	bwn_phy_g_switch_chan(mac, 6, 0);
6247	BWN_RF_READ(mac, 0x51);
6248	if (phy->type == BWN_PHYTYPE_G)
6249		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6250
6251	nanouptime(&ts);
6252	if (time_before(lo->txctl_measured_time,
6253	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6254		bwn_lo_measure_txctl_values(mac);
6255
6256	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6257		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6258	else {
6259		if (phy->type == BWN_PHYTYPE_B)
6260			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6261		else
6262			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6263	}
6264}
6265
6266static void
6267bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6268{
6269	struct bwn_phy *phy = &mac->mac_phy;
6270	struct bwn_phy_g *pg = &phy->phy_g;
6271	uint16_t tmp;
6272
6273	if (phy->rev >= 2) {
6274		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6275		tmp = (pg->pg_pga_gain << 8);
6276		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6277		DELAY(5);
6278		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6279		DELAY(2);
6280		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6281	} else {
6282		tmp = (pg->pg_pga_gain | 0xefa0);
6283		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6284	}
6285	if (phy->type == BWN_PHYTYPE_G) {
6286		if (phy->rev >= 3)
6287			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6288		else
6289			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6290		if (phy->rev >= 2)
6291			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6292		else
6293			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6294	}
6295	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6296	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6297	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6298	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6299	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6300	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6301	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6302	if (!BWN_HAS_TXMAG(phy)) {
6303		tmp = sav->rf2;
6304		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6305	}
6306	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6307	if (phy->type == BWN_PHYTYPE_B &&
6308	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6309		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6310		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6311	}
6312	if (phy->rev >= 2) {
6313		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6314		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6315			      sav->phy_analogoverval);
6316		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6317		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6318		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6319		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6320		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6321	}
6322	if (bwn_has_hwpctl(mac)) {
6323		tmp = (sav->phy_lomask & 0xbfff);
6324		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6325		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6326		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6327		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6328		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6329	}
6330	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6331}
6332
6333static int
6334bwn_lo_probe_loctl(struct bwn_mac *mac,
6335    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6336{
6337	struct bwn_phy *phy = &mac->mac_phy;
6338	struct bwn_phy_g *pg = &phy->phy_g;
6339	struct bwn_loctl orig, test;
6340	struct bwn_loctl prev = { -100, -100 };
6341	static const struct bwn_loctl modifiers[] = {
6342		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6343		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6344	};
6345	int begin, end, lower = 0, i;
6346	uint16_t feedth;
6347
6348	if (d->curstate == 0) {
6349		begin = 1;
6350		end = 8;
6351	} else if (d->curstate % 2 == 0) {
6352		begin = d->curstate - 1;
6353		end = d->curstate + 1;
6354	} else {
6355		begin = d->curstate - 2;
6356		end = d->curstate + 2;
6357	}
6358	if (begin < 1)
6359		begin += 8;
6360	if (end > 8)
6361		end -= 8;
6362
6363	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6364	i = begin;
6365	d->curstate = i;
6366	while (1) {
6367		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6368		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6369		test.i += modifiers[i - 1].i * d->multipler;
6370		test.q += modifiers[i - 1].q * d->multipler;
6371		if ((test.i != prev.i || test.q != prev.q) &&
6372		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6373			bwn_lo_write(mac, &test);
6374			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6375			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6376			if (feedth < d->feedth) {
6377				memcpy(probe, &test,
6378				    sizeof(struct bwn_loctl));
6379				lower = 1;
6380				d->feedth = feedth;
6381				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6382					break;
6383			}
6384		}
6385		memcpy(&prev, &test, sizeof(prev));
6386		if (i == end)
6387			break;
6388		if (i == 8)
6389			i = 1;
6390		else
6391			i++;
6392		d->curstate = i;
6393	}
6394
6395	return (lower);
6396}
6397
6398static void
6399bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6400{
6401	struct bwn_phy *phy = &mac->mac_phy;
6402	struct bwn_phy_g *pg = &phy->phy_g;
6403	struct bwn_lo_g_sm d;
6404	struct bwn_loctl probe;
6405	int lower, repeat, cnt = 0;
6406	uint16_t feedth;
6407
6408	d.nmeasure = 0;
6409	d.multipler = 1;
6410	if (BWN_HAS_LOOPBACK(phy))
6411		d.multipler = 3;
6412
6413	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6414	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6415
6416	do {
6417		bwn_lo_write(mac, &d.loctl);
6418		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6419		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6420		if (feedth < 0x258) {
6421			if (feedth >= 0x12c)
6422				*rxgain += 6;
6423			else
6424				*rxgain += 3;
6425			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6426			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6427		}
6428		d.feedth = feedth;
6429		d.curstate = 0;
6430		do {
6431			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6432			    ("%s:%d: fail", __func__, __LINE__));
6433			memcpy(&probe, &d.loctl,
6434			       sizeof(struct bwn_loctl));
6435			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6436			if (!lower)
6437				break;
6438			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6439				break;
6440			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6441			d.nmeasure++;
6442		} while (d.nmeasure < 24);
6443		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6444
6445		if (BWN_HAS_LOOPBACK(phy)) {
6446			if (d.feedth > 0x1194)
6447				*rxgain -= 6;
6448			else if (d.feedth < 0x5dc)
6449				*rxgain += 3;
6450			if (cnt == 0) {
6451				if (d.feedth <= 0x5dc) {
6452					d.multipler = 1;
6453					cnt++;
6454				} else
6455					d.multipler = 2;
6456			} else if (cnt == 2)
6457				d.multipler = 1;
6458		}
6459		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6460	} while (++cnt < repeat);
6461}
6462
6463static struct bwn_lo_calib *
6464bwn_lo_calibset(struct bwn_mac *mac,
6465    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6466{
6467	struct bwn_phy *phy = &mac->mac_phy;
6468	struct bwn_phy_g *pg = &phy->phy_g;
6469	struct bwn_loctl loctl = { 0, 0 };
6470	struct bwn_lo_calib *cal;
6471	struct bwn_lo_g_value sval = { 0 };
6472	int rxgain;
6473	uint16_t pad, reg, value;
6474
6475	sval.old_channel = phy->chan;
6476	bwn_mac_suspend(mac);
6477	bwn_lo_save(mac, &sval);
6478
6479	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6480	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6481	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6482
6483	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6484	if (rfatt->padmix)
6485		rxgain -= pad;
6486	if (BWN_HAS_LOOPBACK(phy))
6487		rxgain += pg->pg_max_lb_gain;
6488	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6489	bwn_phy_g_set_bbatt(mac, bbatt->att);
6490	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6491
6492	bwn_lo_restore(mac, &sval);
6493	bwn_mac_enable(mac);
6494
6495	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6496	if (!cal) {
6497		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6498		return (NULL);
6499	}
6500	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6501	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6502	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6503
6504	BWN_GETTIME(cal->calib_time);
6505
6506	return (cal);
6507}
6508
6509static struct bwn_lo_calib *
6510bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6511    const struct bwn_rfatt *rfatt)
6512{
6513	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6514	struct bwn_lo_calib *c;
6515
6516	TAILQ_FOREACH(c, &lo->calib_list, list) {
6517		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6518			continue;
6519		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6520			continue;
6521		return (c);
6522	}
6523
6524	c = bwn_lo_calibset(mac, bbatt, rfatt);
6525	if (!c)
6526		return (NULL);
6527	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6528
6529	return (c);
6530}
6531
6532static void
6533bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6534{
6535	struct bwn_phy *phy = &mac->mac_phy;
6536	struct bwn_phy_g *pg = &phy->phy_g;
6537	struct bwn_softc *sc = mac->mac_sc;
6538	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6539	const struct bwn_rfatt *rfatt;
6540	const struct bwn_bbatt *bbatt;
6541	uint64_t pvector;
6542	int i;
6543	int rf_offset, bb_offset;
6544	uint8_t changed = 0;
6545
6546	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6547	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6548	    ("%s:%d: fail", __func__, __LINE__));
6549
6550	pvector = lo->power_vector;
6551	if (!update && !pvector)
6552		return;
6553
6554	bwn_mac_suspend(mac);
6555
6556	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6557		struct bwn_lo_calib *cal;
6558		int idx;
6559		uint16_t val;
6560
6561		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6562			continue;
6563		bb_offset = i / lo->rfatt.len;
6564		rf_offset = i % lo->rfatt.len;
6565		bbatt = &(lo->bbatt.array[bb_offset]);
6566		rfatt = &(lo->rfatt.array[rf_offset]);
6567
6568		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6569		if (!cal) {
6570			device_printf(sc->sc_dev, "LO: Could not "
6571			    "calibrate DC table entry\n");
6572			continue;
6573		}
6574		val = (uint8_t)(cal->ctl.q);
6575		val |= ((uint8_t)(cal->ctl.i)) << 4;
6576		free(cal, M_DEVBUF);
6577
6578		idx = i / 2;
6579		if (i % 2)
6580			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6581			    | ((val & 0x00ff) << 8);
6582		else
6583			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6584			    | (val & 0x00ff);
6585		changed = 1;
6586	}
6587	if (changed) {
6588		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6589			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6590	}
6591	bwn_mac_enable(mac);
6592}
6593
6594static void
6595bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6596{
6597
6598	if (!rf->padmix)
6599		return;
6600	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6601		rf->att = 4;
6602}
6603
6604static void
6605bwn_lo_g_adjust(struct bwn_mac *mac)
6606{
6607	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6608	struct bwn_lo_calib *cal;
6609	struct bwn_rfatt rf;
6610
6611	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6612	bwn_lo_fixup_rfatt(&rf);
6613
6614	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6615	if (!cal)
6616		return;
6617	bwn_lo_write(mac, &cal->ctl);
6618}
6619
6620static void
6621bwn_lo_g_init(struct bwn_mac *mac)
6622{
6623
6624	if (!bwn_has_hwpctl(mac))
6625		return;
6626
6627	bwn_lo_get_powervector(mac);
6628	bwn_phy_g_dc_lookup_init(mac, 1);
6629}
6630
6631static void
6632bwn_mac_suspend(struct bwn_mac *mac)
6633{
6634	struct bwn_softc *sc = mac->mac_sc;
6635	int i;
6636	uint32_t tmp;
6637
6638	KASSERT(mac->mac_suspended >= 0,
6639	    ("%s:%d: fail", __func__, __LINE__));
6640
6641	if (mac->mac_suspended == 0) {
6642		bwn_psctl(mac, BWN_PS_AWAKE);
6643		BWN_WRITE_4(mac, BWN_MACCTL,
6644			    BWN_READ_4(mac, BWN_MACCTL)
6645			    & ~BWN_MACCTL_ON);
6646		BWN_READ_4(mac, BWN_MACCTL);
6647		for (i = 35; i; i--) {
6648			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6649			if (tmp & BWN_INTR_MAC_SUSPENDED)
6650				goto out;
6651			DELAY(10);
6652		}
6653		for (i = 40; i; i--) {
6654			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6655			if (tmp & BWN_INTR_MAC_SUSPENDED)
6656				goto out;
6657			DELAY(1000);
6658		}
6659		device_printf(sc->sc_dev, "MAC suspend failed\n");
6660	}
6661out:
6662	mac->mac_suspended++;
6663}
6664
6665static void
6666bwn_mac_enable(struct bwn_mac *mac)
6667{
6668	struct bwn_softc *sc = mac->mac_sc;
6669	uint16_t state;
6670
6671	state = bwn_shm_read_2(mac, BWN_SHARED,
6672	    BWN_SHARED_UCODESTAT);
6673	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6674	    state != BWN_SHARED_UCODESTAT_SLEEP)
6675		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6676
6677	mac->mac_suspended--;
6678	KASSERT(mac->mac_suspended >= 0,
6679	    ("%s:%d: fail", __func__, __LINE__));
6680	if (mac->mac_suspended == 0) {
6681		BWN_WRITE_4(mac, BWN_MACCTL,
6682		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6683		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6684		BWN_READ_4(mac, BWN_MACCTL);
6685		BWN_READ_4(mac, BWN_INTR_REASON);
6686		bwn_psctl(mac, 0);
6687	}
6688}
6689
6690static void
6691bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6692{
6693	struct bwn_softc *sc = mac->mac_sc;
6694	int i;
6695	uint16_t ucstat;
6696
6697	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6698	    ("%s:%d: fail", __func__, __LINE__));
6699	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6700	    ("%s:%d: fail", __func__, __LINE__));
6701
6702	/* XXX forcibly awake and hwps-off */
6703
6704	BWN_WRITE_4(mac, BWN_MACCTL,
6705	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6706	    ~BWN_MACCTL_HWPS);
6707	BWN_READ_4(mac, BWN_MACCTL);
6708	if (siba_get_revid(sc->sc_dev) >= 5) {
6709		for (i = 0; i < 100; i++) {
6710			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6711			    BWN_SHARED_UCODESTAT);
6712			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6713				break;
6714			DELAY(10);
6715		}
6716	}
6717}
6718
6719static int16_t
6720bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6721{
6722
6723	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6724	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6725}
6726
6727static void
6728bwn_nrssi_threshold(struct bwn_mac *mac)
6729{
6730	struct bwn_phy *phy = &mac->mac_phy;
6731	struct bwn_phy_g *pg = &phy->phy_g;
6732	struct bwn_softc *sc = mac->mac_sc;
6733	int32_t a, b;
6734	int16_t tmp16;
6735	uint16_t tmpu16;
6736
6737	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6738
6739	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6740		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6741			a = 0x13;
6742			b = 0x12;
6743		} else {
6744			a = 0xe;
6745			b = 0x11;
6746		}
6747
6748		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6749		a += (pg->pg_nrssi[0] << 6);
6750		a += (a < 32) ? 31 : 32;
6751		a = a >> 6;
6752		a = MIN(MAX(a, -31), 31);
6753
6754		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6755		b += (pg->pg_nrssi[0] << 6);
6756		if (b < 32)
6757			b += 31;
6758		else
6759			b += 32;
6760		b = b >> 6;
6761		b = MIN(MAX(b, -31), 31);
6762
6763		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6764		tmpu16 |= ((uint32_t)b & 0x0000003f);
6765		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6766		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6767		return;
6768	}
6769
6770	tmp16 = bwn_nrssi_read(mac, 0x20);
6771	if (tmp16 >= 0x20)
6772		tmp16 -= 0x40;
6773	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6774}
6775
6776static void
6777bwn_nrssi_slope_11g(struct bwn_mac *mac)
6778{
6779#define	SAVE_RF_MAX		3
6780#define	SAVE_PHY_COMM_MAX	4
6781#define	SAVE_PHY3_MAX		8
6782	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6783		{ 0x7a, 0x52, 0x43 };
6784	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6785		{ 0x15, 0x5a, 0x59, 0x58 };
6786	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6787		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6788		0x0801, 0x0060, 0x0014, 0x0478
6789	};
6790	struct bwn_phy *phy = &mac->mac_phy;
6791	struct bwn_phy_g *pg = &phy->phy_g;
6792	int32_t i, tmp32, phy3_idx = 0;
6793	uint16_t delta, tmp;
6794	uint16_t save_rf[SAVE_RF_MAX];
6795	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6796	uint16_t save_phy3[SAVE_PHY3_MAX];
6797	uint16_t ant_div, phy0, chan_ex;
6798	int16_t nrssi0, nrssi1;
6799
6800	KASSERT(phy->type == BWN_PHYTYPE_G,
6801	    ("%s:%d: fail", __func__, __LINE__));
6802
6803	if (phy->rf_rev >= 9)
6804		return;
6805	if (phy->rf_rev == 8)
6806		bwn_nrssi_offset(mac);
6807
6808	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6809	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6810
6811	/*
6812	 * Save RF/PHY registers for later restoration
6813	 */
6814	ant_div = BWN_READ_2(mac, 0x03e2);
6815	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6816	for (i = 0; i < SAVE_RF_MAX; ++i)
6817		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6818	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6819		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6820
6821	phy0 = BWN_READ_2(mac, BWN_PHY0);
6822	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6823	if (phy->rev >= 3) {
6824		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6825			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6826		BWN_PHY_WRITE(mac, 0x002e, 0);
6827		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6828		switch (phy->rev) {
6829		case 4:
6830		case 6:
6831		case 7:
6832			BWN_PHY_SET(mac, 0x0478, 0x0100);
6833			BWN_PHY_SET(mac, 0x0801, 0x0040);
6834			break;
6835		case 3:
6836		case 5:
6837			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6838			break;
6839		}
6840		BWN_PHY_SET(mac, 0x0060, 0x0040);
6841		BWN_PHY_SET(mac, 0x0014, 0x0200);
6842	}
6843	/*
6844	 * Calculate nrssi0
6845	 */
6846	BWN_RF_SET(mac, 0x007a, 0x0070);
6847	bwn_set_all_gains(mac, 0, 8, 0);
6848	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6849	if (phy->rev >= 2) {
6850		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6851		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6852	}
6853	BWN_RF_SET(mac, 0x007a, 0x0080);
6854	DELAY(20);
6855
6856	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6857	if (nrssi0 >= 0x0020)
6858		nrssi0 -= 0x0040;
6859
6860	/*
6861	 * Calculate nrssi1
6862	 */
6863	BWN_RF_MASK(mac, 0x007a, 0x007f);
6864	if (phy->rev >= 2)
6865		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6866
6867	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6868	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6869	BWN_RF_SET(mac, 0x007a, 0x000f);
6870	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6871	if (phy->rev >= 2) {
6872		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6873		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6874	}
6875
6876	bwn_set_all_gains(mac, 3, 0, 1);
6877	if (phy->rf_rev == 8) {
6878		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6879	} else {
6880		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6881		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6882		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6883		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6884	}
6885	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6886	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6887	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6888	DELAY(20);
6889	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6890
6891	/*
6892	 * Install calculated narrow RSSI values
6893	 */
6894	if (nrssi1 >= 0x0020)
6895		nrssi1 -= 0x0040;
6896	if (nrssi0 == nrssi1)
6897		pg->pg_nrssi_slope = 0x00010000;
6898	else
6899		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6900	if (nrssi0 >= -4) {
6901		pg->pg_nrssi[0] = nrssi1;
6902		pg->pg_nrssi[1] = nrssi0;
6903	}
6904
6905	/*
6906	 * Restore saved RF/PHY registers
6907	 */
6908	if (phy->rev >= 3) {
6909		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6910			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6911			    save_phy3[phy3_idx]);
6912		}
6913	}
6914	if (phy->rev >= 2) {
6915		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6916		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6917	}
6918
6919	for (i = 0; i < SAVE_RF_MAX; ++i)
6920		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6921
6922	BWN_WRITE_2(mac, 0x03e2, ant_div);
6923	BWN_WRITE_2(mac, 0x03e6, phy0);
6924	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6925
6926	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6927		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6928
6929	bwn_spu_workaround(mac, phy->chan);
6930	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6931	bwn_set_original_gains(mac);
6932	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6933	if (phy->rev >= 3) {
6934		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6935			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6936			    save_phy3[phy3_idx]);
6937		}
6938	}
6939
6940	delta = 0x1f - pg->pg_nrssi[0];
6941	for (i = 0; i < 64; i++) {
6942		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6943		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6944		pg->pg_nrssi_lt[i] = tmp32;
6945	}
6946
6947	bwn_nrssi_threshold(mac);
6948#undef SAVE_RF_MAX
6949#undef SAVE_PHY_COMM_MAX
6950#undef SAVE_PHY3_MAX
6951}
6952
6953static void
6954bwn_nrssi_offset(struct bwn_mac *mac)
6955{
6956#define	SAVE_RF_MAX		2
6957#define	SAVE_PHY_COMM_MAX	10
6958#define	SAVE_PHY6_MAX		8
6959	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6960		{ 0x7a, 0x43 };
6961	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6962		0x0001, 0x0811, 0x0812, 0x0814,
6963		0x0815, 0x005a, 0x0059, 0x0058,
6964		0x000a, 0x0003
6965	};
6966	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6967		0x002e, 0x002f, 0x080f, 0x0810,
6968		0x0801, 0x0060, 0x0014, 0x0478
6969	};
6970	struct bwn_phy *phy = &mac->mac_phy;
6971	int i, phy6_idx = 0;
6972	uint16_t save_rf[SAVE_RF_MAX];
6973	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6974	uint16_t save_phy6[SAVE_PHY6_MAX];
6975	int16_t nrssi;
6976	uint16_t saved = 0xffff;
6977
6978	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6979		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6980	for (i = 0; i < SAVE_RF_MAX; ++i)
6981		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6982
6983	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6984	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6985	BWN_PHY_SET(mac, 0x0811, 0x000c);
6986	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6987	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6988	if (phy->rev >= 6) {
6989		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6990			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6991
6992		BWN_PHY_WRITE(mac, 0x002e, 0);
6993		BWN_PHY_WRITE(mac, 0x002f, 0);
6994		BWN_PHY_WRITE(mac, 0x080f, 0);
6995		BWN_PHY_WRITE(mac, 0x0810, 0);
6996		BWN_PHY_SET(mac, 0x0478, 0x0100);
6997		BWN_PHY_SET(mac, 0x0801, 0x0040);
6998		BWN_PHY_SET(mac, 0x0060, 0x0040);
6999		BWN_PHY_SET(mac, 0x0014, 0x0200);
7000	}
7001	BWN_RF_SET(mac, 0x007a, 0x0070);
7002	BWN_RF_SET(mac, 0x007a, 0x0080);
7003	DELAY(30);
7004
7005	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7006	if (nrssi >= 0x20)
7007		nrssi -= 0x40;
7008	if (nrssi == 31) {
7009		for (i = 7; i >= 4; i--) {
7010			BWN_RF_WRITE(mac, 0x007b, i);
7011			DELAY(20);
7012			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7013			    0x003f);
7014			if (nrssi >= 0x20)
7015				nrssi -= 0x40;
7016			if (nrssi < 31 && saved == 0xffff)
7017				saved = i;
7018		}
7019		if (saved == 0xffff)
7020			saved = 4;
7021	} else {
7022		BWN_RF_MASK(mac, 0x007a, 0x007f);
7023		if (phy->rev != 1) {
7024			BWN_PHY_SET(mac, 0x0814, 0x0001);
7025			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7026		}
7027		BWN_PHY_SET(mac, 0x0811, 0x000c);
7028		BWN_PHY_SET(mac, 0x0812, 0x000c);
7029		BWN_PHY_SET(mac, 0x0811, 0x0030);
7030		BWN_PHY_SET(mac, 0x0812, 0x0030);
7031		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7032		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7033		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7034		if (phy->rev == 0)
7035			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7036		else
7037			BWN_PHY_SET(mac, 0x000a, 0x2000);
7038		if (phy->rev != 1) {
7039			BWN_PHY_SET(mac, 0x0814, 0x0004);
7040			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7041		}
7042		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7043		BWN_RF_SET(mac, 0x007a, 0x000f);
7044		bwn_set_all_gains(mac, 3, 0, 1);
7045		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7046		DELAY(30);
7047		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7048		if (nrssi >= 0x20)
7049			nrssi -= 0x40;
7050		if (nrssi == -32) {
7051			for (i = 0; i < 4; i++) {
7052				BWN_RF_WRITE(mac, 0x007b, i);
7053				DELAY(20);
7054				nrssi = (int16_t)((BWN_PHY_READ(mac,
7055				    0x047f) >> 8) & 0x003f);
7056				if (nrssi >= 0x20)
7057					nrssi -= 0x40;
7058				if (nrssi > -31 && saved == 0xffff)
7059					saved = i;
7060			}
7061			if (saved == 0xffff)
7062				saved = 3;
7063		} else
7064			saved = 0;
7065	}
7066	BWN_RF_WRITE(mac, 0x007b, saved);
7067
7068	/*
7069	 * Restore saved RF/PHY registers
7070	 */
7071	if (phy->rev >= 6) {
7072		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7073			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7074			    save_phy6[phy6_idx]);
7075		}
7076	}
7077	if (phy->rev != 1) {
7078		for (i = 3; i < 5; i++)
7079			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7080			    save_phy_comm[i]);
7081	}
7082	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7083		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7084
7085	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7086		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7087
7088	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7089	BWN_PHY_SET(mac, 0x0429, 0x8000);
7090	bwn_set_original_gains(mac);
7091	if (phy->rev >= 6) {
7092		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7093			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7094			    save_phy6[phy6_idx]);
7095		}
7096	}
7097
7098	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7099	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7100	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7101}
7102
7103static void
7104bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7105    int16_t third)
7106{
7107	struct bwn_phy *phy = &mac->mac_phy;
7108	uint16_t i;
7109	uint16_t start = 0x08, end = 0x18;
7110	uint16_t tmp;
7111	uint16_t table;
7112
7113	if (phy->rev <= 1) {
7114		start = 0x10;
7115		end = 0x20;
7116	}
7117
7118	table = BWN_OFDMTAB_GAINX;
7119	if (phy->rev <= 1)
7120		table = BWN_OFDMTAB_GAINX_R1;
7121	for (i = 0; i < 4; i++)
7122		bwn_ofdmtab_write_2(mac, table, i, first);
7123
7124	for (i = start; i < end; i++)
7125		bwn_ofdmtab_write_2(mac, table, i, second);
7126
7127	if (third != -1) {
7128		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7129		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7130		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7131		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7132	}
7133	bwn_dummy_transmission(mac, 0, 1);
7134}
7135
7136static void
7137bwn_set_original_gains(struct bwn_mac *mac)
7138{
7139	struct bwn_phy *phy = &mac->mac_phy;
7140	uint16_t i, tmp;
7141	uint16_t table;
7142	uint16_t start = 0x0008, end = 0x0018;
7143
7144	if (phy->rev <= 1) {
7145		start = 0x0010;
7146		end = 0x0020;
7147	}
7148
7149	table = BWN_OFDMTAB_GAINX;
7150	if (phy->rev <= 1)
7151		table = BWN_OFDMTAB_GAINX_R1;
7152	for (i = 0; i < 4; i++) {
7153		tmp = (i & 0xfffc);
7154		tmp |= (i & 0x0001) << 1;
7155		tmp |= (i & 0x0002) >> 1;
7156
7157		bwn_ofdmtab_write_2(mac, table, i, tmp);
7158	}
7159
7160	for (i = start; i < end; i++)
7161		bwn_ofdmtab_write_2(mac, table, i, i - start);
7162
7163	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7164	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7165	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7166	bwn_dummy_transmission(mac, 0, 1);
7167}
7168
7169static void
7170bwn_phy_hwpctl_init(struct bwn_mac *mac)
7171{
7172	struct bwn_phy *phy = &mac->mac_phy;
7173	struct bwn_phy_g *pg = &phy->phy_g;
7174	struct bwn_rfatt old_rfatt, rfatt;
7175	struct bwn_bbatt old_bbatt, bbatt;
7176	struct bwn_softc *sc = mac->mac_sc;
7177	uint8_t old_txctl = 0;
7178
7179	KASSERT(phy->type == BWN_PHYTYPE_G,
7180	    ("%s:%d: fail", __func__, __LINE__));
7181
7182	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7183	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7184		return;
7185
7186	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7187
7188	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7189
7190	if (!phy->gmode)
7191		return;
7192	bwn_hwpctl_early_init(mac);
7193	if (pg->pg_curtssi == 0) {
7194		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7195			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7196		} else {
7197			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7198			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7199			old_txctl = pg->pg_txctl;
7200
7201			bbatt.att = 11;
7202			if (phy->rf_rev == 8) {
7203				rfatt.att = 15;
7204				rfatt.padmix = 1;
7205			} else {
7206				rfatt.att = 9;
7207				rfatt.padmix = 0;
7208			}
7209			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7210		}
7211		bwn_dummy_transmission(mac, 0, 1);
7212		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7213		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7214			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7215		else
7216			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7217			    &old_rfatt, old_txctl);
7218	}
7219	bwn_hwpctl_init_gphy(mac);
7220
7221	/* clear TSSI */
7222	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7223	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7224	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7225	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7226}
7227
7228static void
7229bwn_hwpctl_early_init(struct bwn_mac *mac)
7230{
7231	struct bwn_phy *phy = &mac->mac_phy;
7232
7233	if (!bwn_has_hwpctl(mac)) {
7234		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7235		return;
7236	}
7237
7238	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7239	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7240	BWN_PHY_SET(mac, 0x047c, 0x0002);
7241	BWN_PHY_SET(mac, 0x047a, 0xf000);
7242	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7243		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7244		BWN_PHY_SET(mac, 0x005d, 0x8000);
7245		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7246		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7247		BWN_PHY_SET(mac, 0x0036, 0x0400);
7248	} else {
7249		BWN_PHY_SET(mac, 0x0036, 0x0200);
7250		BWN_PHY_SET(mac, 0x0036, 0x0400);
7251		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7252		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7253		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7254		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7255		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7256	}
7257}
7258
7259static void
7260bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7261{
7262	struct bwn_phy *phy = &mac->mac_phy;
7263	struct bwn_phy_g *pg = &phy->phy_g;
7264	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7265	int i;
7266	uint16_t nr_written = 0, tmp, value;
7267	uint8_t rf, bb;
7268
7269	if (!bwn_has_hwpctl(mac)) {
7270		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7271		return;
7272	}
7273
7274	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7275	    (pg->pg_idletssi - pg->pg_curtssi));
7276	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7277	    (pg->pg_idletssi - pg->pg_curtssi));
7278
7279	for (i = 0; i < 32; i++)
7280		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7281	for (i = 32; i < 64; i++)
7282		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7283	for (i = 0; i < 64; i += 2) {
7284		value = (uint16_t) pg->pg_tssi2dbm[i];
7285		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7286		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7287	}
7288
7289	for (rf = 0; rf < lo->rfatt.len; rf++) {
7290		for (bb = 0; bb < lo->bbatt.len; bb++) {
7291			if (nr_written >= 0x40)
7292				return;
7293			tmp = lo->bbatt.array[bb].att;
7294			tmp <<= 8;
7295			if (phy->rf_rev == 8)
7296				tmp |= 0x50;
7297			else
7298				tmp |= 0x40;
7299			tmp |= lo->rfatt.array[rf].att;
7300			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7301			nr_written++;
7302		}
7303	}
7304
7305	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7306	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7307
7308	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7309	BWN_PHY_SET(mac, 0x0478, 0x0800);
7310	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7311	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7312
7313	bwn_phy_g_dc_lookup_init(mac, 1);
7314	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7315}
7316
7317static void
7318bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7319{
7320	struct bwn_softc *sc = mac->mac_sc;
7321
7322	if (spu != 0)
7323		bwn_spu_workaround(mac, channel);
7324
7325	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7326
7327	if (channel == 14) {
7328		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7329			bwn_hf_write(mac,
7330			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7331		else
7332			bwn_hf_write(mac,
7333			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7334		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7335		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7336		return;
7337	}
7338
7339	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7340	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7341}
7342
7343static uint16_t
7344bwn_phy_g_chan2freq(uint8_t channel)
7345{
7346	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7347
7348	KASSERT(channel >= 1 && channel <= 14,
7349	    ("%s:%d: fail", __func__, __LINE__));
7350
7351	return (bwn_phy_g_rf_channels[channel - 1]);
7352}
7353
7354static void
7355bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7356    const struct bwn_rfatt *rfatt, uint8_t txctl)
7357{
7358	struct bwn_phy *phy = &mac->mac_phy;
7359	struct bwn_phy_g *pg = &phy->phy_g;
7360	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7361	uint16_t bb, rf;
7362	uint16_t tx_bias, tx_magn;
7363
7364	bb = bbatt->att;
7365	rf = rfatt->att;
7366	tx_bias = lo->tx_bias;
7367	tx_magn = lo->tx_magn;
7368	if (tx_bias == 0xff)
7369		tx_bias = 0;
7370
7371	pg->pg_txctl = txctl;
7372	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7373	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7374	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7375	bwn_phy_g_set_bbatt(mac, bb);
7376	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7377	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7378		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7379	else {
7380		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7381		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7382	}
7383	if (BWN_HAS_TXMAG(phy))
7384		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7385	else
7386		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7387	bwn_lo_g_adjust(mac);
7388}
7389
7390static void
7391bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7392    uint16_t bbatt)
7393{
7394	struct bwn_phy *phy = &mac->mac_phy;
7395
7396	if (phy->analog == 0) {
7397		BWN_WRITE_2(mac, BWN_PHY0,
7398		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7399		return;
7400	}
7401	if (phy->analog > 1) {
7402		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7403		return;
7404	}
7405	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7406}
7407
7408static uint16_t
7409bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7410{
7411	struct bwn_phy *phy = &mac->mac_phy;
7412	struct bwn_phy_g *pg = &phy->phy_g;
7413	struct bwn_softc *sc = mac->mac_sc;
7414	int max_lb_gain;
7415	uint16_t extlna;
7416	uint16_t i;
7417
7418	if (phy->gmode == 0)
7419		return (0);
7420
7421	if (BWN_HAS_LOOPBACK(phy)) {
7422		max_lb_gain = pg->pg_max_lb_gain;
7423		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7424		if (max_lb_gain >= 0x46) {
7425			extlna = 0x3000;
7426			max_lb_gain -= 0x46;
7427		} else if (max_lb_gain >= 0x3a) {
7428			extlna = 0x1000;
7429			max_lb_gain -= 0x3a;
7430		} else if (max_lb_gain >= 0x2e) {
7431			extlna = 0x2000;
7432			max_lb_gain -= 0x2e;
7433		} else {
7434			extlna = 0;
7435			max_lb_gain -= 0x10;
7436		}
7437
7438		for (i = 0; i < 16; i++) {
7439			max_lb_gain -= (i * 6);
7440			if (max_lb_gain < 6)
7441				break;
7442		}
7443
7444		if ((phy->rev < 7) ||
7445		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7446			if (reg == BWN_PHY_RFOVER) {
7447				return (0x1b3);
7448			} else if (reg == BWN_PHY_RFOVERVAL) {
7449				extlna |= (i << 8);
7450				switch (lpd) {
7451				case BWN_LPD(0, 1, 1):
7452					return (0x0f92);
7453				case BWN_LPD(0, 0, 1):
7454				case BWN_LPD(1, 0, 1):
7455					return (0x0092 | extlna);
7456				case BWN_LPD(1, 0, 0):
7457					return (0x0093 | extlna);
7458				}
7459				KASSERT(0 == 1,
7460				    ("%s:%d: fail", __func__, __LINE__));
7461			}
7462			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7463		} else {
7464			if (reg == BWN_PHY_RFOVER)
7465				return (0x9b3);
7466			if (reg == BWN_PHY_RFOVERVAL) {
7467				if (extlna)
7468					extlna |= 0x8000;
7469				extlna |= (i << 8);
7470				switch (lpd) {
7471				case BWN_LPD(0, 1, 1):
7472					return (0x8f92);
7473				case BWN_LPD(0, 0, 1):
7474					return (0x8092 | extlna);
7475				case BWN_LPD(1, 0, 1):
7476					return (0x2092 | extlna);
7477				case BWN_LPD(1, 0, 0):
7478					return (0x2093 | extlna);
7479				}
7480				KASSERT(0 == 1,
7481				    ("%s:%d: fail", __func__, __LINE__));
7482			}
7483			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7484		}
7485		return (0);
7486	}
7487
7488	if ((phy->rev < 7) ||
7489	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7490		if (reg == BWN_PHY_RFOVER) {
7491			return (0x1b3);
7492		} else if (reg == BWN_PHY_RFOVERVAL) {
7493			switch (lpd) {
7494			case BWN_LPD(0, 1, 1):
7495				return (0x0fb2);
7496			case BWN_LPD(0, 0, 1):
7497				return (0x00b2);
7498			case BWN_LPD(1, 0, 1):
7499				return (0x30b2);
7500			case BWN_LPD(1, 0, 0):
7501				return (0x30b3);
7502			}
7503			KASSERT(0 == 1,
7504			    ("%s:%d: fail", __func__, __LINE__));
7505		}
7506		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7507	} else {
7508		if (reg == BWN_PHY_RFOVER) {
7509			return (0x9b3);
7510		} else if (reg == BWN_PHY_RFOVERVAL) {
7511			switch (lpd) {
7512			case BWN_LPD(0, 1, 1):
7513				return (0x8fb2);
7514			case BWN_LPD(0, 0, 1):
7515				return (0x80b2);
7516			case BWN_LPD(1, 0, 1):
7517				return (0x20b2);
7518			case BWN_LPD(1, 0, 0):
7519				return (0x20b3);
7520			}
7521			KASSERT(0 == 1,
7522			    ("%s:%d: fail", __func__, __LINE__));
7523		}
7524		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7525	}
7526	return (0);
7527}
7528
7529static void
7530bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7531{
7532
7533	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7534		return;
7535	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7536	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7537	DELAY(1000);
7538	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7539}
7540
7541static int
7542bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7543{
7544	struct bwn_softc *sc = mac->mac_sc;
7545	struct bwn_fw *fw = &mac->mac_fw;
7546	const uint8_t rev = siba_get_revid(sc->sc_dev);
7547	const char *filename;
7548	uint32_t high;
7549	int error;
7550
7551	/* microcode */
7552	if (rev >= 5 && rev <= 10)
7553		filename = "ucode5";
7554	else if (rev >= 11 && rev <= 12)
7555		filename = "ucode11";
7556	else if (rev == 13)
7557		filename = "ucode13";
7558	else if (rev == 14)
7559		filename = "ucode14";
7560	else if (rev >= 15)
7561		filename = "ucode15";
7562	else {
7563		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7564		bwn_release_firmware(mac);
7565		return (EOPNOTSUPP);
7566	}
7567	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7568	if (error) {
7569		bwn_release_firmware(mac);
7570		return (error);
7571	}
7572
7573	/* PCM */
7574	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7575	if (rev >= 5 && rev <= 10) {
7576		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7577		if (error == ENOENT)
7578			fw->no_pcmfile = 1;
7579		else if (error) {
7580			bwn_release_firmware(mac);
7581			return (error);
7582		}
7583	} else if (rev < 11) {
7584		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7585		return (EOPNOTSUPP);
7586	}
7587
7588	/* initvals */
7589	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7590	switch (mac->mac_phy.type) {
7591	case BWN_PHYTYPE_A:
7592		if (rev < 5 || rev > 10)
7593			goto fail1;
7594		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7595			filename = "a0g1initvals5";
7596		else
7597			filename = "a0g0initvals5";
7598		break;
7599	case BWN_PHYTYPE_G:
7600		if (rev >= 5 && rev <= 10)
7601			filename = "b0g0initvals5";
7602		else if (rev >= 13)
7603			filename = "b0g0initvals13";
7604		else
7605			goto fail1;
7606		break;
7607	case BWN_PHYTYPE_LP:
7608		if (rev == 13)
7609			filename = "lp0initvals13";
7610		else if (rev == 14)
7611			filename = "lp0initvals14";
7612		else if (rev >= 15)
7613			filename = "lp0initvals15";
7614		else
7615			goto fail1;
7616		break;
7617	case BWN_PHYTYPE_N:
7618		if (rev >= 11 && rev <= 12)
7619			filename = "n0initvals11";
7620		else
7621			goto fail1;
7622		break;
7623	default:
7624		goto fail1;
7625	}
7626	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7627	if (error) {
7628		bwn_release_firmware(mac);
7629		return (error);
7630	}
7631
7632	/* bandswitch initvals */
7633	switch (mac->mac_phy.type) {
7634	case BWN_PHYTYPE_A:
7635		if (rev >= 5 && rev <= 10) {
7636			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7637				filename = "a0g1bsinitvals5";
7638			else
7639				filename = "a0g0bsinitvals5";
7640		} else if (rev >= 11)
7641			filename = NULL;
7642		else
7643			goto fail1;
7644		break;
7645	case BWN_PHYTYPE_G:
7646		if (rev >= 5 && rev <= 10)
7647			filename = "b0g0bsinitvals5";
7648		else if (rev >= 11)
7649			filename = NULL;
7650		else
7651			goto fail1;
7652		break;
7653	case BWN_PHYTYPE_LP:
7654		if (rev == 13)
7655			filename = "lp0bsinitvals13";
7656		else if (rev == 14)
7657			filename = "lp0bsinitvals14";
7658		else if (rev >= 15)
7659			filename = "lp0bsinitvals15";
7660		else
7661			goto fail1;
7662		break;
7663	case BWN_PHYTYPE_N:
7664		if (rev >= 11 && rev <= 12)
7665			filename = "n0bsinitvals11";
7666		else
7667			goto fail1;
7668		break;
7669	default:
7670		goto fail1;
7671	}
7672	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7673	if (error) {
7674		bwn_release_firmware(mac);
7675		return (error);
7676	}
7677	return (0);
7678fail1:
7679	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7680	bwn_release_firmware(mac);
7681	return (EOPNOTSUPP);
7682}
7683
7684static int
7685bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7686    const char *name, struct bwn_fwfile *bfw)
7687{
7688	const struct bwn_fwhdr *hdr;
7689	struct bwn_softc *sc = mac->mac_sc;
7690	const struct firmware *fw;
7691	char namebuf[64];
7692
7693	if (name == NULL) {
7694		bwn_do_release_fw(bfw);
7695		return (0);
7696	}
7697	if (bfw->filename != NULL) {
7698		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7699			return (0);
7700		bwn_do_release_fw(bfw);
7701	}
7702
7703	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7704	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7705	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7706	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7707	fw = firmware_get(namebuf);
7708	if (fw == NULL) {
7709		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7710		    namebuf);
7711		return (ENOENT);
7712	}
7713	if (fw->datasize < sizeof(struct bwn_fwhdr))
7714		goto fail;
7715	hdr = (const struct bwn_fwhdr *)(fw->data);
7716	switch (hdr->type) {
7717	case BWN_FWTYPE_UCODE:
7718	case BWN_FWTYPE_PCM:
7719		if (be32toh(hdr->size) !=
7720		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7721			goto fail;
7722		/* FALLTHROUGH */
7723	case BWN_FWTYPE_IV:
7724		if (hdr->ver != 1)
7725			goto fail;
7726		break;
7727	default:
7728		goto fail;
7729	}
7730	bfw->filename = name;
7731	bfw->fw = fw;
7732	bfw->type = type;
7733	return (0);
7734fail:
7735	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7736	if (fw != NULL)
7737		firmware_put(fw, FIRMWARE_UNLOAD);
7738	return (EPROTO);
7739}
7740
7741static void
7742bwn_release_firmware(struct bwn_mac *mac)
7743{
7744
7745	bwn_do_release_fw(&mac->mac_fw.ucode);
7746	bwn_do_release_fw(&mac->mac_fw.pcm);
7747	bwn_do_release_fw(&mac->mac_fw.initvals);
7748	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7749}
7750
7751static void
7752bwn_do_release_fw(struct bwn_fwfile *bfw)
7753{
7754
7755	if (bfw->fw != NULL)
7756		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7757	bfw->fw = NULL;
7758	bfw->filename = NULL;
7759}
7760
7761static int
7762bwn_fw_loaducode(struct bwn_mac *mac)
7763{
7764#define	GETFWOFFSET(fwp, offset)	\
7765	((const uint32_t *)((const char *)fwp.fw->data + offset))
7766#define	GETFWSIZE(fwp, offset)	\
7767	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7768	struct bwn_softc *sc = mac->mac_sc;
7769	const uint32_t *data;
7770	unsigned int i;
7771	uint32_t ctl;
7772	uint16_t date, fwcaps, time;
7773	int error = 0;
7774
7775	ctl = BWN_READ_4(mac, BWN_MACCTL);
7776	ctl |= BWN_MACCTL_MCODE_JMP0;
7777	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7778	    __LINE__));
7779	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7780	for (i = 0; i < 64; i++)
7781		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7782	for (i = 0; i < 4096; i += 2)
7783		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7784
7785	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7786	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7787	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7788	     i++) {
7789		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7790		DELAY(10);
7791	}
7792
7793	if (mac->mac_fw.pcm.fw) {
7794		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7795		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7796		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7797		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7798		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7799		    sizeof(struct bwn_fwhdr)); i++) {
7800			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7801			DELAY(10);
7802		}
7803	}
7804
7805	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7806	BWN_WRITE_4(mac, BWN_MACCTL,
7807	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7808	    BWN_MACCTL_MCODE_RUN);
7809
7810	for (i = 0; i < 21; i++) {
7811		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7812			break;
7813		if (i >= 20) {
7814			device_printf(sc->sc_dev, "ucode timeout\n");
7815			error = ENXIO;
7816			goto error;
7817		}
7818		DELAY(50000);
7819	}
7820	BWN_READ_4(mac, BWN_INTR_REASON);
7821
7822	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7823	if (mac->mac_fw.rev <= 0x128) {
7824		device_printf(sc->sc_dev, "the firmware is too old\n");
7825		error = EOPNOTSUPP;
7826		goto error;
7827	}
7828	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7829	    BWN_SHARED_UCODE_PATCH);
7830	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7831	mac->mac_fw.opensource = (date == 0xffff);
7832	if (bwn_wme != 0)
7833		mac->mac_flags |= BWN_MAC_FLAG_WME;
7834	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7835
7836	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7837	if (mac->mac_fw.opensource == 0) {
7838		device_printf(sc->sc_dev,
7839		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7840		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7841		if (mac->mac_fw.no_pcmfile)
7842			device_printf(sc->sc_dev,
7843			    "no HW crypto acceleration due to pcm5\n");
7844	} else {
7845		mac->mac_fw.patch = time;
7846		fwcaps = bwn_fwcaps_read(mac);
7847		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7848			device_printf(sc->sc_dev,
7849			    "disabling HW crypto acceleration\n");
7850			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7851		}
7852		if (!(fwcaps & BWN_FWCAPS_WME)) {
7853			device_printf(sc->sc_dev, "disabling WME support\n");
7854			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7855		}
7856	}
7857
7858	if (BWN_ISOLDFMT(mac))
7859		device_printf(sc->sc_dev, "using old firmware image\n");
7860
7861	return (0);
7862
7863error:
7864	BWN_WRITE_4(mac, BWN_MACCTL,
7865	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7866	    BWN_MACCTL_MCODE_JMP0);
7867
7868	return (error);
7869#undef GETFWSIZE
7870#undef GETFWOFFSET
7871}
7872
7873/* OpenFirmware only */
7874static uint16_t
7875bwn_fwcaps_read(struct bwn_mac *mac)
7876{
7877
7878	KASSERT(mac->mac_fw.opensource == 1,
7879	    ("%s:%d: fail", __func__, __LINE__));
7880	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7881}
7882
7883static int
7884bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7885    size_t count, size_t array_size)
7886{
7887#define	GET_NEXTIV16(iv)						\
7888	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7889	    sizeof(uint16_t) + sizeof(uint16_t)))
7890#define	GET_NEXTIV32(iv)						\
7891	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7892	    sizeof(uint16_t) + sizeof(uint32_t)))
7893	struct bwn_softc *sc = mac->mac_sc;
7894	const struct bwn_fwinitvals *iv;
7895	uint16_t offset;
7896	size_t i;
7897	uint8_t bit32;
7898
7899	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7900	    ("%s:%d: fail", __func__, __LINE__));
7901	iv = ivals;
7902	for (i = 0; i < count; i++) {
7903		if (array_size < sizeof(iv->offset_size))
7904			goto fail;
7905		array_size -= sizeof(iv->offset_size);
7906		offset = be16toh(iv->offset_size);
7907		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7908		offset &= BWN_FWINITVALS_OFFSET_MASK;
7909		if (offset >= 0x1000)
7910			goto fail;
7911		if (bit32) {
7912			if (array_size < sizeof(iv->data.d32))
7913				goto fail;
7914			array_size -= sizeof(iv->data.d32);
7915			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7916			iv = GET_NEXTIV32(iv);
7917		} else {
7918
7919			if (array_size < sizeof(iv->data.d16))
7920				goto fail;
7921			array_size -= sizeof(iv->data.d16);
7922			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7923
7924			iv = GET_NEXTIV16(iv);
7925		}
7926	}
7927	if (array_size != 0)
7928		goto fail;
7929	return (0);
7930fail:
7931	device_printf(sc->sc_dev, "initvals: invalid format\n");
7932	return (EPROTO);
7933#undef GET_NEXTIV16
7934#undef GET_NEXTIV32
7935}
7936
7937static int
7938bwn_switch_channel(struct bwn_mac *mac, int chan)
7939{
7940	struct bwn_phy *phy = &(mac->mac_phy);
7941	struct bwn_softc *sc = mac->mac_sc;
7942	struct ifnet *ifp = sc->sc_ifp;
7943	struct ieee80211com *ic = ifp->if_l2com;
7944	uint16_t channelcookie, savedcookie;
7945	int error;
7946
7947	if (chan == 0xffff)
7948		chan = phy->get_default_chan(mac);
7949
7950	channelcookie = chan;
7951	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7952		channelcookie |= 0x100;
7953	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7954	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7955	error = phy->switch_channel(mac, chan);
7956	if (error)
7957		goto fail;
7958
7959	mac->mac_phy.chan = chan;
7960	DELAY(8000);
7961	return (0);
7962fail:
7963	device_printf(sc->sc_dev, "failed to switch channel\n");
7964	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7965	return (error);
7966}
7967
7968static uint16_t
7969bwn_ant2phy(int antenna)
7970{
7971
7972	switch (antenna) {
7973	case BWN_ANT0:
7974		return (BWN_TX_PHY_ANT0);
7975	case BWN_ANT1:
7976		return (BWN_TX_PHY_ANT1);
7977	case BWN_ANT2:
7978		return (BWN_TX_PHY_ANT2);
7979	case BWN_ANT3:
7980		return (BWN_TX_PHY_ANT3);
7981	case BWN_ANTAUTO:
7982		return (BWN_TX_PHY_ANT01AUTO);
7983	}
7984	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7985	return (0);
7986}
7987
7988static void
7989bwn_wme_load(struct bwn_mac *mac)
7990{
7991	struct bwn_softc *sc = mac->mac_sc;
7992	int i;
7993
7994	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7995	    ("%s:%d: fail", __func__, __LINE__));
7996
7997	bwn_mac_suspend(mac);
7998	for (i = 0; i < N(sc->sc_wmeParams); i++)
7999		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8000		    bwn_wme_shm_offsets[i]);
8001	bwn_mac_enable(mac);
8002}
8003
8004static void
8005bwn_wme_loadparams(struct bwn_mac *mac,
8006    const struct wmeParams *p, uint16_t shm_offset)
8007{
8008#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8009	struct bwn_softc *sc = mac->mac_sc;
8010	uint16_t params[BWN_NR_WMEPARAMS];
8011	int slot, tmp;
8012	unsigned int i;
8013
8014	slot = BWN_READ_2(mac, BWN_RNG) &
8015	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8016
8017	memset(&params, 0, sizeof(params));
8018
8019	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8020	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8021	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8022
8023	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8024	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8025	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8026	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8027	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8028	params[BWN_WMEPARAM_BSLOTS] = slot;
8029	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8030
8031	for (i = 0; i < N(params); i++) {
8032		if (i == BWN_WMEPARAM_STATUS) {
8033			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8034			    shm_offset + (i * 2));
8035			tmp |= 0x100;
8036			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8037			    tmp);
8038		} else {
8039			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040			    params[i]);
8041		}
8042	}
8043}
8044
8045static void
8046bwn_mac_write_bssid(struct bwn_mac *mac)
8047{
8048	struct bwn_softc *sc = mac->mac_sc;
8049	uint32_t tmp;
8050	int i;
8051	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8052
8053	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8054	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8055	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8056	    IEEE80211_ADDR_LEN);
8057
8058	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8059		tmp = (uint32_t) (mac_bssid[i + 0]);
8060		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8061		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8062		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8063		bwn_ram_write(mac, 0x20 + i, tmp);
8064	}
8065}
8066
8067static void
8068bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8069    const uint8_t *macaddr)
8070{
8071	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8072	uint16_t data;
8073
8074	if (!mac)
8075		macaddr = zero;
8076
8077	offset |= 0x0020;
8078	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8079
8080	data = macaddr[0];
8081	data |= macaddr[1] << 8;
8082	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8083	data = macaddr[2];
8084	data |= macaddr[3] << 8;
8085	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086	data = macaddr[4];
8087	data |= macaddr[5] << 8;
8088	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089}
8090
8091static void
8092bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8093    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8094{
8095	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8096	uint8_t per_sta_keys_start = 8;
8097
8098	if (BWN_SEC_NEWAPI(mac))
8099		per_sta_keys_start = 4;
8100
8101	KASSERT(index < mac->mac_max_nr_keys,
8102	    ("%s:%d: fail", __func__, __LINE__));
8103	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8104	    ("%s:%d: fail", __func__, __LINE__));
8105
8106	if (index >= per_sta_keys_start)
8107		bwn_key_macwrite(mac, index, NULL);
8108	if (key)
8109		memcpy(buf, key, key_len);
8110	bwn_key_write(mac, index, algorithm, buf);
8111	if (index >= per_sta_keys_start)
8112		bwn_key_macwrite(mac, index, mac_addr);
8113
8114	mac->mac_key[index].algorithm = algorithm;
8115}
8116
8117static void
8118bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8119{
8120	struct bwn_softc *sc = mac->mac_sc;
8121	uint32_t addrtmp[2] = { 0, 0 };
8122	uint8_t start = 8;
8123
8124	if (BWN_SEC_NEWAPI(mac))
8125		start = 4;
8126
8127	KASSERT(index >= start,
8128	    ("%s:%d: fail", __func__, __LINE__));
8129	index -= start;
8130
8131	if (addr) {
8132		addrtmp[0] = addr[0];
8133		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8134		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8135		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8136		addrtmp[1] = addr[4];
8137		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8138	}
8139
8140	if (siba_get_revid(sc->sc_dev) >= 5) {
8141		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8142		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8143	} else {
8144		if (index >= 8) {
8145			bwn_shm_write_4(mac, BWN_SHARED,
8146			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8147			bwn_shm_write_2(mac, BWN_SHARED,
8148			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8149		}
8150	}
8151}
8152
8153static void
8154bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8155    const uint8_t *key)
8156{
8157	unsigned int i;
8158	uint32_t offset;
8159	uint16_t kidx, value;
8160
8161	kidx = BWN_SEC_KEY2FW(mac, index);
8162	bwn_shm_write_2(mac, BWN_SHARED,
8163	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8164
8165	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8166	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8167		value = key[i];
8168		value |= (uint16_t)(key[i + 1]) << 8;
8169		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8170	}
8171}
8172
8173static void
8174bwn_phy_exit(struct bwn_mac *mac)
8175{
8176
8177	mac->mac_phy.rf_onoff(mac, 0);
8178	if (mac->mac_phy.exit != NULL)
8179		mac->mac_phy.exit(mac);
8180}
8181
8182static void
8183bwn_dma_free(struct bwn_mac *mac)
8184{
8185	struct bwn_dma *dma;
8186
8187	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8188		return;
8189	dma = &mac->mac_method.dma;
8190
8191	bwn_dma_ringfree(&dma->rx);
8192	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8193	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8194	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8195	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8196	bwn_dma_ringfree(&dma->mcast);
8197}
8198
8199static void
8200bwn_core_stop(struct bwn_mac *mac)
8201{
8202	struct bwn_softc *sc = mac->mac_sc;
8203
8204	BWN_ASSERT_LOCKED(sc);
8205
8206	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8207		return;
8208
8209	callout_stop(&sc->sc_rfswitch_ch);
8210	callout_stop(&sc->sc_task_ch);
8211	callout_stop(&sc->sc_watchdog_ch);
8212	sc->sc_watchdog_timer = 0;
8213	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8214	BWN_READ_4(mac, BWN_INTR_MASK);
8215	bwn_mac_suspend(mac);
8216
8217	mac->mac_status = BWN_MAC_STATUS_INITED;
8218}
8219
8220static int
8221bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8222{
8223	struct bwn_mac *up_dev = NULL;
8224	struct bwn_mac *down_dev;
8225	struct bwn_mac *mac;
8226	int err, status;
8227	uint8_t gmode;
8228
8229	BWN_ASSERT_LOCKED(sc);
8230
8231	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8232		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8233		    mac->mac_phy.supports_2ghz) {
8234			up_dev = mac;
8235			gmode = 1;
8236		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8237		    mac->mac_phy.supports_5ghz) {
8238			up_dev = mac;
8239			gmode = 0;
8240		} else {
8241			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8242			return (EINVAL);
8243		}
8244		if (up_dev != NULL)
8245			break;
8246	}
8247	if (up_dev == NULL) {
8248		device_printf(sc->sc_dev, "Could not find a device\n");
8249		return (ENODEV);
8250	}
8251	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8252		return (0);
8253
8254	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8255	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8256
8257	down_dev = sc->sc_curmac;
8258	status = down_dev->mac_status;
8259	if (status >= BWN_MAC_STATUS_STARTED)
8260		bwn_core_stop(down_dev);
8261	if (status >= BWN_MAC_STATUS_INITED)
8262		bwn_core_exit(down_dev);
8263
8264	if (down_dev != up_dev)
8265		bwn_phy_reset(down_dev);
8266
8267	up_dev->mac_phy.gmode = gmode;
8268	if (status >= BWN_MAC_STATUS_INITED) {
8269		err = bwn_core_init(up_dev);
8270		if (err) {
8271			device_printf(sc->sc_dev,
8272			    "fatal: failed to initialize for %s-GHz\n",
8273			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8274			goto fail;
8275		}
8276	}
8277	if (status >= BWN_MAC_STATUS_STARTED)
8278		bwn_core_start(up_dev);
8279	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8280	sc->sc_curmac = up_dev;
8281
8282	return (0);
8283fail:
8284	sc->sc_curmac = NULL;
8285	return (err);
8286}
8287
8288static void
8289bwn_rf_turnon(struct bwn_mac *mac)
8290{
8291
8292	bwn_mac_suspend(mac);
8293	mac->mac_phy.rf_onoff(mac, 1);
8294	mac->mac_phy.rf_on = 1;
8295	bwn_mac_enable(mac);
8296}
8297
8298static void
8299bwn_rf_turnoff(struct bwn_mac *mac)
8300{
8301
8302	bwn_mac_suspend(mac);
8303	mac->mac_phy.rf_onoff(mac, 0);
8304	mac->mac_phy.rf_on = 0;
8305	bwn_mac_enable(mac);
8306}
8307
8308static void
8309bwn_phy_reset(struct bwn_mac *mac)
8310{
8311	struct bwn_softc *sc = mac->mac_sc;
8312
8313	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8314	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8315	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8316	DELAY(1000);
8317	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8318	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8319	    BWN_TGSLOW_PHYRESET);
8320	DELAY(1000);
8321}
8322
8323static int
8324bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8325{
8326	struct bwn_vap *bvp = BWN_VAP(vap);
8327	struct ieee80211com *ic= vap->iv_ic;
8328	struct ifnet *ifp = ic->ic_ifp;
8329	enum ieee80211_state ostate = vap->iv_state;
8330	struct bwn_softc *sc = ic->ic_softc;
8331	struct bwn_mac *mac = sc->sc_curmac;
8332	int error;
8333
8334	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8335	    ieee80211_state_name[vap->iv_state],
8336	    ieee80211_state_name[nstate]);
8337
8338	error = bvp->bv_newstate(vap, nstate, arg);
8339	if (error != 0)
8340		return (error);
8341
8342	BWN_LOCK(sc);
8343
8344	bwn_led_newstate(mac, nstate);
8345
8346	/*
8347	 * Clear the BSSID when we stop a STA
8348	 */
8349	if (vap->iv_opmode == IEEE80211_M_STA) {
8350		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8351			/*
8352			 * Clear out the BSSID.  If we reassociate to
8353			 * the same AP, this will reinialize things
8354			 * correctly...
8355			 */
8356			if (ic->ic_opmode == IEEE80211_M_STA &&
8357			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8358				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8359				bwn_set_macaddr(mac);
8360			}
8361		}
8362	}
8363
8364	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8365	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8366		/* XXX nothing to do? */
8367	} else if (nstate == IEEE80211_S_RUN) {
8368		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8369		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8370		bwn_set_opmode(mac);
8371		bwn_set_pretbtt(mac);
8372		bwn_spu_setdelay(mac, 0);
8373		bwn_set_macaddr(mac);
8374	}
8375
8376	BWN_UNLOCK(sc);
8377
8378	return (error);
8379}
8380
8381static void
8382bwn_set_pretbtt(struct bwn_mac *mac)
8383{
8384	struct bwn_softc *sc = mac->mac_sc;
8385	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8386	uint16_t pretbtt;
8387
8388	if (ic->ic_opmode == IEEE80211_M_IBSS)
8389		pretbtt = 2;
8390	else
8391		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8392	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8393	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8394}
8395
8396static int
8397bwn_intr(void *arg)
8398{
8399	struct bwn_mac *mac = arg;
8400	struct bwn_softc *sc = mac->mac_sc;
8401	uint32_t reason;
8402
8403	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8404	    (sc->sc_flags & BWN_FLAG_INVALID))
8405		return (FILTER_STRAY);
8406
8407	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8408	if (reason == 0xffffffff)	/* shared IRQ */
8409		return (FILTER_STRAY);
8410	reason &= mac->mac_intr_mask;
8411	if (reason == 0)
8412		return (FILTER_HANDLED);
8413
8414	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8415	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8416	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8417	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8418	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8419	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8420	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8421	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8422	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8423	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8424	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8425
8426	/* Disable interrupts. */
8427	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8428
8429	mac->mac_reason_intr = reason;
8430
8431	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8432	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8433
8434	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8435	return (FILTER_HANDLED);
8436}
8437
8438static void
8439bwn_intrtask(void *arg, int npending)
8440{
8441	struct bwn_mac *mac = arg;
8442	struct bwn_softc *sc = mac->mac_sc;
8443	struct ifnet *ifp = sc->sc_ifp;
8444	uint32_t merged = 0;
8445	int i, tx = 0, rx = 0;
8446
8447	BWN_LOCK(sc);
8448	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8449	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8450		BWN_UNLOCK(sc);
8451		return;
8452	}
8453
8454	for (i = 0; i < N(mac->mac_reason); i++)
8455		merged |= mac->mac_reason[i];
8456
8457	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8458		device_printf(sc->sc_dev, "MAC trans error\n");
8459
8460	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8461		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8462		mac->mac_phy.txerrors--;
8463		if (mac->mac_phy.txerrors == 0) {
8464			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8465			bwn_restart(mac, "PHY TX errors");
8466		}
8467	}
8468
8469	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8470		if (merged & BWN_DMAINTR_FATALMASK) {
8471			device_printf(sc->sc_dev,
8472			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8473			    mac->mac_reason[0], mac->mac_reason[1],
8474			    mac->mac_reason[2], mac->mac_reason[3],
8475			    mac->mac_reason[4], mac->mac_reason[5]);
8476			bwn_restart(mac, "DMA error");
8477			BWN_UNLOCK(sc);
8478			return;
8479		}
8480		if (merged & BWN_DMAINTR_NONFATALMASK) {
8481			device_printf(sc->sc_dev,
8482			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8483			    mac->mac_reason[0], mac->mac_reason[1],
8484			    mac->mac_reason[2], mac->mac_reason[3],
8485			    mac->mac_reason[4], mac->mac_reason[5]);
8486		}
8487	}
8488
8489	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8490		bwn_intr_ucode_debug(mac);
8491	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8492		bwn_intr_tbtt_indication(mac);
8493	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8494		bwn_intr_atim_end(mac);
8495	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8496		bwn_intr_beacon(mac);
8497	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8498		bwn_intr_pmq(mac);
8499	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8500		bwn_intr_noise(mac);
8501
8502	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8503		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8504			bwn_dma_rx(mac->mac_method.dma.rx);
8505			rx = 1;
8506		}
8507	} else
8508		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8509
8510	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8511	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8512	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8513	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515
8516	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8517		bwn_intr_txeof(mac);
8518		tx = 1;
8519	}
8520
8521	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8522
8523	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8524		int evt = BWN_LED_EVENT_NONE;
8525
8526		if (tx && rx) {
8527			if (sc->sc_rx_rate > sc->sc_tx_rate)
8528				evt = BWN_LED_EVENT_RX;
8529			else
8530				evt = BWN_LED_EVENT_TX;
8531		} else if (tx) {
8532			evt = BWN_LED_EVENT_TX;
8533		} else if (rx) {
8534			evt = BWN_LED_EVENT_RX;
8535		} else if (rx == 0) {
8536			evt = BWN_LED_EVENT_POLL;
8537		}
8538
8539		if (evt != BWN_LED_EVENT_NONE)
8540			bwn_led_event(mac, evt);
8541       }
8542
8543	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8544		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8545			bwn_start_locked(ifp);
8546	}
8547
8548	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8549	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8550
8551	BWN_UNLOCK(sc);
8552}
8553
8554static void
8555bwn_restart(struct bwn_mac *mac, const char *msg)
8556{
8557	struct bwn_softc *sc = mac->mac_sc;
8558	struct ifnet *ifp = sc->sc_ifp;
8559	struct ieee80211com *ic = ifp->if_l2com;
8560
8561	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8562		return;
8563
8564	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8565	ieee80211_runtask(ic, &mac->mac_hwreset);
8566}
8567
8568static void
8569bwn_intr_ucode_debug(struct bwn_mac *mac)
8570{
8571	struct bwn_softc *sc = mac->mac_sc;
8572	uint16_t reason;
8573
8574	if (mac->mac_fw.opensource == 0)
8575		return;
8576
8577	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8578	switch (reason) {
8579	case BWN_DEBUGINTR_PANIC:
8580		bwn_handle_fwpanic(mac);
8581		break;
8582	case BWN_DEBUGINTR_DUMP_SHM:
8583		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8584		break;
8585	case BWN_DEBUGINTR_DUMP_REGS:
8586		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8587		break;
8588	case BWN_DEBUGINTR_MARKER:
8589		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8590		break;
8591	default:
8592		device_printf(sc->sc_dev,
8593		    "ucode debug unknown reason: %#x\n", reason);
8594	}
8595
8596	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8597	    BWN_DEBUGINTR_ACK);
8598}
8599
8600static void
8601bwn_intr_tbtt_indication(struct bwn_mac *mac)
8602{
8603	struct bwn_softc *sc = mac->mac_sc;
8604	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8605
8606	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8607		bwn_psctl(mac, 0);
8608	if (ic->ic_opmode == IEEE80211_M_IBSS)
8609		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8610}
8611
8612static void
8613bwn_intr_atim_end(struct bwn_mac *mac)
8614{
8615
8616	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8617		BWN_WRITE_4(mac, BWN_MACCMD,
8618		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8619		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8620	}
8621}
8622
8623static void
8624bwn_intr_beacon(struct bwn_mac *mac)
8625{
8626	struct bwn_softc *sc = mac->mac_sc;
8627	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8628	uint32_t cmd, beacon0, beacon1;
8629
8630	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8631	    ic->ic_opmode == IEEE80211_M_MBSS)
8632		return;
8633
8634	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8635
8636	cmd = BWN_READ_4(mac, BWN_MACCMD);
8637	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8638	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8639
8640	if (beacon0 && beacon1) {
8641		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8642		mac->mac_intr_mask |= BWN_INTR_BEACON;
8643		return;
8644	}
8645
8646	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8647		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8648		bwn_load_beacon0(mac);
8649		bwn_load_beacon1(mac);
8650		cmd = BWN_READ_4(mac, BWN_MACCMD);
8651		cmd |= BWN_MACCMD_BEACON0_VALID;
8652		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8653	} else {
8654		if (!beacon0) {
8655			bwn_load_beacon0(mac);
8656			cmd = BWN_READ_4(mac, BWN_MACCMD);
8657			cmd |= BWN_MACCMD_BEACON0_VALID;
8658			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8659		} else if (!beacon1) {
8660			bwn_load_beacon1(mac);
8661			cmd = BWN_READ_4(mac, BWN_MACCMD);
8662			cmd |= BWN_MACCMD_BEACON1_VALID;
8663			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8664		}
8665	}
8666}
8667
8668static void
8669bwn_intr_pmq(struct bwn_mac *mac)
8670{
8671	uint32_t tmp;
8672
8673	while (1) {
8674		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8675		if (!(tmp & 0x00000008))
8676			break;
8677	}
8678	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8679}
8680
8681static void
8682bwn_intr_noise(struct bwn_mac *mac)
8683{
8684	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8685	uint16_t tmp;
8686	uint8_t noise[4];
8687	uint8_t i, j;
8688	int32_t average;
8689
8690	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8691		return;
8692
8693	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8694	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8695	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8696	    noise[3] == 0x7f)
8697		goto new;
8698
8699	KASSERT(mac->mac_noise.noi_nsamples < 8,
8700	    ("%s:%d: fail", __func__, __LINE__));
8701	i = mac->mac_noise.noi_nsamples;
8702	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8703	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8704	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8705	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8706	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8707	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8708	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8709	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8710	mac->mac_noise.noi_nsamples++;
8711	if (mac->mac_noise.noi_nsamples == 8) {
8712		average = 0;
8713		for (i = 0; i < 8; i++) {
8714			for (j = 0; j < 4; j++)
8715				average += mac->mac_noise.noi_samples[i][j];
8716		}
8717		average = (((average / 32) * 125) + 64) / 128;
8718		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8719		if (tmp >= 8)
8720			average += 2;
8721		else
8722			average -= 25;
8723		average -= (tmp == 8) ? 72 : 48;
8724
8725		mac->mac_stats.link_noise = average;
8726		mac->mac_noise.noi_running = 0;
8727		return;
8728	}
8729new:
8730	bwn_noise_gensample(mac);
8731}
8732
8733static int
8734bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8735{
8736	struct bwn_mac *mac = prq->prq_mac;
8737	struct bwn_softc *sc = mac->mac_sc;
8738	unsigned int i;
8739
8740	BWN_ASSERT_LOCKED(sc);
8741
8742	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8743		return (0);
8744
8745	for (i = 0; i < 5000; i++) {
8746		if (bwn_pio_rxeof(prq) == 0)
8747			break;
8748	}
8749	if (i >= 5000)
8750		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8751	return ((i > 0) ? 1 : 0);
8752}
8753
8754static void
8755bwn_dma_rx(struct bwn_dma_ring *dr)
8756{
8757	int slot, curslot;
8758
8759	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8760	curslot = dr->get_curslot(dr);
8761	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8762	    ("%s:%d: fail", __func__, __LINE__));
8763
8764	slot = dr->dr_curslot;
8765	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8766		bwn_dma_rxeof(dr, &slot);
8767
8768	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8769	    BUS_DMASYNC_PREWRITE);
8770
8771	dr->set_curslot(dr, slot);
8772	dr->dr_curslot = slot;
8773}
8774
8775static void
8776bwn_intr_txeof(struct bwn_mac *mac)
8777{
8778	struct bwn_txstatus stat;
8779	uint32_t stat0, stat1;
8780	uint16_t tmp;
8781
8782	BWN_ASSERT_LOCKED(mac->mac_sc);
8783
8784	while (1) {
8785		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8786		if (!(stat0 & 0x00000001))
8787			break;
8788		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8789
8790		stat.cookie = (stat0 >> 16);
8791		stat.seq = (stat1 & 0x0000ffff);
8792		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8793		tmp = (stat0 & 0x0000ffff);
8794		stat.framecnt = ((tmp & 0xf000) >> 12);
8795		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8796		stat.sreason = ((tmp & 0x001c) >> 2);
8797		stat.pm = (tmp & 0x0080) ? 1 : 0;
8798		stat.im = (tmp & 0x0040) ? 1 : 0;
8799		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8800		stat.ack = (tmp & 0x0002) ? 1 : 0;
8801
8802		bwn_handle_txeof(mac, &stat);
8803	}
8804}
8805
8806static void
8807bwn_hwreset(void *arg, int npending)
8808{
8809	struct bwn_mac *mac = arg;
8810	struct bwn_softc *sc = mac->mac_sc;
8811	int error = 0;
8812	int prev_status;
8813
8814	BWN_LOCK(sc);
8815
8816	prev_status = mac->mac_status;
8817	if (prev_status >= BWN_MAC_STATUS_STARTED)
8818		bwn_core_stop(mac);
8819	if (prev_status >= BWN_MAC_STATUS_INITED)
8820		bwn_core_exit(mac);
8821
8822	if (prev_status >= BWN_MAC_STATUS_INITED) {
8823		error = bwn_core_init(mac);
8824		if (error)
8825			goto out;
8826	}
8827	if (prev_status >= BWN_MAC_STATUS_STARTED)
8828		bwn_core_start(mac);
8829out:
8830	if (error) {
8831		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8832		sc->sc_curmac = NULL;
8833	}
8834	BWN_UNLOCK(sc);
8835}
8836
8837static void
8838bwn_handle_fwpanic(struct bwn_mac *mac)
8839{
8840	struct bwn_softc *sc = mac->mac_sc;
8841	uint16_t reason;
8842
8843	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8844	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8845
8846	if (reason == BWN_FWPANIC_RESTART)
8847		bwn_restart(mac, "ucode panic");
8848}
8849
8850static void
8851bwn_load_beacon0(struct bwn_mac *mac)
8852{
8853
8854	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8855}
8856
8857static void
8858bwn_load_beacon1(struct bwn_mac *mac)
8859{
8860
8861	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8862}
8863
8864static uint32_t
8865bwn_jssi_read(struct bwn_mac *mac)
8866{
8867	uint32_t val = 0;
8868
8869	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8870	val <<= 16;
8871	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8872
8873	return (val);
8874}
8875
8876static void
8877bwn_noise_gensample(struct bwn_mac *mac)
8878{
8879	uint32_t jssi = 0x7f7f7f7f;
8880
8881	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8882	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8883	BWN_WRITE_4(mac, BWN_MACCMD,
8884	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8885}
8886
8887static int
8888bwn_dma_freeslot(struct bwn_dma_ring *dr)
8889{
8890	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8891
8892	return (dr->dr_numslots - dr->dr_usedslot);
8893}
8894
8895static int
8896bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8897{
8898	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8899
8900	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8901	    ("%s:%d: fail", __func__, __LINE__));
8902	if (slot == dr->dr_numslots - 1)
8903		return (0);
8904	return (slot + 1);
8905}
8906
8907static void
8908bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8909{
8910	struct bwn_mac *mac = dr->dr_mac;
8911	struct bwn_softc *sc = mac->mac_sc;
8912	struct bwn_dma *dma = &mac->mac_method.dma;
8913	struct bwn_dmadesc_generic *desc;
8914	struct bwn_dmadesc_meta *meta;
8915	struct bwn_rxhdr4 *rxhdr;
8916	struct ifnet *ifp = sc->sc_ifp;
8917	struct mbuf *m;
8918	uint32_t macstat;
8919	int32_t tmp;
8920	int cnt = 0;
8921	uint16_t len;
8922
8923	dr->getdesc(dr, *slot, &desc, &meta);
8924
8925	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8926	m = meta->mt_m;
8927
8928	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8929		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8930		return;
8931	}
8932
8933	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8934	len = le16toh(rxhdr->frame_len);
8935	if (len <= 0) {
8936		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8937		return;
8938	}
8939	if (bwn_dma_check_redzone(dr, m)) {
8940		device_printf(sc->sc_dev, "redzone error.\n");
8941		bwn_dma_set_redzone(dr, m);
8942		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8943		    BUS_DMASYNC_PREWRITE);
8944		return;
8945	}
8946	if (len > dr->dr_rx_bufsize) {
8947		tmp = len;
8948		while (1) {
8949			dr->getdesc(dr, *slot, &desc, &meta);
8950			bwn_dma_set_redzone(dr, meta->mt_m);
8951			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8952			    BUS_DMASYNC_PREWRITE);
8953			*slot = bwn_dma_nextslot(dr, *slot);
8954			cnt++;
8955			tmp -= dr->dr_rx_bufsize;
8956			if (tmp <= 0)
8957				break;
8958		}
8959		device_printf(sc->sc_dev, "too small buffer "
8960		       "(len %u buffer %u dropped %d)\n",
8961		       len, dr->dr_rx_bufsize, cnt);
8962		return;
8963	}
8964	macstat = le32toh(rxhdr->mac_status);
8965	if (macstat & BWN_RX_MAC_FCSERR) {
8966		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8967			device_printf(sc->sc_dev, "RX drop\n");
8968			return;
8969		}
8970	}
8971
8972	m->m_pkthdr.rcvif = ifp;
8973	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8974	m_adj(m, dr->dr_frameoffset);
8975
8976	bwn_rxeof(dr->dr_mac, m, rxhdr);
8977}
8978
8979static void
8980bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8981{
8982	struct bwn_dma_ring *dr;
8983	struct bwn_dmadesc_generic *desc;
8984	struct bwn_dmadesc_meta *meta;
8985	struct bwn_pio_txqueue *tq;
8986	struct bwn_pio_txpkt *tp = NULL;
8987	struct bwn_softc *sc = mac->mac_sc;
8988	struct bwn_stats *stats = &mac->mac_stats;
8989	struct ieee80211_node *ni;
8990	struct ieee80211vap *vap;
8991	int retrycnt = 0, slot;
8992
8993	BWN_ASSERT_LOCKED(mac->mac_sc);
8994
8995	if (status->im)
8996		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8997	if (status->ampdu)
8998		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8999	if (status->rtscnt) {
9000		if (status->rtscnt == 0xf)
9001			stats->rtsfail++;
9002		else
9003			stats->rts++;
9004	}
9005
9006	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9007		if (status->ack) {
9008			dr = bwn_dma_parse_cookie(mac, status,
9009			    status->cookie, &slot);
9010			if (dr == NULL) {
9011				device_printf(sc->sc_dev,
9012				    "failed to parse cookie\n");
9013				return;
9014			}
9015			while (1) {
9016				dr->getdesc(dr, slot, &desc, &meta);
9017				if (meta->mt_islast) {
9018					ni = meta->mt_ni;
9019					vap = ni->ni_vap;
9020					ieee80211_ratectl_tx_complete(vap, ni,
9021					    status->ack ?
9022					      IEEE80211_RATECTL_TX_SUCCESS :
9023					      IEEE80211_RATECTL_TX_FAILURE,
9024					    &retrycnt, 0);
9025					break;
9026				}
9027				slot = bwn_dma_nextslot(dr, slot);
9028			}
9029		}
9030		bwn_dma_handle_txeof(mac, status);
9031	} else {
9032		if (status->ack) {
9033			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9034			if (tq == NULL) {
9035				device_printf(sc->sc_dev,
9036				    "failed to parse cookie\n");
9037				return;
9038			}
9039			ni = tp->tp_ni;
9040			vap = ni->ni_vap;
9041			ieee80211_ratectl_tx_complete(vap, ni,
9042			    status->ack ?
9043			      IEEE80211_RATECTL_TX_SUCCESS :
9044			      IEEE80211_RATECTL_TX_FAILURE,
9045			    &retrycnt, 0);
9046		}
9047		bwn_pio_handle_txeof(mac, status);
9048	}
9049
9050	bwn_phy_txpower_check(mac, 0);
9051}
9052
9053static uint8_t
9054bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9055{
9056	struct bwn_mac *mac = prq->prq_mac;
9057	struct bwn_softc *sc = mac->mac_sc;
9058	struct bwn_rxhdr4 rxhdr;
9059	struct ifnet *ifp = sc->sc_ifp;
9060	struct mbuf *m;
9061	uint32_t ctl32, macstat, v32;
9062	unsigned int i, padding;
9063	uint16_t ctl16, len, totlen, v16;
9064	unsigned char *mp;
9065	char *data;
9066
9067	memset(&rxhdr, 0, sizeof(rxhdr));
9068
9069	if (prq->prq_rev >= 8) {
9070		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9071		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9072			return (0);
9073		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9074		    BWN_PIO8_RXCTL_FRAMEREADY);
9075		for (i = 0; i < 10; i++) {
9076			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9077			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9078				goto ready;
9079			DELAY(10);
9080		}
9081	} else {
9082		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9083		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9084			return (0);
9085		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9086		    BWN_PIO_RXCTL_FRAMEREADY);
9087		for (i = 0; i < 10; i++) {
9088			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9089			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9090				goto ready;
9091			DELAY(10);
9092		}
9093	}
9094	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9095	return (1);
9096ready:
9097	if (prq->prq_rev >= 8)
9098		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9099		    prq->prq_base + BWN_PIO8_RXDATA);
9100	else
9101		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102		    prq->prq_base + BWN_PIO_RXDATA);
9103	len = le16toh(rxhdr.frame_len);
9104	if (len > 0x700) {
9105		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9106		goto error;
9107	}
9108	if (len == 0) {
9109		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9110		goto error;
9111	}
9112
9113	macstat = le32toh(rxhdr.mac_status);
9114	if (macstat & BWN_RX_MAC_FCSERR) {
9115		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9116			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9117			goto error;
9118		}
9119	}
9120
9121	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9122	totlen = len + padding;
9123	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9124	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9125	if (m == NULL) {
9126		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9127		goto error;
9128	}
9129	mp = mtod(m, unsigned char *);
9130	if (prq->prq_rev >= 8) {
9131		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9132		    prq->prq_base + BWN_PIO8_RXDATA);
9133		if (totlen & 3) {
9134			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9135			data = &(mp[totlen - 1]);
9136			switch (totlen & 3) {
9137			case 3:
9138				*data = (v32 >> 16);
9139				data--;
9140			case 2:
9141				*data = (v32 >> 8);
9142				data--;
9143			case 1:
9144				*data = v32;
9145			}
9146		}
9147	} else {
9148		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9149		    prq->prq_base + BWN_PIO_RXDATA);
9150		if (totlen & 1) {
9151			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9152			mp[totlen - 1] = v16;
9153		}
9154	}
9155
9156	m->m_pkthdr.rcvif = ifp;
9157	m->m_len = m->m_pkthdr.len = totlen;
9158
9159	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9160
9161	return (1);
9162error:
9163	if (prq->prq_rev >= 8)
9164		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9165		    BWN_PIO8_RXCTL_DATAREADY);
9166	else
9167		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9168	return (1);
9169}
9170
9171static int
9172bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9173    struct bwn_dmadesc_meta *meta, int init)
9174{
9175	struct bwn_mac *mac = dr->dr_mac;
9176	struct bwn_dma *dma = &mac->mac_method.dma;
9177	struct bwn_rxhdr4 *hdr;
9178	bus_dmamap_t map;
9179	bus_addr_t paddr;
9180	struct mbuf *m;
9181	int error;
9182
9183	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9184	if (m == NULL) {
9185		error = ENOBUFS;
9186
9187		/*
9188		 * If the NIC is up and running, we need to:
9189		 * - Clear RX buffer's header.
9190		 * - Restore RX descriptor settings.
9191		 */
9192		if (init)
9193			return (error);
9194		else
9195			goto back;
9196	}
9197	m->m_len = m->m_pkthdr.len = MCLBYTES;
9198
9199	bwn_dma_set_redzone(dr, m);
9200
9201	/*
9202	 * Try to load RX buf into temporary DMA map
9203	 */
9204	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9205	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9206	if (error) {
9207		m_freem(m);
9208
9209		/*
9210		 * See the comment above
9211		 */
9212		if (init)
9213			return (error);
9214		else
9215			goto back;
9216	}
9217
9218	if (!init)
9219		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9220	meta->mt_m = m;
9221	meta->mt_paddr = paddr;
9222
9223	/*
9224	 * Swap RX buf's DMA map with the loaded temporary one
9225	 */
9226	map = meta->mt_dmap;
9227	meta->mt_dmap = dr->dr_spare_dmap;
9228	dr->dr_spare_dmap = map;
9229
9230back:
9231	/*
9232	 * Clear RX buf header
9233	 */
9234	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9235	bzero(hdr, sizeof(*hdr));
9236	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9237	    BUS_DMASYNC_PREWRITE);
9238
9239	/*
9240	 * Setup RX buf descriptor
9241	 */
9242	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9243	    sizeof(*hdr), 0, 0, 0);
9244	return (error);
9245}
9246
9247static void
9248bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9249		 bus_size_t mapsz __unused, int error)
9250{
9251
9252	if (!error) {
9253		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9254		*((bus_addr_t *)arg) = seg->ds_addr;
9255	}
9256}
9257
9258static int
9259bwn_hwrate2ieeerate(int rate)
9260{
9261
9262	switch (rate) {
9263	case BWN_CCK_RATE_1MB:
9264		return (2);
9265	case BWN_CCK_RATE_2MB:
9266		return (4);
9267	case BWN_CCK_RATE_5MB:
9268		return (11);
9269	case BWN_CCK_RATE_11MB:
9270		return (22);
9271	case BWN_OFDM_RATE_6MB:
9272		return (12);
9273	case BWN_OFDM_RATE_9MB:
9274		return (18);
9275	case BWN_OFDM_RATE_12MB:
9276		return (24);
9277	case BWN_OFDM_RATE_18MB:
9278		return (36);
9279	case BWN_OFDM_RATE_24MB:
9280		return (48);
9281	case BWN_OFDM_RATE_36MB:
9282		return (72);
9283	case BWN_OFDM_RATE_48MB:
9284		return (96);
9285	case BWN_OFDM_RATE_54MB:
9286		return (108);
9287	default:
9288		printf("Ooops\n");
9289		return (0);
9290	}
9291}
9292
9293static void
9294bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9295{
9296	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9297	struct bwn_plcp6 *plcp;
9298	struct bwn_softc *sc = mac->mac_sc;
9299	struct ieee80211_frame_min *wh;
9300	struct ieee80211_node *ni;
9301	struct ifnet *ifp = sc->sc_ifp;
9302	struct ieee80211com *ic = ifp->if_l2com;
9303	uint32_t macstat;
9304	int padding, rate, rssi = 0, noise = 0, type;
9305	uint16_t phytype, phystat0, phystat3, chanstat;
9306	unsigned char *mp = mtod(m, unsigned char *);
9307	static int rx_mac_dec_rpt = 0;
9308
9309	BWN_ASSERT_LOCKED(sc);
9310
9311	phystat0 = le16toh(rxhdr->phy_status0);
9312	phystat3 = le16toh(rxhdr->phy_status3);
9313	macstat = le32toh(rxhdr->mac_status);
9314	chanstat = le16toh(rxhdr->channel);
9315	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9316
9317	if (macstat & BWN_RX_MAC_FCSERR)
9318		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9319	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9320		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9321	if (macstat & BWN_RX_MAC_DECERR)
9322		goto drop;
9323
9324	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9325	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9326		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9327		    m->m_pkthdr.len);
9328		goto drop;
9329	}
9330	plcp = (struct bwn_plcp6 *)(mp + padding);
9331	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9332	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9333		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9334		    m->m_pkthdr.len);
9335		goto drop;
9336	}
9337	wh = mtod(m, struct ieee80211_frame_min *);
9338
9339	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9340		device_printf(sc->sc_dev,
9341		    "RX decryption attempted (old %d keyidx %#x)\n",
9342		    BWN_ISOLDFMT(mac),
9343		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9344
9345	/* XXX calculating RSSI & noise & antenna */
9346
9347	if (phystat0 & BWN_RX_PHYST0_OFDM)
9348		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9349		    phytype == BWN_PHYTYPE_A);
9350	else
9351		rate = bwn_plcp_get_cckrate(mac, plcp);
9352	if (rate == -1) {
9353		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9354			goto drop;
9355	}
9356	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9357
9358	/* RX radio tap */
9359	if (ieee80211_radiotap_active(ic))
9360		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9361	m_adj(m, -IEEE80211_CRC_LEN);
9362
9363	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9364	noise = mac->mac_stats.link_noise;
9365
9366	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
9367
9368	BWN_UNLOCK(sc);
9369
9370	ni = ieee80211_find_rxnode(ic, wh);
9371	if (ni != NULL) {
9372		type = ieee80211_input(ni, m, rssi, noise);
9373		ieee80211_free_node(ni);
9374	} else
9375		type = ieee80211_input_all(ic, m, rssi, noise);
9376
9377	BWN_LOCK(sc);
9378	return;
9379drop:
9380	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9381}
9382
9383static void
9384bwn_dma_handle_txeof(struct bwn_mac *mac,
9385    const struct bwn_txstatus *status)
9386{
9387	struct bwn_dma *dma = &mac->mac_method.dma;
9388	struct bwn_dma_ring *dr;
9389	struct bwn_dmadesc_generic *desc;
9390	struct bwn_dmadesc_meta *meta;
9391	struct bwn_softc *sc = mac->mac_sc;
9392	struct ieee80211_node *ni;
9393	struct ifnet *ifp = sc->sc_ifp;
9394	struct mbuf *m;
9395	int slot;
9396
9397	BWN_ASSERT_LOCKED(sc);
9398
9399	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9400	if (dr == NULL) {
9401		device_printf(sc->sc_dev, "failed to parse cookie\n");
9402		return;
9403	}
9404	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9405
9406	while (1) {
9407		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9408		    ("%s:%d: fail", __func__, __LINE__));
9409		dr->getdesc(dr, slot, &desc, &meta);
9410
9411		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9412			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9413		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9414			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9415
9416		if (meta->mt_islast) {
9417			KASSERT(meta->mt_m != NULL,
9418			    ("%s:%d: fail", __func__, __LINE__));
9419
9420			ni = meta->mt_ni;
9421			m = meta->mt_m;
9422			if (ni != NULL) {
9423				/*
9424				 * Do any tx complete callback. Note this must
9425				 * be done before releasing the node reference.
9426				 */
9427				if (m->m_flags & M_TXCB)
9428					ieee80211_process_callback(ni, m, 0);
9429				ieee80211_free_node(ni);
9430				meta->mt_ni = NULL;
9431			}
9432			m_freem(m);
9433			meta->mt_m = NULL;
9434		} else {
9435			KASSERT(meta->mt_m == NULL,
9436			    ("%s:%d: fail", __func__, __LINE__));
9437		}
9438
9439		dr->dr_usedslot--;
9440		if (meta->mt_islast) {
9441			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9442			break;
9443		}
9444		slot = bwn_dma_nextslot(dr, slot);
9445	}
9446	sc->sc_watchdog_timer = 0;
9447	if (dr->dr_stop) {
9448		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9449		    ("%s:%d: fail", __func__, __LINE__));
9450		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9451		dr->dr_stop = 0;
9452	}
9453}
9454
9455static void
9456bwn_pio_handle_txeof(struct bwn_mac *mac,
9457    const struct bwn_txstatus *status)
9458{
9459	struct bwn_pio_txqueue *tq;
9460	struct bwn_pio_txpkt *tp = NULL;
9461	struct bwn_softc *sc = mac->mac_sc;
9462	struct ifnet *ifp = sc->sc_ifp;
9463
9464	BWN_ASSERT_LOCKED(sc);
9465
9466	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9467	if (tq == NULL)
9468		return;
9469
9470	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9471	tq->tq_free++;
9472
9473	if (tp->tp_ni != NULL) {
9474		/*
9475		 * Do any tx complete callback.  Note this must
9476		 * be done before releasing the node reference.
9477		 */
9478		if (tp->tp_m->m_flags & M_TXCB)
9479			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9480		ieee80211_free_node(tp->tp_ni);
9481		tp->tp_ni = NULL;
9482	}
9483	m_freem(tp->tp_m);
9484	tp->tp_m = NULL;
9485	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9486
9487	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9488
9489	sc->sc_watchdog_timer = 0;
9490	if (tq->tq_stop) {
9491		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9492		tq->tq_stop = 0;
9493	}
9494}
9495
9496static void
9497bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9498{
9499	struct bwn_softc *sc = mac->mac_sc;
9500	struct bwn_phy *phy = &mac->mac_phy;
9501	struct ifnet *ifp = sc->sc_ifp;
9502	struct ieee80211com *ic = ifp->if_l2com;
9503	unsigned long now;
9504	int result;
9505
9506	BWN_GETTIME(now);
9507
9508	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9509		return;
9510	phy->nexttime = now + 2 * 1000;
9511
9512	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9513	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9514		return;
9515
9516	if (phy->recalc_txpwr != NULL) {
9517		result = phy->recalc_txpwr(mac,
9518		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9519		if (result == BWN_TXPWR_RES_DONE)
9520			return;
9521		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9522		    ("%s: fail", __func__));
9523		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9524
9525		ieee80211_runtask(ic, &mac->mac_txpower);
9526	}
9527}
9528
9529static uint16_t
9530bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9531{
9532
9533	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9534}
9535
9536static uint32_t
9537bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9538{
9539
9540	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9541}
9542
9543static void
9544bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9545{
9546
9547	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9548}
9549
9550static void
9551bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9552{
9553
9554	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9555}
9556
9557static int
9558bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9559{
9560
9561	switch (rate) {
9562	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9563	case 12:
9564		return (BWN_OFDM_RATE_6MB);
9565	case 18:
9566		return (BWN_OFDM_RATE_9MB);
9567	case 24:
9568		return (BWN_OFDM_RATE_12MB);
9569	case 36:
9570		return (BWN_OFDM_RATE_18MB);
9571	case 48:
9572		return (BWN_OFDM_RATE_24MB);
9573	case 72:
9574		return (BWN_OFDM_RATE_36MB);
9575	case 96:
9576		return (BWN_OFDM_RATE_48MB);
9577	case 108:
9578		return (BWN_OFDM_RATE_54MB);
9579	/* CCK rates (NB: not IEEE std, device-specific) */
9580	case 2:
9581		return (BWN_CCK_RATE_1MB);
9582	case 4:
9583		return (BWN_CCK_RATE_2MB);
9584	case 11:
9585		return (BWN_CCK_RATE_5MB);
9586	case 22:
9587		return (BWN_CCK_RATE_11MB);
9588	}
9589
9590	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9591	return (BWN_CCK_RATE_1MB);
9592}
9593
9594static int
9595bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9596    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9597{
9598	const struct bwn_phy *phy = &mac->mac_phy;
9599	struct bwn_softc *sc = mac->mac_sc;
9600	struct ieee80211_frame *wh;
9601	struct ieee80211_frame *protwh;
9602	struct ieee80211_frame_cts *cts;
9603	struct ieee80211_frame_rts *rts;
9604	const struct ieee80211_txparam *tp;
9605	struct ieee80211vap *vap = ni->ni_vap;
9606	struct ifnet *ifp = sc->sc_ifp;
9607	struct ieee80211com *ic = ifp->if_l2com;
9608	struct mbuf *mprot;
9609	unsigned int len;
9610	uint32_t macctl = 0;
9611	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9612	uint16_t phyctl = 0;
9613	uint8_t rate, rate_fb;
9614
9615	wh = mtod(m, struct ieee80211_frame *);
9616	memset(txhdr, 0, sizeof(*txhdr));
9617
9618	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9619	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9620	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9621
9622	/*
9623	 * Find TX rate
9624	 */
9625	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9626	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9627		rate = rate_fb = tp->mgmtrate;
9628	else if (ismcast)
9629		rate = rate_fb = tp->mcastrate;
9630	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9631		rate = rate_fb = tp->ucastrate;
9632	else {
9633		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9634		rate = ni->ni_txrate;
9635
9636		if (rix > 0)
9637			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9638			    IEEE80211_RATE_VAL;
9639		else
9640			rate_fb = rate;
9641	}
9642
9643	sc->sc_tx_rate = rate;
9644
9645	rate = bwn_ieeerate2hwrate(sc, rate);
9646	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9647
9648	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9649	    bwn_plcp_getcck(rate);
9650	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9651	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9652
9653	if ((rate_fb == rate) ||
9654	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9655	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9656		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9657	else
9658		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9659		    m->m_pkthdr.len, rate, isshort);
9660
9661	/* XXX TX encryption */
9662	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9663	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9664	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9665	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9666	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9667	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9668
9669	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9670	    BWN_TX_EFT_FB_CCK;
9671	txhdr->chan = phy->chan;
9672	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9673	    BWN_TX_PHY_ENC_CCK;
9674	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9675	     rate == BWN_CCK_RATE_11MB))
9676		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9677
9678	/* XXX TX antenna selection */
9679
9680	switch (bwn_antenna_sanitize(mac, 0)) {
9681	case 0:
9682		phyctl |= BWN_TX_PHY_ANT01AUTO;
9683		break;
9684	case 1:
9685		phyctl |= BWN_TX_PHY_ANT0;
9686		break;
9687	case 2:
9688		phyctl |= BWN_TX_PHY_ANT1;
9689		break;
9690	case 3:
9691		phyctl |= BWN_TX_PHY_ANT2;
9692		break;
9693	case 4:
9694		phyctl |= BWN_TX_PHY_ANT3;
9695		break;
9696	default:
9697		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9698	}
9699
9700	if (!ismcast)
9701		macctl |= BWN_TX_MAC_ACK;
9702
9703	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9704	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9705	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9706		macctl |= BWN_TX_MAC_LONGFRAME;
9707
9708	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9709		/* XXX RTS rate is always 1MB??? */
9710		rts_rate = BWN_CCK_RATE_1MB;
9711		rts_rate_fb = bwn_get_fbrate(rts_rate);
9712
9713		protdur = ieee80211_compute_duration(ic->ic_rt,
9714		    m->m_pkthdr.len, rate, isshort) +
9715		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9716
9717		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9718			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9719			    (txhdr->body.old.rts_frame) :
9720			    (txhdr->body.new.rts_frame));
9721			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9722			    protdur);
9723			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9724			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9725			    mprot->m_pkthdr.len);
9726			m_freem(mprot);
9727			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9728			len = sizeof(struct ieee80211_frame_cts);
9729		} else {
9730			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9731			    (txhdr->body.old.rts_frame) :
9732			    (txhdr->body.new.rts_frame));
9733			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9734			    isshort);
9735			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9736			    wh->i_addr2, protdur);
9737			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9738			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9739			    mprot->m_pkthdr.len);
9740			m_freem(mprot);
9741			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9742			len = sizeof(struct ieee80211_frame_rts);
9743		}
9744		len += IEEE80211_CRC_LEN;
9745		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9746		    &txhdr->body.old.rts_plcp :
9747		    &txhdr->body.new.rts_plcp), len, rts_rate);
9748		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9749		    rts_rate_fb);
9750
9751		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9752		    (&txhdr->body.old.rts_frame) :
9753		    (&txhdr->body.new.rts_frame));
9754		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9755
9756		if (BWN_ISOFDMRATE(rts_rate)) {
9757			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9758			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9759		} else {
9760			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9761			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9762		}
9763		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9764		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9765	}
9766
9767	if (BWN_ISOLDFMT(mac))
9768		txhdr->body.old.cookie = htole16(cookie);
9769	else
9770		txhdr->body.new.cookie = htole16(cookie);
9771
9772	txhdr->macctl = htole32(macctl);
9773	txhdr->phyctl = htole16(phyctl);
9774
9775	/*
9776	 * TX radio tap
9777	 */
9778	if (ieee80211_radiotap_active_vap(vap)) {
9779		sc->sc_tx_th.wt_flags = 0;
9780		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9781			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9782		if (isshort &&
9783		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9784		     rate == BWN_CCK_RATE_11MB))
9785			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9786		sc->sc_tx_th.wt_rate = rate;
9787
9788		ieee80211_radiotap_tx(vap, m);
9789	}
9790
9791	return (0);
9792}
9793
9794static void
9795bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9796    const uint8_t rate)
9797{
9798	uint32_t d, plen;
9799	uint8_t *raw = plcp->o.raw;
9800
9801	if (BWN_ISOFDMRATE(rate)) {
9802		d = bwn_plcp_getofdm(rate);
9803		KASSERT(!(octets & 0xf000),
9804		    ("%s:%d: fail", __func__, __LINE__));
9805		d |= (octets << 5);
9806		plcp->o.data = htole32(d);
9807	} else {
9808		plen = octets * 16 / rate;
9809		if ((octets * 16 % rate) > 0) {
9810			plen++;
9811			if ((rate == BWN_CCK_RATE_11MB)
9812			    && ((octets * 8 % 11) < 4)) {
9813				raw[1] = 0x84;
9814			} else
9815				raw[1] = 0x04;
9816		} else
9817			raw[1] = 0x04;
9818		plcp->o.data |= htole32(plen << 16);
9819		raw[0] = bwn_plcp_getcck(rate);
9820	}
9821}
9822
9823static uint8_t
9824bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9825{
9826	struct bwn_softc *sc = mac->mac_sc;
9827	uint8_t mask;
9828
9829	if (n == 0)
9830		return (0);
9831	if (mac->mac_phy.gmode)
9832		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9833	else
9834		mask = siba_sprom_get_ant_a(sc->sc_dev);
9835	if (!(mask & (1 << (n - 1))))
9836		return (0);
9837	return (n);
9838}
9839
9840static uint8_t
9841bwn_get_fbrate(uint8_t bitrate)
9842{
9843	switch (bitrate) {
9844	case BWN_CCK_RATE_1MB:
9845		return (BWN_CCK_RATE_1MB);
9846	case BWN_CCK_RATE_2MB:
9847		return (BWN_CCK_RATE_1MB);
9848	case BWN_CCK_RATE_5MB:
9849		return (BWN_CCK_RATE_2MB);
9850	case BWN_CCK_RATE_11MB:
9851		return (BWN_CCK_RATE_5MB);
9852	case BWN_OFDM_RATE_6MB:
9853		return (BWN_CCK_RATE_5MB);
9854	case BWN_OFDM_RATE_9MB:
9855		return (BWN_OFDM_RATE_6MB);
9856	case BWN_OFDM_RATE_12MB:
9857		return (BWN_OFDM_RATE_9MB);
9858	case BWN_OFDM_RATE_18MB:
9859		return (BWN_OFDM_RATE_12MB);
9860	case BWN_OFDM_RATE_24MB:
9861		return (BWN_OFDM_RATE_18MB);
9862	case BWN_OFDM_RATE_36MB:
9863		return (BWN_OFDM_RATE_24MB);
9864	case BWN_OFDM_RATE_48MB:
9865		return (BWN_OFDM_RATE_36MB);
9866	case BWN_OFDM_RATE_54MB:
9867		return (BWN_OFDM_RATE_48MB);
9868	}
9869	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9870	return (0);
9871}
9872
9873static uint32_t
9874bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9875    uint32_t ctl, const void *_data, int len)
9876{
9877	struct bwn_softc *sc = mac->mac_sc;
9878	uint32_t value = 0;
9879	const uint8_t *data = _data;
9880
9881	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9882	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9883	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9884
9885	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9886	    tq->tq_base + BWN_PIO8_TXDATA);
9887	if (len & 3) {
9888		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9889		    BWN_PIO8_TXCTL_24_31);
9890		data = &(data[len - 1]);
9891		switch (len & 3) {
9892		case 3:
9893			ctl |= BWN_PIO8_TXCTL_16_23;
9894			value |= (uint32_t)(*data) << 16;
9895			data--;
9896		case 2:
9897			ctl |= BWN_PIO8_TXCTL_8_15;
9898			value |= (uint32_t)(*data) << 8;
9899			data--;
9900		case 1:
9901			value |= (uint32_t)(*data);
9902		}
9903		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9904		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9905	}
9906
9907	return (ctl);
9908}
9909
9910static void
9911bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9912    uint16_t offset, uint32_t value)
9913{
9914
9915	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9916}
9917
9918static uint16_t
9919bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9920    uint16_t ctl, const void *_data, int len)
9921{
9922	struct bwn_softc *sc = mac->mac_sc;
9923	const uint8_t *data = _data;
9924
9925	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9926	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9927
9928	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9929	    tq->tq_base + BWN_PIO_TXDATA);
9930	if (len & 1) {
9931		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9932		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9933		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9934	}
9935
9936	return (ctl);
9937}
9938
9939static uint16_t
9940bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9941    uint16_t ctl, struct mbuf *m0)
9942{
9943	int i, j = 0;
9944	uint16_t data = 0;
9945	const uint8_t *buf;
9946	struct mbuf *m = m0;
9947
9948	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9949	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9950
9951	for (; m != NULL; m = m->m_next) {
9952		buf = mtod(m, const uint8_t *);
9953		for (i = 0; i < m->m_len; i++) {
9954			if (!((j++) % 2))
9955				data |= buf[i];
9956			else {
9957				data |= (buf[i] << 8);
9958				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9959				data = 0;
9960			}
9961		}
9962	}
9963	if (m0->m_pkthdr.len % 2) {
9964		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9965		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9966		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9967	}
9968
9969	return (ctl);
9970}
9971
9972static void
9973bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9974{
9975
9976	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9977		return;
9978	BWN_WRITE_2(mac, 0x684, 510 + time);
9979	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9980}
9981
9982static struct bwn_dma_ring *
9983bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9984{
9985
9986	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9987		return (mac->mac_method.dma.wme[WME_AC_BE]);
9988
9989	switch (prio) {
9990	case 3:
9991		return (mac->mac_method.dma.wme[WME_AC_VO]);
9992	case 2:
9993		return (mac->mac_method.dma.wme[WME_AC_VI]);
9994	case 0:
9995		return (mac->mac_method.dma.wme[WME_AC_BE]);
9996	case 1:
9997		return (mac->mac_method.dma.wme[WME_AC_BK]);
9998	}
9999	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10000	return (NULL);
10001}
10002
10003static int
10004bwn_dma_getslot(struct bwn_dma_ring *dr)
10005{
10006	int slot;
10007
10008	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10009
10010	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10011	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10012	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10013
10014	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10015	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10016	dr->dr_curslot = slot;
10017	dr->dr_usedslot++;
10018
10019	return (slot);
10020}
10021
10022static int
10023bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10024{
10025	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10026	unsigned int a, b, c, d;
10027	unsigned int avg;
10028	uint32_t tmp;
10029
10030	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10031	a = tmp & 0xff;
10032	b = (tmp >> 8) & 0xff;
10033	c = (tmp >> 16) & 0xff;
10034	d = (tmp >> 24) & 0xff;
10035	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10036	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10037		return (ENOENT);
10038	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10039	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10040	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10041
10042	if (ofdm) {
10043		a = (a + 32) & 0x3f;
10044		b = (b + 32) & 0x3f;
10045		c = (c + 32) & 0x3f;
10046		d = (d + 32) & 0x3f;
10047	}
10048
10049	avg = (a + b + c + d + 2) / 4;
10050	if (ofdm) {
10051		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10052		    & BWN_HF_4DB_CCK_POWERBOOST)
10053			avg = (avg >= 13) ? (avg - 13) : 0;
10054	}
10055	return (avg);
10056}
10057
10058static void
10059bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10060{
10061	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10062	int rfatt = *rfattp;
10063	int bbatt = *bbattp;
10064
10065	while (1) {
10066		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10067			break;
10068		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10069			break;
10070		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10071			break;
10072		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10073			break;
10074		if (bbatt > lo->bbatt.max) {
10075			bbatt -= 4;
10076			rfatt += 1;
10077			continue;
10078		}
10079		if (bbatt < lo->bbatt.min) {
10080			bbatt += 4;
10081			rfatt -= 1;
10082			continue;
10083		}
10084		if (rfatt > lo->rfatt.max) {
10085			rfatt -= 1;
10086			bbatt += 4;
10087			continue;
10088		}
10089		if (rfatt < lo->rfatt.min) {
10090			rfatt += 1;
10091			bbatt -= 4;
10092			continue;
10093		}
10094		break;
10095	}
10096
10097	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10098	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10099}
10100
10101static void
10102bwn_phy_lock(struct bwn_mac *mac)
10103{
10104	struct bwn_softc *sc = mac->mac_sc;
10105	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10106
10107	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10108	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10109
10110	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10111		bwn_psctl(mac, BWN_PS_AWAKE);
10112}
10113
10114static void
10115bwn_phy_unlock(struct bwn_mac *mac)
10116{
10117	struct bwn_softc *sc = mac->mac_sc;
10118	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10119
10120	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10121	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10122
10123	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10124		bwn_psctl(mac, 0);
10125}
10126
10127static void
10128bwn_rf_lock(struct bwn_mac *mac)
10129{
10130
10131	BWN_WRITE_4(mac, BWN_MACCTL,
10132	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10133	BWN_READ_4(mac, BWN_MACCTL);
10134	DELAY(10);
10135}
10136
10137static void
10138bwn_rf_unlock(struct bwn_mac *mac)
10139{
10140
10141	BWN_READ_2(mac, BWN_PHYVER);
10142	BWN_WRITE_4(mac, BWN_MACCTL,
10143	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10144}
10145
10146static struct bwn_pio_txqueue *
10147bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10148    struct bwn_pio_txpkt **pack)
10149{
10150	struct bwn_pio *pio = &mac->mac_method.pio;
10151	struct bwn_pio_txqueue *tq = NULL;
10152	unsigned int index;
10153
10154	switch (cookie & 0xf000) {
10155	case 0x1000:
10156		tq = &pio->wme[WME_AC_BK];
10157		break;
10158	case 0x2000:
10159		tq = &pio->wme[WME_AC_BE];
10160		break;
10161	case 0x3000:
10162		tq = &pio->wme[WME_AC_VI];
10163		break;
10164	case 0x4000:
10165		tq = &pio->wme[WME_AC_VO];
10166		break;
10167	case 0x5000:
10168		tq = &pio->mcast;
10169		break;
10170	}
10171	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10172	if (tq == NULL)
10173		return (NULL);
10174	index = (cookie & 0x0fff);
10175	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10176	if (index >= N(tq->tq_pkts))
10177		return (NULL);
10178	*pack = &tq->tq_pkts[index];
10179	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10180	return (tq);
10181}
10182
10183static void
10184bwn_txpwr(void *arg, int npending)
10185{
10186	struct bwn_mac *mac = arg;
10187	struct bwn_softc *sc = mac->mac_sc;
10188
10189	BWN_LOCK(sc);
10190	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10191	    mac->mac_phy.set_txpwr != NULL)
10192		mac->mac_phy.set_txpwr(mac);
10193	BWN_UNLOCK(sc);
10194}
10195
10196static void
10197bwn_task_15s(struct bwn_mac *mac)
10198{
10199	uint16_t reg;
10200
10201	if (mac->mac_fw.opensource) {
10202		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10203		if (reg) {
10204			bwn_restart(mac, "fw watchdog");
10205			return;
10206		}
10207		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10208	}
10209	if (mac->mac_phy.task_15s)
10210		mac->mac_phy.task_15s(mac);
10211
10212	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10213}
10214
10215static void
10216bwn_task_30s(struct bwn_mac *mac)
10217{
10218
10219	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10220		return;
10221	mac->mac_noise.noi_running = 1;
10222	mac->mac_noise.noi_nsamples = 0;
10223
10224	bwn_noise_gensample(mac);
10225}
10226
10227static void
10228bwn_task_60s(struct bwn_mac *mac)
10229{
10230
10231	if (mac->mac_phy.task_60s)
10232		mac->mac_phy.task_60s(mac);
10233	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10234}
10235
10236static void
10237bwn_tasks(void *arg)
10238{
10239	struct bwn_mac *mac = arg;
10240	struct bwn_softc *sc = mac->mac_sc;
10241
10242	BWN_ASSERT_LOCKED(sc);
10243	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10244		return;
10245
10246	if (mac->mac_task_state % 4 == 0)
10247		bwn_task_60s(mac);
10248	if (mac->mac_task_state % 2 == 0)
10249		bwn_task_30s(mac);
10250	bwn_task_15s(mac);
10251
10252	mac->mac_task_state++;
10253	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10254}
10255
10256static int
10257bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10258{
10259	struct bwn_softc *sc = mac->mac_sc;
10260
10261	KASSERT(a == 0, ("not support APHY\n"));
10262
10263	switch (plcp->o.raw[0] & 0xf) {
10264	case 0xb:
10265		return (BWN_OFDM_RATE_6MB);
10266	case 0xf:
10267		return (BWN_OFDM_RATE_9MB);
10268	case 0xa:
10269		return (BWN_OFDM_RATE_12MB);
10270	case 0xe:
10271		return (BWN_OFDM_RATE_18MB);
10272	case 0x9:
10273		return (BWN_OFDM_RATE_24MB);
10274	case 0xd:
10275		return (BWN_OFDM_RATE_36MB);
10276	case 0x8:
10277		return (BWN_OFDM_RATE_48MB);
10278	case 0xc:
10279		return (BWN_OFDM_RATE_54MB);
10280	}
10281	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10282	    plcp->o.raw[0] & 0xf);
10283	return (-1);
10284}
10285
10286static int
10287bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10288{
10289	struct bwn_softc *sc = mac->mac_sc;
10290
10291	switch (plcp->o.raw[0]) {
10292	case 0x0a:
10293		return (BWN_CCK_RATE_1MB);
10294	case 0x14:
10295		return (BWN_CCK_RATE_2MB);
10296	case 0x37:
10297		return (BWN_CCK_RATE_5MB);
10298	case 0x6e:
10299		return (BWN_CCK_RATE_11MB);
10300	}
10301	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10302	return (-1);
10303}
10304
10305static void
10306bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10307    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10308    int rssi, int noise)
10309{
10310	struct bwn_softc *sc = mac->mac_sc;
10311	const struct ieee80211_frame_min *wh;
10312	uint64_t tsf;
10313	uint16_t low_mactime_now;
10314
10315	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10316		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10317
10318	wh = mtod(m, const struct ieee80211_frame_min *);
10319	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10320		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10321
10322	bwn_tsf_read(mac, &tsf);
10323	low_mactime_now = tsf;
10324	tsf = tsf & ~0xffffULL;
10325	tsf += le16toh(rxhdr->mac_time);
10326	if (low_mactime_now < le16toh(rxhdr->mac_time))
10327		tsf -= 0x10000;
10328
10329	sc->sc_rx_th.wr_tsf = tsf;
10330	sc->sc_rx_th.wr_rate = rate;
10331	sc->sc_rx_th.wr_antsignal = rssi;
10332	sc->sc_rx_th.wr_antnoise = noise;
10333}
10334
10335static void
10336bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10337{
10338	uint32_t low, high;
10339
10340	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10341	    ("%s:%d: fail", __func__, __LINE__));
10342
10343	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10344	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10345	*tsf = high;
10346	*tsf <<= 32;
10347	*tsf |= low;
10348}
10349
10350static int
10351bwn_dma_attach(struct bwn_mac *mac)
10352{
10353	struct bwn_dma *dma = &mac->mac_method.dma;
10354	struct bwn_softc *sc = mac->mac_sc;
10355	bus_addr_t lowaddr = 0;
10356	int error;
10357
10358	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10359		return (0);
10360
10361	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10362
10363	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10364
10365	dma->dmatype = bwn_dma_gettype(mac);
10366	if (dma->dmatype == BWN_DMA_30BIT)
10367		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10368	else if (dma->dmatype == BWN_DMA_32BIT)
10369		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10370	else
10371		lowaddr = BUS_SPACE_MAXADDR;
10372
10373	/*
10374	 * Create top level DMA tag
10375	 */
10376	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10377			       BWN_ALIGN, 0,		/* alignment, bounds */
10378			       lowaddr,			/* lowaddr */
10379			       BUS_SPACE_MAXADDR,	/* highaddr */
10380			       NULL, NULL,		/* filter, filterarg */
10381			       BUS_SPACE_MAXSIZE,	/* maxsize */
10382			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10383			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10384			       0,			/* flags */
10385			       NULL, NULL,		/* lockfunc, lockarg */
10386			       &dma->parent_dtag);
10387	if (error) {
10388		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10389		return (error);
10390	}
10391
10392	/*
10393	 * Create TX/RX mbuf DMA tag
10394	 */
10395	error = bus_dma_tag_create(dma->parent_dtag,
10396				1,
10397				0,
10398				BUS_SPACE_MAXADDR,
10399				BUS_SPACE_MAXADDR,
10400				NULL, NULL,
10401				MCLBYTES,
10402				1,
10403				BUS_SPACE_MAXSIZE_32BIT,
10404				0,
10405				NULL, NULL,
10406				&dma->rxbuf_dtag);
10407	if (error) {
10408		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10409		goto fail0;
10410	}
10411	error = bus_dma_tag_create(dma->parent_dtag,
10412				1,
10413				0,
10414				BUS_SPACE_MAXADDR,
10415				BUS_SPACE_MAXADDR,
10416				NULL, NULL,
10417				MCLBYTES,
10418				1,
10419				BUS_SPACE_MAXSIZE_32BIT,
10420				0,
10421				NULL, NULL,
10422				&dma->txbuf_dtag);
10423	if (error) {
10424		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10425		goto fail1;
10426	}
10427
10428	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10429	if (!dma->wme[WME_AC_BK])
10430		goto fail2;
10431
10432	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10433	if (!dma->wme[WME_AC_BE])
10434		goto fail3;
10435
10436	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10437	if (!dma->wme[WME_AC_VI])
10438		goto fail4;
10439
10440	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10441	if (!dma->wme[WME_AC_VO])
10442		goto fail5;
10443
10444	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10445	if (!dma->mcast)
10446		goto fail6;
10447	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10448	if (!dma->rx)
10449		goto fail7;
10450
10451	return (error);
10452
10453fail7:	bwn_dma_ringfree(&dma->mcast);
10454fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10455fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10456fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10457fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10458fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10459fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10460fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10461	return (error);
10462}
10463
10464static struct bwn_dma_ring *
10465bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10466    uint16_t cookie, int *slot)
10467{
10468	struct bwn_dma *dma = &mac->mac_method.dma;
10469	struct bwn_dma_ring *dr;
10470	struct bwn_softc *sc = mac->mac_sc;
10471
10472	BWN_ASSERT_LOCKED(mac->mac_sc);
10473
10474	switch (cookie & 0xf000) {
10475	case 0x1000:
10476		dr = dma->wme[WME_AC_BK];
10477		break;
10478	case 0x2000:
10479		dr = dma->wme[WME_AC_BE];
10480		break;
10481	case 0x3000:
10482		dr = dma->wme[WME_AC_VI];
10483		break;
10484	case 0x4000:
10485		dr = dma->wme[WME_AC_VO];
10486		break;
10487	case 0x5000:
10488		dr = dma->mcast;
10489		break;
10490	default:
10491		dr = NULL;
10492		KASSERT(0 == 1,
10493		    ("invalid cookie value %d", cookie & 0xf000));
10494	}
10495	*slot = (cookie & 0x0fff);
10496	if (*slot < 0 || *slot >= dr->dr_numslots) {
10497		/*
10498		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10499		 * that it occurs events which have same H/W sequence numbers.
10500		 * When it's occurred just prints a WARNING msgs and ignores.
10501		 */
10502		KASSERT(status->seq == dma->lastseq,
10503		    ("%s:%d: fail", __func__, __LINE__));
10504		device_printf(sc->sc_dev,
10505		    "out of slot ranges (0 < %d < %d)\n", *slot,
10506		    dr->dr_numslots);
10507		return (NULL);
10508	}
10509	dma->lastseq = status->seq;
10510	return (dr);
10511}
10512
10513static void
10514bwn_dma_stop(struct bwn_mac *mac)
10515{
10516	struct bwn_dma *dma;
10517
10518	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10519		return;
10520	dma = &mac->mac_method.dma;
10521
10522	bwn_dma_ringstop(&dma->rx);
10523	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10524	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10525	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10526	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10527	bwn_dma_ringstop(&dma->mcast);
10528}
10529
10530static void
10531bwn_dma_ringstop(struct bwn_dma_ring **dr)
10532{
10533
10534	if (dr == NULL)
10535		return;
10536
10537	bwn_dma_cleanup(*dr);
10538}
10539
10540static void
10541bwn_pio_stop(struct bwn_mac *mac)
10542{
10543	struct bwn_pio *pio;
10544
10545	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10546		return;
10547	pio = &mac->mac_method.pio;
10548
10549	bwn_destroy_queue_tx(&pio->mcast);
10550	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10551	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10552	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10553	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10554}
10555
10556static void
10557bwn_led_attach(struct bwn_mac *mac)
10558{
10559	struct bwn_softc *sc = mac->mac_sc;
10560	const uint8_t *led_act = NULL;
10561	uint16_t val[BWN_LED_MAX];
10562	int i;
10563
10564	sc->sc_led_idle = (2350 * hz) / 1000;
10565	sc->sc_led_blink = 1;
10566
10567	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10568		if (siba_get_pci_subvendor(sc->sc_dev) ==
10569		    bwn_vendor_led_act[i].vid) {
10570			led_act = bwn_vendor_led_act[i].led_act;
10571			break;
10572		}
10573	}
10574	if (led_act == NULL)
10575		led_act = bwn_default_led_act;
10576
10577	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10578	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10579	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10580	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10581
10582	for (i = 0; i < BWN_LED_MAX; ++i) {
10583		struct bwn_led *led = &sc->sc_leds[i];
10584
10585		if (val[i] == 0xff) {
10586			led->led_act = led_act[i];
10587		} else {
10588			if (val[i] & BWN_LED_ACT_LOW)
10589				led->led_flags |= BWN_LED_F_ACTLOW;
10590			led->led_act = val[i] & BWN_LED_ACT_MASK;
10591		}
10592		led->led_mask = (1 << i);
10593
10594		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10595		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10596		    led->led_act == BWN_LED_ACT_BLINK) {
10597			led->led_flags |= BWN_LED_F_BLINK;
10598			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10599				led->led_flags |= BWN_LED_F_POLLABLE;
10600			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10601				led->led_flags |= BWN_LED_F_SLOW;
10602
10603			if (sc->sc_blink_led == NULL) {
10604				sc->sc_blink_led = led;
10605				if (led->led_flags & BWN_LED_F_SLOW)
10606					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10607			}
10608		}
10609
10610		DPRINTF(sc, BWN_DEBUG_LED,
10611		    "%dth led, act %d, lowact %d\n", i,
10612		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10613	}
10614	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10615}
10616
10617static __inline uint16_t
10618bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10619{
10620
10621	if (led->led_flags & BWN_LED_F_ACTLOW)
10622		on = !on;
10623	if (on)
10624		val |= led->led_mask;
10625	else
10626		val &= ~led->led_mask;
10627	return val;
10628}
10629
10630static void
10631bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10632{
10633	struct bwn_softc *sc = mac->mac_sc;
10634	struct ifnet *ifp = sc->sc_ifp;
10635	struct ieee80211com *ic = ifp->if_l2com;
10636	uint16_t val;
10637	int i;
10638
10639	if (nstate == IEEE80211_S_INIT) {
10640		callout_stop(&sc->sc_led_blink_ch);
10641		sc->sc_led_blinking = 0;
10642	}
10643
10644	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10645		return;
10646
10647	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10648	for (i = 0; i < BWN_LED_MAX; ++i) {
10649		struct bwn_led *led = &sc->sc_leds[i];
10650		int on;
10651
10652		if (led->led_act == BWN_LED_ACT_UNKN ||
10653		    led->led_act == BWN_LED_ACT_NULL)
10654			continue;
10655
10656		if ((led->led_flags & BWN_LED_F_BLINK) &&
10657		    nstate != IEEE80211_S_INIT)
10658			continue;
10659
10660		switch (led->led_act) {
10661		case BWN_LED_ACT_ON:    /* Always on */
10662			on = 1;
10663			break;
10664		case BWN_LED_ACT_OFF:   /* Always off */
10665		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10666			on = 0;
10667			break;
10668		default:
10669			on = 1;
10670			switch (nstate) {
10671			case IEEE80211_S_INIT:
10672				on = 0;
10673				break;
10674			case IEEE80211_S_RUN:
10675				if (led->led_act == BWN_LED_ACT_11G &&
10676				    ic->ic_curmode != IEEE80211_MODE_11G)
10677					on = 0;
10678				break;
10679			default:
10680				if (led->led_act == BWN_LED_ACT_ASSOC)
10681					on = 0;
10682				break;
10683			}
10684			break;
10685		}
10686
10687		val = bwn_led_onoff(led, val, on);
10688	}
10689	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10690}
10691
10692static void
10693bwn_led_event(struct bwn_mac *mac, int event)
10694{
10695	struct bwn_softc *sc = mac->mac_sc;
10696	struct bwn_led *led = sc->sc_blink_led;
10697	int rate;
10698
10699	if (event == BWN_LED_EVENT_POLL) {
10700		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10701			return;
10702		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10703			return;
10704	}
10705
10706	sc->sc_led_ticks = ticks;
10707	if (sc->sc_led_blinking)
10708		return;
10709
10710	switch (event) {
10711	case BWN_LED_EVENT_RX:
10712		rate = sc->sc_rx_rate;
10713		break;
10714	case BWN_LED_EVENT_TX:
10715		rate = sc->sc_tx_rate;
10716		break;
10717	case BWN_LED_EVENT_POLL:
10718		rate = 0;
10719		break;
10720	default:
10721		panic("unknown LED event %d\n", event);
10722		break;
10723	}
10724	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10725	    bwn_led_duration[rate].off_dur);
10726}
10727
10728static void
10729bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10730{
10731	struct bwn_softc *sc = mac->mac_sc;
10732	struct bwn_led *led = sc->sc_blink_led;
10733	uint16_t val;
10734
10735	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10736	val = bwn_led_onoff(led, val, 1);
10737	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10738
10739	if (led->led_flags & BWN_LED_F_SLOW) {
10740		BWN_LED_SLOWDOWN(on_dur);
10741		BWN_LED_SLOWDOWN(off_dur);
10742	}
10743
10744	sc->sc_led_blinking = 1;
10745	sc->sc_led_blink_offdur = off_dur;
10746
10747	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10748}
10749
10750static void
10751bwn_led_blink_next(void *arg)
10752{
10753	struct bwn_mac *mac = arg;
10754	struct bwn_softc *sc = mac->mac_sc;
10755	uint16_t val;
10756
10757	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10758	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10759	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10760
10761	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10762	    bwn_led_blink_end, mac);
10763}
10764
10765static void
10766bwn_led_blink_end(void *arg)
10767{
10768	struct bwn_mac *mac = arg;
10769	struct bwn_softc *sc = mac->mac_sc;
10770
10771	sc->sc_led_blinking = 0;
10772}
10773
10774static int
10775bwn_suspend(device_t dev)
10776{
10777	struct bwn_softc *sc = device_get_softc(dev);
10778
10779	bwn_stop(sc, 1);
10780	return (0);
10781}
10782
10783static int
10784bwn_resume(device_t dev)
10785{
10786	struct bwn_softc *sc = device_get_softc(dev);
10787	struct ifnet *ifp = sc->sc_ifp;
10788
10789	if (ifp->if_flags & IFF_UP)
10790		bwn_init(sc);
10791	return (0);
10792}
10793
10794static void
10795bwn_rfswitch(void *arg)
10796{
10797	struct bwn_softc *sc = arg;
10798	struct bwn_mac *mac = sc->sc_curmac;
10799	int cur = 0, prev = 0;
10800
10801	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10802	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10803
10804	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10805		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10806			& BWN_RF_HWENABLED_HI_MASK))
10807			cur = 1;
10808	} else {
10809		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10810		    & BWN_RF_HWENABLED_LO_MASK)
10811			cur = 1;
10812	}
10813
10814	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10815		prev = 1;
10816
10817	if (cur != prev) {
10818		if (cur)
10819			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10820		else
10821			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10822
10823		device_printf(sc->sc_dev,
10824		    "status of RF switch is changed to %s\n",
10825		    cur ? "ON" : "OFF");
10826		if (cur != mac->mac_phy.rf_on) {
10827			if (cur)
10828				bwn_rf_turnon(mac);
10829			else
10830				bwn_rf_turnoff(mac);
10831		}
10832	}
10833
10834	callout_schedule(&sc->sc_rfswitch_ch, hz);
10835}
10836
10837static void
10838bwn_phy_lp_init_pre(struct bwn_mac *mac)
10839{
10840	struct bwn_phy *phy = &mac->mac_phy;
10841	struct bwn_phy_lp *plp = &phy->phy_lp;
10842
10843	plp->plp_antenna = BWN_ANT_DEFAULT;
10844}
10845
10846static int
10847bwn_phy_lp_init(struct bwn_mac *mac)
10848{
10849	static const struct bwn_stxtable tables[] = {
10850		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10851		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10852		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10853		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10854		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10855		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10856		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10857		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10858		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10859		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10860		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10861		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10862		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10863		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10864		{ 2, 11, 0x40, 0, 0x0f }
10865	};
10866	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10867	struct bwn_softc *sc = mac->mac_sc;
10868	const struct bwn_stxtable *st;
10869	struct ifnet *ifp = sc->sc_ifp;
10870	struct ieee80211com *ic = ifp->if_l2com;
10871	int i, error;
10872	uint16_t tmp;
10873
10874	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10875	bwn_phy_lp_bbinit(mac);
10876
10877	/* initialize RF */
10878	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10879	DELAY(1);
10880	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10881	DELAY(1);
10882
10883	if (mac->mac_phy.rf_ver == 0x2062)
10884		bwn_phy_lp_b2062_init(mac);
10885	else {
10886		bwn_phy_lp_b2063_init(mac);
10887
10888		/* synchronize stx table. */
10889		for (i = 0; i < N(tables); i++) {
10890			st = &tables[i];
10891			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10892			tmp >>= st->st_rfshift;
10893			tmp <<= st->st_physhift;
10894			BWN_PHY_SETMASK(mac,
10895			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10896			    ~(st->st_mask << st->st_physhift), tmp);
10897		}
10898
10899		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10900		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10901	}
10902
10903	/* calibrate RC */
10904	if (mac->mac_phy.rev >= 2)
10905		bwn_phy_lp_rxcal_r2(mac);
10906	else if (!plp->plp_rccap) {
10907		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10908			bwn_phy_lp_rccal_r12(mac);
10909	} else
10910		bwn_phy_lp_set_rccap(mac);
10911
10912	error = bwn_phy_lp_switch_channel(mac, 7);
10913	if (error)
10914		device_printf(sc->sc_dev,
10915		    "failed to change channel 7 (%d)\n", error);
10916	bwn_phy_lp_txpctl_init(mac);
10917	bwn_phy_lp_calib(mac);
10918	return (0);
10919}
10920
10921static uint16_t
10922bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10923{
10924
10925	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10926	return (BWN_READ_2(mac, BWN_PHYDATA));
10927}
10928
10929static void
10930bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10931{
10932
10933	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10934	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10935}
10936
10937static void
10938bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10939    uint16_t set)
10940{
10941
10942	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10943	BWN_WRITE_2(mac, BWN_PHYDATA,
10944	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10945}
10946
10947static uint16_t
10948bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10949{
10950
10951	KASSERT(reg != 1, ("unaccessible register %d", reg));
10952	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10953		reg |= 0x100;
10954	if (mac->mac_phy.rev >= 2)
10955		reg |= 0x200;
10956	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10957	return BWN_READ_2(mac, BWN_RFDATALO);
10958}
10959
10960static void
10961bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10962{
10963
10964	KASSERT(reg != 1, ("unaccessible register %d", reg));
10965	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10966	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10967}
10968
10969static void
10970bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10971{
10972
10973	if (on) {
10974		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10975		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10976		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10977		return;
10978	}
10979
10980	if (mac->mac_phy.rev >= 2) {
10981		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10982		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10983		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10984		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10985		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10986		return;
10987	}
10988
10989	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10990	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10991	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10992	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10993}
10994
10995static int
10996bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10997{
10998	struct bwn_phy *phy = &mac->mac_phy;
10999	struct bwn_phy_lp *plp = &phy->phy_lp;
11000	int error;
11001
11002	if (phy->rf_ver == 0x2063) {
11003		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11004		if (error)
11005			return (error);
11006	} else {
11007		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11008		if (error)
11009			return (error);
11010		bwn_phy_lp_set_anafilter(mac, chan);
11011		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11012	}
11013
11014	plp->plp_chan = chan;
11015	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11016	return (0);
11017}
11018
11019static uint32_t
11020bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11021{
11022	struct bwn_softc *sc = mac->mac_sc;
11023	struct ifnet *ifp = sc->sc_ifp;
11024	struct ieee80211com *ic = ifp->if_l2com;
11025
11026	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11027}
11028
11029static void
11030bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11031{
11032	struct bwn_phy *phy = &mac->mac_phy;
11033	struct bwn_phy_lp *plp = &phy->phy_lp;
11034
11035	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11036		return;
11037
11038	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11039	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11040	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11041	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11042	plp->plp_antenna = antenna;
11043}
11044
11045static void
11046bwn_phy_lp_task_60s(struct bwn_mac *mac)
11047{
11048
11049	bwn_phy_lp_calib(mac);
11050}
11051
11052static void
11053bwn_phy_lp_readsprom(struct bwn_mac *mac)
11054{
11055	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11056	struct bwn_softc *sc = mac->mac_sc;
11057	struct ifnet *ifp = sc->sc_ifp;
11058	struct ieee80211com *ic = ifp->if_l2com;
11059
11060	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11061		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11062		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11063		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11064		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11065		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11066		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11067		return;
11068	}
11069
11070	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11071	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11072	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11073	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11074	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11075	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11076	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11077	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11078}
11079
11080static void
11081bwn_phy_lp_bbinit(struct bwn_mac *mac)
11082{
11083
11084	bwn_phy_lp_tblinit(mac);
11085	if (mac->mac_phy.rev >= 2)
11086		bwn_phy_lp_bbinit_r2(mac);
11087	else
11088		bwn_phy_lp_bbinit_r01(mac);
11089}
11090
11091static void
11092bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11093{
11094	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11095	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11096	struct bwn_softc *sc = mac->mac_sc;
11097	struct ifnet *ifp = sc->sc_ifp;
11098	struct ieee80211com *ic = ifp->if_l2com;
11099
11100	bwn_phy_lp_set_txgain(mac,
11101	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11102	bwn_phy_lp_set_bbmult(mac, 150);
11103}
11104
11105static void
11106bwn_phy_lp_calib(struct bwn_mac *mac)
11107{
11108	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11109	struct bwn_softc *sc = mac->mac_sc;
11110	struct ifnet *ifp = sc->sc_ifp;
11111	struct ieee80211com *ic = ifp->if_l2com;
11112	const struct bwn_rxcompco *rc = NULL;
11113	struct bwn_txgain ogain;
11114	int i, omode, oafeovr, orf, obbmult;
11115	uint8_t mode, fc = 0;
11116
11117	if (plp->plp_chanfullcal != plp->plp_chan) {
11118		plp->plp_chanfullcal = plp->plp_chan;
11119		fc = 1;
11120	}
11121
11122	bwn_mac_suspend(mac);
11123
11124	/* BlueTooth Coexistance Override */
11125	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11126	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11127
11128	if (mac->mac_phy.rev >= 2)
11129		bwn_phy_lp_digflt_save(mac);
11130	bwn_phy_lp_get_txpctlmode(mac);
11131	mode = plp->plp_txpctlmode;
11132	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11133	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11134		bwn_phy_lp_bugfix(mac);
11135	if (mac->mac_phy.rev >= 2 && fc == 1) {
11136		bwn_phy_lp_get_txpctlmode(mac);
11137		omode = plp->plp_txpctlmode;
11138		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11139		if (oafeovr)
11140			ogain = bwn_phy_lp_get_txgain(mac);
11141		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11142		obbmult = bwn_phy_lp_get_bbmult(mac);
11143		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11144		if (oafeovr)
11145			bwn_phy_lp_set_txgain(mac, &ogain);
11146		bwn_phy_lp_set_bbmult(mac, obbmult);
11147		bwn_phy_lp_set_txpctlmode(mac, omode);
11148		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11149	}
11150	bwn_phy_lp_set_txpctlmode(mac, mode);
11151	if (mac->mac_phy.rev >= 2)
11152		bwn_phy_lp_digflt_restore(mac);
11153
11154	/* do RX IQ Calculation; assumes that noise is true. */
11155	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11156		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11157			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11158				rc = &bwn_rxcompco_5354[i];
11159		}
11160	} else if (mac->mac_phy.rev >= 2)
11161		rc = &bwn_rxcompco_r2;
11162	else {
11163		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11164			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11165				rc = &bwn_rxcompco_r12[i];
11166		}
11167	}
11168	if (rc == NULL)
11169		goto fail;
11170
11171	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11172	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11173
11174	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11175
11176	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11177		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11178		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11179	} else {
11180		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11181		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11182	}
11183
11184	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11185	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11186	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11187	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11188	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11189	bwn_phy_lp_set_deaf(mac, 0);
11190	/* XXX no checking return value? */
11191	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11192	bwn_phy_lp_clear_deaf(mac, 0);
11193	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11194	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11195	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11196
11197	/* disable RX GAIN override. */
11198	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11199	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11200	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11201	if (mac->mac_phy.rev >= 2) {
11202		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11203		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11204			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11205			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11206		}
11207	} else {
11208		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11209	}
11210
11211	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11212	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11213fail:
11214	bwn_mac_enable(mac);
11215}
11216
11217static void
11218bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11219{
11220
11221	if (on) {
11222		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11223		return;
11224	}
11225
11226	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11227	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11228}
11229
11230static int
11231bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11232{
11233	static const struct bwn_b206x_chan *bc = NULL;
11234	struct bwn_softc *sc = mac->mac_sc;
11235	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11236	    tmp[6];
11237	uint16_t old, scale, tmp16;
11238	int i, div;
11239
11240	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11241		if (bwn_b2063_chantable[i].bc_chan == chan) {
11242			bc = &bwn_b2063_chantable[i];
11243			break;
11244		}
11245	}
11246	if (bc == NULL)
11247		return (EINVAL);
11248
11249	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11250	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11251	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11252	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11253	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11254	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11255	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11256	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11257	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11258	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11259	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11260	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11261
11262	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11263	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11264
11265	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11266	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11267	freqref = freqxtal * 3;
11268	div = (freqxtal <= 26000000 ? 1 : 2);
11269	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11270	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11271		999999) / 1000000) + 1;
11272
11273	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11274	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11275	    0xfff8, timeout >> 2);
11276	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11277	    0xff9f,timeout << 5);
11278	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11279
11280	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11281	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11282	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11283
11284	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11285	    (timeoutref + 1)) - 1;
11286	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11287	    0xf0, count >> 8);
11288	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11289
11290	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11291	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11292	while (tmp[1] >= freqref) {
11293		tmp[0]++;
11294		tmp[1] -= freqref;
11295	}
11296	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11297	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11298	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11299	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11300	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11301
11302	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11303	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11304	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11305	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11306
11307	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11308	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11309
11310	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11311		scale = 1;
11312		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11313	} else {
11314		scale = 0;
11315		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11316	}
11317	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11318	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11319
11320	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11321	    (scale + 1);
11322	if (tmp[5] > 150)
11323		tmp[5] = 0;
11324
11325	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11326	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11327
11328	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11329	if (freqxtal > 26000000)
11330		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11331	else
11332		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11333
11334	if (val[0] == 45)
11335		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11336	else
11337		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11338
11339	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11340	DELAY(1);
11341	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11342
11343	/* VCO Calibration */
11344	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11345	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11346	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11347	DELAY(1);
11348	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11349	DELAY(1);
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11351	DELAY(1);
11352	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11353	DELAY(300);
11354	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11355
11356	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11357	return (0);
11358}
11359
11360static int
11361bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11362{
11363	struct bwn_softc *sc = mac->mac_sc;
11364	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11365	const struct bwn_b206x_chan *bc = NULL;
11366	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11367	uint32_t tmp[9];
11368	int i;
11369
11370	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11371		if (bwn_b2062_chantable[i].bc_chan == chan) {
11372			bc = &bwn_b2062_chantable[i];
11373			break;
11374		}
11375	}
11376
11377	if (bc == NULL)
11378		return (EINVAL);
11379
11380	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11381	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11382	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11383	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11384	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11385	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11386	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11387	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11388	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11389	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11390
11391	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11392	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11393	bwn_phy_lp_b2062_reset_pllbias(mac);
11394	tmp[0] = freqxtal / 1000;
11395	tmp[1] = plp->plp_div * 1000;
11396	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11397	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11398		tmp[2] *= 2;
11399	tmp[3] = 48 * tmp[0];
11400	tmp[5] = tmp[2] / tmp[3];
11401	tmp[6] = tmp[2] % tmp[3];
11402	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11403	tmp[4] = tmp[6] * 0x100;
11404	tmp[5] = tmp[4] / tmp[3];
11405	tmp[6] = tmp[4] % tmp[3];
11406	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11407	tmp[4] = tmp[6] * 0x100;
11408	tmp[5] = tmp[4] / tmp[3];
11409	tmp[6] = tmp[4] % tmp[3];
11410	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11411	tmp[4] = tmp[6] * 0x100;
11412	tmp[5] = tmp[4] / tmp[3];
11413	tmp[6] = tmp[4] % tmp[3];
11414	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11415	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11416	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11417	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11418	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11419	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11420
11421	bwn_phy_lp_b2062_vco_calib(mac);
11422	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11423		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11424		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11425		bwn_phy_lp_b2062_reset_pllbias(mac);
11426		bwn_phy_lp_b2062_vco_calib(mac);
11427		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11428			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11429			return (EIO);
11430		}
11431	}
11432	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11433	return (0);
11434}
11435
11436static void
11437bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11438{
11439	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11440	uint16_t tmp = (channel == 14);
11441
11442	if (mac->mac_phy.rev < 2) {
11443		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11444		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11445			bwn_phy_lp_set_rccap(mac);
11446		return;
11447	}
11448
11449	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11450}
11451
11452static void
11453bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11454{
11455	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11456	struct bwn_softc *sc = mac->mac_sc;
11457	struct ifnet *ifp = sc->sc_ifp;
11458	struct ieee80211com *ic = ifp->if_l2com;
11459	uint16_t iso, tmp[3];
11460
11461	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11462
11463	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11464		iso = plp->plp_txisoband_m;
11465	else if (freq <= 5320)
11466		iso = plp->plp_txisoband_l;
11467	else if (freq <= 5700)
11468		iso = plp->plp_txisoband_m;
11469	else
11470		iso = plp->plp_txisoband_h;
11471
11472	tmp[0] = ((iso - 26) / 12) << 12;
11473	tmp[1] = tmp[0] + 0x1000;
11474	tmp[2] = tmp[0] + 0x2000;
11475
11476	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11477	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11478}
11479
11480static void
11481bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11482{
11483	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11484	int i;
11485	static const uint16_t addr[] = {
11486		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11487		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11488		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11489		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11490		BWN_PHY_OFDM(0xcf),
11491	};
11492	static const uint16_t val[] = {
11493		0xde5e, 0xe832, 0xe331, 0x4d26,
11494		0x0026, 0x1420, 0x0020, 0xfe08,
11495		0x0008,
11496	};
11497
11498	for (i = 0; i < N(addr); i++) {
11499		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11500		BWN_PHY_WRITE(mac, addr[i], val[i]);
11501	}
11502}
11503
11504static void
11505bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11506{
11507	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11508	struct bwn_softc *sc = mac->mac_sc;
11509	uint16_t ctl;
11510
11511	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11512	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11513	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11514		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11515		break;
11516	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11517		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11518		break;
11519	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11520		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11521		break;
11522	default:
11523		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11524		device_printf(sc->sc_dev, "unknown command mode\n");
11525		break;
11526	}
11527}
11528
11529static void
11530bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11531{
11532	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11533	uint16_t ctl;
11534	uint8_t old;
11535
11536	bwn_phy_lp_get_txpctlmode(mac);
11537	old = plp->plp_txpctlmode;
11538	if (old == mode)
11539		return;
11540	plp->plp_txpctlmode = mode;
11541
11542	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11543		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11544		    plp->plp_tssiidx);
11545		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11546		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11547
11548		/* disable TX GAIN override */
11549		if (mac->mac_phy.rev < 2)
11550			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11551		else {
11552			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11553			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11554		}
11555		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11556
11557		plp->plp_txpwridx = -1;
11558	}
11559	if (mac->mac_phy.rev >= 2) {
11560		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11561			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11562		else
11563			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11564	}
11565
11566	/* writes TX Power Control mode */
11567	switch (plp->plp_txpctlmode) {
11568	case BWN_PHYLP_TXPCTL_OFF:
11569		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11570		break;
11571	case BWN_PHYLP_TXPCTL_ON_HW:
11572		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11573		break;
11574	case BWN_PHYLP_TXPCTL_ON_SW:
11575		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11576		break;
11577	default:
11578		ctl = 0;
11579		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11580	}
11581	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11582	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11583}
11584
11585static void
11586bwn_phy_lp_bugfix(struct bwn_mac *mac)
11587{
11588	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11589	struct bwn_softc *sc = mac->mac_sc;
11590	const unsigned int size = 256;
11591	struct bwn_txgain tg;
11592	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11593	uint16_t tssinpt, tssiidx, value[2];
11594	uint8_t mode;
11595	int8_t txpwridx;
11596
11597	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11598	    M_NOWAIT | M_ZERO);
11599	if (tabs == NULL) {
11600		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11601		return;
11602	}
11603
11604	bwn_phy_lp_get_txpctlmode(mac);
11605	mode = plp->plp_txpctlmode;
11606	txpwridx = plp->plp_txpwridx;
11607	tssinpt = plp->plp_tssinpt;
11608	tssiidx = plp->plp_tssiidx;
11609
11610	bwn_tab_read_multi(mac,
11611	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11612	    BWN_TAB_4(7, 0x140), size, tabs);
11613
11614	bwn_phy_lp_tblinit(mac);
11615	bwn_phy_lp_bbinit(mac);
11616	bwn_phy_lp_txpctl_init(mac);
11617	bwn_phy_lp_rf_onoff(mac, 1);
11618	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11619
11620	bwn_tab_write_multi(mac,
11621	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11622	    BWN_TAB_4(7, 0x140), size, tabs);
11623
11624	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11625	plp->plp_tssinpt = tssinpt;
11626	plp->plp_tssiidx = tssiidx;
11627	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11628	if (txpwridx != -1) {
11629		/* set TX power by index */
11630		plp->plp_txpwridx = txpwridx;
11631		bwn_phy_lp_get_txpctlmode(mac);
11632		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11633			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11634		if (mac->mac_phy.rev >= 2) {
11635			rxcomp = bwn_tab_read(mac,
11636			    BWN_TAB_4(7, txpwridx + 320));
11637			txgain = bwn_tab_read(mac,
11638			    BWN_TAB_4(7, txpwridx + 192));
11639			tg.tg_pad = (txgain >> 16) & 0xff;
11640			tg.tg_gm = txgain & 0xff;
11641			tg.tg_pga = (txgain >> 8) & 0xff;
11642			tg.tg_dac = (rxcomp >> 28) & 0xff;
11643			bwn_phy_lp_set_txgain(mac, &tg);
11644		} else {
11645			rxcomp = bwn_tab_read(mac,
11646			    BWN_TAB_4(10, txpwridx + 320));
11647			txgain = bwn_tab_read(mac,
11648			    BWN_TAB_4(10, txpwridx + 192));
11649			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11650			    0xf800, (txgain >> 4) & 0x7fff);
11651			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11652			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11653		}
11654		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11655
11656		/* set TX IQCC */
11657		value[0] = (rxcomp >> 10) & 0x3ff;
11658		value[1] = rxcomp & 0x3ff;
11659		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11660
11661		coeff = bwn_tab_read(mac,
11662		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11663		    BWN_TAB_4(10, txpwridx + 448));
11664		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11665		if (mac->mac_phy.rev >= 2) {
11666			rfpwr = bwn_tab_read(mac,
11667			    BWN_TAB_4(7, txpwridx + 576));
11668			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11669			    rfpwr & 0xffff);
11670		}
11671		bwn_phy_lp_set_txgain_override(mac);
11672	}
11673	if (plp->plp_rccap)
11674		bwn_phy_lp_set_rccap(mac);
11675	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11676	bwn_phy_lp_set_txpctlmode(mac, mode);
11677	free(tabs, M_DEVBUF);
11678}
11679
11680static void
11681bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11682{
11683	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11684	int i;
11685	static const uint16_t addr[] = {
11686		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11687		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11688		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11689		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11690		BWN_PHY_OFDM(0xcf),
11691	};
11692
11693	for (i = 0; i < N(addr); i++)
11694		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11695}
11696
11697static void
11698bwn_phy_lp_tblinit(struct bwn_mac *mac)
11699{
11700	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11701
11702	if (mac->mac_phy.rev < 2) {
11703		bwn_phy_lp_tblinit_r01(mac);
11704		bwn_phy_lp_tblinit_txgain(mac);
11705		bwn_phy_lp_set_gaintbl(mac, freq);
11706		return;
11707	}
11708
11709	bwn_phy_lp_tblinit_r2(mac);
11710	bwn_phy_lp_tblinit_txgain(mac);
11711}
11712
11713struct bwn_wpair {
11714	uint16_t		reg;
11715	uint16_t		value;
11716};
11717
11718struct bwn_smpair {
11719	uint16_t		offset;
11720	uint16_t		mask;
11721	uint16_t		set;
11722};
11723
11724static void
11725bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11726{
11727	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11728	struct bwn_softc *sc = mac->mac_sc;
11729	struct ifnet *ifp = sc->sc_ifp;
11730	struct ieee80211com *ic = ifp->if_l2com;
11731	static const struct bwn_wpair v1[] = {
11732		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11733		{ BWN_PHY_AFE_CTL, 0x8800 },
11734		{ BWN_PHY_AFE_CTL_OVR, 0 },
11735		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11736		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11737		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11738		{ BWN_PHY_OFDM(0xf9), 0 },
11739		{ BWN_PHY_TR_LOOKUP_1, 0 }
11740	};
11741	static const struct bwn_smpair v2[] = {
11742		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11743		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11744		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11745		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11746		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11747	};
11748	static const struct bwn_smpair v3[] = {
11749		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11750		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11751		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11752		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11753		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11754		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11755		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11756		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11757		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11758		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11759
11760	};
11761	int i;
11762
11763	for (i = 0; i < N(v1); i++)
11764		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11765	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11766	for (i = 0; i < N(v2); i++)
11767		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11768
11769	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11770	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11771	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11772	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11773		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11774		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11775	} else {
11776		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11777	}
11778	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11779	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11780	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11781	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11782	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11783	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11784	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11785	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11786	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11787	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11788	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11789	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11790	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11791		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11792		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11793	} else {
11794		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11795		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11796	}
11797	for (i = 0; i < N(v3); i++)
11798		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11799	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11800	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11801		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11802		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11803	}
11804
11805	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11806		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11807		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11808		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11809		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11810		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11811		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11812	} else
11813		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11814
11815	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11816	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11817	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11818	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11819	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11820	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11821	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11822	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11823	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11824
11825	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11826	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11827		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11828		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11829		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11830	}
11831
11832	bwn_phy_lp_digflt_save(mac);
11833}
11834
11835static void
11836bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11837{
11838	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11839	struct bwn_softc *sc = mac->mac_sc;
11840	struct ifnet *ifp = sc->sc_ifp;
11841	struct ieee80211com *ic = ifp->if_l2com;
11842	static const struct bwn_smpair v1[] = {
11843		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11844		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11845		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11846		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11847		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11848		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11849		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11850	};
11851	static const struct bwn_smpair v2[] = {
11852		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11853		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11854		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11855		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11856		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11857		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11858		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11859		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11860		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11861		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11862		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11863		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11864		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11865		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11866		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11867		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11868	};
11869	static const struct bwn_smpair v3[] = {
11870		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11871		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11872		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11873		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11874		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11875		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11876		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11877		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11878	};
11879	static const struct bwn_smpair v4[] = {
11880		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11881		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11882		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11883		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11884		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11885		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11886		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11887		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11888	};
11889	static const struct bwn_smpair v5[] = {
11890		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11891		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11892		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11893		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11894		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11895		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11896		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11897		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11898	};
11899	int i;
11900	uint16_t tmp, tmp2;
11901
11902	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11903	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11904	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11905	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11906	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11907	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11908	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11909	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11910	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11911	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11912	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11913	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11914	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11915	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11916	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11917	for (i = 0; i < N(v1); i++)
11918		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11919	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11920	    0xff00, plp->plp_rxpwroffset);
11921	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11922	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11923	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11924		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11925		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11926		if (mac->mac_phy.rev == 0)
11927			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11928			    0xffcf, 0x0010);
11929		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11930	} else {
11931		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11932		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11933		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11934	}
11935	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11936	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11937	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11938		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11939	else
11940		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11941	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11942	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11943	    0xfff9, (plp->plp_bxarch << 1));
11944	if (mac->mac_phy.rev == 1 &&
11945	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11946		for (i = 0; i < N(v2); i++)
11947			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11948			    v2[i].set);
11949	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11950	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11951	    ((mac->mac_phy.rev == 0) &&
11952	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11953		for (i = 0; i < N(v3); i++)
11954			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11955			    v3[i].set);
11956	} else if (mac->mac_phy.rev == 1 ||
11957		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11958		for (i = 0; i < N(v4); i++)
11959			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11960			    v4[i].set);
11961	} else {
11962		for (i = 0; i < N(v5); i++)
11963			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11964			    v5[i].set);
11965	}
11966	if (mac->mac_phy.rev == 1 &&
11967	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11968		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11969		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11970		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11971		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11972	}
11973	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11974	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11975	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11976		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11977		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11978		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11979		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11980	}
11981	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11982		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11983		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11984		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11985		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11986		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11987		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11988		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11989		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11990	} else {
11991		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11992		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11993	}
11994	if (mac->mac_phy.rev == 1) {
11995		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11996		tmp2 = (tmp & 0x03e0) >> 5;
11997		tmp2 |= tmp2 << 5;
11998		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11999		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12000		tmp2 = (tmp & 0x1f00) >> 8;
12001		tmp2 |= tmp2 << 5;
12002		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12003		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12004		tmp2 = tmp & 0x00ff;
12005		tmp2 |= tmp << 8;
12006		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12007	}
12008}
12009
12010struct bwn_b2062_freq {
12011	uint16_t		freq;
12012	uint8_t			value[6];
12013};
12014
12015static void
12016bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12017{
12018#define	CALC_CTL7(freq, div)						\
12019	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12020#define	CALC_CTL18(freq, div)						\
12021	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12022#define	CALC_CTL19(freq, div)						\
12023	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12024	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12025	struct bwn_softc *sc = mac->mac_sc;
12026	struct ifnet *ifp = sc->sc_ifp;
12027	struct ieee80211com *ic = ifp->if_l2com;
12028	static const struct bwn_b2062_freq freqdata_tab[] = {
12029		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12030		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12031		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12032		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12033		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12034		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12035	};
12036	static const struct bwn_wpair v1[] = {
12037		{ BWN_B2062_N_TXCTL3, 0 },
12038		{ BWN_B2062_N_TXCTL4, 0 },
12039		{ BWN_B2062_N_TXCTL5, 0 },
12040		{ BWN_B2062_N_TXCTL6, 0 },
12041		{ BWN_B2062_N_PDNCTL0, 0x40 },
12042		{ BWN_B2062_N_PDNCTL0, 0 },
12043		{ BWN_B2062_N_CALIB_TS, 0x10 },
12044		{ BWN_B2062_N_CALIB_TS, 0 }
12045	};
12046	const struct bwn_b2062_freq *f = NULL;
12047	uint32_t xtalfreq, ref;
12048	unsigned int i;
12049
12050	bwn_phy_lp_b2062_tblinit(mac);
12051
12052	for (i = 0; i < N(v1); i++)
12053		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12054	if (mac->mac_phy.rev > 0)
12055		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12056		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12057	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12058		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12059	else
12060		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12061
12062	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12063	    ("%s:%d: fail", __func__, __LINE__));
12064	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12065	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12066
12067	if (xtalfreq <= 30000000) {
12068		plp->plp_div = 1;
12069		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12070	} else {
12071		plp->plp_div = 2;
12072		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12073	}
12074
12075	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12076	    CALC_CTL7(xtalfreq, plp->plp_div));
12077	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12078	    CALC_CTL18(xtalfreq, plp->plp_div));
12079	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12080	    CALC_CTL19(xtalfreq, plp->plp_div));
12081
12082	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12083	ref &= 0xffff;
12084	for (i = 0; i < N(freqdata_tab); i++) {
12085		if (ref < freqdata_tab[i].freq) {
12086			f = &freqdata_tab[i];
12087			break;
12088		}
12089	}
12090	if (f == NULL)
12091		f = &freqdata_tab[N(freqdata_tab) - 1];
12092	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12093	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12094	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12095	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12096	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12097	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12098#undef CALC_CTL7
12099#undef CALC_CTL18
12100#undef CALC_CTL19
12101}
12102
12103static void
12104bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12105{
12106
12107	bwn_phy_lp_b2063_tblinit(mac);
12108	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12109	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12110	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12111	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12112	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12113	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12114	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12115	if (mac->mac_phy.rev == 2) {
12116		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12117		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12118		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12119	} else {
12120		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12121		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12122	}
12123}
12124
12125static void
12126bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12127{
12128	struct bwn_softc *sc = mac->mac_sc;
12129	static const struct bwn_wpair v1[] = {
12130		{ BWN_B2063_RX_BB_SP8, 0x0 },
12131		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12132		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12133		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12134		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12135		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12136		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12137		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12138	};
12139	static const struct bwn_wpair v2[] = {
12140		{ BWN_B2063_TX_BB_SP3, 0x0 },
12141		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12142		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12143		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12144		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12145	};
12146	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12147	int i;
12148	uint8_t tmp;
12149
12150	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12151
12152	for (i = 0; i < 2; i++)
12153		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12154	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12155	for (i = 2; i < N(v1); i++)
12156		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157	for (i = 0; i < 10000; i++) {
12158		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12159			break;
12160		DELAY(1000);
12161	}
12162
12163	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12164		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12165
12166	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12167
12168	for (i = 0; i < N(v2); i++)
12169		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12170	if (freqxtal == 24000000) {
12171		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12172		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12173	} else {
12174		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12175		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12176	}
12177	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12178	for (i = 0; i < 10000; i++) {
12179		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12180			break;
12181		DELAY(1000);
12182	}
12183	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12184		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12185	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12186}
12187
12188static void
12189bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12190{
12191	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12192	struct bwn_softc *sc = mac->mac_sc;
12193	struct bwn_phy_lp_iq_est ie;
12194	struct bwn_txgain tx_gains;
12195	static const uint32_t pwrtbl[21] = {
12196		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12197		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12198		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12199		0x0004c, 0x0002c, 0x0001a,
12200	};
12201	uint32_t npwr, ipwr, sqpwr, tmp;
12202	int loopback, i, j, sum, error;
12203	uint16_t save[7];
12204	uint8_t txo, bbmult, txpctlmode;
12205
12206	error = bwn_phy_lp_switch_channel(mac, 7);
12207	if (error)
12208		device_printf(sc->sc_dev,
12209		    "failed to change channel to 7 (%d)\n", error);
12210	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12211	bbmult = bwn_phy_lp_get_bbmult(mac);
12212	if (txo)
12213		tx_gains = bwn_phy_lp_get_txgain(mac);
12214
12215	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12216	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12217	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12218	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12219	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12220	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12221	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12222
12223	bwn_phy_lp_get_txpctlmode(mac);
12224	txpctlmode = plp->plp_txpctlmode;
12225	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12226
12227	/* disable CRS */
12228	bwn_phy_lp_set_deaf(mac, 1);
12229	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12230	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12231	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12232	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12233	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12234	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12235	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12236	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12237	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12238	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12239	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12240	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12241	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12242	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12243	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12244	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12245	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12246	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12247	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12248	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12249	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12250	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12251	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12252	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12253
12254	loopback = bwn_phy_lp_loopback(mac);
12255	if (loopback == -1)
12256		goto done;
12257	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12258	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12259	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12260	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12261	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12262
12263	tmp = 0;
12264	memset(&ie, 0, sizeof(ie));
12265	for (i = 128; i <= 159; i++) {
12266		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12267		sum = 0;
12268		for (j = 5; j <= 25; j++) {
12269			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12270			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12271				goto done;
12272			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12273			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12274			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12275			    12);
12276			sum += ((ipwr - npwr) * (ipwr - npwr));
12277			if ((i == 128) || (sum < tmp)) {
12278				plp->plp_rccap = i;
12279				tmp = sum;
12280			}
12281		}
12282	}
12283	bwn_phy_lp_ddfs_turnoff(mac);
12284done:
12285	/* restore CRS */
12286	bwn_phy_lp_clear_deaf(mac, 1);
12287	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12288	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12289
12290	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12291	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12292	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12293	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12294	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12295	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12296	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12297
12298	bwn_phy_lp_set_bbmult(mac, bbmult);
12299	if (txo)
12300		bwn_phy_lp_set_txgain(mac, &tx_gains);
12301	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12302	if (plp->plp_rccap)
12303		bwn_phy_lp_set_rccap(mac);
12304}
12305
12306static void
12307bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12308{
12309	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12310	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12311
12312	if (mac->mac_phy.rev == 1)
12313		rc_cap = MIN(rc_cap + 5, 15);
12314
12315	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12316	    MAX(plp->plp_rccap - 4, 0x80));
12317	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12318	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12319	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12320}
12321
12322static uint32_t
12323bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12324{
12325	uint32_t i, q, r;
12326
12327	if (div == 0)
12328		return (0);
12329
12330	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12331		q <<= 1;
12332		if (r << 1 >= div) {
12333			q++;
12334			r = (r << 1) - div;
12335		}
12336	}
12337	if (r << 1 >= div)
12338		q++;
12339	return (q);
12340}
12341
12342static void
12343bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12344{
12345	struct bwn_softc *sc = mac->mac_sc;
12346
12347	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12348	DELAY(20);
12349	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12350		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12351		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12352	} else {
12353		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12354	}
12355	DELAY(5);
12356}
12357
12358static void
12359bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12360{
12361
12362	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12363	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12364	DELAY(200);
12365}
12366
12367static void
12368bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12369{
12370#define	FLAG_A	0x01
12371#define	FLAG_G	0x02
12372	struct bwn_softc *sc = mac->mac_sc;
12373	struct ifnet *ifp = sc->sc_ifp;
12374	struct ieee80211com *ic = ifp->if_l2com;
12375	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12376		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12377		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12378		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12379		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12380		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12381		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12382		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12383		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12384		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12385		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12386		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12387		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12388		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12389		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12390		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12391		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12392		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12393		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12394		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12399		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12400		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12423	};
12424	const struct bwn_b206x_rfinit_entry *br;
12425	unsigned int i;
12426
12427	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12428		br = &bwn_b2062_init_tab[i];
12429		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12430			if (br->br_flags & FLAG_G)
12431				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12432		} else {
12433			if (br->br_flags & FLAG_A)
12434				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12435		}
12436	}
12437#undef FLAG_A
12438#undef FLAG_B
12439}
12440
12441static void
12442bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12443{
12444#define	FLAG_A	0x01
12445#define	FLAG_G	0x02
12446	struct bwn_softc *sc = mac->mac_sc;
12447	struct ifnet *ifp = sc->sc_ifp;
12448	struct ieee80211com *ic = ifp->if_l2com;
12449	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12450		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12451		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12452		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12453		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12454		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12455		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12456		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12457		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12458		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12459		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12460		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12461		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12462		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12463		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12464		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12465		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12466		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12467		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12468		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12469		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12470		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12471		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12472		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12473		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12474		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12475		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12476		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12477		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12478		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12479		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12480		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12482		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12483		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12484		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12485		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12487		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12488		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12491		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12492	};
12493	const struct bwn_b206x_rfinit_entry *br;
12494	unsigned int i;
12495
12496	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12497		br = &bwn_b2063_init_tab[i];
12498		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12499			if (br->br_flags & FLAG_G)
12500				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12501		} else {
12502			if (br->br_flags & FLAG_A)
12503				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12504		}
12505	}
12506#undef FLAG_A
12507#undef FLAG_B
12508}
12509
12510static void
12511bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12512    int count, void *_data)
12513{
12514	unsigned int i;
12515	uint32_t offset, type;
12516	uint8_t *data = _data;
12517
12518	type = BWN_TAB_GETTYPE(typenoffset);
12519	offset = BWN_TAB_GETOFFSET(typenoffset);
12520	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12521
12522	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12523
12524	for (i = 0; i < count; i++) {
12525		switch (type) {
12526		case BWN_TAB_8BIT:
12527			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12528			data++;
12529			break;
12530		case BWN_TAB_16BIT:
12531			*((uint16_t *)data) = BWN_PHY_READ(mac,
12532			    BWN_PHY_TABLEDATALO);
12533			data += 2;
12534			break;
12535		case BWN_TAB_32BIT:
12536			*((uint32_t *)data) = BWN_PHY_READ(mac,
12537			    BWN_PHY_TABLEDATAHI);
12538			*((uint32_t *)data) <<= 16;
12539			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12540			    BWN_PHY_TABLEDATALO);
12541			data += 4;
12542			break;
12543		default:
12544			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12545		}
12546	}
12547}
12548
12549static void
12550bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12551    int count, const void *_data)
12552{
12553	uint32_t offset, type, value;
12554	const uint8_t *data = _data;
12555	unsigned int i;
12556
12557	type = BWN_TAB_GETTYPE(typenoffset);
12558	offset = BWN_TAB_GETOFFSET(typenoffset);
12559	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12560
12561	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12562
12563	for (i = 0; i < count; i++) {
12564		switch (type) {
12565		case BWN_TAB_8BIT:
12566			value = *data;
12567			data++;
12568			KASSERT(!(value & ~0xff),
12569			    ("%s:%d: fail", __func__, __LINE__));
12570			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12571			break;
12572		case BWN_TAB_16BIT:
12573			value = *((const uint16_t *)data);
12574			data += 2;
12575			KASSERT(!(value & ~0xffff),
12576			    ("%s:%d: fail", __func__, __LINE__));
12577			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12578			break;
12579		case BWN_TAB_32BIT:
12580			value = *((const uint32_t *)data);
12581			data += 4;
12582			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12583			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12584			break;
12585		default:
12586			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12587		}
12588	}
12589}
12590
12591static struct bwn_txgain
12592bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12593{
12594	struct bwn_txgain tg;
12595	uint16_t tmp;
12596
12597	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12598	if (mac->mac_phy.rev < 2) {
12599		tmp = BWN_PHY_READ(mac,
12600		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12601		tg.tg_gm = tmp & 0x0007;
12602		tg.tg_pga = (tmp & 0x0078) >> 3;
12603		tg.tg_pad = (tmp & 0x780) >> 7;
12604		return (tg);
12605	}
12606
12607	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12608	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12609	tg.tg_gm = tmp & 0xff;
12610	tg.tg_pga = (tmp >> 8) & 0xff;
12611	return (tg);
12612}
12613
12614static uint8_t
12615bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12616{
12617
12618	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12619}
12620
12621static void
12622bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12623{
12624	uint16_t pa;
12625
12626	if (mac->mac_phy.rev < 2) {
12627		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12628		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12629		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12630		bwn_phy_lp_set_txgain_override(mac);
12631		return;
12632	}
12633
12634	pa = bwn_phy_lp_get_pa_gain(mac);
12635	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12636	    (tg->tg_pga << 8) | tg->tg_gm);
12637	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12638	    tg->tg_pad | (pa << 6));
12639	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12640	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12641	    tg->tg_pad | (pa << 8));
12642	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12643	bwn_phy_lp_set_txgain_override(mac);
12644}
12645
12646static void
12647bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12648{
12649
12650	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12651}
12652
12653static void
12654bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12655{
12656	uint16_t trsw = (tx << 1) | rx;
12657
12658	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12659	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12660}
12661
12662static void
12663bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12664{
12665	struct bwn_softc *sc = mac->mac_sc;
12666	struct ifnet *ifp = sc->sc_ifp;
12667	struct ieee80211com *ic = ifp->if_l2com;
12668	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12669
12670	if (mac->mac_phy.rev < 2) {
12671		trsw = gain & 0x1;
12672		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12673		ext_lna = (gain & 2) >> 1;
12674
12675		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12676		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12677		    0xfbff, ext_lna << 10);
12678		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12679		    0xf7ff, ext_lna << 11);
12680		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12681	} else {
12682		low_gain = gain & 0xffff;
12683		high_gain = (gain >> 16) & 0xf;
12684		ext_lna = (gain >> 21) & 0x1;
12685		trsw = ~(gain >> 20) & 0x1;
12686
12687		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12688		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12689		    0xfdff, ext_lna << 9);
12690		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12691		    0xfbff, ext_lna << 10);
12692		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12693		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12694		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12695			tmp = (gain >> 2) & 0x3;
12696			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12697			    0xe7ff, tmp<<11);
12698			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12699			    tmp << 3);
12700		}
12701	}
12702
12703	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12704	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12705	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12706	if (mac->mac_phy.rev >= 2) {
12707		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12708		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12709			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12710			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12711		}
12712		return;
12713	}
12714	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12715}
12716
12717static void
12718bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12719{
12720	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12721
12722	if (user)
12723		plp->plp_crsusr_off = 1;
12724	else
12725		plp->plp_crssys_off = 1;
12726
12727	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12728}
12729
12730static void
12731bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12732{
12733	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12734	struct bwn_softc *sc = mac->mac_sc;
12735	struct ifnet *ifp = sc->sc_ifp;
12736	struct ieee80211com *ic = ifp->if_l2com;
12737
12738	if (user)
12739		plp->plp_crsusr_off = 0;
12740	else
12741		plp->plp_crssys_off = 0;
12742
12743	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12744		return;
12745
12746	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12747		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12748	else
12749		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12750}
12751
12752static unsigned int
12753bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12754{
12755	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12756	static uint8_t sqrt_table[256] = {
12757		10, 14, 17, 20, 22, 24, 26, 28,
12758		30, 31, 33, 34, 36, 37, 38, 40,
12759		41, 42, 43, 44, 45, 46, 47, 48,
12760		50, 50, 51, 52, 53, 54, 55, 56,
12761		57, 58, 59, 60, 60, 61, 62, 63,
12762		64, 64, 65, 66, 67, 67, 68, 69,
12763		70, 70, 71, 72, 72, 73, 74, 74,
12764		75, 76, 76, 77, 78, 78, 79, 80,
12765		80, 81, 81, 82, 83, 83, 84, 84,
12766		85, 86, 86, 87, 87, 88, 88, 89,
12767		90, 90, 91, 91, 92, 92, 93, 93,
12768		94, 94, 95, 95, 96, 96, 97, 97,
12769		98, 98, 99, 100, 100, 100, 101, 101,
12770		102, 102, 103, 103, 104, 104, 105, 105,
12771		106, 106, 107, 107, 108, 108, 109, 109,
12772		110, 110, 110, 111, 111, 112, 112, 113,
12773		113, 114, 114, 114, 115, 115, 116, 116,
12774		117, 117, 117, 118, 118, 119, 119, 120,
12775		120, 120, 121, 121, 122, 122, 122, 123,
12776		123, 124, 124, 124, 125, 125, 126, 126,
12777		126, 127, 127, 128, 128, 128, 129, 129,
12778		130, 130, 130, 131, 131, 131, 132, 132,
12779		133, 133, 133, 134, 134, 134, 135, 135,
12780		136, 136, 136, 137, 137, 137, 138, 138,
12781		138, 139, 139, 140, 140, 140, 141, 141,
12782		141, 142, 142, 142, 143, 143, 143, 144,
12783		144, 144, 145, 145, 145, 146, 146, 146,
12784		147, 147, 147, 148, 148, 148, 149, 149,
12785		150, 150, 150, 150, 151, 151, 151, 152,
12786		152, 152, 153, 153, 153, 154, 154, 154,
12787		155, 155, 155, 156, 156, 156, 157, 157,
12788		157, 158, 158, 158, 159, 159, 159, 160
12789	};
12790
12791	if (x == 0)
12792		return (0);
12793	if (x >= 256) {
12794		unsigned int tmp;
12795
12796		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12797			/* do nothing */ ;
12798		return (tmp);
12799	}
12800	return (sqrt_table[x - 1] / 10);
12801}
12802
12803static int
12804bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12805{
12806#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12807	int _t;								\
12808	_t = _x - 20;							\
12809	if (_t >= 0) {							\
12810		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12811	} else {							\
12812		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12813	}								\
12814} while (0)
12815#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12816	int _t;								\
12817	_t = _x - 11;							\
12818	if (_t >= 0)							\
12819		_v = (_y << (31 - _x)) / (_z >> _t);			\
12820	else								\
12821		_v = (_y << (31 - _x)) / (_z << -_t);			\
12822} while (0)
12823	struct bwn_phy_lp_iq_est ie;
12824	uint16_t v0, v1;
12825	int tmp[2], ret;
12826
12827	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12828	v0 = v1 >> 8;
12829	v1 |= 0xff;
12830
12831	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12832	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12833
12834	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12835	if (ret == 0)
12836		goto done;
12837
12838	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12839		ret = 0;
12840		goto done;
12841	}
12842
12843	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12844	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12845
12846	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12847	v0 = tmp[0] >> 3;
12848	v1 = tmp[1] >> 4;
12849done:
12850	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12851	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12852	return ret;
12853#undef CALC_COEFF
12854#undef CALC_COEFF2
12855}
12856
12857static void
12858bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12859{
12860	static const uint16_t noisescale[] = {
12861		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12862		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12863		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12864		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12865		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12866	};
12867	static const uint16_t crsgainnft[] = {
12868		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12869		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12870		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12871		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12872		0x013d,
12873	};
12874	static const uint16_t filterctl[] = {
12875		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12876		0xff53, 0x0127,
12877	};
12878	static const uint32_t psctl[] = {
12879		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12880		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12881		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12882		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12883		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12884		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12885		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12886		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12887	};
12888	static const uint16_t ofdmcckgain_r0[] = {
12889		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12890		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12891		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12892		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12893		0x755d,
12894	};
12895	static const uint16_t ofdmcckgain_r1[] = {
12896		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12897		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12898		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12899		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12900		0x755d,
12901	};
12902	static const uint16_t gaindelta[] = {
12903		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12904		0x0000,
12905	};
12906	static const uint32_t txpwrctl[] = {
12907		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12908		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12909		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12910		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12911		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12912		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12913		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12914		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12915		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12916		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12917		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12918		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12919		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12920		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12921		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
12946		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12947		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12948		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12949		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12950		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12951		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12952		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12953		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12954		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12955		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12956		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12957		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12958		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12959		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12960		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12961		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12962		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12963		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12964		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12965		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12966		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12967		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12968		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12969		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12970		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12971		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12972		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
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, 0x000000ff, 0x000002fc,
12997		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12998		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12999		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13000		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13001		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13002		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13003		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13004		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13005		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13006		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13007		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13008		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13009		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13010		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13011		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13012		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13013		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13014		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13015		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13016		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13017		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13018		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13019		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13020		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13021		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13022		0x00000702,
13023	};
13024
13025	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13026
13027	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13028	    bwn_tab_sigsq_tbl);
13029	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13030	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13031	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13032	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13033	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13034	    bwn_tab_pllfrac_tbl);
13035	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13036	    bwn_tabl_iqlocal_tbl);
13037	if (mac->mac_phy.rev == 0) {
13038		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13039		    ofdmcckgain_r0);
13040		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13041		    ofdmcckgain_r0);
13042	} else {
13043		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13044		    ofdmcckgain_r1);
13045		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13046		    ofdmcckgain_r1);
13047	}
13048	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13049	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13050}
13051
13052static void
13053bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13054{
13055	struct bwn_softc *sc = mac->mac_sc;
13056	int i;
13057	static const uint16_t noisescale[] = {
13058		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13059		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13060		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13061		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13065	};
13066	static const uint32_t filterctl[] = {
13067		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13068		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13069	};
13070	static const uint32_t psctl[] = {
13071		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13072		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13073		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13074		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13075	};
13076	static const uint32_t gainidx[] = {
13077		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13078		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13079		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13080		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13081		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13082		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13083		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13084		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13085		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13086		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13087		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13088		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13089		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13090		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13091		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13092		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13093		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13094		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13095		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13096		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13097		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13098		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13099		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13100		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13101		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13102		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13103		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13104		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13105		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13106		0x0000001a, 0x64ca55ad, 0x0000001a
13107	};
13108	static const uint16_t auxgainidx[] = {
13109		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13110		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13111		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13112		0x0004, 0x0016
13113	};
13114	static const uint16_t swctl[] = {
13115		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13116		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13117		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13118		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13119		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13121		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13122		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13123	};
13124	static const uint8_t hf[] = {
13125		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13126		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13127	};
13128	static const uint32_t gainval[] = {
13129		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13130		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13131		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13132		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13133		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13134		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13135		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13136		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13137		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13138		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13139		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13140		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13141		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13142		0x000000f1, 0x00000000, 0x00000000
13143	};
13144	static const uint16_t gain[] = {
13145		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13146		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13147		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13148		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13149		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13150		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13151		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13152		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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	};
13158	static const uint32_t papdeps[] = {
13159		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13160		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13161		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13162		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13163		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13164		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13165		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13166		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13167		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13168		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13169		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13170		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13171		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13172	};
13173	static const uint32_t papdmult[] = {
13174		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13175		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13176		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13177		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13178		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13179		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13180		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13181		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13182		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13183		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13184		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13185		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13186		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13187	};
13188	static const uint32_t gainidx_a0[] = {
13189		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13190		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13191		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13192		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13193		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13194		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13195		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13196		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13197		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13198		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13199		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13200		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13201		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13202	};
13203	static const uint16_t auxgainidx_a0[] = {
13204		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13205		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13206		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13207		0x0002, 0x0014
13208	};
13209	static const uint32_t gainval_a0[] = {
13210		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13211		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13212		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13213		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13214		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13215		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13216		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13217		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13218		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13219		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13220		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13221		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13222		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13223		0x000000f7, 0x00000000, 0x00000000
13224	};
13225	static const uint16_t gain_a0[] = {
13226		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13227		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13228		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13229		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13230		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13231		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13232		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13233		0x0000, 0x0000, 0x0000, 0x0000, 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	};
13239
13240	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13241
13242	for (i = 0; i < 704; i++)
13243		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13244
13245	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13246	    bwn_tab_sigsq_tbl);
13247	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13248	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13249	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13250	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13251	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13252	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13253	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13254	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13255	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13256	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13257	    bwn_tab_pllfrac_tbl);
13258	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13259	    bwn_tabl_iqlocal_tbl);
13260	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13261	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13262
13263	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13264	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13265		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13266		    gainidx_a0);
13267		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13268		    auxgainidx_a0);
13269		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13270		    gainval_a0);
13271		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13272	}
13273}
13274
13275static void
13276bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13277{
13278	struct bwn_softc *sc = mac->mac_sc;
13279	struct ifnet *ifp = sc->sc_ifp;
13280	struct ieee80211com *ic = ifp->if_l2com;
13281	static struct bwn_txgain_entry txgain_r2[] = {
13282		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13283		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13284		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13285		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13286		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13287		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13288		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13289		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13290		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13291		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13292		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13293		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13294		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13295		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13296		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13297		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13298		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13299		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13300		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13301		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13302		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13303		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13304		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13305		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13306		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13307		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13308		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13309		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13310		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13311		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13312		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13313		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13314		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13315		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13316		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13317		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13318		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13319		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13320		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13321		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13322		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13323		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13324		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13325		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13326		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13327		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13328		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13329		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13330		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13331		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13332		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13333		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13334		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13335		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13336		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13337		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13338		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13339		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13340		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13341		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13342		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13343		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13344		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13345		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13346	};
13347	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13348		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13349		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13350		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13351		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13352		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13353		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13354		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13355		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13356		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13357		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13358		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13359		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13360		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13361		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13362		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13363		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13364		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13365		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13366		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13367		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13368		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13369		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13370		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13371		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13372		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13373		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13374		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13375		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13376		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13377		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13378		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13379		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13380		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13381		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13382		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13383		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13384		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13385		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13386		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13387		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13388		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13389		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13390		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13391		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13392		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13393		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13394		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13395		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13396		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13397		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13398		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13399		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13400		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13401		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13402		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13403		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13404		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13405		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13406		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13407		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13408		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13409		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13410		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13411		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13412	};
13413	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13414		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13415		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13416		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13417		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13418		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13419		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13420		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13421		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13422		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13423		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13424		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13425		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13426		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13427		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13428		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13429		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13430		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13431		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13432		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13433		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13434		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13435		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13436		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13437		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13438		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13439		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13440		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13441		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13442		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13443		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13444		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13445		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13446		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13447		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13448		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13449		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13450		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13451		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13452		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13453		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13454		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13455		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13456		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13457		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13458		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13459		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13460		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13461		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13462		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13463		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13464		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13465		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13466		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13467		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13468		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13469		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13470		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13471		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13472		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13473		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13474		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13475		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13476		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13477		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13478	};
13479	static struct bwn_txgain_entry txgain_r0[] = {
13480		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13481		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13482		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13483		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13484		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13485		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13486		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13487		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13488		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13489		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13490		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13491		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13492		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13493		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13494		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13495		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13496		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13497		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13498		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13499		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13500		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13501		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13502		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13503		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13504		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13505		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13506		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13507		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13508		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13509		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13510		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13511		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13512		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13513		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13514		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13515		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13516		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13517		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13518		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13519		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13520		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13521		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13522		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13523		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13524		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13525		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13526		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13527		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13528		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13529		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13530		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13531		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13532		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13533		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13534		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13535		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13536		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13537		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13538		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13539		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13540		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13541		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13542		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13543		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13544	};
13545	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13546		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13547		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13548		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13549		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13550		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13551		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13552		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13553		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13554		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13555		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13556		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13557		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13558		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13559		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13560		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13561		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13562		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13563		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13564		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13565		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13566		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13567		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13568		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13569		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13570		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13571		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13572		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13573		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13574		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13575		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13576		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13577		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13578		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13579		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13580		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13581		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13582		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13583		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13584		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13585		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13586		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13587		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13588		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13589		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13590		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13591		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13592		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13593		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13594		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13595		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13596		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13597		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13598		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13599		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13600		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13601		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13602		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13603		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13604		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13605		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13606		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13607		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13608		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13609		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13610	};
13611	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13612		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13613		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13614		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13615		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13616		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13617		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13618		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13619		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13620		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13621		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13622		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13623		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13624		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13625		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13626		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13627		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13628		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13629		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13630		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13631		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13632		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13633		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13634		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13635		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13636		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13637		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13638		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13639		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13640		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13641		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13642		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13643		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13644		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13645		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13646		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13647		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13648		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13649		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13650		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13651		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13652		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13653		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13654		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13655		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13656		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13657		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13658		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13659		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13660		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13661		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13662		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13663		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13664		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13665		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13666		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13667		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13668		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13669		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13670		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13671		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13672		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13673		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13674		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13675		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13676	};
13677	static struct bwn_txgain_entry txgain_r1[] = {
13678		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13679		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13680		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13681		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13682		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13683		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13684		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13685		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13686		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13687		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13688		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13689		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13690		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13691		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13692		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13693		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13694		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13695		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13696		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13697		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13698		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13699		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13700		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13701		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13702		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13703		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13704		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13705		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13706		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13707		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13708		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13709		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13710		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13711		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13712		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13713		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13714		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13715		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13716		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13717		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13718		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13719		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13720		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13721		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13722		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13723		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13724		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13725		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13726		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13727		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13728		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13729		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13730		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13731		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13732		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13733		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13734		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13735		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13736		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13737		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13738		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13739		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13740		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13741		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13742		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13743		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13744		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13745		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13746		{ 7, 11, 6, 0, 71 }
13747	};
13748	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13749		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13750		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13751		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13752		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13753		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13754		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13755		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13756		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13757		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13758		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13759		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13760		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13761		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13762		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13763		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13764		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13765		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13766		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13767		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13768		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13769		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13770		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13771		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13772		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13773		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13774		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13775		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13776		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13777		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13778		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13779		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13780		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13781		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13782		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13783		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13784		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13785		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13786		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13787		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13788		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13789		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13790		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13791		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13792		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13793		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13794		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13795		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13796		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13797		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13798		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13799		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13800		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13801		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13802		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13803		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13804		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13805		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13806		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13807		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13808		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13809		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13810		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13811		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13812		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13813	};
13814	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13815		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13816		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13817		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13818		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13819		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13820		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13821		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13822		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13823		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13824		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13825		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13826		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13827		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13828		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13829		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13830		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13831		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13832		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13833		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13834		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13835		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13836		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13837		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13838		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13839		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13840		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13841		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13842		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13843		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13844		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13845		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13846		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13847		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13848		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13849		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13850		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13851		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13852		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13853		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13854		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13855		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13856		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13857		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13858		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13859		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13860		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13861		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13862		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13863		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13864		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13865		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13866		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13867		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13868		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13869		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13870		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13871		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13872		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13873		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13874		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13875		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13876		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13877		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13878		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13879	};
13880
13881	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13882		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13883			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13884		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13885			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13886			    txgain_2ghz_r2);
13887		else
13888			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13889			    txgain_5ghz_r2);
13890		return;
13891	}
13892
13893	if (mac->mac_phy.rev == 0) {
13894		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13895		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13896			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13897		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13898			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13899			    txgain_2ghz_r0);
13900		else
13901			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902			    txgain_5ghz_r0);
13903		return;
13904	}
13905
13906	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13907	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13908		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13909	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13910		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13911	else
13912		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13913}
13914
13915static void
13916bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13917{
13918	uint32_t offset, type;
13919
13920	type = BWN_TAB_GETTYPE(typeoffset);
13921	offset = BWN_TAB_GETOFFSET(typeoffset);
13922	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13923
13924	switch (type) {
13925	case BWN_TAB_8BIT:
13926		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13927		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13928		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13929		break;
13930	case BWN_TAB_16BIT:
13931		KASSERT(!(value & ~0xffff),
13932		    ("%s:%d: fail", __func__, __LINE__));
13933		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13934		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13935		break;
13936	case BWN_TAB_32BIT:
13937		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13938		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13939		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13940		break;
13941	default:
13942		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13943	}
13944}
13945
13946static int
13947bwn_phy_lp_loopback(struct bwn_mac *mac)
13948{
13949	struct bwn_phy_lp_iq_est ie;
13950	int i, index = -1;
13951	uint32_t tmp;
13952
13953	memset(&ie, 0, sizeof(ie));
13954
13955	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13956	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13957	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13958	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13959	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13960	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13961	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13962	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13963	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13964	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13965	for (i = 0; i < 32; i++) {
13966		bwn_phy_lp_set_rxgain_idx(mac, i);
13967		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13968		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13969			continue;
13970		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13971		if ((tmp > 4000) && (tmp < 10000)) {
13972			index = i;
13973			break;
13974		}
13975	}
13976	bwn_phy_lp_ddfs_turnoff(mac);
13977	return (index);
13978}
13979
13980static void
13981bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13982{
13983
13984	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13985}
13986
13987static void
13988bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13989    int incr1, int incr2, int scale_idx)
13990{
13991
13992	bwn_phy_lp_ddfs_turnoff(mac);
13993	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13994	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13995	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13996	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13997	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13998	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13999	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14000	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14001	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14002	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14003}
14004
14005static uint8_t
14006bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14007    struct bwn_phy_lp_iq_est *ie)
14008{
14009	int i;
14010
14011	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14012	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14013	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14014	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14015	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14016
14017	for (i = 0; i < 500; i++) {
14018		if (!(BWN_PHY_READ(mac,
14019		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14020			break;
14021		DELAY(1000);
14022	}
14023	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14024		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14025		return 0;
14026	}
14027
14028	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14029	ie->ie_iqprod <<= 16;
14030	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14031	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14032	ie->ie_ipwr <<= 16;
14033	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14034	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14035	ie->ie_qpwr <<= 16;
14036	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14037
14038	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14039	return 1;
14040}
14041
14042static uint32_t
14043bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14044{
14045	uint32_t offset, type, value;
14046
14047	type = BWN_TAB_GETTYPE(typeoffset);
14048	offset = BWN_TAB_GETOFFSET(typeoffset);
14049	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14050
14051	switch (type) {
14052	case BWN_TAB_8BIT:
14053		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14054		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14055		break;
14056	case BWN_TAB_16BIT:
14057		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14058		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14059		break;
14060	case BWN_TAB_32BIT:
14061		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14062		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14063		value <<= 16;
14064		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14065		break;
14066	default:
14067		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14068		value = 0;
14069	}
14070
14071	return (value);
14072}
14073
14074static void
14075bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14076{
14077
14078	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14079	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14080}
14081
14082static void
14083bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14084{
14085	uint16_t ctl;
14086
14087	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14088	ctl |= dac << 7;
14089	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14090}
14091
14092static void
14093bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14094{
14095
14096	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14097	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14098}
14099
14100static void
14101bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14102{
14103
14104	if (mac->mac_phy.rev < 2)
14105		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14106	else {
14107		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14108		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14109	}
14110	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14111}
14112
14113static uint16_t
14114bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14115{
14116
14117	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14118}
14119
14120static uint8_t
14121bwn_nbits(int32_t val)
14122{
14123	uint32_t tmp;
14124	uint8_t nbits = 0;
14125
14126	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14127		nbits++;
14128	return (nbits);
14129}
14130
14131static void
14132bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14133    struct bwn_txgain_entry *table)
14134{
14135	int i;
14136
14137	for (i = offset; i < count; i++)
14138		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14139}
14140
14141static void
14142bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14143    struct bwn_txgain_entry data)
14144{
14145
14146	if (mac->mac_phy.rev >= 2)
14147		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14148	else
14149		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14150}
14151
14152static void
14153bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14154    struct bwn_txgain_entry te)
14155{
14156	struct bwn_softc *sc = mac->mac_sc;
14157	struct ifnet *ifp = sc->sc_ifp;
14158	struct ieee80211com *ic = ifp->if_l2com;
14159	uint32_t tmp;
14160
14161	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14162
14163	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14164	if (mac->mac_phy.rev >= 3) {
14165		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14166		    (0x10 << 24) : (0x70 << 24));
14167	} else {
14168		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14169		    (0x14 << 24) : (0x7f << 24));
14170	}
14171	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14172	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14173	    te.te_bbmult << 20 | te.te_dac << 28);
14174}
14175
14176static void
14177bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14178    struct bwn_txgain_entry te)
14179{
14180
14181	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14182
14183	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14184	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14185	    te.te_dac);
14186	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14187}
14188
14189static void
14190bwn_sysctl_node(struct bwn_softc *sc)
14191{
14192	device_t dev = sc->sc_dev;
14193	struct bwn_mac *mac;
14194	struct bwn_stats *stats;
14195
14196	/* XXX assume that count of MAC is only 1. */
14197
14198	if ((mac = sc->sc_curmac) == NULL)
14199		return;
14200	stats = &mac->mac_stats;
14201
14202	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14203	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14204	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14205	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14206	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14207	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14208	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14209	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14210	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14211
14212#ifdef BWN_DEBUG
14213	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14214	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14215	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14216#endif
14217}
14218
14219static device_method_t bwn_methods[] = {
14220	/* Device interface */
14221	DEVMETHOD(device_probe,		bwn_probe),
14222	DEVMETHOD(device_attach,	bwn_attach),
14223	DEVMETHOD(device_detach,	bwn_detach),
14224	DEVMETHOD(device_suspend,	bwn_suspend),
14225	DEVMETHOD(device_resume,	bwn_resume),
14226	DEVMETHOD_END
14227};
14228static driver_t bwn_driver = {
14229	"bwn",
14230	bwn_methods,
14231	sizeof(struct bwn_softc)
14232};
14233static devclass_t bwn_devclass;
14234DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14235MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14236MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14237MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14238MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14239