if_bwn.c revision 283537
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 283537 2015-05-25 18:50:26Z glebius $");
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 ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
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(ifp);
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 = ifp->if_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 ifnet *ifp)
2776{
2777	struct bwn_softc *sc = ifp->if_softc;
2778	struct ieee80211com *ic = ifp->if_l2com;
2779	struct bwn_mac *mac;
2780
2781	BWN_LOCK(sc);
2782	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2783		mac = (struct bwn_mac *)sc->sc_curmac;
2784		bwn_set_slot_time(mac,
2785		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2786	}
2787	BWN_UNLOCK(sc);
2788}
2789
2790/*
2791 * Callback from the 802.11 layer after a promiscuous mode change.
2792 * Note this interface does not check the operating mode as this
2793 * is an internal callback and we are expected to honor the current
2794 * state (e.g. this is used for setting the interface in promiscuous
2795 * mode when operating in hostap mode to do ACS).
2796 */
2797static void
2798bwn_update_promisc(struct ifnet *ifp)
2799{
2800	struct bwn_softc *sc = ifp->if_softc;
2801	struct bwn_mac *mac = sc->sc_curmac;
2802
2803	BWN_LOCK(sc);
2804	mac = sc->sc_curmac;
2805	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2806		if (ifp->if_flags & IFF_PROMISC)
2807			sc->sc_filters |= BWN_MACCTL_PROMISC;
2808		else
2809			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2810		bwn_set_opmode(mac);
2811	}
2812	BWN_UNLOCK(sc);
2813}
2814
2815/*
2816 * Callback from the 802.11 layer to update WME parameters.
2817 */
2818static int
2819bwn_wme_update(struct ieee80211com *ic)
2820{
2821	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2822	struct bwn_mac *mac = sc->sc_curmac;
2823	struct wmeParams *wmep;
2824	int i;
2825
2826	BWN_LOCK(sc);
2827	mac = sc->sc_curmac;
2828	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2829		bwn_mac_suspend(mac);
2830		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2831			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2832			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2833		}
2834		bwn_mac_enable(mac);
2835	}
2836	BWN_UNLOCK(sc);
2837	return (0);
2838}
2839
2840static void
2841bwn_scan_start(struct ieee80211com *ic)
2842{
2843	struct ifnet *ifp = ic->ic_ifp;
2844	struct bwn_softc *sc = ifp->if_softc;
2845	struct bwn_mac *mac;
2846
2847	BWN_LOCK(sc);
2848	mac = sc->sc_curmac;
2849	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2850		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2851		bwn_set_opmode(mac);
2852		/* disable CFP update during scan */
2853		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2854	}
2855	BWN_UNLOCK(sc);
2856}
2857
2858static void
2859bwn_scan_end(struct ieee80211com *ic)
2860{
2861	struct ifnet *ifp = ic->ic_ifp;
2862	struct bwn_softc *sc = ifp->if_softc;
2863	struct bwn_mac *mac;
2864
2865	BWN_LOCK(sc);
2866	mac = sc->sc_curmac;
2867	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2868		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2869		bwn_set_opmode(mac);
2870		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2871	}
2872	BWN_UNLOCK(sc);
2873}
2874
2875static void
2876bwn_set_channel(struct ieee80211com *ic)
2877{
2878	struct ifnet *ifp = ic->ic_ifp;
2879	struct bwn_softc *sc = ifp->if_softc;
2880	struct bwn_mac *mac = sc->sc_curmac;
2881	struct bwn_phy *phy = &mac->mac_phy;
2882	int chan, error;
2883
2884	BWN_LOCK(sc);
2885
2886	error = bwn_switch_band(sc, ic->ic_curchan);
2887	if (error)
2888		goto fail;
2889	bwn_mac_suspend(mac);
2890	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2891	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2892	if (chan != phy->chan)
2893		bwn_switch_channel(mac, chan);
2894
2895	/* TX power level */
2896	if (ic->ic_curchan->ic_maxpower != 0 &&
2897	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2898		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2899		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2900		    BWN_TXPWR_IGNORE_TSSI);
2901	}
2902
2903	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2904	if (phy->set_antenna)
2905		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2906
2907	if (sc->sc_rf_enabled != phy->rf_on) {
2908		if (sc->sc_rf_enabled) {
2909			bwn_rf_turnon(mac);
2910			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2911				device_printf(sc->sc_dev,
2912				    "please turn on the RF switch\n");
2913		} else
2914			bwn_rf_turnoff(mac);
2915	}
2916
2917	bwn_mac_enable(mac);
2918
2919fail:
2920	/*
2921	 * Setup radio tap channel freq and flags
2922	 */
2923	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2924		htole16(ic->ic_curchan->ic_freq);
2925	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2926		htole16(ic->ic_curchan->ic_flags & 0xffff);
2927
2928	BWN_UNLOCK(sc);
2929}
2930
2931static struct ieee80211vap *
2932bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2933    enum ieee80211_opmode opmode, int flags,
2934    const uint8_t bssid[IEEE80211_ADDR_LEN],
2935    const uint8_t mac0[IEEE80211_ADDR_LEN])
2936{
2937	struct ifnet *ifp = ic->ic_ifp;
2938	struct bwn_softc *sc = ifp->if_softc;
2939	struct ieee80211vap *vap;
2940	struct bwn_vap *bvp;
2941	uint8_t mac[IEEE80211_ADDR_LEN];
2942
2943	IEEE80211_ADDR_COPY(mac, mac0);
2944	switch (opmode) {
2945	case IEEE80211_M_HOSTAP:
2946	case IEEE80211_M_MBSS:
2947	case IEEE80211_M_STA:
2948	case IEEE80211_M_WDS:
2949	case IEEE80211_M_MONITOR:
2950	case IEEE80211_M_IBSS:
2951	case IEEE80211_M_AHDEMO:
2952		break;
2953	default:
2954		return (NULL);
2955	}
2956
2957	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2958
2959	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2960	    M_80211_VAP, M_NOWAIT | M_ZERO);
2961	if (bvp == NULL) {
2962		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2963		return (NULL);
2964	}
2965	vap = &bvp->bv_vap;
2966	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2967	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2968	/* override with driver methods */
2969	bvp->bv_newstate = vap->iv_newstate;
2970	vap->iv_newstate = bwn_newstate;
2971
2972	/* override max aid so sta's cannot assoc when we're out of sta id's */
2973	vap->iv_max_aid = BWN_STAID_MAX;
2974
2975	ieee80211_ratectl_init(vap);
2976
2977	/* complete setup */
2978	ieee80211_vap_attach(vap, ieee80211_media_change,
2979	    ieee80211_media_status);
2980	return (vap);
2981}
2982
2983static void
2984bwn_vap_delete(struct ieee80211vap *vap)
2985{
2986	struct bwn_vap *bvp = BWN_VAP(vap);
2987
2988	ieee80211_ratectl_deinit(vap);
2989	ieee80211_vap_detach(vap);
2990	free(bvp, M_80211_VAP);
2991}
2992
2993static void
2994bwn_init(void *arg)
2995{
2996	struct bwn_softc *sc = arg;
2997	struct ifnet *ifp = sc->sc_ifp;
2998	struct ieee80211com *ic = ifp->if_l2com;
2999	int error = 0;
3000
3001	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3002		__func__, ifp->if_flags);
3003
3004	BWN_LOCK(sc);
3005	error = bwn_init_locked(sc);
3006	BWN_UNLOCK(sc);
3007
3008	if (error == 0)
3009		ieee80211_start_all(ic);	/* start all vap's */
3010}
3011
3012static int
3013bwn_init_locked(struct bwn_softc *sc)
3014{
3015	struct bwn_mac *mac;
3016	struct ifnet *ifp = sc->sc_ifp;
3017	int error;
3018
3019	BWN_ASSERT_LOCKED(sc);
3020
3021	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3022	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3023	sc->sc_filters = 0;
3024	bwn_wme_clear(sc);
3025	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3026	sc->sc_rf_enabled = 1;
3027
3028	mac = sc->sc_curmac;
3029	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3030		error = bwn_core_init(mac);
3031		if (error != 0)
3032			return (error);
3033	}
3034	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3035		bwn_core_start(mac);
3036
3037	bwn_set_opmode(mac);
3038	bwn_set_pretbtt(mac);
3039	bwn_spu_setdelay(mac, 0);
3040	bwn_set_macaddr(mac);
3041
3042	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3043	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3044	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3045
3046	return (0);
3047}
3048
3049static void
3050bwn_stop(struct bwn_softc *sc, int statechg)
3051{
3052
3053	BWN_LOCK(sc);
3054	bwn_stop_locked(sc, statechg);
3055	BWN_UNLOCK(sc);
3056}
3057
3058static void
3059bwn_stop_locked(struct bwn_softc *sc, int statechg)
3060{
3061	struct bwn_mac *mac = sc->sc_curmac;
3062	struct ifnet *ifp = sc->sc_ifp;
3063
3064	BWN_ASSERT_LOCKED(sc);
3065
3066	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3067		/* XXX FIXME opmode not based on VAP */
3068		bwn_set_opmode(mac);
3069		bwn_set_macaddr(mac);
3070	}
3071
3072	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3073		bwn_core_stop(mac);
3074
3075	callout_stop(&sc->sc_led_blink_ch);
3076	sc->sc_led_blinking = 0;
3077
3078	bwn_core_exit(mac);
3079	sc->sc_rf_enabled = 0;
3080
3081	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3082}
3083
3084static void
3085bwn_wme_clear(struct bwn_softc *sc)
3086{
3087#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3088	struct wmeParams *p;
3089	unsigned int i;
3090
3091	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3092	    ("%s:%d: fail", __func__, __LINE__));
3093
3094	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3095		p = &(sc->sc_wmeParams[i]);
3096
3097		switch (bwn_wme_shm_offsets[i]) {
3098		case BWN_WME_VOICE:
3099			p->wmep_txopLimit = 0;
3100			p->wmep_aifsn = 2;
3101			/* XXX FIXME: log2(cwmin) */
3102			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3103			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3104			break;
3105		case BWN_WME_VIDEO:
3106			p->wmep_txopLimit = 0;
3107			p->wmep_aifsn = 2;
3108			/* XXX FIXME: log2(cwmin) */
3109			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3110			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3111			break;
3112		case BWN_WME_BESTEFFORT:
3113			p->wmep_txopLimit = 0;
3114			p->wmep_aifsn = 3;
3115			/* XXX FIXME: log2(cwmin) */
3116			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3117			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3118			break;
3119		case BWN_WME_BACKGROUND:
3120			p->wmep_txopLimit = 0;
3121			p->wmep_aifsn = 7;
3122			/* XXX FIXME: log2(cwmin) */
3123			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3124			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3125			break;
3126		default:
3127			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3128		}
3129	}
3130}
3131
3132static int
3133bwn_core_init(struct bwn_mac *mac)
3134{
3135	struct bwn_softc *sc = mac->mac_sc;
3136	uint64_t hf;
3137	int error;
3138
3139	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3140	    ("%s:%d: fail", __func__, __LINE__));
3141
3142	siba_powerup(sc->sc_dev, 0);
3143	if (!siba_dev_isup(sc->sc_dev))
3144		bwn_reset_core(mac,
3145		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3146
3147	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3148	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3149	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3150	BWN_GETTIME(mac->mac_phy.nexttime);
3151	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3152	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3153	mac->mac_stats.link_noise = -95;
3154	mac->mac_reason_intr = 0;
3155	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3156	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3157#ifdef BWN_DEBUG
3158	if (sc->sc_debug & BWN_DEBUG_XMIT)
3159		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3160#endif
3161	mac->mac_suspended = 1;
3162	mac->mac_task_state = 0;
3163	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3164
3165	mac->mac_phy.init_pre(mac);
3166
3167	siba_pcicore_intr(sc->sc_dev);
3168
3169	siba_fix_imcfglobug(sc->sc_dev);
3170	bwn_bt_disable(mac);
3171	if (mac->mac_phy.prepare_hw) {
3172		error = mac->mac_phy.prepare_hw(mac);
3173		if (error)
3174			goto fail0;
3175	}
3176	error = bwn_chip_init(mac);
3177	if (error)
3178		goto fail0;
3179	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3180	    siba_get_revid(sc->sc_dev));
3181	hf = bwn_hf_read(mac);
3182	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3183		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3184		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3185			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3186		if (mac->mac_phy.rev == 1)
3187			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3188	}
3189	if (mac->mac_phy.rf_ver == 0x2050) {
3190		if (mac->mac_phy.rf_rev < 6)
3191			hf |= BWN_HF_FORCE_VCO_RECALC;
3192		if (mac->mac_phy.rf_rev == 6)
3193			hf |= BWN_HF_4318_TSSI;
3194	}
3195	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3196		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3197	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3198	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3199		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3200	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3201	bwn_hf_write(mac, hf);
3202
3203	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3204	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3205	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3206	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3207
3208	bwn_rate_init(mac);
3209	bwn_set_phytxctl(mac);
3210
3211	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3212	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3213	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3214
3215	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3216		bwn_pio_init(mac);
3217	else
3218		bwn_dma_init(mac);
3219	bwn_wme_init(mac);
3220	bwn_spu_setdelay(mac, 1);
3221	bwn_bt_enable(mac);
3222
3223	siba_powerup(sc->sc_dev,
3224	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3225	bwn_set_macaddr(mac);
3226	bwn_crypt_init(mac);
3227
3228	/* XXX LED initializatin */
3229
3230	mac->mac_status = BWN_MAC_STATUS_INITED;
3231
3232	return (error);
3233
3234fail0:
3235	siba_powerdown(sc->sc_dev);
3236	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3237	    ("%s:%d: fail", __func__, __LINE__));
3238	return (error);
3239}
3240
3241static void
3242bwn_core_start(struct bwn_mac *mac)
3243{
3244	struct bwn_softc *sc = mac->mac_sc;
3245	uint32_t tmp;
3246
3247	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3248	    ("%s:%d: fail", __func__, __LINE__));
3249
3250	if (siba_get_revid(sc->sc_dev) < 5)
3251		return;
3252
3253	while (1) {
3254		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3255		if (!(tmp & 0x00000001))
3256			break;
3257		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3258	}
3259
3260	bwn_mac_enable(mac);
3261	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3262	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3263
3264	mac->mac_status = BWN_MAC_STATUS_STARTED;
3265}
3266
3267static void
3268bwn_core_exit(struct bwn_mac *mac)
3269{
3270	struct bwn_softc *sc = mac->mac_sc;
3271	uint32_t macctl;
3272
3273	BWN_ASSERT_LOCKED(mac->mac_sc);
3274
3275	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3276	    ("%s:%d: fail", __func__, __LINE__));
3277
3278	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3279		return;
3280	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3281
3282	macctl = BWN_READ_4(mac, BWN_MACCTL);
3283	macctl &= ~BWN_MACCTL_MCODE_RUN;
3284	macctl |= BWN_MACCTL_MCODE_JMP0;
3285	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3286
3287	bwn_dma_stop(mac);
3288	bwn_pio_stop(mac);
3289	bwn_chip_exit(mac);
3290	mac->mac_phy.switch_analog(mac, 0);
3291	siba_dev_down(sc->sc_dev, 0);
3292	siba_powerdown(sc->sc_dev);
3293}
3294
3295static void
3296bwn_bt_disable(struct bwn_mac *mac)
3297{
3298	struct bwn_softc *sc = mac->mac_sc;
3299
3300	(void)sc;
3301	/* XXX do nothing yet */
3302}
3303
3304static int
3305bwn_chip_init(struct bwn_mac *mac)
3306{
3307	struct bwn_softc *sc = mac->mac_sc;
3308	struct bwn_phy *phy = &mac->mac_phy;
3309	uint32_t macctl;
3310	int error;
3311
3312	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3313	if (phy->gmode)
3314		macctl |= BWN_MACCTL_GMODE;
3315	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3316
3317	error = bwn_fw_fillinfo(mac);
3318	if (error)
3319		return (error);
3320	error = bwn_fw_loaducode(mac);
3321	if (error)
3322		return (error);
3323
3324	error = bwn_gpio_init(mac);
3325	if (error)
3326		return (error);
3327
3328	error = bwn_fw_loadinitvals(mac);
3329	if (error) {
3330		siba_gpio_set(sc->sc_dev, 0);
3331		return (error);
3332	}
3333	phy->switch_analog(mac, 1);
3334	error = bwn_phy_init(mac);
3335	if (error) {
3336		siba_gpio_set(sc->sc_dev, 0);
3337		return (error);
3338	}
3339	if (phy->set_im)
3340		phy->set_im(mac, BWN_IMMODE_NONE);
3341	if (phy->set_antenna)
3342		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3343	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3344
3345	if (phy->type == BWN_PHYTYPE_B)
3346		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3347	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3348	if (siba_get_revid(sc->sc_dev) < 5)
3349		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3350
3351	BWN_WRITE_4(mac, BWN_MACCTL,
3352	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3353	BWN_WRITE_4(mac, BWN_MACCTL,
3354	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3355	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3356
3357	bwn_set_opmode(mac);
3358	if (siba_get_revid(sc->sc_dev) < 3) {
3359		BWN_WRITE_2(mac, 0x060e, 0x0000);
3360		BWN_WRITE_2(mac, 0x0610, 0x8000);
3361		BWN_WRITE_2(mac, 0x0604, 0x0000);
3362		BWN_WRITE_2(mac, 0x0606, 0x0200);
3363	} else {
3364		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3365		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3366	}
3367	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3368	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3369	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3370	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3371	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3372	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3373	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3374	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3375	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3376	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3377	return (error);
3378}
3379
3380/* read hostflags */
3381static uint64_t
3382bwn_hf_read(struct bwn_mac *mac)
3383{
3384	uint64_t ret;
3385
3386	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3387	ret <<= 16;
3388	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3389	ret <<= 16;
3390	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3391	return (ret);
3392}
3393
3394static void
3395bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3396{
3397
3398	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3399	    (value & 0x00000000ffffull));
3400	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3401	    (value & 0x0000ffff0000ull) >> 16);
3402	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3403	    (value & 0xffff00000000ULL) >> 32);
3404}
3405
3406static void
3407bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3408{
3409
3410	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3411	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3412}
3413
3414static void
3415bwn_rate_init(struct bwn_mac *mac)
3416{
3417
3418	switch (mac->mac_phy.type) {
3419	case BWN_PHYTYPE_A:
3420	case BWN_PHYTYPE_G:
3421	case BWN_PHYTYPE_LP:
3422	case BWN_PHYTYPE_N:
3423		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3424		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3425		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3427		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3428		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3429		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3430		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3431			break;
3432		/* FALLTHROUGH */
3433	case BWN_PHYTYPE_B:
3434		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3435		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3436		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3437		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3438		break;
3439	default:
3440		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3441	}
3442}
3443
3444static void
3445bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3446{
3447	uint16_t offset;
3448
3449	if (ofdm) {
3450		offset = 0x480;
3451		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3452	} else {
3453		offset = 0x4c0;
3454		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3455	}
3456	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3457	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3458}
3459
3460static uint8_t
3461bwn_plcp_getcck(const uint8_t bitrate)
3462{
3463
3464	switch (bitrate) {
3465	case BWN_CCK_RATE_1MB:
3466		return (0x0a);
3467	case BWN_CCK_RATE_2MB:
3468		return (0x14);
3469	case BWN_CCK_RATE_5MB:
3470		return (0x37);
3471	case BWN_CCK_RATE_11MB:
3472		return (0x6e);
3473	}
3474	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3475	return (0);
3476}
3477
3478static uint8_t
3479bwn_plcp_getofdm(const uint8_t bitrate)
3480{
3481
3482	switch (bitrate) {
3483	case BWN_OFDM_RATE_6MB:
3484		return (0xb);
3485	case BWN_OFDM_RATE_9MB:
3486		return (0xf);
3487	case BWN_OFDM_RATE_12MB:
3488		return (0xa);
3489	case BWN_OFDM_RATE_18MB:
3490		return (0xe);
3491	case BWN_OFDM_RATE_24MB:
3492		return (0x9);
3493	case BWN_OFDM_RATE_36MB:
3494		return (0xd);
3495	case BWN_OFDM_RATE_48MB:
3496		return (0x8);
3497	case BWN_OFDM_RATE_54MB:
3498		return (0xc);
3499	}
3500	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3501	return (0);
3502}
3503
3504static void
3505bwn_set_phytxctl(struct bwn_mac *mac)
3506{
3507	uint16_t ctl;
3508
3509	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3510	    BWN_TX_PHY_TXPWR);
3511	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3512	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3513	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3514}
3515
3516static void
3517bwn_pio_init(struct bwn_mac *mac)
3518{
3519	struct bwn_pio *pio = &mac->mac_method.pio;
3520
3521	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3522	    & ~BWN_MACCTL_BIGENDIAN);
3523	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3524
3525	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3526	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3527	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3528	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3529	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3530	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3531}
3532
3533static void
3534bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3535    int index)
3536{
3537	struct bwn_pio_txpkt *tp;
3538	struct bwn_softc *sc = mac->mac_sc;
3539	unsigned int i;
3540
3541	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3542	tq->tq_index = index;
3543
3544	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3545	if (siba_get_revid(sc->sc_dev) >= 8)
3546		tq->tq_size = 1920;
3547	else {
3548		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3549		tq->tq_size -= 80;
3550	}
3551
3552	TAILQ_INIT(&tq->tq_pktlist);
3553	for (i = 0; i < N(tq->tq_pkts); i++) {
3554		tp = &(tq->tq_pkts[i]);
3555		tp->tp_index = i;
3556		tp->tp_queue = tq;
3557		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3558	}
3559}
3560
3561static uint16_t
3562bwn_pio_idx2base(struct bwn_mac *mac, int index)
3563{
3564	struct bwn_softc *sc = mac->mac_sc;
3565	static const uint16_t bases[] = {
3566		BWN_PIO_BASE0,
3567		BWN_PIO_BASE1,
3568		BWN_PIO_BASE2,
3569		BWN_PIO_BASE3,
3570		BWN_PIO_BASE4,
3571		BWN_PIO_BASE5,
3572		BWN_PIO_BASE6,
3573		BWN_PIO_BASE7,
3574	};
3575	static const uint16_t bases_rev11[] = {
3576		BWN_PIO11_BASE0,
3577		BWN_PIO11_BASE1,
3578		BWN_PIO11_BASE2,
3579		BWN_PIO11_BASE3,
3580		BWN_PIO11_BASE4,
3581		BWN_PIO11_BASE5,
3582	};
3583
3584	if (siba_get_revid(sc->sc_dev) >= 11) {
3585		if (index >= N(bases_rev11))
3586			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3587		return (bases_rev11[index]);
3588	}
3589	if (index >= N(bases))
3590		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3591	return (bases[index]);
3592}
3593
3594static void
3595bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3596    int index)
3597{
3598	struct bwn_softc *sc = mac->mac_sc;
3599
3600	prq->prq_mac = mac;
3601	prq->prq_rev = siba_get_revid(sc->sc_dev);
3602	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3603	bwn_dma_rxdirectfifo(mac, index, 1);
3604}
3605
3606static void
3607bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3608{
3609	if (tq == NULL)
3610		return;
3611	bwn_pio_cancel_tx_packets(tq);
3612}
3613
3614static void
3615bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3616{
3617
3618	bwn_destroy_pioqueue_tx(pio);
3619}
3620
3621static uint16_t
3622bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3623    uint16_t offset)
3624{
3625
3626	return (BWN_READ_2(mac, tq->tq_base + offset));
3627}
3628
3629static void
3630bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3631{
3632	uint32_t ctl;
3633	int type;
3634	uint16_t base;
3635
3636	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3637	base = bwn_dma_base(type, idx);
3638	if (type == BWN_DMA_64BIT) {
3639		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3640		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3641		if (enable)
3642			ctl |= BWN_DMA64_RXDIRECTFIFO;
3643		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3644	} else {
3645		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3646		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3647		if (enable)
3648			ctl |= BWN_DMA32_RXDIRECTFIFO;
3649		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3650	}
3651}
3652
3653static uint64_t
3654bwn_dma_mask(struct bwn_mac *mac)
3655{
3656	uint32_t tmp;
3657	uint16_t base;
3658
3659	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3660	if (tmp & SIBA_TGSHIGH_DMA64)
3661		return (BWN_DMA_BIT_MASK(64));
3662	base = bwn_dma_base(0, 0);
3663	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3664	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3665	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3666		return (BWN_DMA_BIT_MASK(32));
3667
3668	return (BWN_DMA_BIT_MASK(30));
3669}
3670
3671static int
3672bwn_dma_mask2type(uint64_t dmamask)
3673{
3674
3675	if (dmamask == BWN_DMA_BIT_MASK(30))
3676		return (BWN_DMA_30BIT);
3677	if (dmamask == BWN_DMA_BIT_MASK(32))
3678		return (BWN_DMA_32BIT);
3679	if (dmamask == BWN_DMA_BIT_MASK(64))
3680		return (BWN_DMA_64BIT);
3681	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3682	return (BWN_DMA_30BIT);
3683}
3684
3685static void
3686bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3687{
3688	struct bwn_pio_txpkt *tp;
3689	unsigned int i;
3690
3691	for (i = 0; i < N(tq->tq_pkts); i++) {
3692		tp = &(tq->tq_pkts[i]);
3693		if (tp->tp_m) {
3694			m_freem(tp->tp_m);
3695			tp->tp_m = NULL;
3696		}
3697	}
3698}
3699
3700static uint16_t
3701bwn_dma_base(int type, int controller_idx)
3702{
3703	static const uint16_t map64[] = {
3704		BWN_DMA64_BASE0,
3705		BWN_DMA64_BASE1,
3706		BWN_DMA64_BASE2,
3707		BWN_DMA64_BASE3,
3708		BWN_DMA64_BASE4,
3709		BWN_DMA64_BASE5,
3710	};
3711	static const uint16_t map32[] = {
3712		BWN_DMA32_BASE0,
3713		BWN_DMA32_BASE1,
3714		BWN_DMA32_BASE2,
3715		BWN_DMA32_BASE3,
3716		BWN_DMA32_BASE4,
3717		BWN_DMA32_BASE5,
3718	};
3719
3720	if (type == BWN_DMA_64BIT) {
3721		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3722		    ("%s:%d: fail", __func__, __LINE__));
3723		return (map64[controller_idx]);
3724	}
3725	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3726	    ("%s:%d: fail", __func__, __LINE__));
3727	return (map32[controller_idx]);
3728}
3729
3730static void
3731bwn_dma_init(struct bwn_mac *mac)
3732{
3733	struct bwn_dma *dma = &mac->mac_method.dma;
3734
3735	/* setup TX DMA channels. */
3736	bwn_dma_setup(dma->wme[WME_AC_BK]);
3737	bwn_dma_setup(dma->wme[WME_AC_BE]);
3738	bwn_dma_setup(dma->wme[WME_AC_VI]);
3739	bwn_dma_setup(dma->wme[WME_AC_VO]);
3740	bwn_dma_setup(dma->mcast);
3741	/* setup RX DMA channel. */
3742	bwn_dma_setup(dma->rx);
3743}
3744
3745static struct bwn_dma_ring *
3746bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3747    int for_tx, int type)
3748{
3749	struct bwn_dma *dma = &mac->mac_method.dma;
3750	struct bwn_dma_ring *dr;
3751	struct bwn_dmadesc_generic *desc;
3752	struct bwn_dmadesc_meta *mt;
3753	struct bwn_softc *sc = mac->mac_sc;
3754	int error, i;
3755
3756	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3757	if (dr == NULL)
3758		goto out;
3759	dr->dr_numslots = BWN_RXRING_SLOTS;
3760	if (for_tx)
3761		dr->dr_numslots = BWN_TXRING_SLOTS;
3762
3763	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3764	    M_DEVBUF, M_NOWAIT | M_ZERO);
3765	if (dr->dr_meta == NULL)
3766		goto fail0;
3767
3768	dr->dr_type = type;
3769	dr->dr_mac = mac;
3770	dr->dr_base = bwn_dma_base(type, controller_index);
3771	dr->dr_index = controller_index;
3772	if (type == BWN_DMA_64BIT) {
3773		dr->getdesc = bwn_dma_64_getdesc;
3774		dr->setdesc = bwn_dma_64_setdesc;
3775		dr->start_transfer = bwn_dma_64_start_transfer;
3776		dr->suspend = bwn_dma_64_suspend;
3777		dr->resume = bwn_dma_64_resume;
3778		dr->get_curslot = bwn_dma_64_get_curslot;
3779		dr->set_curslot = bwn_dma_64_set_curslot;
3780	} else {
3781		dr->getdesc = bwn_dma_32_getdesc;
3782		dr->setdesc = bwn_dma_32_setdesc;
3783		dr->start_transfer = bwn_dma_32_start_transfer;
3784		dr->suspend = bwn_dma_32_suspend;
3785		dr->resume = bwn_dma_32_resume;
3786		dr->get_curslot = bwn_dma_32_get_curslot;
3787		dr->set_curslot = bwn_dma_32_set_curslot;
3788	}
3789	if (for_tx) {
3790		dr->dr_tx = 1;
3791		dr->dr_curslot = -1;
3792	} else {
3793		if (dr->dr_index == 0) {
3794			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3795			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3796		} else
3797			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3798	}
3799
3800	error = bwn_dma_allocringmemory(dr);
3801	if (error)
3802		goto fail2;
3803
3804	if (for_tx) {
3805		/*
3806		 * Assumption: BWN_TXRING_SLOTS can be divided by
3807		 * BWN_TX_SLOTS_PER_FRAME
3808		 */
3809		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3810		    ("%s:%d: fail", __func__, __LINE__));
3811
3812		dr->dr_txhdr_cache =
3813		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3814			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3815		KASSERT(dr->dr_txhdr_cache != NULL,
3816		    ("%s:%d: fail", __func__, __LINE__));
3817
3818		/*
3819		 * Create TX ring DMA stuffs
3820		 */
3821		error = bus_dma_tag_create(dma->parent_dtag,
3822				    BWN_ALIGN, 0,
3823				    BUS_SPACE_MAXADDR,
3824				    BUS_SPACE_MAXADDR,
3825				    NULL, NULL,
3826				    BWN_HDRSIZE(mac),
3827				    1,
3828				    BUS_SPACE_MAXSIZE_32BIT,
3829				    0,
3830				    NULL, NULL,
3831				    &dr->dr_txring_dtag);
3832		if (error) {
3833			device_printf(sc->sc_dev,
3834			    "can't create TX ring DMA tag: TODO frees\n");
3835			goto fail1;
3836		}
3837
3838		for (i = 0; i < dr->dr_numslots; i += 2) {
3839			dr->getdesc(dr, i, &desc, &mt);
3840
3841			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3842			mt->mt_m = NULL;
3843			mt->mt_ni = NULL;
3844			mt->mt_islast = 0;
3845			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3846			    &mt->mt_dmap);
3847			if (error) {
3848				device_printf(sc->sc_dev,
3849				     "can't create RX buf DMA map\n");
3850				goto fail1;
3851			}
3852
3853			dr->getdesc(dr, i + 1, &desc, &mt);
3854
3855			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3856			mt->mt_m = NULL;
3857			mt->mt_ni = NULL;
3858			mt->mt_islast = 1;
3859			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3860			    &mt->mt_dmap);
3861			if (error) {
3862				device_printf(sc->sc_dev,
3863				     "can't create RX buf DMA map\n");
3864				goto fail1;
3865			}
3866		}
3867	} else {
3868		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3869		    &dr->dr_spare_dmap);
3870		if (error) {
3871			device_printf(sc->sc_dev,
3872			    "can't create RX buf DMA map\n");
3873			goto out;		/* XXX wrong! */
3874		}
3875
3876		for (i = 0; i < dr->dr_numslots; i++) {
3877			dr->getdesc(dr, i, &desc, &mt);
3878
3879			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3880			    &mt->mt_dmap);
3881			if (error) {
3882				device_printf(sc->sc_dev,
3883				    "can't create RX buf DMA map\n");
3884				goto out;	/* XXX wrong! */
3885			}
3886			error = bwn_dma_newbuf(dr, desc, mt, 1);
3887			if (error) {
3888				device_printf(sc->sc_dev,
3889				    "failed to allocate RX buf\n");
3890				goto out;	/* XXX wrong! */
3891			}
3892		}
3893
3894		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3895		    BUS_DMASYNC_PREWRITE);
3896
3897		dr->dr_usedslot = dr->dr_numslots;
3898	}
3899
3900      out:
3901	return (dr);
3902
3903fail2:
3904	free(dr->dr_txhdr_cache, M_DEVBUF);
3905fail1:
3906	free(dr->dr_meta, M_DEVBUF);
3907fail0:
3908	free(dr, M_DEVBUF);
3909	return (NULL);
3910}
3911
3912static void
3913bwn_dma_ringfree(struct bwn_dma_ring **dr)
3914{
3915
3916	if (dr == NULL)
3917		return;
3918
3919	bwn_dma_free_descbufs(*dr);
3920	bwn_dma_free_ringmemory(*dr);
3921
3922	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3923	free((*dr)->dr_meta, M_DEVBUF);
3924	free(*dr, M_DEVBUF);
3925
3926	*dr = NULL;
3927}
3928
3929static void
3930bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3931    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3932{
3933	struct bwn_dmadesc32 *desc;
3934
3935	*meta = &(dr->dr_meta[slot]);
3936	desc = dr->dr_ring_descbase;
3937	desc = &(desc[slot]);
3938
3939	*gdesc = (struct bwn_dmadesc_generic *)desc;
3940}
3941
3942static void
3943bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3944    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3945    int start, int end, int irq)
3946{
3947	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3948	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3949	uint32_t addr, addrext, ctl;
3950	int slot;
3951
3952	slot = (int)(&(desc->dma.dma32) - descbase);
3953	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3954	    ("%s:%d: fail", __func__, __LINE__));
3955
3956	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3957	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3958	addr |= siba_dma_translation(sc->sc_dev);
3959	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3960	if (slot == dr->dr_numslots - 1)
3961		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3962	if (start)
3963		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3964	if (end)
3965		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3966	if (irq)
3967		ctl |= BWN_DMA32_DCTL_IRQ;
3968	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3969	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3970
3971	desc->dma.dma32.control = htole32(ctl);
3972	desc->dma.dma32.address = htole32(addr);
3973}
3974
3975static void
3976bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3977{
3978
3979	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3980	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3981}
3982
3983static void
3984bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3985{
3986
3987	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3988	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3989}
3990
3991static void
3992bwn_dma_32_resume(struct bwn_dma_ring *dr)
3993{
3994
3995	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3996	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3997}
3998
3999static int
4000bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4001{
4002	uint32_t val;
4003
4004	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4005	val &= BWN_DMA32_RXDPTR;
4006
4007	return (val / sizeof(struct bwn_dmadesc32));
4008}
4009
4010static void
4011bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4012{
4013
4014	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4015	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4016}
4017
4018static void
4019bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4020    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4021{
4022	struct bwn_dmadesc64 *desc;
4023
4024	*meta = &(dr->dr_meta[slot]);
4025	desc = dr->dr_ring_descbase;
4026	desc = &(desc[slot]);
4027
4028	*gdesc = (struct bwn_dmadesc_generic *)desc;
4029}
4030
4031static void
4032bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4033    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4034    int start, int end, int irq)
4035{
4036	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4037	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4038	int slot;
4039	uint32_t ctl0 = 0, ctl1 = 0;
4040	uint32_t addrlo, addrhi;
4041	uint32_t addrext;
4042
4043	slot = (int)(&(desc->dma.dma64) - descbase);
4044	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4045	    ("%s:%d: fail", __func__, __LINE__));
4046
4047	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4048	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4049	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4050	    30;
4051	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4052	if (slot == dr->dr_numslots - 1)
4053		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4054	if (start)
4055		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4056	if (end)
4057		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4058	if (irq)
4059		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4060	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4061	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4062	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4063
4064	desc->dma.dma64.control0 = htole32(ctl0);
4065	desc->dma.dma64.control1 = htole32(ctl1);
4066	desc->dma.dma64.address_low = htole32(addrlo);
4067	desc->dma.dma64.address_high = htole32(addrhi);
4068}
4069
4070static void
4071bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4072{
4073
4074	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4075	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4076}
4077
4078static void
4079bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4080{
4081
4082	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4083	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4084}
4085
4086static void
4087bwn_dma_64_resume(struct bwn_dma_ring *dr)
4088{
4089
4090	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4091	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4092}
4093
4094static int
4095bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4096{
4097	uint32_t val;
4098
4099	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4100	val &= BWN_DMA64_RXSTATDPTR;
4101
4102	return (val / sizeof(struct bwn_dmadesc64));
4103}
4104
4105static void
4106bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4107{
4108
4109	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4110	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4111}
4112
4113static int
4114bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4115{
4116	struct bwn_mac *mac = dr->dr_mac;
4117	struct bwn_dma *dma = &mac->mac_method.dma;
4118	struct bwn_softc *sc = mac->mac_sc;
4119	int error;
4120
4121	error = bus_dma_tag_create(dma->parent_dtag,
4122			    BWN_ALIGN, 0,
4123			    BUS_SPACE_MAXADDR,
4124			    BUS_SPACE_MAXADDR,
4125			    NULL, NULL,
4126			    BWN_DMA_RINGMEMSIZE,
4127			    1,
4128			    BUS_SPACE_MAXSIZE_32BIT,
4129			    0,
4130			    NULL, NULL,
4131			    &dr->dr_ring_dtag);
4132	if (error) {
4133		device_printf(sc->sc_dev,
4134		    "can't create TX ring DMA tag: TODO frees\n");
4135		return (-1);
4136	}
4137
4138	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4139	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4140	    &dr->dr_ring_dmap);
4141	if (error) {
4142		device_printf(sc->sc_dev,
4143		    "can't allocate DMA mem: TODO frees\n");
4144		return (-1);
4145	}
4146	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4147	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4148	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4149	if (error) {
4150		device_printf(sc->sc_dev,
4151		    "can't load DMA mem: TODO free\n");
4152		return (-1);
4153	}
4154
4155	return (0);
4156}
4157
4158static void
4159bwn_dma_setup(struct bwn_dma_ring *dr)
4160{
4161	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4162	uint64_t ring64;
4163	uint32_t addrext, ring32, value;
4164	uint32_t trans = siba_dma_translation(sc->sc_dev);
4165
4166	if (dr->dr_tx) {
4167		dr->dr_curslot = -1;
4168
4169		if (dr->dr_type == BWN_DMA_64BIT) {
4170			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4171			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4172			    >> 30;
4173			value = BWN_DMA64_TXENABLE;
4174			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4175			    & BWN_DMA64_TXADDREXT_MASK;
4176			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4177			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4178			    (ring64 & 0xffffffff));
4179			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4180			    ((ring64 >> 32) &
4181			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4182		} else {
4183			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4184			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4185			value = BWN_DMA32_TXENABLE;
4186			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4187			    & BWN_DMA32_TXADDREXT_MASK;
4188			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4189			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4190			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4191		}
4192		return;
4193	}
4194
4195	/*
4196	 * set for RX
4197	 */
4198	dr->dr_usedslot = dr->dr_numslots;
4199
4200	if (dr->dr_type == BWN_DMA_64BIT) {
4201		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4202		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4203		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4204		value |= BWN_DMA64_RXENABLE;
4205		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4206		    & BWN_DMA64_RXADDREXT_MASK;
4207		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4208		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4209		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4210		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4211		    | (trans << 1));
4212		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4213		    sizeof(struct bwn_dmadesc64));
4214	} else {
4215		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4216		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4217		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4218		value |= BWN_DMA32_RXENABLE;
4219		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4220		    & BWN_DMA32_RXADDREXT_MASK;
4221		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4222		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4223		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4224		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4225		    sizeof(struct bwn_dmadesc32));
4226	}
4227}
4228
4229static void
4230bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4231{
4232
4233	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4234	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4235	    dr->dr_ring_dmap);
4236}
4237
4238static void
4239bwn_dma_cleanup(struct bwn_dma_ring *dr)
4240{
4241
4242	if (dr->dr_tx) {
4243		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4244		if (dr->dr_type == BWN_DMA_64BIT) {
4245			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4246			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4247		} else
4248			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4249	} else {
4250		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4251		if (dr->dr_type == BWN_DMA_64BIT) {
4252			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4253			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4254		} else
4255			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4256	}
4257}
4258
4259static void
4260bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4261{
4262	struct bwn_dmadesc_generic *desc;
4263	struct bwn_dmadesc_meta *meta;
4264	struct bwn_mac *mac = dr->dr_mac;
4265	struct bwn_dma *dma = &mac->mac_method.dma;
4266	struct bwn_softc *sc = mac->mac_sc;
4267	int i;
4268
4269	if (!dr->dr_usedslot)
4270		return;
4271	for (i = 0; i < dr->dr_numslots; i++) {
4272		dr->getdesc(dr, i, &desc, &meta);
4273
4274		if (meta->mt_m == NULL) {
4275			if (!dr->dr_tx)
4276				device_printf(sc->sc_dev, "%s: not TX?\n",
4277				    __func__);
4278			continue;
4279		}
4280		if (dr->dr_tx) {
4281			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4282				bus_dmamap_unload(dr->dr_txring_dtag,
4283				    meta->mt_dmap);
4284			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4285				bus_dmamap_unload(dma->txbuf_dtag,
4286				    meta->mt_dmap);
4287		} else
4288			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4289		bwn_dma_free_descbuf(dr, meta);
4290	}
4291}
4292
4293static int
4294bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4295    int type)
4296{
4297	struct bwn_softc *sc = mac->mac_sc;
4298	uint32_t value;
4299	int i;
4300	uint16_t offset;
4301
4302	for (i = 0; i < 10; i++) {
4303		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4304		    BWN_DMA32_TXSTATUS;
4305		value = BWN_READ_4(mac, base + offset);
4306		if (type == BWN_DMA_64BIT) {
4307			value &= BWN_DMA64_TXSTAT;
4308			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4309			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4310			    value == BWN_DMA64_TXSTAT_STOPPED)
4311				break;
4312		} else {
4313			value &= BWN_DMA32_TXSTATE;
4314			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4315			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4316			    value == BWN_DMA32_TXSTAT_STOPPED)
4317				break;
4318		}
4319		DELAY(1000);
4320	}
4321	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4322	BWN_WRITE_4(mac, base + offset, 0);
4323	for (i = 0; i < 10; i++) {
4324		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4325						   BWN_DMA32_TXSTATUS;
4326		value = BWN_READ_4(mac, base + offset);
4327		if (type == BWN_DMA_64BIT) {
4328			value &= BWN_DMA64_TXSTAT;
4329			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4330				i = -1;
4331				break;
4332			}
4333		} else {
4334			value &= BWN_DMA32_TXSTATE;
4335			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4336				i = -1;
4337				break;
4338			}
4339		}
4340		DELAY(1000);
4341	}
4342	if (i != -1) {
4343		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4344		return (ENODEV);
4345	}
4346	DELAY(1000);
4347
4348	return (0);
4349}
4350
4351static int
4352bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4353    int type)
4354{
4355	struct bwn_softc *sc = mac->mac_sc;
4356	uint32_t value;
4357	int i;
4358	uint16_t offset;
4359
4360	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4361	BWN_WRITE_4(mac, base + offset, 0);
4362	for (i = 0; i < 10; i++) {
4363		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4364		    BWN_DMA32_RXSTATUS;
4365		value = BWN_READ_4(mac, base + offset);
4366		if (type == BWN_DMA_64BIT) {
4367			value &= BWN_DMA64_RXSTAT;
4368			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4369				i = -1;
4370				break;
4371			}
4372		} else {
4373			value &= BWN_DMA32_RXSTATE;
4374			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4375				i = -1;
4376				break;
4377			}
4378		}
4379		DELAY(1000);
4380	}
4381	if (i != -1) {
4382		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4383		return (ENODEV);
4384	}
4385
4386	return (0);
4387}
4388
4389static void
4390bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4391    struct bwn_dmadesc_meta *meta)
4392{
4393
4394	if (meta->mt_m != NULL) {
4395		m_freem(meta->mt_m);
4396		meta->mt_m = NULL;
4397	}
4398	if (meta->mt_ni != NULL) {
4399		ieee80211_free_node(meta->mt_ni);
4400		meta->mt_ni = NULL;
4401	}
4402}
4403
4404static void
4405bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4406{
4407	struct bwn_rxhdr4 *rxhdr;
4408	unsigned char *frame;
4409
4410	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4411	rxhdr->frame_len = 0;
4412
4413	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4414	    sizeof(struct bwn_plcp6) + 2,
4415	    ("%s:%d: fail", __func__, __LINE__));
4416	frame = mtod(m, char *) + dr->dr_frameoffset;
4417	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4418}
4419
4420static uint8_t
4421bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4422{
4423	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4424
4425	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4426	    == 0xff);
4427}
4428
4429static void
4430bwn_wme_init(struct bwn_mac *mac)
4431{
4432
4433	bwn_wme_load(mac);
4434
4435	/* enable WME support. */
4436	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4437	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4438	    BWN_IFSCTL_USE_EDCF);
4439}
4440
4441static void
4442bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4443{
4444	struct bwn_softc *sc = mac->mac_sc;
4445	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4446	uint16_t delay;	/* microsec */
4447
4448	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4449	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4450		delay = 500;
4451	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4452		delay = max(delay, (uint16_t)2400);
4453
4454	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4455}
4456
4457static void
4458bwn_bt_enable(struct bwn_mac *mac)
4459{
4460	struct bwn_softc *sc = mac->mac_sc;
4461	uint64_t hf;
4462
4463	if (bwn_bluetooth == 0)
4464		return;
4465	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4466		return;
4467	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4468		return;
4469
4470	hf = bwn_hf_read(mac);
4471	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4472		hf |= BWN_HF_BT_COEXISTALT;
4473	else
4474		hf |= BWN_HF_BT_COEXIST;
4475	bwn_hf_write(mac, hf);
4476}
4477
4478static void
4479bwn_set_macaddr(struct bwn_mac *mac)
4480{
4481
4482	bwn_mac_write_bssid(mac);
4483	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4484}
4485
4486static void
4487bwn_clear_keys(struct bwn_mac *mac)
4488{
4489	int i;
4490
4491	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4492		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4493		    ("%s:%d: fail", __func__, __LINE__));
4494
4495		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4496		    NULL, BWN_SEC_KEYSIZE, NULL);
4497		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4498			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4499			    NULL, BWN_SEC_KEYSIZE, NULL);
4500		}
4501		mac->mac_key[i].keyconf = NULL;
4502	}
4503}
4504
4505static void
4506bwn_crypt_init(struct bwn_mac *mac)
4507{
4508	struct bwn_softc *sc = mac->mac_sc;
4509
4510	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4511	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4512	    ("%s:%d: fail", __func__, __LINE__));
4513	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4514	mac->mac_ktp *= 2;
4515	if (siba_get_revid(sc->sc_dev) >= 5)
4516		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4517	bwn_clear_keys(mac);
4518}
4519
4520static void
4521bwn_chip_exit(struct bwn_mac *mac)
4522{
4523	struct bwn_softc *sc = mac->mac_sc;
4524
4525	bwn_phy_exit(mac);
4526	siba_gpio_set(sc->sc_dev, 0);
4527}
4528
4529static int
4530bwn_fw_fillinfo(struct bwn_mac *mac)
4531{
4532	int error;
4533
4534	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4535	if (error == 0)
4536		return (0);
4537	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4538	if (error == 0)
4539		return (0);
4540	return (error);
4541}
4542
4543static int
4544bwn_gpio_init(struct bwn_mac *mac)
4545{
4546	struct bwn_softc *sc = mac->mac_sc;
4547	uint32_t mask = 0x1f, set = 0xf, value;
4548
4549	BWN_WRITE_4(mac, BWN_MACCTL,
4550	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4551	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4552	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4553
4554	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4555		mask |= 0x0060;
4556		set |= 0x0060;
4557	}
4558	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4559		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4560		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4561		mask |= 0x0200;
4562		set |= 0x0200;
4563	}
4564	if (siba_get_revid(sc->sc_dev) >= 2)
4565		mask |= 0x0010;
4566
4567	value = siba_gpio_get(sc->sc_dev);
4568	if (value == -1)
4569		return (0);
4570	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4571
4572	return (0);
4573}
4574
4575static int
4576bwn_fw_loadinitvals(struct bwn_mac *mac)
4577{
4578#define	GETFWOFFSET(fwp, offset)				\
4579	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4580	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4581	const struct bwn_fwhdr *hdr;
4582	struct bwn_fw *fw = &mac->mac_fw;
4583	int error;
4584
4585	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4586	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4587	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4588	if (error)
4589		return (error);
4590	if (fw->initvals_band.fw) {
4591		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4592		error = bwn_fwinitvals_write(mac,
4593		    GETFWOFFSET(fw->initvals_band, hdr_len),
4594		    be32toh(hdr->size),
4595		    fw->initvals_band.fw->datasize - hdr_len);
4596	}
4597	return (error);
4598#undef GETFWOFFSET
4599}
4600
4601static int
4602bwn_phy_init(struct bwn_mac *mac)
4603{
4604	struct bwn_softc *sc = mac->mac_sc;
4605	int error;
4606
4607	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4608	mac->mac_phy.rf_onoff(mac, 1);
4609	error = mac->mac_phy.init(mac);
4610	if (error) {
4611		device_printf(sc->sc_dev, "PHY init failed\n");
4612		goto fail0;
4613	}
4614	error = bwn_switch_channel(mac,
4615	    mac->mac_phy.get_default_chan(mac));
4616	if (error) {
4617		device_printf(sc->sc_dev,
4618		    "failed to switch default channel\n");
4619		goto fail1;
4620	}
4621	return (0);
4622fail1:
4623	if (mac->mac_phy.exit)
4624		mac->mac_phy.exit(mac);
4625fail0:
4626	mac->mac_phy.rf_onoff(mac, 0);
4627
4628	return (error);
4629}
4630
4631static void
4632bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4633{
4634	uint16_t ant;
4635	uint16_t tmp;
4636
4637	ant = bwn_ant2phy(antenna);
4638
4639	/* For ACK/CTS */
4640	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4641	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4642	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4643	/* For Probe Resposes */
4644	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4645	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4646	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4647}
4648
4649static void
4650bwn_set_opmode(struct bwn_mac *mac)
4651{
4652	struct bwn_softc *sc = mac->mac_sc;
4653	struct ifnet *ifp = sc->sc_ifp;
4654	struct ieee80211com *ic = ifp->if_l2com;
4655	uint32_t ctl;
4656	uint16_t cfp_pretbtt;
4657
4658	ctl = BWN_READ_4(mac, BWN_MACCTL);
4659	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4660	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4661	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4662	ctl |= BWN_MACCTL_STA;
4663
4664	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4665	    ic->ic_opmode == IEEE80211_M_MBSS)
4666		ctl |= BWN_MACCTL_HOSTAP;
4667	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4668		ctl &= ~BWN_MACCTL_STA;
4669	ctl |= sc->sc_filters;
4670
4671	if (siba_get_revid(sc->sc_dev) <= 4)
4672		ctl |= BWN_MACCTL_PROMISC;
4673
4674	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4675
4676	cfp_pretbtt = 2;
4677	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4678		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4679		    siba_get_chiprev(sc->sc_dev) == 3)
4680			cfp_pretbtt = 100;
4681		else
4682			cfp_pretbtt = 50;
4683	}
4684	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4685}
4686
4687static int
4688bwn_dma_gettype(struct bwn_mac *mac)
4689{
4690	uint32_t tmp;
4691	uint16_t base;
4692
4693	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4694	if (tmp & SIBA_TGSHIGH_DMA64)
4695		return (BWN_DMA_64BIT);
4696	base = bwn_dma_base(0, 0);
4697	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4698	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4699	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4700		return (BWN_DMA_32BIT);
4701
4702	return (BWN_DMA_30BIT);
4703}
4704
4705static void
4706bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4707{
4708	if (!error) {
4709		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4710		*((bus_addr_t *)arg) = seg->ds_addr;
4711	}
4712}
4713
4714static void
4715bwn_phy_g_init_sub(struct bwn_mac *mac)
4716{
4717	struct bwn_phy *phy = &mac->mac_phy;
4718	struct bwn_phy_g *pg = &phy->phy_g;
4719	struct bwn_softc *sc = mac->mac_sc;
4720	uint16_t i, tmp;
4721
4722	if (phy->rev == 1)
4723		bwn_phy_init_b5(mac);
4724	else
4725		bwn_phy_init_b6(mac);
4726
4727	if (phy->rev >= 2 || phy->gmode)
4728		bwn_phy_init_a(mac);
4729
4730	if (phy->rev >= 2) {
4731		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4732		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4733	}
4734	if (phy->rev == 2) {
4735		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4736		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4737	}
4738	if (phy->rev > 5) {
4739		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4740		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4741	}
4742	if (phy->gmode || phy->rev >= 2) {
4743		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4744		tmp &= BWN_PHYVER_VERSION;
4745		if (tmp == 3 || tmp == 5) {
4746			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4747			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4748		}
4749		if (tmp == 5) {
4750			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4751			    0x1f00);
4752		}
4753	}
4754	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4755		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4756	if (phy->rf_rev == 8) {
4757		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4758		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4759	}
4760	if (BWN_HAS_LOOPBACK(phy))
4761		bwn_loopback_calcgain(mac);
4762
4763	if (phy->rf_rev != 8) {
4764		if (pg->pg_initval == 0xffff)
4765			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4766		else
4767			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4768	}
4769	bwn_lo_g_init(mac);
4770	if (BWN_HAS_TXMAG(phy)) {
4771		BWN_RF_WRITE(mac, 0x52,
4772		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4773		    | pg->pg_loctl.tx_bias |
4774		    pg->pg_loctl.tx_magn);
4775	} else {
4776		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4777	}
4778	if (phy->rev >= 6) {
4779		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4780		    (pg->pg_loctl.tx_bias << 12));
4781	}
4782	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4783		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4784	else
4785		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4786	if (phy->rev < 2)
4787		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4788	else
4789		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4790	if (phy->gmode || phy->rev >= 2) {
4791		bwn_lo_g_adjust(mac);
4792		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4793	}
4794
4795	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4796		for (i = 0; i < 64; i++) {
4797			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4798			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4799			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4800			    -32), 31));
4801		}
4802		bwn_nrssi_threshold(mac);
4803	} else if (phy->gmode || phy->rev >= 2) {
4804		if (pg->pg_nrssi[0] == -1000) {
4805			KASSERT(pg->pg_nrssi[1] == -1000,
4806			    ("%s:%d: fail", __func__, __LINE__));
4807			bwn_nrssi_slope_11g(mac);
4808		} else
4809			bwn_nrssi_threshold(mac);
4810	}
4811	if (phy->rf_rev == 8)
4812		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4813	bwn_phy_hwpctl_init(mac);
4814	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4815	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4816		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4817		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4818	}
4819}
4820
4821static uint8_t
4822bwn_has_hwpctl(struct bwn_mac *mac)
4823{
4824
4825	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4826		return (0);
4827	return (mac->mac_phy.use_hwpctl(mac));
4828}
4829
4830static void
4831bwn_phy_init_b5(struct bwn_mac *mac)
4832{
4833	struct bwn_phy *phy = &mac->mac_phy;
4834	struct bwn_phy_g *pg = &phy->phy_g;
4835	struct bwn_softc *sc = mac->mac_sc;
4836	uint16_t offset, value;
4837	uint8_t old_channel;
4838
4839	if (phy->analog == 1)
4840		BWN_RF_SET(mac, 0x007a, 0x0050);
4841	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4842	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4843		value = 0x2120;
4844		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4845			BWN_PHY_WRITE(mac, offset, value);
4846			value += 0x202;
4847		}
4848	}
4849	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4850	if (phy->rf_ver == 0x2050)
4851		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4852
4853	if (phy->gmode || phy->rev >= 2) {
4854		if (phy->rf_ver == 0x2050) {
4855			BWN_RF_SET(mac, 0x007a, 0x0020);
4856			BWN_RF_SET(mac, 0x0051, 0x0004);
4857		}
4858		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4859
4860		BWN_PHY_SET(mac, 0x0802, 0x0100);
4861		BWN_PHY_SET(mac, 0x042b, 0x2000);
4862
4863		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4864
4865		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4866		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4867		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4868	}
4869
4870	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4871		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4872
4873	if (phy->analog == 1) {
4874		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4875		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4876		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4877		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4878		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4879	} else
4880		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4881	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4882	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4883
4884	if (phy->analog == 1)
4885		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4886	else
4887		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4888
4889	if (phy->analog == 0)
4890		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4891
4892	old_channel = phy->chan;
4893	bwn_phy_g_switch_chan(mac, 7, 0);
4894
4895	if (phy->rf_ver != 0x2050) {
4896		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4897		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4898	}
4899
4900	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4901	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4902
4903	if (phy->rf_ver == 0x2050) {
4904		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4905		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4906	}
4907
4908	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4909	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4910	BWN_RF_SET(mac, 0x007a, 0x0007);
4911
4912	bwn_phy_g_switch_chan(mac, old_channel, 0);
4913	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4914	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4915	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4916
4917	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4918	    pg->pg_txctl);
4919
4920	if (phy->rf_ver == 0x2050)
4921		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4922
4923	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4924}
4925
4926static void
4927bwn_loopback_calcgain(struct bwn_mac *mac)
4928{
4929	struct bwn_phy *phy = &mac->mac_phy;
4930	struct bwn_phy_g *pg = &phy->phy_g;
4931	struct bwn_softc *sc = mac->mac_sc;
4932	uint16_t backup_phy[16] = { 0 };
4933	uint16_t backup_radio[3];
4934	uint16_t backup_bband;
4935	uint16_t i, j, loop_i_max;
4936	uint16_t trsw_rx;
4937	uint16_t loop1_outer_done, loop1_inner_done;
4938
4939	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4940	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4941	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4942	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4943	if (phy->rev != 1) {
4944		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4945		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4946	}
4947	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4948	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4949	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4950	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4951	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4952	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4953	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4954	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4955	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4956	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4957	backup_bband = pg->pg_bbatt.att;
4958	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4959	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4960	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4961
4962	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4963	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4964	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4965	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4966	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4967	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4968	if (phy->rev != 1) {
4969		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4970		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4971		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4972		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4973	}
4974	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4975	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4976	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4977	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4978
4979	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4980	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4981	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4982
4983	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4984	if (phy->rev != 1) {
4985		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4986		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4987	}
4988	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4989
4990	if (phy->rf_rev == 8)
4991		BWN_RF_WRITE(mac, 0x43, 0x000f);
4992	else {
4993		BWN_RF_WRITE(mac, 0x52, 0);
4994		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4995	}
4996	bwn_phy_g_set_bbatt(mac, 11);
4997
4998	if (phy->rev >= 3)
4999		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5000	else
5001		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5002	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5003
5004	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5005	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5006
5007	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5008	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5009
5010	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5011		if (phy->rev >= 7) {
5012			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5013			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5014		}
5015	}
5016	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5017
5018	j = 0;
5019	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5020	for (i = 0; i < loop_i_max; i++) {
5021		for (j = 0; j < 16; j++) {
5022			BWN_RF_WRITE(mac, 0x43, i);
5023			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5024			    (j << 8));
5025			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5026			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5027			DELAY(20);
5028			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5029				goto done0;
5030		}
5031	}
5032done0:
5033	loop1_outer_done = i;
5034	loop1_inner_done = j;
5035	if (j >= 8) {
5036		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5037		trsw_rx = 0x1b;
5038		for (j = j - 8; j < 16; j++) {
5039			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5040			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5041			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5042			DELAY(20);
5043			trsw_rx -= 3;
5044			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5045				goto done1;
5046		}
5047	} else
5048		trsw_rx = 0x18;
5049done1:
5050
5051	if (phy->rev != 1) {
5052		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5053		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5054	}
5055	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5056	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5061	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5062	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5063	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5064
5065	bwn_phy_g_set_bbatt(mac, backup_bband);
5066
5067	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5068	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5069	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5070
5071	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5072	DELAY(10);
5073	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5074	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5075	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5076	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5077
5078	pg->pg_max_lb_gain =
5079	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5080	pg->pg_trsw_rx_gain = trsw_rx * 2;
5081}
5082
5083static uint16_t
5084bwn_rf_init_bcm2050(struct bwn_mac *mac)
5085{
5086	struct bwn_phy *phy = &mac->mac_phy;
5087	uint32_t tmp1 = 0, tmp2 = 0;
5088	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5089	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5090	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5091	static const uint8_t rcc_table[] = {
5092		0x02, 0x03, 0x01, 0x0f,
5093		0x06, 0x07, 0x05, 0x0f,
5094		0x0a, 0x0b, 0x09, 0x0f,
5095		0x0e, 0x0f, 0x0d, 0x0f,
5096	};
5097
5098	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5099	    rfoverval = rfover = cck3 = 0;
5100	radio0 = BWN_RF_READ(mac, 0x43);
5101	radio1 = BWN_RF_READ(mac, 0x51);
5102	radio2 = BWN_RF_READ(mac, 0x52);
5103	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5104	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5105	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5106	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5107
5108	if (phy->type == BWN_PHYTYPE_B) {
5109		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5110		reg0 = BWN_READ_2(mac, 0x3ec);
5111
5112		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5113		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5114	} else if (phy->gmode || phy->rev >= 2) {
5115		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5116		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5117		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5118		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5119		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5120		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5121
5122		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5123		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5124		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5125		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5126		if (BWN_HAS_LOOPBACK(phy)) {
5127			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5128			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5129			if (phy->rev >= 3)
5130				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5131			else
5132				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5133			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5134		}
5135
5136		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5137		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5138			BWN_LPD(0, 1, 1)));
5139		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5140		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5141	}
5142	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5143
5144	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5145	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5146	reg1 = BWN_READ_2(mac, 0x3e6);
5147	reg2 = BWN_READ_2(mac, 0x3f4);
5148
5149	if (phy->analog == 0)
5150		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5151	else {
5152		if (phy->analog >= 2)
5153			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5154		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5155		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5156	}
5157
5158	reg = BWN_RF_READ(mac, 0x60);
5159	index = (reg & 0x001e) >> 1;
5160	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5161
5162	if (phy->type == BWN_PHYTYPE_B)
5163		BWN_RF_WRITE(mac, 0x78, 0x26);
5164	if (phy->gmode || phy->rev >= 2) {
5165		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5166		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5167			BWN_LPD(0, 1, 1)));
5168	}
5169	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5170	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5171	if (phy->gmode || phy->rev >= 2) {
5172		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5173		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5174			BWN_LPD(0, 0, 1)));
5175	}
5176	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5177	BWN_RF_SET(mac, 0x51, 0x0004);
5178	if (phy->rf_rev == 8)
5179		BWN_RF_WRITE(mac, 0x43, 0x1f);
5180	else {
5181		BWN_RF_WRITE(mac, 0x52, 0);
5182		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5183	}
5184	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5185
5186	for (i = 0; i < 16; i++) {
5187		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5188		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5189		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5190		if (phy->gmode || phy->rev >= 2) {
5191			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5192			    bwn_rf_2050_rfoverval(mac,
5193				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5194		}
5195		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5196		DELAY(10);
5197		if (phy->gmode || phy->rev >= 2) {
5198			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5199			    bwn_rf_2050_rfoverval(mac,
5200				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5201		}
5202		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5203		DELAY(10);
5204		if (phy->gmode || phy->rev >= 2) {
5205			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5206			    bwn_rf_2050_rfoverval(mac,
5207				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5208		}
5209		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5210		DELAY(20);
5211		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5212		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5213		if (phy->gmode || phy->rev >= 2) {
5214			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5215			    bwn_rf_2050_rfoverval(mac,
5216				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5217		}
5218		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5219	}
5220	DELAY(10);
5221
5222	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5223	tmp1++;
5224	tmp1 >>= 9;
5225
5226	for (i = 0; i < 16; i++) {
5227		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5228		BWN_RF_WRITE(mac, 0x78, radio78);
5229		DELAY(10);
5230		for (j = 0; j < 16; j++) {
5231			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5232			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5233			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5234			if (phy->gmode || phy->rev >= 2) {
5235				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5236				    bwn_rf_2050_rfoverval(mac,
5237					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5238			}
5239			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5240			DELAY(10);
5241			if (phy->gmode || phy->rev >= 2) {
5242				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5243				    bwn_rf_2050_rfoverval(mac,
5244					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5245			}
5246			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5247			DELAY(10);
5248			if (phy->gmode || phy->rev >= 2) {
5249				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5250				    bwn_rf_2050_rfoverval(mac,
5251					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5252			}
5253			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5254			DELAY(10);
5255			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5256			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5257			if (phy->gmode || phy->rev >= 2) {
5258				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5259				    bwn_rf_2050_rfoverval(mac,
5260					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5261			}
5262			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5263		}
5264		tmp2++;
5265		tmp2 >>= 8;
5266		if (tmp1 < tmp2)
5267			break;
5268	}
5269
5270	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5271	BWN_RF_WRITE(mac, 0x51, radio1);
5272	BWN_RF_WRITE(mac, 0x52, radio2);
5273	BWN_RF_WRITE(mac, 0x43, radio0);
5274	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5275	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5276	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5277	BWN_WRITE_2(mac, 0x3e6, reg1);
5278	if (phy->analog != 0)
5279		BWN_WRITE_2(mac, 0x3f4, reg2);
5280	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5281	bwn_spu_workaround(mac, phy->chan);
5282	if (phy->type == BWN_PHYTYPE_B) {
5283		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5284		BWN_WRITE_2(mac, 0x3ec, reg0);
5285	} else if (phy->gmode) {
5286		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5287			    BWN_READ_2(mac, BWN_PHY_RADIO)
5288			    & 0x7fff);
5289		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5290		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5291		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5292		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5293			      analogoverval);
5294		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5295		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5296		if (BWN_HAS_LOOPBACK(phy)) {
5297			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5298			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5299		}
5300	}
5301
5302	return ((i > 15) ? radio78 : rcc);
5303}
5304
5305static void
5306bwn_phy_init_b6(struct bwn_mac *mac)
5307{
5308	struct bwn_phy *phy = &mac->mac_phy;
5309	struct bwn_phy_g *pg = &phy->phy_g;
5310	struct bwn_softc *sc = mac->mac_sc;
5311	uint16_t offset, val;
5312	uint8_t old_channel;
5313
5314	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5315	    ("%s:%d: fail", __func__, __LINE__));
5316
5317	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5318	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5319	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5320		BWN_RF_WRITE(mac, 0x51, 0x37);
5321		BWN_RF_WRITE(mac, 0x52, 0x70);
5322		BWN_RF_WRITE(mac, 0x53, 0xb3);
5323		BWN_RF_WRITE(mac, 0x54, 0x9b);
5324		BWN_RF_WRITE(mac, 0x5a, 0x88);
5325		BWN_RF_WRITE(mac, 0x5b, 0x88);
5326		BWN_RF_WRITE(mac, 0x5d, 0x88);
5327		BWN_RF_WRITE(mac, 0x5e, 0x88);
5328		BWN_RF_WRITE(mac, 0x7d, 0x88);
5329		bwn_hf_write(mac,
5330		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5331	}
5332	if (phy->rf_rev == 8) {
5333		BWN_RF_WRITE(mac, 0x51, 0);
5334		BWN_RF_WRITE(mac, 0x52, 0x40);
5335		BWN_RF_WRITE(mac, 0x53, 0xb7);
5336		BWN_RF_WRITE(mac, 0x54, 0x98);
5337		BWN_RF_WRITE(mac, 0x5a, 0x88);
5338		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5339		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5340		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5341			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5342			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5343		} else {
5344			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5345			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5346		}
5347		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5348		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5349		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5350		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5351	}
5352	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5353		BWN_PHY_WRITE(mac, offset, val);
5354		val -= 0x0202;
5355	}
5356	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5357		BWN_PHY_WRITE(mac, offset, val);
5358		val -= 0x0202;
5359	}
5360	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5361		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5362		val += 0x0202;
5363	}
5364	if (phy->type == BWN_PHYTYPE_G) {
5365		BWN_RF_SET(mac, 0x007a, 0x0020);
5366		BWN_RF_SET(mac, 0x0051, 0x0004);
5367		BWN_PHY_SET(mac, 0x0802, 0x0100);
5368		BWN_PHY_SET(mac, 0x042b, 0x2000);
5369		BWN_PHY_WRITE(mac, 0x5b, 0);
5370		BWN_PHY_WRITE(mac, 0x5c, 0);
5371	}
5372
5373	old_channel = phy->chan;
5374	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5375
5376	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5377	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5378	DELAY(40);
5379	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5380		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5381		BWN_RF_WRITE(mac, 0x50, 0x20);
5382	}
5383	if (phy->rf_rev <= 2) {
5384		BWN_RF_WRITE(mac, 0x7c, 0x20);
5385		BWN_RF_WRITE(mac, 0x5a, 0x70);
5386		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5387		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5388	}
5389	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5390
5391	bwn_phy_g_switch_chan(mac, old_channel, 0);
5392
5393	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5394	if (phy->rf_rev >= 6)
5395		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5396	else
5397		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5398	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5399	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5400	    pg->pg_txctl);
5401	if (phy->rf_rev <= 5)
5402		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5403	if (phy->rf_rev <= 2)
5404		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5405
5406	if (phy->analog == 4) {
5407		BWN_WRITE_2(mac, 0x3e4, 9);
5408		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5409	} else
5410		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5411	if (phy->type == BWN_PHYTYPE_B)
5412		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5413	else if (phy->type == BWN_PHYTYPE_G)
5414		BWN_WRITE_2(mac, 0x03e6, 0x0);
5415}
5416
5417static void
5418bwn_phy_init_a(struct bwn_mac *mac)
5419{
5420	struct bwn_phy *phy = &mac->mac_phy;
5421	struct bwn_softc *sc = mac->mac_sc;
5422
5423	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5424	    ("%s:%d: fail", __func__, __LINE__));
5425
5426	if (phy->rev >= 6) {
5427		if (phy->type == BWN_PHYTYPE_A)
5428			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5429		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5430			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5431		else
5432			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5433	}
5434
5435	bwn_wa_init(mac);
5436
5437	if (phy->type == BWN_PHYTYPE_G &&
5438	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5439		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5440}
5441
5442static void
5443bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5444{
5445	int i;
5446
5447	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5448		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5449}
5450
5451static void
5452bwn_wa_agc(struct bwn_mac *mac)
5453{
5454	struct bwn_phy *phy = &mac->mac_phy;
5455
5456	if (phy->rev == 1) {
5457		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5463		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5464		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5465		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5466	} else {
5467		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5468		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5469		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5470		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5471	}
5472
5473	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5474	    0x5700);
5475	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5476	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5478	BWN_RF_SET(mac, 0x7a, 0x0008);
5479	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5480	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5481	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5482	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5483	if (phy->rev == 1)
5484		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5485	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5491	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5492	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5493	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5494	if (phy->rev == 1) {
5495		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5496		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5497	} else {
5498		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5499		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5500		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5501		if (phy->rev >= 6) {
5502			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5503			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5504			    (uint16_t)~0xf000, 0x3000);
5505		}
5506	}
5507	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5508	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5509	if (phy->rev == 1) {
5510		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5511		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5512		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5513		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5518	} else {
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5522		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5523	}
5524	if (phy->rev >= 6) {
5525		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5526		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5527	}
5528	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5529}
5530
5531static void
5532bwn_wa_grev1(struct bwn_mac *mac)
5533{
5534	struct bwn_phy *phy = &mac->mac_phy;
5535	int i;
5536	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5537	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5538	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5539
5540	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5541
5542	/* init CRSTHRES and ANTDWELL */
5543	if (phy->rev == 1) {
5544		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5545	} else if (phy->rev == 2) {
5546		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5547		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5548		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5549	} else {
5550		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5551		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5552		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5553		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5554	}
5555	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5556	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5557	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5558
5559	/* XXX support PHY-A??? */
5560	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5561		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5562		    bwn_tab_finefreqg[i]);
5563
5564	/* XXX support PHY-A??? */
5565	if (phy->rev == 1)
5566		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5567			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5568			    bwn_tab_noise_g1[i]);
5569	else
5570		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5571			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5572			    bwn_tab_noise_g2[i]);
5573
5574
5575	for (i = 0; i < N(bwn_tab_rotor); i++)
5576		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5577		    bwn_tab_rotor[i]);
5578
5579	/* XXX support PHY-A??? */
5580	if (phy->rev >= 6) {
5581		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5582		    BWN_PHY_ENCORE_EN)
5583			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5584		else
5585			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5586	} else
5587		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5588
5589	for (i = 0; i < N(bwn_tab_retard); i++)
5590		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5591		    bwn_tab_retard[i]);
5592
5593	if (phy->rev == 1) {
5594		for (i = 0; i < 16; i++)
5595			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5596			    i, 0x0020);
5597	} else {
5598		for (i = 0; i < 32; i++)
5599			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5600	}
5601
5602	bwn_wa_agc(mac);
5603}
5604
5605static void
5606bwn_wa_grev26789(struct bwn_mac *mac)
5607{
5608	struct bwn_phy *phy = &mac->mac_phy;
5609	int i;
5610	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5611	uint16_t ofdmrev;
5612
5613	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5614
5615	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5616
5617	/* init CRSTHRES and ANTDWELL */
5618	if (phy->rev == 1)
5619		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5620	else if (phy->rev == 2) {
5621		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5622		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5623		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5624	} else {
5625		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5626		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5627		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5628		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5629	}
5630
5631	for (i = 0; i < 64; i++)
5632		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5633
5634	/* XXX support PHY-A??? */
5635	if (phy->rev == 1)
5636		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5637			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5638			    bwn_tab_noise_g1[i]);
5639	else
5640		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5641			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5642			    bwn_tab_noise_g2[i]);
5643
5644	/* XXX support PHY-A??? */
5645	if (phy->rev >= 6) {
5646		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5647		    BWN_PHY_ENCORE_EN)
5648			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5649		else
5650			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5651	} else
5652		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5653
5654	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5655		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5656		    bwn_tab_sigmasqr2[i]);
5657
5658	if (phy->rev == 1) {
5659		for (i = 0; i < 16; i++)
5660			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5661			    0x0020);
5662	} else {
5663		for (i = 0; i < 32; i++)
5664			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5665	}
5666
5667	bwn_wa_agc(mac);
5668
5669	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5670	if (ofdmrev > 2) {
5671		if (phy->type == BWN_PHYTYPE_A)
5672			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5673		else
5674			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5675	} else {
5676		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5677		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5678		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5679	}
5680
5681	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5682	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5683}
5684
5685static void
5686bwn_wa_init(struct bwn_mac *mac)
5687{
5688	struct bwn_phy *phy = &mac->mac_phy;
5689	struct bwn_softc *sc = mac->mac_sc;
5690
5691	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5692
5693	switch (phy->rev) {
5694	case 1:
5695		bwn_wa_grev1(mac);
5696		break;
5697	case 2:
5698	case 6:
5699	case 7:
5700	case 8:
5701	case 9:
5702		bwn_wa_grev26789(mac);
5703		break;
5704	default:
5705		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5706	}
5707
5708	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5709	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5710	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5711		if (phy->rev < 2) {
5712			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5713			    0x0002);
5714			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5715			    0x0001);
5716		} else {
5717			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5718			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5719			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5720			     BWN_BFL_EXTLNA) &&
5721			    (phy->rev >= 7)) {
5722				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5723				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5724				    0x0020, 0x0001);
5725				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726				    0x0021, 0x0001);
5727				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728				    0x0022, 0x0001);
5729				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730				    0x0023, 0x0000);
5731				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732				    0x0000, 0x0000);
5733				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5734				    0x0003, 0x0002);
5735			}
5736		}
5737	}
5738	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5739		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5740		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5741	}
5742
5743	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5744	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5745}
5746
5747static void
5748bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5749    uint16_t value)
5750{
5751	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5752	uint16_t addr;
5753
5754	addr = table + offset;
5755	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5756	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5757		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5758		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5759	}
5760	pg->pg_ofdmtab_addr = addr;
5761	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5762}
5763
5764static void
5765bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5766    uint32_t value)
5767{
5768	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5769	uint16_t addr;
5770
5771	addr = table + offset;
5772	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5773	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5774		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5775		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5776	}
5777	pg->pg_ofdmtab_addr = addr;
5778
5779	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5780	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5781}
5782
5783static void
5784bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5785    uint16_t value)
5786{
5787
5788	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5789	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5790}
5791
5792static void
5793bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5794{
5795	struct bwn_phy *phy = &mac->mac_phy;
5796	struct bwn_softc *sc = mac->mac_sc;
5797	unsigned int i, max_loop;
5798	uint16_t value;
5799	uint32_t buffer[5] = {
5800		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5801	};
5802
5803	if (ofdm) {
5804		max_loop = 0x1e;
5805		buffer[0] = 0x000201cc;
5806	} else {
5807		max_loop = 0xfa;
5808		buffer[0] = 0x000b846e;
5809	}
5810
5811	BWN_ASSERT_LOCKED(mac->mac_sc);
5812
5813	for (i = 0; i < 5; i++)
5814		bwn_ram_write(mac, i * 4, buffer[i]);
5815
5816	BWN_WRITE_2(mac, 0x0568, 0x0000);
5817	BWN_WRITE_2(mac, 0x07c0,
5818	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5819	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5820	BWN_WRITE_2(mac, 0x050c, value);
5821	if (phy->type == BWN_PHYTYPE_LP)
5822		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5823	BWN_WRITE_2(mac, 0x0508, 0x0000);
5824	BWN_WRITE_2(mac, 0x050a, 0x0000);
5825	BWN_WRITE_2(mac, 0x054c, 0x0000);
5826	BWN_WRITE_2(mac, 0x056a, 0x0014);
5827	BWN_WRITE_2(mac, 0x0568, 0x0826);
5828	BWN_WRITE_2(mac, 0x0500, 0x0000);
5829	if (phy->type == BWN_PHYTYPE_LP)
5830		BWN_WRITE_2(mac, 0x0502, 0x0050);
5831	else
5832		BWN_WRITE_2(mac, 0x0502, 0x0030);
5833
5834	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5835		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5836	for (i = 0x00; i < max_loop; i++) {
5837		value = BWN_READ_2(mac, 0x050e);
5838		if (value & 0x0080)
5839			break;
5840		DELAY(10);
5841	}
5842	for (i = 0x00; i < 0x0a; i++) {
5843		value = BWN_READ_2(mac, 0x050e);
5844		if (value & 0x0400)
5845			break;
5846		DELAY(10);
5847	}
5848	for (i = 0x00; i < 0x19; i++) {
5849		value = BWN_READ_2(mac, 0x0690);
5850		if (!(value & 0x0100))
5851			break;
5852		DELAY(10);
5853	}
5854	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5855		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5856}
5857
5858static void
5859bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5860{
5861	uint32_t macctl;
5862
5863	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5864
5865	macctl = BWN_READ_4(mac, BWN_MACCTL);
5866	if (macctl & BWN_MACCTL_BIGENDIAN)
5867		printf("TODO: need swap\n");
5868
5869	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5870	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5871	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5872}
5873
5874static void
5875bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5876{
5877	uint16_t value;
5878
5879	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5880	    ("%s:%d: fail", __func__, __LINE__));
5881
5882	value = (uint8_t) (ctl->q);
5883	value |= ((uint8_t) (ctl->i)) << 8;
5884	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5885}
5886
5887static uint16_t
5888bwn_lo_calcfeed(struct bwn_mac *mac,
5889    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5890{
5891	struct bwn_phy *phy = &mac->mac_phy;
5892	struct bwn_softc *sc = mac->mac_sc;
5893	uint16_t rfover;
5894	uint16_t feedthrough;
5895
5896	if (phy->gmode) {
5897		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5898		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5899
5900		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5901		    ("%s:%d: fail", __func__, __LINE__));
5902		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5903		    ("%s:%d: fail", __func__, __LINE__));
5904
5905		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5906
5907		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5908		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5909		    phy->rev > 6)
5910			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5911
5912		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5913		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5914		DELAY(10);
5915		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5916		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5917		DELAY(10);
5918		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5919		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5920		DELAY(10);
5921		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5922	} else {
5923		pga |= BWN_PHY_PGACTL_UNKNOWN;
5924		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5925		DELAY(10);
5926		pga |= BWN_PHY_PGACTL_LOWBANDW;
5927		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5928		DELAY(10);
5929		pga |= BWN_PHY_PGACTL_LPF;
5930		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5931	}
5932	DELAY(21);
5933	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5934
5935	return (feedthrough);
5936}
5937
5938static uint16_t
5939bwn_lo_txctl_regtable(struct bwn_mac *mac,
5940    uint16_t *value, uint16_t *pad_mix_gain)
5941{
5942	struct bwn_phy *phy = &mac->mac_phy;
5943	uint16_t reg, v, padmix;
5944
5945	if (phy->type == BWN_PHYTYPE_B) {
5946		v = 0x30;
5947		if (phy->rf_rev <= 5) {
5948			reg = 0x43;
5949			padmix = 0;
5950		} else {
5951			reg = 0x52;
5952			padmix = 5;
5953		}
5954	} else {
5955		if (phy->rev >= 2 && phy->rf_rev == 8) {
5956			reg = 0x43;
5957			v = 0x10;
5958			padmix = 2;
5959		} else {
5960			reg = 0x52;
5961			v = 0x30;
5962			padmix = 5;
5963		}
5964	}
5965	if (value)
5966		*value = v;
5967	if (pad_mix_gain)
5968		*pad_mix_gain = padmix;
5969
5970	return (reg);
5971}
5972
5973static void
5974bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5975{
5976	struct bwn_phy *phy = &mac->mac_phy;
5977	struct bwn_phy_g *pg = &phy->phy_g;
5978	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5979	uint16_t reg, mask;
5980	uint16_t trsw_rx, pga;
5981	uint16_t rf_pctl_reg;
5982
5983	static const uint8_t tx_bias_values[] = {
5984		0x09, 0x08, 0x0a, 0x01, 0x00,
5985		0x02, 0x05, 0x04, 0x06,
5986	};
5987	static const uint8_t tx_magn_values[] = {
5988		0x70, 0x40,
5989	};
5990
5991	if (!BWN_HAS_LOOPBACK(phy)) {
5992		rf_pctl_reg = 6;
5993		trsw_rx = 2;
5994		pga = 0;
5995	} else {
5996		int lb_gain;
5997
5998		trsw_rx = 0;
5999		lb_gain = pg->pg_max_lb_gain / 2;
6000		if (lb_gain > 10) {
6001			rf_pctl_reg = 0;
6002			pga = abs(10 - lb_gain) / 6;
6003			pga = MIN(MAX(pga, 0), 15);
6004		} else {
6005			int cmp_val;
6006			int tmp;
6007
6008			pga = 0;
6009			cmp_val = 0x24;
6010			if ((phy->rev >= 2) &&
6011			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6012				cmp_val = 0x3c;
6013			tmp = lb_gain;
6014			if ((10 - lb_gain) < cmp_val)
6015				tmp = (10 - lb_gain);
6016			if (tmp < 0)
6017				tmp += 6;
6018			else
6019				tmp += 3;
6020			cmp_val /= 4;
6021			tmp /= 4;
6022			if (tmp >= cmp_val)
6023				rf_pctl_reg = cmp_val;
6024			else
6025				rf_pctl_reg = tmp;
6026		}
6027	}
6028	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6029	bwn_phy_g_set_bbatt(mac, 2);
6030
6031	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6032	mask = ~mask;
6033	BWN_RF_MASK(mac, reg, mask);
6034
6035	if (BWN_HAS_TXMAG(phy)) {
6036		int i, j;
6037		int feedthrough;
6038		int min_feedth = 0xffff;
6039		uint8_t tx_magn, tx_bias;
6040
6041		for (i = 0; i < N(tx_magn_values); i++) {
6042			tx_magn = tx_magn_values[i];
6043			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6044			for (j = 0; j < N(tx_bias_values); j++) {
6045				tx_bias = tx_bias_values[j];
6046				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6047				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6048				    trsw_rx);
6049				if (feedthrough < min_feedth) {
6050					lo->tx_bias = tx_bias;
6051					lo->tx_magn = tx_magn;
6052					min_feedth = feedthrough;
6053				}
6054				if (lo->tx_bias == 0)
6055					break;
6056			}
6057			BWN_RF_WRITE(mac, 0x52,
6058					  (BWN_RF_READ(mac, 0x52)
6059					   & 0xff00) | lo->tx_bias | lo->
6060					  tx_magn);
6061		}
6062	} else {
6063		lo->tx_magn = 0;
6064		lo->tx_bias = 0;
6065		BWN_RF_MASK(mac, 0x52, 0xfff0);
6066	}
6067
6068	BWN_GETTIME(lo->txctl_measured_time);
6069}
6070
6071static void
6072bwn_lo_get_powervector(struct bwn_mac *mac)
6073{
6074	struct bwn_phy *phy = &mac->mac_phy;
6075	struct bwn_phy_g *pg = &phy->phy_g;
6076	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6077	int i;
6078	uint64_t tmp;
6079	uint64_t power_vector = 0;
6080
6081	for (i = 0; i < 8; i += 2) {
6082		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6083		power_vector |= (tmp << (i * 8));
6084		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6085	}
6086	if (power_vector)
6087		lo->power_vector = power_vector;
6088
6089	BWN_GETTIME(lo->pwr_vec_read_time);
6090}
6091
6092static void
6093bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6094    int use_trsw_rx)
6095{
6096	struct bwn_phy *phy = &mac->mac_phy;
6097	struct bwn_phy_g *pg = &phy->phy_g;
6098	uint16_t tmp;
6099
6100	if (max_rx_gain < 0)
6101		max_rx_gain = 0;
6102
6103	if (BWN_HAS_LOOPBACK(phy)) {
6104		int trsw_rx = 0;
6105		int trsw_rx_gain;
6106
6107		if (use_trsw_rx) {
6108			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6109			if (max_rx_gain >= trsw_rx_gain) {
6110				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6111				trsw_rx = 0x20;
6112			}
6113		} else
6114			trsw_rx_gain = max_rx_gain;
6115		if (trsw_rx_gain < 9) {
6116			pg->pg_lna_lod_gain = 0;
6117		} else {
6118			pg->pg_lna_lod_gain = 1;
6119			trsw_rx_gain -= 8;
6120		}
6121		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6122		pg->pg_pga_gain = trsw_rx_gain / 3;
6123		if (pg->pg_pga_gain >= 5) {
6124			pg->pg_pga_gain -= 5;
6125			pg->pg_lna_gain = 2;
6126		} else
6127			pg->pg_lna_gain = 0;
6128	} else {
6129		pg->pg_lna_gain = 0;
6130		pg->pg_trsw_rx_gain = 0x20;
6131		if (max_rx_gain >= 0x14) {
6132			pg->pg_lna_lod_gain = 1;
6133			pg->pg_pga_gain = 2;
6134		} else if (max_rx_gain >= 0x12) {
6135			pg->pg_lna_lod_gain = 1;
6136			pg->pg_pga_gain = 1;
6137		} else if (max_rx_gain >= 0xf) {
6138			pg->pg_lna_lod_gain = 1;
6139			pg->pg_pga_gain = 0;
6140		} else {
6141			pg->pg_lna_lod_gain = 0;
6142			pg->pg_pga_gain = 0;
6143		}
6144	}
6145
6146	tmp = BWN_RF_READ(mac, 0x7a);
6147	if (pg->pg_lna_lod_gain == 0)
6148		tmp &= ~0x0008;
6149	else
6150		tmp |= 0x0008;
6151	BWN_RF_WRITE(mac, 0x7a, tmp);
6152}
6153
6154static void
6155bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6156{
6157	struct bwn_phy *phy = &mac->mac_phy;
6158	struct bwn_phy_g *pg = &phy->phy_g;
6159	struct bwn_softc *sc = mac->mac_sc;
6160	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6161	struct timespec ts;
6162	uint16_t tmp;
6163
6164	if (bwn_has_hwpctl(mac)) {
6165		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6166		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6167		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6168		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6169		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6170
6171		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6172		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6173		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6174		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6175	}
6176	if (phy->type == BWN_PHYTYPE_B &&
6177	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6178		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6179		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6180	}
6181	if (phy->rev >= 2) {
6182		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6183		sav->phy_analogoverval =
6184		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6185		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6186		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6187		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6188		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6189		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6190
6191		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6192		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6193		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6194		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6195		if (phy->type == BWN_PHYTYPE_G) {
6196			if ((phy->rev >= 7) &&
6197			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6198			     BWN_BFL_EXTLNA)) {
6199				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6200			} else {
6201				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6202			}
6203		} else {
6204			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6205		}
6206		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6207	}
6208	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6209	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6210	sav->rf0 = BWN_RF_READ(mac, 0x43);
6211	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6212	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6213	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6214	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6215	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6216
6217	if (!BWN_HAS_TXMAG(phy)) {
6218		sav->rf2 = BWN_RF_READ(mac, 0x52);
6219		sav->rf2 &= 0x00f0;
6220	}
6221	if (phy->type == BWN_PHYTYPE_B) {
6222		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6223		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6224		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6225		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6226	} else {
6227		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6228			    | 0x8000);
6229	}
6230	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6231		    & 0xf000);
6232
6233	tmp =
6234	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6235	BWN_PHY_WRITE(mac, tmp, 0x007f);
6236
6237	tmp = sav->phy_syncctl;
6238	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6239	tmp = sav->rf1;
6240	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6241
6242	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6243	if (phy->type == BWN_PHYTYPE_G ||
6244	    (phy->type == BWN_PHYTYPE_B &&
6245	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6246		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6247	} else
6248		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6249	if (phy->rev >= 2)
6250		bwn_dummy_transmission(mac, 0, 1);
6251	bwn_phy_g_switch_chan(mac, 6, 0);
6252	BWN_RF_READ(mac, 0x51);
6253	if (phy->type == BWN_PHYTYPE_G)
6254		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6255
6256	nanouptime(&ts);
6257	if (time_before(lo->txctl_measured_time,
6258	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6259		bwn_lo_measure_txctl_values(mac);
6260
6261	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6262		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6263	else {
6264		if (phy->type == BWN_PHYTYPE_B)
6265			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6266		else
6267			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6268	}
6269}
6270
6271static void
6272bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6273{
6274	struct bwn_phy *phy = &mac->mac_phy;
6275	struct bwn_phy_g *pg = &phy->phy_g;
6276	uint16_t tmp;
6277
6278	if (phy->rev >= 2) {
6279		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6280		tmp = (pg->pg_pga_gain << 8);
6281		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6282		DELAY(5);
6283		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6284		DELAY(2);
6285		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6286	} else {
6287		tmp = (pg->pg_pga_gain | 0xefa0);
6288		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6289	}
6290	if (phy->type == BWN_PHYTYPE_G) {
6291		if (phy->rev >= 3)
6292			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6293		else
6294			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6295		if (phy->rev >= 2)
6296			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6297		else
6298			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6299	}
6300	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6301	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6302	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6303	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6304	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6305	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6306	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6307	if (!BWN_HAS_TXMAG(phy)) {
6308		tmp = sav->rf2;
6309		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6310	}
6311	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6312	if (phy->type == BWN_PHYTYPE_B &&
6313	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6314		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6315		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6316	}
6317	if (phy->rev >= 2) {
6318		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6319		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6320			      sav->phy_analogoverval);
6321		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6322		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6323		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6324		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6325		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6326	}
6327	if (bwn_has_hwpctl(mac)) {
6328		tmp = (sav->phy_lomask & 0xbfff);
6329		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6330		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6331		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6332		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6333		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6334	}
6335	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6336}
6337
6338static int
6339bwn_lo_probe_loctl(struct bwn_mac *mac,
6340    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6341{
6342	struct bwn_phy *phy = &mac->mac_phy;
6343	struct bwn_phy_g *pg = &phy->phy_g;
6344	struct bwn_loctl orig, test;
6345	struct bwn_loctl prev = { -100, -100 };
6346	static const struct bwn_loctl modifiers[] = {
6347		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6348		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6349	};
6350	int begin, end, lower = 0, i;
6351	uint16_t feedth;
6352
6353	if (d->curstate == 0) {
6354		begin = 1;
6355		end = 8;
6356	} else if (d->curstate % 2 == 0) {
6357		begin = d->curstate - 1;
6358		end = d->curstate + 1;
6359	} else {
6360		begin = d->curstate - 2;
6361		end = d->curstate + 2;
6362	}
6363	if (begin < 1)
6364		begin += 8;
6365	if (end > 8)
6366		end -= 8;
6367
6368	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6369	i = begin;
6370	d->curstate = i;
6371	while (1) {
6372		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6373		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6374		test.i += modifiers[i - 1].i * d->multipler;
6375		test.q += modifiers[i - 1].q * d->multipler;
6376		if ((test.i != prev.i || test.q != prev.q) &&
6377		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6378			bwn_lo_write(mac, &test);
6379			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6380			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6381			if (feedth < d->feedth) {
6382				memcpy(probe, &test,
6383				    sizeof(struct bwn_loctl));
6384				lower = 1;
6385				d->feedth = feedth;
6386				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6387					break;
6388			}
6389		}
6390		memcpy(&prev, &test, sizeof(prev));
6391		if (i == end)
6392			break;
6393		if (i == 8)
6394			i = 1;
6395		else
6396			i++;
6397		d->curstate = i;
6398	}
6399
6400	return (lower);
6401}
6402
6403static void
6404bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6405{
6406	struct bwn_phy *phy = &mac->mac_phy;
6407	struct bwn_phy_g *pg = &phy->phy_g;
6408	struct bwn_lo_g_sm d;
6409	struct bwn_loctl probe;
6410	int lower, repeat, cnt = 0;
6411	uint16_t feedth;
6412
6413	d.nmeasure = 0;
6414	d.multipler = 1;
6415	if (BWN_HAS_LOOPBACK(phy))
6416		d.multipler = 3;
6417
6418	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6419	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6420
6421	do {
6422		bwn_lo_write(mac, &d.loctl);
6423		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6424		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6425		if (feedth < 0x258) {
6426			if (feedth >= 0x12c)
6427				*rxgain += 6;
6428			else
6429				*rxgain += 3;
6430			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6431			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6432		}
6433		d.feedth = feedth;
6434		d.curstate = 0;
6435		do {
6436			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6437			    ("%s:%d: fail", __func__, __LINE__));
6438			memcpy(&probe, &d.loctl,
6439			       sizeof(struct bwn_loctl));
6440			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6441			if (!lower)
6442				break;
6443			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6444				break;
6445			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6446			d.nmeasure++;
6447		} while (d.nmeasure < 24);
6448		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6449
6450		if (BWN_HAS_LOOPBACK(phy)) {
6451			if (d.feedth > 0x1194)
6452				*rxgain -= 6;
6453			else if (d.feedth < 0x5dc)
6454				*rxgain += 3;
6455			if (cnt == 0) {
6456				if (d.feedth <= 0x5dc) {
6457					d.multipler = 1;
6458					cnt++;
6459				} else
6460					d.multipler = 2;
6461			} else if (cnt == 2)
6462				d.multipler = 1;
6463		}
6464		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6465	} while (++cnt < repeat);
6466}
6467
6468static struct bwn_lo_calib *
6469bwn_lo_calibset(struct bwn_mac *mac,
6470    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6471{
6472	struct bwn_phy *phy = &mac->mac_phy;
6473	struct bwn_phy_g *pg = &phy->phy_g;
6474	struct bwn_loctl loctl = { 0, 0 };
6475	struct bwn_lo_calib *cal;
6476	struct bwn_lo_g_value sval = { 0 };
6477	int rxgain;
6478	uint16_t pad, reg, value;
6479
6480	sval.old_channel = phy->chan;
6481	bwn_mac_suspend(mac);
6482	bwn_lo_save(mac, &sval);
6483
6484	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6485	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6486	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6487
6488	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6489	if (rfatt->padmix)
6490		rxgain -= pad;
6491	if (BWN_HAS_LOOPBACK(phy))
6492		rxgain += pg->pg_max_lb_gain;
6493	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6494	bwn_phy_g_set_bbatt(mac, bbatt->att);
6495	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6496
6497	bwn_lo_restore(mac, &sval);
6498	bwn_mac_enable(mac);
6499
6500	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6501	if (!cal) {
6502		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6503		return (NULL);
6504	}
6505	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6506	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6507	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6508
6509	BWN_GETTIME(cal->calib_time);
6510
6511	return (cal);
6512}
6513
6514static struct bwn_lo_calib *
6515bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6516    const struct bwn_rfatt *rfatt)
6517{
6518	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6519	struct bwn_lo_calib *c;
6520
6521	TAILQ_FOREACH(c, &lo->calib_list, list) {
6522		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6523			continue;
6524		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6525			continue;
6526		return (c);
6527	}
6528
6529	c = bwn_lo_calibset(mac, bbatt, rfatt);
6530	if (!c)
6531		return (NULL);
6532	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6533
6534	return (c);
6535}
6536
6537static void
6538bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6539{
6540	struct bwn_phy *phy = &mac->mac_phy;
6541	struct bwn_phy_g *pg = &phy->phy_g;
6542	struct bwn_softc *sc = mac->mac_sc;
6543	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6544	const struct bwn_rfatt *rfatt;
6545	const struct bwn_bbatt *bbatt;
6546	uint64_t pvector;
6547	int i;
6548	int rf_offset, bb_offset;
6549	uint8_t changed = 0;
6550
6551	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6552	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6553	    ("%s:%d: fail", __func__, __LINE__));
6554
6555	pvector = lo->power_vector;
6556	if (!update && !pvector)
6557		return;
6558
6559	bwn_mac_suspend(mac);
6560
6561	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6562		struct bwn_lo_calib *cal;
6563		int idx;
6564		uint16_t val;
6565
6566		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6567			continue;
6568		bb_offset = i / lo->rfatt.len;
6569		rf_offset = i % lo->rfatt.len;
6570		bbatt = &(lo->bbatt.array[bb_offset]);
6571		rfatt = &(lo->rfatt.array[rf_offset]);
6572
6573		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6574		if (!cal) {
6575			device_printf(sc->sc_dev, "LO: Could not "
6576			    "calibrate DC table entry\n");
6577			continue;
6578		}
6579		val = (uint8_t)(cal->ctl.q);
6580		val |= ((uint8_t)(cal->ctl.i)) << 4;
6581		free(cal, M_DEVBUF);
6582
6583		idx = i / 2;
6584		if (i % 2)
6585			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6586			    | ((val & 0x00ff) << 8);
6587		else
6588			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6589			    | (val & 0x00ff);
6590		changed = 1;
6591	}
6592	if (changed) {
6593		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6594			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6595	}
6596	bwn_mac_enable(mac);
6597}
6598
6599static void
6600bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6601{
6602
6603	if (!rf->padmix)
6604		return;
6605	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6606		rf->att = 4;
6607}
6608
6609static void
6610bwn_lo_g_adjust(struct bwn_mac *mac)
6611{
6612	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6613	struct bwn_lo_calib *cal;
6614	struct bwn_rfatt rf;
6615
6616	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6617	bwn_lo_fixup_rfatt(&rf);
6618
6619	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6620	if (!cal)
6621		return;
6622	bwn_lo_write(mac, &cal->ctl);
6623}
6624
6625static void
6626bwn_lo_g_init(struct bwn_mac *mac)
6627{
6628
6629	if (!bwn_has_hwpctl(mac))
6630		return;
6631
6632	bwn_lo_get_powervector(mac);
6633	bwn_phy_g_dc_lookup_init(mac, 1);
6634}
6635
6636static void
6637bwn_mac_suspend(struct bwn_mac *mac)
6638{
6639	struct bwn_softc *sc = mac->mac_sc;
6640	int i;
6641	uint32_t tmp;
6642
6643	KASSERT(mac->mac_suspended >= 0,
6644	    ("%s:%d: fail", __func__, __LINE__));
6645
6646	if (mac->mac_suspended == 0) {
6647		bwn_psctl(mac, BWN_PS_AWAKE);
6648		BWN_WRITE_4(mac, BWN_MACCTL,
6649			    BWN_READ_4(mac, BWN_MACCTL)
6650			    & ~BWN_MACCTL_ON);
6651		BWN_READ_4(mac, BWN_MACCTL);
6652		for (i = 35; i; i--) {
6653			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6654			if (tmp & BWN_INTR_MAC_SUSPENDED)
6655				goto out;
6656			DELAY(10);
6657		}
6658		for (i = 40; i; i--) {
6659			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6660			if (tmp & BWN_INTR_MAC_SUSPENDED)
6661				goto out;
6662			DELAY(1000);
6663		}
6664		device_printf(sc->sc_dev, "MAC suspend failed\n");
6665	}
6666out:
6667	mac->mac_suspended++;
6668}
6669
6670static void
6671bwn_mac_enable(struct bwn_mac *mac)
6672{
6673	struct bwn_softc *sc = mac->mac_sc;
6674	uint16_t state;
6675
6676	state = bwn_shm_read_2(mac, BWN_SHARED,
6677	    BWN_SHARED_UCODESTAT);
6678	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6679	    state != BWN_SHARED_UCODESTAT_SLEEP)
6680		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6681
6682	mac->mac_suspended--;
6683	KASSERT(mac->mac_suspended >= 0,
6684	    ("%s:%d: fail", __func__, __LINE__));
6685	if (mac->mac_suspended == 0) {
6686		BWN_WRITE_4(mac, BWN_MACCTL,
6687		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6688		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6689		BWN_READ_4(mac, BWN_MACCTL);
6690		BWN_READ_4(mac, BWN_INTR_REASON);
6691		bwn_psctl(mac, 0);
6692	}
6693}
6694
6695static void
6696bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6697{
6698	struct bwn_softc *sc = mac->mac_sc;
6699	int i;
6700	uint16_t ucstat;
6701
6702	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6703	    ("%s:%d: fail", __func__, __LINE__));
6704	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6705	    ("%s:%d: fail", __func__, __LINE__));
6706
6707	/* XXX forcibly awake and hwps-off */
6708
6709	BWN_WRITE_4(mac, BWN_MACCTL,
6710	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6711	    ~BWN_MACCTL_HWPS);
6712	BWN_READ_4(mac, BWN_MACCTL);
6713	if (siba_get_revid(sc->sc_dev) >= 5) {
6714		for (i = 0; i < 100; i++) {
6715			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6716			    BWN_SHARED_UCODESTAT);
6717			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6718				break;
6719			DELAY(10);
6720		}
6721	}
6722}
6723
6724static int16_t
6725bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6726{
6727
6728	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6729	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6730}
6731
6732static void
6733bwn_nrssi_threshold(struct bwn_mac *mac)
6734{
6735	struct bwn_phy *phy = &mac->mac_phy;
6736	struct bwn_phy_g *pg = &phy->phy_g;
6737	struct bwn_softc *sc = mac->mac_sc;
6738	int32_t a, b;
6739	int16_t tmp16;
6740	uint16_t tmpu16;
6741
6742	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6743
6744	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6745		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6746			a = 0x13;
6747			b = 0x12;
6748		} else {
6749			a = 0xe;
6750			b = 0x11;
6751		}
6752
6753		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6754		a += (pg->pg_nrssi[0] << 6);
6755		a += (a < 32) ? 31 : 32;
6756		a = a >> 6;
6757		a = MIN(MAX(a, -31), 31);
6758
6759		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6760		b += (pg->pg_nrssi[0] << 6);
6761		if (b < 32)
6762			b += 31;
6763		else
6764			b += 32;
6765		b = b >> 6;
6766		b = MIN(MAX(b, -31), 31);
6767
6768		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6769		tmpu16 |= ((uint32_t)b & 0x0000003f);
6770		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6771		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6772		return;
6773	}
6774
6775	tmp16 = bwn_nrssi_read(mac, 0x20);
6776	if (tmp16 >= 0x20)
6777		tmp16 -= 0x40;
6778	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6779}
6780
6781static void
6782bwn_nrssi_slope_11g(struct bwn_mac *mac)
6783{
6784#define	SAVE_RF_MAX		3
6785#define	SAVE_PHY_COMM_MAX	4
6786#define	SAVE_PHY3_MAX		8
6787	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6788		{ 0x7a, 0x52, 0x43 };
6789	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6790		{ 0x15, 0x5a, 0x59, 0x58 };
6791	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6792		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6793		0x0801, 0x0060, 0x0014, 0x0478
6794	};
6795	struct bwn_phy *phy = &mac->mac_phy;
6796	struct bwn_phy_g *pg = &phy->phy_g;
6797	int32_t i, tmp32, phy3_idx = 0;
6798	uint16_t delta, tmp;
6799	uint16_t save_rf[SAVE_RF_MAX];
6800	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6801	uint16_t save_phy3[SAVE_PHY3_MAX];
6802	uint16_t ant_div, phy0, chan_ex;
6803	int16_t nrssi0, nrssi1;
6804
6805	KASSERT(phy->type == BWN_PHYTYPE_G,
6806	    ("%s:%d: fail", __func__, __LINE__));
6807
6808	if (phy->rf_rev >= 9)
6809		return;
6810	if (phy->rf_rev == 8)
6811		bwn_nrssi_offset(mac);
6812
6813	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6814	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6815
6816	/*
6817	 * Save RF/PHY registers for later restoration
6818	 */
6819	ant_div = BWN_READ_2(mac, 0x03e2);
6820	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6821	for (i = 0; i < SAVE_RF_MAX; ++i)
6822		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6823	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6824		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6825
6826	phy0 = BWN_READ_2(mac, BWN_PHY0);
6827	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6828	if (phy->rev >= 3) {
6829		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6830			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6831		BWN_PHY_WRITE(mac, 0x002e, 0);
6832		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6833		switch (phy->rev) {
6834		case 4:
6835		case 6:
6836		case 7:
6837			BWN_PHY_SET(mac, 0x0478, 0x0100);
6838			BWN_PHY_SET(mac, 0x0801, 0x0040);
6839			break;
6840		case 3:
6841		case 5:
6842			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6843			break;
6844		}
6845		BWN_PHY_SET(mac, 0x0060, 0x0040);
6846		BWN_PHY_SET(mac, 0x0014, 0x0200);
6847	}
6848	/*
6849	 * Calculate nrssi0
6850	 */
6851	BWN_RF_SET(mac, 0x007a, 0x0070);
6852	bwn_set_all_gains(mac, 0, 8, 0);
6853	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6854	if (phy->rev >= 2) {
6855		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6856		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6857	}
6858	BWN_RF_SET(mac, 0x007a, 0x0080);
6859	DELAY(20);
6860
6861	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6862	if (nrssi0 >= 0x0020)
6863		nrssi0 -= 0x0040;
6864
6865	/*
6866	 * Calculate nrssi1
6867	 */
6868	BWN_RF_MASK(mac, 0x007a, 0x007f);
6869	if (phy->rev >= 2)
6870		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6871
6872	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6873	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6874	BWN_RF_SET(mac, 0x007a, 0x000f);
6875	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6876	if (phy->rev >= 2) {
6877		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6878		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6879	}
6880
6881	bwn_set_all_gains(mac, 3, 0, 1);
6882	if (phy->rf_rev == 8) {
6883		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6884	} else {
6885		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6886		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6887		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6888		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6889	}
6890	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6891	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6892	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6893	DELAY(20);
6894	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6895
6896	/*
6897	 * Install calculated narrow RSSI values
6898	 */
6899	if (nrssi1 >= 0x0020)
6900		nrssi1 -= 0x0040;
6901	if (nrssi0 == nrssi1)
6902		pg->pg_nrssi_slope = 0x00010000;
6903	else
6904		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6905	if (nrssi0 >= -4) {
6906		pg->pg_nrssi[0] = nrssi1;
6907		pg->pg_nrssi[1] = nrssi0;
6908	}
6909
6910	/*
6911	 * Restore saved RF/PHY registers
6912	 */
6913	if (phy->rev >= 3) {
6914		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6915			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6916			    save_phy3[phy3_idx]);
6917		}
6918	}
6919	if (phy->rev >= 2) {
6920		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6921		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6922	}
6923
6924	for (i = 0; i < SAVE_RF_MAX; ++i)
6925		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6926
6927	BWN_WRITE_2(mac, 0x03e2, ant_div);
6928	BWN_WRITE_2(mac, 0x03e6, phy0);
6929	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6930
6931	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6932		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6933
6934	bwn_spu_workaround(mac, phy->chan);
6935	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6936	bwn_set_original_gains(mac);
6937	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6938	if (phy->rev >= 3) {
6939		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6940			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6941			    save_phy3[phy3_idx]);
6942		}
6943	}
6944
6945	delta = 0x1f - pg->pg_nrssi[0];
6946	for (i = 0; i < 64; i++) {
6947		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6948		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6949		pg->pg_nrssi_lt[i] = tmp32;
6950	}
6951
6952	bwn_nrssi_threshold(mac);
6953#undef SAVE_RF_MAX
6954#undef SAVE_PHY_COMM_MAX
6955#undef SAVE_PHY3_MAX
6956}
6957
6958static void
6959bwn_nrssi_offset(struct bwn_mac *mac)
6960{
6961#define	SAVE_RF_MAX		2
6962#define	SAVE_PHY_COMM_MAX	10
6963#define	SAVE_PHY6_MAX		8
6964	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6965		{ 0x7a, 0x43 };
6966	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6967		0x0001, 0x0811, 0x0812, 0x0814,
6968		0x0815, 0x005a, 0x0059, 0x0058,
6969		0x000a, 0x0003
6970	};
6971	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6972		0x002e, 0x002f, 0x080f, 0x0810,
6973		0x0801, 0x0060, 0x0014, 0x0478
6974	};
6975	struct bwn_phy *phy = &mac->mac_phy;
6976	int i, phy6_idx = 0;
6977	uint16_t save_rf[SAVE_RF_MAX];
6978	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6979	uint16_t save_phy6[SAVE_PHY6_MAX];
6980	int16_t nrssi;
6981	uint16_t saved = 0xffff;
6982
6983	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6984		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6985	for (i = 0; i < SAVE_RF_MAX; ++i)
6986		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6987
6988	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6989	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6990	BWN_PHY_SET(mac, 0x0811, 0x000c);
6991	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6992	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6993	if (phy->rev >= 6) {
6994		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6995			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6996
6997		BWN_PHY_WRITE(mac, 0x002e, 0);
6998		BWN_PHY_WRITE(mac, 0x002f, 0);
6999		BWN_PHY_WRITE(mac, 0x080f, 0);
7000		BWN_PHY_WRITE(mac, 0x0810, 0);
7001		BWN_PHY_SET(mac, 0x0478, 0x0100);
7002		BWN_PHY_SET(mac, 0x0801, 0x0040);
7003		BWN_PHY_SET(mac, 0x0060, 0x0040);
7004		BWN_PHY_SET(mac, 0x0014, 0x0200);
7005	}
7006	BWN_RF_SET(mac, 0x007a, 0x0070);
7007	BWN_RF_SET(mac, 0x007a, 0x0080);
7008	DELAY(30);
7009
7010	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7011	if (nrssi >= 0x20)
7012		nrssi -= 0x40;
7013	if (nrssi == 31) {
7014		for (i = 7; i >= 4; i--) {
7015			BWN_RF_WRITE(mac, 0x007b, i);
7016			DELAY(20);
7017			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7018			    0x003f);
7019			if (nrssi >= 0x20)
7020				nrssi -= 0x40;
7021			if (nrssi < 31 && saved == 0xffff)
7022				saved = i;
7023		}
7024		if (saved == 0xffff)
7025			saved = 4;
7026	} else {
7027		BWN_RF_MASK(mac, 0x007a, 0x007f);
7028		if (phy->rev != 1) {
7029			BWN_PHY_SET(mac, 0x0814, 0x0001);
7030			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7031		}
7032		BWN_PHY_SET(mac, 0x0811, 0x000c);
7033		BWN_PHY_SET(mac, 0x0812, 0x000c);
7034		BWN_PHY_SET(mac, 0x0811, 0x0030);
7035		BWN_PHY_SET(mac, 0x0812, 0x0030);
7036		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7037		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7038		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7039		if (phy->rev == 0)
7040			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7041		else
7042			BWN_PHY_SET(mac, 0x000a, 0x2000);
7043		if (phy->rev != 1) {
7044			BWN_PHY_SET(mac, 0x0814, 0x0004);
7045			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7046		}
7047		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7048		BWN_RF_SET(mac, 0x007a, 0x000f);
7049		bwn_set_all_gains(mac, 3, 0, 1);
7050		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7051		DELAY(30);
7052		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7053		if (nrssi >= 0x20)
7054			nrssi -= 0x40;
7055		if (nrssi == -32) {
7056			for (i = 0; i < 4; i++) {
7057				BWN_RF_WRITE(mac, 0x007b, i);
7058				DELAY(20);
7059				nrssi = (int16_t)((BWN_PHY_READ(mac,
7060				    0x047f) >> 8) & 0x003f);
7061				if (nrssi >= 0x20)
7062					nrssi -= 0x40;
7063				if (nrssi > -31 && saved == 0xffff)
7064					saved = i;
7065			}
7066			if (saved == 0xffff)
7067				saved = 3;
7068		} else
7069			saved = 0;
7070	}
7071	BWN_RF_WRITE(mac, 0x007b, saved);
7072
7073	/*
7074	 * Restore saved RF/PHY registers
7075	 */
7076	if (phy->rev >= 6) {
7077		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7078			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7079			    save_phy6[phy6_idx]);
7080		}
7081	}
7082	if (phy->rev != 1) {
7083		for (i = 3; i < 5; i++)
7084			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7085			    save_phy_comm[i]);
7086	}
7087	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7088		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7089
7090	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7091		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7092
7093	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7094	BWN_PHY_SET(mac, 0x0429, 0x8000);
7095	bwn_set_original_gains(mac);
7096	if (phy->rev >= 6) {
7097		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7098			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7099			    save_phy6[phy6_idx]);
7100		}
7101	}
7102
7103	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7104	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7105	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7106}
7107
7108static void
7109bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7110    int16_t third)
7111{
7112	struct bwn_phy *phy = &mac->mac_phy;
7113	uint16_t i;
7114	uint16_t start = 0x08, end = 0x18;
7115	uint16_t tmp;
7116	uint16_t table;
7117
7118	if (phy->rev <= 1) {
7119		start = 0x10;
7120		end = 0x20;
7121	}
7122
7123	table = BWN_OFDMTAB_GAINX;
7124	if (phy->rev <= 1)
7125		table = BWN_OFDMTAB_GAINX_R1;
7126	for (i = 0; i < 4; i++)
7127		bwn_ofdmtab_write_2(mac, table, i, first);
7128
7129	for (i = start; i < end; i++)
7130		bwn_ofdmtab_write_2(mac, table, i, second);
7131
7132	if (third != -1) {
7133		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7134		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7135		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7136		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7137	}
7138	bwn_dummy_transmission(mac, 0, 1);
7139}
7140
7141static void
7142bwn_set_original_gains(struct bwn_mac *mac)
7143{
7144	struct bwn_phy *phy = &mac->mac_phy;
7145	uint16_t i, tmp;
7146	uint16_t table;
7147	uint16_t start = 0x0008, end = 0x0018;
7148
7149	if (phy->rev <= 1) {
7150		start = 0x0010;
7151		end = 0x0020;
7152	}
7153
7154	table = BWN_OFDMTAB_GAINX;
7155	if (phy->rev <= 1)
7156		table = BWN_OFDMTAB_GAINX_R1;
7157	for (i = 0; i < 4; i++) {
7158		tmp = (i & 0xfffc);
7159		tmp |= (i & 0x0001) << 1;
7160		tmp |= (i & 0x0002) >> 1;
7161
7162		bwn_ofdmtab_write_2(mac, table, i, tmp);
7163	}
7164
7165	for (i = start; i < end; i++)
7166		bwn_ofdmtab_write_2(mac, table, i, i - start);
7167
7168	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7169	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7170	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7171	bwn_dummy_transmission(mac, 0, 1);
7172}
7173
7174static void
7175bwn_phy_hwpctl_init(struct bwn_mac *mac)
7176{
7177	struct bwn_phy *phy = &mac->mac_phy;
7178	struct bwn_phy_g *pg = &phy->phy_g;
7179	struct bwn_rfatt old_rfatt, rfatt;
7180	struct bwn_bbatt old_bbatt, bbatt;
7181	struct bwn_softc *sc = mac->mac_sc;
7182	uint8_t old_txctl = 0;
7183
7184	KASSERT(phy->type == BWN_PHYTYPE_G,
7185	    ("%s:%d: fail", __func__, __LINE__));
7186
7187	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7188	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7189		return;
7190
7191	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7192
7193	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7194
7195	if (!phy->gmode)
7196		return;
7197	bwn_hwpctl_early_init(mac);
7198	if (pg->pg_curtssi == 0) {
7199		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7200			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7201		} else {
7202			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7203			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7204			old_txctl = pg->pg_txctl;
7205
7206			bbatt.att = 11;
7207			if (phy->rf_rev == 8) {
7208				rfatt.att = 15;
7209				rfatt.padmix = 1;
7210			} else {
7211				rfatt.att = 9;
7212				rfatt.padmix = 0;
7213			}
7214			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7215		}
7216		bwn_dummy_transmission(mac, 0, 1);
7217		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7218		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7219			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7220		else
7221			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7222			    &old_rfatt, old_txctl);
7223	}
7224	bwn_hwpctl_init_gphy(mac);
7225
7226	/* clear TSSI */
7227	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7228	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7229	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7230	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7231}
7232
7233static void
7234bwn_hwpctl_early_init(struct bwn_mac *mac)
7235{
7236	struct bwn_phy *phy = &mac->mac_phy;
7237
7238	if (!bwn_has_hwpctl(mac)) {
7239		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7240		return;
7241	}
7242
7243	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7244	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7245	BWN_PHY_SET(mac, 0x047c, 0x0002);
7246	BWN_PHY_SET(mac, 0x047a, 0xf000);
7247	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7248		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7249		BWN_PHY_SET(mac, 0x005d, 0x8000);
7250		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7251		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7252		BWN_PHY_SET(mac, 0x0036, 0x0400);
7253	} else {
7254		BWN_PHY_SET(mac, 0x0036, 0x0200);
7255		BWN_PHY_SET(mac, 0x0036, 0x0400);
7256		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7257		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7258		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7259		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7260		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7261	}
7262}
7263
7264static void
7265bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7266{
7267	struct bwn_phy *phy = &mac->mac_phy;
7268	struct bwn_phy_g *pg = &phy->phy_g;
7269	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7270	int i;
7271	uint16_t nr_written = 0, tmp, value;
7272	uint8_t rf, bb;
7273
7274	if (!bwn_has_hwpctl(mac)) {
7275		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7276		return;
7277	}
7278
7279	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7280	    (pg->pg_idletssi - pg->pg_curtssi));
7281	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7282	    (pg->pg_idletssi - pg->pg_curtssi));
7283
7284	for (i = 0; i < 32; i++)
7285		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7286	for (i = 32; i < 64; i++)
7287		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7288	for (i = 0; i < 64; i += 2) {
7289		value = (uint16_t) pg->pg_tssi2dbm[i];
7290		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7291		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7292	}
7293
7294	for (rf = 0; rf < lo->rfatt.len; rf++) {
7295		for (bb = 0; bb < lo->bbatt.len; bb++) {
7296			if (nr_written >= 0x40)
7297				return;
7298			tmp = lo->bbatt.array[bb].att;
7299			tmp <<= 8;
7300			if (phy->rf_rev == 8)
7301				tmp |= 0x50;
7302			else
7303				tmp |= 0x40;
7304			tmp |= lo->rfatt.array[rf].att;
7305			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7306			nr_written++;
7307		}
7308	}
7309
7310	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7311	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7312
7313	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7314	BWN_PHY_SET(mac, 0x0478, 0x0800);
7315	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7316	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7317
7318	bwn_phy_g_dc_lookup_init(mac, 1);
7319	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7320}
7321
7322static void
7323bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7324{
7325	struct bwn_softc *sc = mac->mac_sc;
7326
7327	if (spu != 0)
7328		bwn_spu_workaround(mac, channel);
7329
7330	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7331
7332	if (channel == 14) {
7333		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7334			bwn_hf_write(mac,
7335			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7336		else
7337			bwn_hf_write(mac,
7338			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7339		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7340		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7341		return;
7342	}
7343
7344	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7345	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7346}
7347
7348static uint16_t
7349bwn_phy_g_chan2freq(uint8_t channel)
7350{
7351	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7352
7353	KASSERT(channel >= 1 && channel <= 14,
7354	    ("%s:%d: fail", __func__, __LINE__));
7355
7356	return (bwn_phy_g_rf_channels[channel - 1]);
7357}
7358
7359static void
7360bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7361    const struct bwn_rfatt *rfatt, uint8_t txctl)
7362{
7363	struct bwn_phy *phy = &mac->mac_phy;
7364	struct bwn_phy_g *pg = &phy->phy_g;
7365	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7366	uint16_t bb, rf;
7367	uint16_t tx_bias, tx_magn;
7368
7369	bb = bbatt->att;
7370	rf = rfatt->att;
7371	tx_bias = lo->tx_bias;
7372	tx_magn = lo->tx_magn;
7373	if (tx_bias == 0xff)
7374		tx_bias = 0;
7375
7376	pg->pg_txctl = txctl;
7377	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7378	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7379	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7380	bwn_phy_g_set_bbatt(mac, bb);
7381	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7382	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7383		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7384	else {
7385		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7386		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7387	}
7388	if (BWN_HAS_TXMAG(phy))
7389		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7390	else
7391		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7392	bwn_lo_g_adjust(mac);
7393}
7394
7395static void
7396bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7397    uint16_t bbatt)
7398{
7399	struct bwn_phy *phy = &mac->mac_phy;
7400
7401	if (phy->analog == 0) {
7402		BWN_WRITE_2(mac, BWN_PHY0,
7403		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7404		return;
7405	}
7406	if (phy->analog > 1) {
7407		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7408		return;
7409	}
7410	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7411}
7412
7413static uint16_t
7414bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7415{
7416	struct bwn_phy *phy = &mac->mac_phy;
7417	struct bwn_phy_g *pg = &phy->phy_g;
7418	struct bwn_softc *sc = mac->mac_sc;
7419	int max_lb_gain;
7420	uint16_t extlna;
7421	uint16_t i;
7422
7423	if (phy->gmode == 0)
7424		return (0);
7425
7426	if (BWN_HAS_LOOPBACK(phy)) {
7427		max_lb_gain = pg->pg_max_lb_gain;
7428		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7429		if (max_lb_gain >= 0x46) {
7430			extlna = 0x3000;
7431			max_lb_gain -= 0x46;
7432		} else if (max_lb_gain >= 0x3a) {
7433			extlna = 0x1000;
7434			max_lb_gain -= 0x3a;
7435		} else if (max_lb_gain >= 0x2e) {
7436			extlna = 0x2000;
7437			max_lb_gain -= 0x2e;
7438		} else {
7439			extlna = 0;
7440			max_lb_gain -= 0x10;
7441		}
7442
7443		for (i = 0; i < 16; i++) {
7444			max_lb_gain -= (i * 6);
7445			if (max_lb_gain < 6)
7446				break;
7447		}
7448
7449		if ((phy->rev < 7) ||
7450		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7451			if (reg == BWN_PHY_RFOVER) {
7452				return (0x1b3);
7453			} else if (reg == BWN_PHY_RFOVERVAL) {
7454				extlna |= (i << 8);
7455				switch (lpd) {
7456				case BWN_LPD(0, 1, 1):
7457					return (0x0f92);
7458				case BWN_LPD(0, 0, 1):
7459				case BWN_LPD(1, 0, 1):
7460					return (0x0092 | extlna);
7461				case BWN_LPD(1, 0, 0):
7462					return (0x0093 | extlna);
7463				}
7464				KASSERT(0 == 1,
7465				    ("%s:%d: fail", __func__, __LINE__));
7466			}
7467			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7468		} else {
7469			if (reg == BWN_PHY_RFOVER)
7470				return (0x9b3);
7471			if (reg == BWN_PHY_RFOVERVAL) {
7472				if (extlna)
7473					extlna |= 0x8000;
7474				extlna |= (i << 8);
7475				switch (lpd) {
7476				case BWN_LPD(0, 1, 1):
7477					return (0x8f92);
7478				case BWN_LPD(0, 0, 1):
7479					return (0x8092 | extlna);
7480				case BWN_LPD(1, 0, 1):
7481					return (0x2092 | extlna);
7482				case BWN_LPD(1, 0, 0):
7483					return (0x2093 | extlna);
7484				}
7485				KASSERT(0 == 1,
7486				    ("%s:%d: fail", __func__, __LINE__));
7487			}
7488			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7489		}
7490		return (0);
7491	}
7492
7493	if ((phy->rev < 7) ||
7494	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7495		if (reg == BWN_PHY_RFOVER) {
7496			return (0x1b3);
7497		} else if (reg == BWN_PHY_RFOVERVAL) {
7498			switch (lpd) {
7499			case BWN_LPD(0, 1, 1):
7500				return (0x0fb2);
7501			case BWN_LPD(0, 0, 1):
7502				return (0x00b2);
7503			case BWN_LPD(1, 0, 1):
7504				return (0x30b2);
7505			case BWN_LPD(1, 0, 0):
7506				return (0x30b3);
7507			}
7508			KASSERT(0 == 1,
7509			    ("%s:%d: fail", __func__, __LINE__));
7510		}
7511		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7512	} else {
7513		if (reg == BWN_PHY_RFOVER) {
7514			return (0x9b3);
7515		} else if (reg == BWN_PHY_RFOVERVAL) {
7516			switch (lpd) {
7517			case BWN_LPD(0, 1, 1):
7518				return (0x8fb2);
7519			case BWN_LPD(0, 0, 1):
7520				return (0x80b2);
7521			case BWN_LPD(1, 0, 1):
7522				return (0x20b2);
7523			case BWN_LPD(1, 0, 0):
7524				return (0x20b3);
7525			}
7526			KASSERT(0 == 1,
7527			    ("%s:%d: fail", __func__, __LINE__));
7528		}
7529		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7530	}
7531	return (0);
7532}
7533
7534static void
7535bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7536{
7537
7538	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7539		return;
7540	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7541	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7542	DELAY(1000);
7543	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7544}
7545
7546static int
7547bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7548{
7549	struct bwn_softc *sc = mac->mac_sc;
7550	struct bwn_fw *fw = &mac->mac_fw;
7551	const uint8_t rev = siba_get_revid(sc->sc_dev);
7552	const char *filename;
7553	uint32_t high;
7554	int error;
7555
7556	/* microcode */
7557	if (rev >= 5 && rev <= 10)
7558		filename = "ucode5";
7559	else if (rev >= 11 && rev <= 12)
7560		filename = "ucode11";
7561	else if (rev == 13)
7562		filename = "ucode13";
7563	else if (rev == 14)
7564		filename = "ucode14";
7565	else if (rev >= 15)
7566		filename = "ucode15";
7567	else {
7568		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7569		bwn_release_firmware(mac);
7570		return (EOPNOTSUPP);
7571	}
7572	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7573	if (error) {
7574		bwn_release_firmware(mac);
7575		return (error);
7576	}
7577
7578	/* PCM */
7579	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7580	if (rev >= 5 && rev <= 10) {
7581		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7582		if (error == ENOENT)
7583			fw->no_pcmfile = 1;
7584		else if (error) {
7585			bwn_release_firmware(mac);
7586			return (error);
7587		}
7588	} else if (rev < 11) {
7589		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7590		return (EOPNOTSUPP);
7591	}
7592
7593	/* initvals */
7594	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7595	switch (mac->mac_phy.type) {
7596	case BWN_PHYTYPE_A:
7597		if (rev < 5 || rev > 10)
7598			goto fail1;
7599		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7600			filename = "a0g1initvals5";
7601		else
7602			filename = "a0g0initvals5";
7603		break;
7604	case BWN_PHYTYPE_G:
7605		if (rev >= 5 && rev <= 10)
7606			filename = "b0g0initvals5";
7607		else if (rev >= 13)
7608			filename = "b0g0initvals13";
7609		else
7610			goto fail1;
7611		break;
7612	case BWN_PHYTYPE_LP:
7613		if (rev == 13)
7614			filename = "lp0initvals13";
7615		else if (rev == 14)
7616			filename = "lp0initvals14";
7617		else if (rev >= 15)
7618			filename = "lp0initvals15";
7619		else
7620			goto fail1;
7621		break;
7622	case BWN_PHYTYPE_N:
7623		if (rev >= 11 && rev <= 12)
7624			filename = "n0initvals11";
7625		else
7626			goto fail1;
7627		break;
7628	default:
7629		goto fail1;
7630	}
7631	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7632	if (error) {
7633		bwn_release_firmware(mac);
7634		return (error);
7635	}
7636
7637	/* bandswitch initvals */
7638	switch (mac->mac_phy.type) {
7639	case BWN_PHYTYPE_A:
7640		if (rev >= 5 && rev <= 10) {
7641			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7642				filename = "a0g1bsinitvals5";
7643			else
7644				filename = "a0g0bsinitvals5";
7645		} else if (rev >= 11)
7646			filename = NULL;
7647		else
7648			goto fail1;
7649		break;
7650	case BWN_PHYTYPE_G:
7651		if (rev >= 5 && rev <= 10)
7652			filename = "b0g0bsinitvals5";
7653		else if (rev >= 11)
7654			filename = NULL;
7655		else
7656			goto fail1;
7657		break;
7658	case BWN_PHYTYPE_LP:
7659		if (rev == 13)
7660			filename = "lp0bsinitvals13";
7661		else if (rev == 14)
7662			filename = "lp0bsinitvals14";
7663		else if (rev >= 15)
7664			filename = "lp0bsinitvals15";
7665		else
7666			goto fail1;
7667		break;
7668	case BWN_PHYTYPE_N:
7669		if (rev >= 11 && rev <= 12)
7670			filename = "n0bsinitvals11";
7671		else
7672			goto fail1;
7673		break;
7674	default:
7675		goto fail1;
7676	}
7677	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7678	if (error) {
7679		bwn_release_firmware(mac);
7680		return (error);
7681	}
7682	return (0);
7683fail1:
7684	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7685	bwn_release_firmware(mac);
7686	return (EOPNOTSUPP);
7687}
7688
7689static int
7690bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7691    const char *name, struct bwn_fwfile *bfw)
7692{
7693	const struct bwn_fwhdr *hdr;
7694	struct bwn_softc *sc = mac->mac_sc;
7695	const struct firmware *fw;
7696	char namebuf[64];
7697
7698	if (name == NULL) {
7699		bwn_do_release_fw(bfw);
7700		return (0);
7701	}
7702	if (bfw->filename != NULL) {
7703		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7704			return (0);
7705		bwn_do_release_fw(bfw);
7706	}
7707
7708	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7709	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7710	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7711	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7712	fw = firmware_get(namebuf);
7713	if (fw == NULL) {
7714		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7715		    namebuf);
7716		return (ENOENT);
7717	}
7718	if (fw->datasize < sizeof(struct bwn_fwhdr))
7719		goto fail;
7720	hdr = (const struct bwn_fwhdr *)(fw->data);
7721	switch (hdr->type) {
7722	case BWN_FWTYPE_UCODE:
7723	case BWN_FWTYPE_PCM:
7724		if (be32toh(hdr->size) !=
7725		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7726			goto fail;
7727		/* FALLTHROUGH */
7728	case BWN_FWTYPE_IV:
7729		if (hdr->ver != 1)
7730			goto fail;
7731		break;
7732	default:
7733		goto fail;
7734	}
7735	bfw->filename = name;
7736	bfw->fw = fw;
7737	bfw->type = type;
7738	return (0);
7739fail:
7740	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7741	if (fw != NULL)
7742		firmware_put(fw, FIRMWARE_UNLOAD);
7743	return (EPROTO);
7744}
7745
7746static void
7747bwn_release_firmware(struct bwn_mac *mac)
7748{
7749
7750	bwn_do_release_fw(&mac->mac_fw.ucode);
7751	bwn_do_release_fw(&mac->mac_fw.pcm);
7752	bwn_do_release_fw(&mac->mac_fw.initvals);
7753	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7754}
7755
7756static void
7757bwn_do_release_fw(struct bwn_fwfile *bfw)
7758{
7759
7760	if (bfw->fw != NULL)
7761		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7762	bfw->fw = NULL;
7763	bfw->filename = NULL;
7764}
7765
7766static int
7767bwn_fw_loaducode(struct bwn_mac *mac)
7768{
7769#define	GETFWOFFSET(fwp, offset)	\
7770	((const uint32_t *)((const char *)fwp.fw->data + offset))
7771#define	GETFWSIZE(fwp, offset)	\
7772	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7773	struct bwn_softc *sc = mac->mac_sc;
7774	const uint32_t *data;
7775	unsigned int i;
7776	uint32_t ctl;
7777	uint16_t date, fwcaps, time;
7778	int error = 0;
7779
7780	ctl = BWN_READ_4(mac, BWN_MACCTL);
7781	ctl |= BWN_MACCTL_MCODE_JMP0;
7782	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7783	    __LINE__));
7784	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7785	for (i = 0; i < 64; i++)
7786		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7787	for (i = 0; i < 4096; i += 2)
7788		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7789
7790	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7791	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7792	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7793	     i++) {
7794		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7795		DELAY(10);
7796	}
7797
7798	if (mac->mac_fw.pcm.fw) {
7799		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7800		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7801		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7802		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7803		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7804		    sizeof(struct bwn_fwhdr)); i++) {
7805			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7806			DELAY(10);
7807		}
7808	}
7809
7810	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7811	BWN_WRITE_4(mac, BWN_MACCTL,
7812	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7813	    BWN_MACCTL_MCODE_RUN);
7814
7815	for (i = 0; i < 21; i++) {
7816		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7817			break;
7818		if (i >= 20) {
7819			device_printf(sc->sc_dev, "ucode timeout\n");
7820			error = ENXIO;
7821			goto error;
7822		}
7823		DELAY(50000);
7824	}
7825	BWN_READ_4(mac, BWN_INTR_REASON);
7826
7827	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7828	if (mac->mac_fw.rev <= 0x128) {
7829		device_printf(sc->sc_dev, "the firmware is too old\n");
7830		error = EOPNOTSUPP;
7831		goto error;
7832	}
7833	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7834	    BWN_SHARED_UCODE_PATCH);
7835	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7836	mac->mac_fw.opensource = (date == 0xffff);
7837	if (bwn_wme != 0)
7838		mac->mac_flags |= BWN_MAC_FLAG_WME;
7839	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7840
7841	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7842	if (mac->mac_fw.opensource == 0) {
7843		device_printf(sc->sc_dev,
7844		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7845		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7846		if (mac->mac_fw.no_pcmfile)
7847			device_printf(sc->sc_dev,
7848			    "no HW crypto acceleration due to pcm5\n");
7849	} else {
7850		mac->mac_fw.patch = time;
7851		fwcaps = bwn_fwcaps_read(mac);
7852		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7853			device_printf(sc->sc_dev,
7854			    "disabling HW crypto acceleration\n");
7855			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7856		}
7857		if (!(fwcaps & BWN_FWCAPS_WME)) {
7858			device_printf(sc->sc_dev, "disabling WME support\n");
7859			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7860		}
7861	}
7862
7863	if (BWN_ISOLDFMT(mac))
7864		device_printf(sc->sc_dev, "using old firmware image\n");
7865
7866	return (0);
7867
7868error:
7869	BWN_WRITE_4(mac, BWN_MACCTL,
7870	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7871	    BWN_MACCTL_MCODE_JMP0);
7872
7873	return (error);
7874#undef GETFWSIZE
7875#undef GETFWOFFSET
7876}
7877
7878/* OpenFirmware only */
7879static uint16_t
7880bwn_fwcaps_read(struct bwn_mac *mac)
7881{
7882
7883	KASSERT(mac->mac_fw.opensource == 1,
7884	    ("%s:%d: fail", __func__, __LINE__));
7885	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7886}
7887
7888static int
7889bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7890    size_t count, size_t array_size)
7891{
7892#define	GET_NEXTIV16(iv)						\
7893	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7894	    sizeof(uint16_t) + sizeof(uint16_t)))
7895#define	GET_NEXTIV32(iv)						\
7896	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7897	    sizeof(uint16_t) + sizeof(uint32_t)))
7898	struct bwn_softc *sc = mac->mac_sc;
7899	const struct bwn_fwinitvals *iv;
7900	uint16_t offset;
7901	size_t i;
7902	uint8_t bit32;
7903
7904	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7905	    ("%s:%d: fail", __func__, __LINE__));
7906	iv = ivals;
7907	for (i = 0; i < count; i++) {
7908		if (array_size < sizeof(iv->offset_size))
7909			goto fail;
7910		array_size -= sizeof(iv->offset_size);
7911		offset = be16toh(iv->offset_size);
7912		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7913		offset &= BWN_FWINITVALS_OFFSET_MASK;
7914		if (offset >= 0x1000)
7915			goto fail;
7916		if (bit32) {
7917			if (array_size < sizeof(iv->data.d32))
7918				goto fail;
7919			array_size -= sizeof(iv->data.d32);
7920			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7921			iv = GET_NEXTIV32(iv);
7922		} else {
7923
7924			if (array_size < sizeof(iv->data.d16))
7925				goto fail;
7926			array_size -= sizeof(iv->data.d16);
7927			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7928
7929			iv = GET_NEXTIV16(iv);
7930		}
7931	}
7932	if (array_size != 0)
7933		goto fail;
7934	return (0);
7935fail:
7936	device_printf(sc->sc_dev, "initvals: invalid format\n");
7937	return (EPROTO);
7938#undef GET_NEXTIV16
7939#undef GET_NEXTIV32
7940}
7941
7942static int
7943bwn_switch_channel(struct bwn_mac *mac, int chan)
7944{
7945	struct bwn_phy *phy = &(mac->mac_phy);
7946	struct bwn_softc *sc = mac->mac_sc;
7947	struct ifnet *ifp = sc->sc_ifp;
7948	struct ieee80211com *ic = ifp->if_l2com;
7949	uint16_t channelcookie, savedcookie;
7950	int error;
7951
7952	if (chan == 0xffff)
7953		chan = phy->get_default_chan(mac);
7954
7955	channelcookie = chan;
7956	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7957		channelcookie |= 0x100;
7958	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7959	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7960	error = phy->switch_channel(mac, chan);
7961	if (error)
7962		goto fail;
7963
7964	mac->mac_phy.chan = chan;
7965	DELAY(8000);
7966	return (0);
7967fail:
7968	device_printf(sc->sc_dev, "failed to switch channel\n");
7969	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7970	return (error);
7971}
7972
7973static uint16_t
7974bwn_ant2phy(int antenna)
7975{
7976
7977	switch (antenna) {
7978	case BWN_ANT0:
7979		return (BWN_TX_PHY_ANT0);
7980	case BWN_ANT1:
7981		return (BWN_TX_PHY_ANT1);
7982	case BWN_ANT2:
7983		return (BWN_TX_PHY_ANT2);
7984	case BWN_ANT3:
7985		return (BWN_TX_PHY_ANT3);
7986	case BWN_ANTAUTO:
7987		return (BWN_TX_PHY_ANT01AUTO);
7988	}
7989	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7990	return (0);
7991}
7992
7993static void
7994bwn_wme_load(struct bwn_mac *mac)
7995{
7996	struct bwn_softc *sc = mac->mac_sc;
7997	int i;
7998
7999	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8000	    ("%s:%d: fail", __func__, __LINE__));
8001
8002	bwn_mac_suspend(mac);
8003	for (i = 0; i < N(sc->sc_wmeParams); i++)
8004		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8005		    bwn_wme_shm_offsets[i]);
8006	bwn_mac_enable(mac);
8007}
8008
8009static void
8010bwn_wme_loadparams(struct bwn_mac *mac,
8011    const struct wmeParams *p, uint16_t shm_offset)
8012{
8013#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8014	struct bwn_softc *sc = mac->mac_sc;
8015	uint16_t params[BWN_NR_WMEPARAMS];
8016	int slot, tmp;
8017	unsigned int i;
8018
8019	slot = BWN_READ_2(mac, BWN_RNG) &
8020	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8021
8022	memset(&params, 0, sizeof(params));
8023
8024	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8025	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8026	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8027
8028	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8029	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8030	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8031	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8032	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8033	params[BWN_WMEPARAM_BSLOTS] = slot;
8034	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8035
8036	for (i = 0; i < N(params); i++) {
8037		if (i == BWN_WMEPARAM_STATUS) {
8038			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8039			    shm_offset + (i * 2));
8040			tmp |= 0x100;
8041			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8042			    tmp);
8043		} else {
8044			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8045			    params[i]);
8046		}
8047	}
8048}
8049
8050static void
8051bwn_mac_write_bssid(struct bwn_mac *mac)
8052{
8053	struct bwn_softc *sc = mac->mac_sc;
8054	uint32_t tmp;
8055	int i;
8056	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8057
8058	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8059	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8060	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8061	    IEEE80211_ADDR_LEN);
8062
8063	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8064		tmp = (uint32_t) (mac_bssid[i + 0]);
8065		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8066		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8067		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8068		bwn_ram_write(mac, 0x20 + i, tmp);
8069	}
8070}
8071
8072static void
8073bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8074    const uint8_t *macaddr)
8075{
8076	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8077	uint16_t data;
8078
8079	if (!mac)
8080		macaddr = zero;
8081
8082	offset |= 0x0020;
8083	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8084
8085	data = macaddr[0];
8086	data |= macaddr[1] << 8;
8087	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8088	data = macaddr[2];
8089	data |= macaddr[3] << 8;
8090	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8091	data = macaddr[4];
8092	data |= macaddr[5] << 8;
8093	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8094}
8095
8096static void
8097bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8098    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8099{
8100	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8101	uint8_t per_sta_keys_start = 8;
8102
8103	if (BWN_SEC_NEWAPI(mac))
8104		per_sta_keys_start = 4;
8105
8106	KASSERT(index < mac->mac_max_nr_keys,
8107	    ("%s:%d: fail", __func__, __LINE__));
8108	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8109	    ("%s:%d: fail", __func__, __LINE__));
8110
8111	if (index >= per_sta_keys_start)
8112		bwn_key_macwrite(mac, index, NULL);
8113	if (key)
8114		memcpy(buf, key, key_len);
8115	bwn_key_write(mac, index, algorithm, buf);
8116	if (index >= per_sta_keys_start)
8117		bwn_key_macwrite(mac, index, mac_addr);
8118
8119	mac->mac_key[index].algorithm = algorithm;
8120}
8121
8122static void
8123bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8124{
8125	struct bwn_softc *sc = mac->mac_sc;
8126	uint32_t addrtmp[2] = { 0, 0 };
8127	uint8_t start = 8;
8128
8129	if (BWN_SEC_NEWAPI(mac))
8130		start = 4;
8131
8132	KASSERT(index >= start,
8133	    ("%s:%d: fail", __func__, __LINE__));
8134	index -= start;
8135
8136	if (addr) {
8137		addrtmp[0] = addr[0];
8138		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8139		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8140		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8141		addrtmp[1] = addr[4];
8142		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8143	}
8144
8145	if (siba_get_revid(sc->sc_dev) >= 5) {
8146		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8147		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8148	} else {
8149		if (index >= 8) {
8150			bwn_shm_write_4(mac, BWN_SHARED,
8151			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8152			bwn_shm_write_2(mac, BWN_SHARED,
8153			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8154		}
8155	}
8156}
8157
8158static void
8159bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8160    const uint8_t *key)
8161{
8162	unsigned int i;
8163	uint32_t offset;
8164	uint16_t kidx, value;
8165
8166	kidx = BWN_SEC_KEY2FW(mac, index);
8167	bwn_shm_write_2(mac, BWN_SHARED,
8168	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8169
8170	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8171	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8172		value = key[i];
8173		value |= (uint16_t)(key[i + 1]) << 8;
8174		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8175	}
8176}
8177
8178static void
8179bwn_phy_exit(struct bwn_mac *mac)
8180{
8181
8182	mac->mac_phy.rf_onoff(mac, 0);
8183	if (mac->mac_phy.exit != NULL)
8184		mac->mac_phy.exit(mac);
8185}
8186
8187static void
8188bwn_dma_free(struct bwn_mac *mac)
8189{
8190	struct bwn_dma *dma;
8191
8192	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8193		return;
8194	dma = &mac->mac_method.dma;
8195
8196	bwn_dma_ringfree(&dma->rx);
8197	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8198	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8199	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8200	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8201	bwn_dma_ringfree(&dma->mcast);
8202}
8203
8204static void
8205bwn_core_stop(struct bwn_mac *mac)
8206{
8207	struct bwn_softc *sc = mac->mac_sc;
8208
8209	BWN_ASSERT_LOCKED(sc);
8210
8211	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8212		return;
8213
8214	callout_stop(&sc->sc_rfswitch_ch);
8215	callout_stop(&sc->sc_task_ch);
8216	callout_stop(&sc->sc_watchdog_ch);
8217	sc->sc_watchdog_timer = 0;
8218	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8219	BWN_READ_4(mac, BWN_INTR_MASK);
8220	bwn_mac_suspend(mac);
8221
8222	mac->mac_status = BWN_MAC_STATUS_INITED;
8223}
8224
8225static int
8226bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8227{
8228	struct bwn_mac *up_dev = NULL;
8229	struct bwn_mac *down_dev;
8230	struct bwn_mac *mac;
8231	int err, status;
8232	uint8_t gmode;
8233
8234	BWN_ASSERT_LOCKED(sc);
8235
8236	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8237		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8238		    mac->mac_phy.supports_2ghz) {
8239			up_dev = mac;
8240			gmode = 1;
8241		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8242		    mac->mac_phy.supports_5ghz) {
8243			up_dev = mac;
8244			gmode = 0;
8245		} else {
8246			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8247			return (EINVAL);
8248		}
8249		if (up_dev != NULL)
8250			break;
8251	}
8252	if (up_dev == NULL) {
8253		device_printf(sc->sc_dev, "Could not find a device\n");
8254		return (ENODEV);
8255	}
8256	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8257		return (0);
8258
8259	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8260	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8261
8262	down_dev = sc->sc_curmac;
8263	status = down_dev->mac_status;
8264	if (status >= BWN_MAC_STATUS_STARTED)
8265		bwn_core_stop(down_dev);
8266	if (status >= BWN_MAC_STATUS_INITED)
8267		bwn_core_exit(down_dev);
8268
8269	if (down_dev != up_dev)
8270		bwn_phy_reset(down_dev);
8271
8272	up_dev->mac_phy.gmode = gmode;
8273	if (status >= BWN_MAC_STATUS_INITED) {
8274		err = bwn_core_init(up_dev);
8275		if (err) {
8276			device_printf(sc->sc_dev,
8277			    "fatal: failed to initialize for %s-GHz\n",
8278			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8279			goto fail;
8280		}
8281	}
8282	if (status >= BWN_MAC_STATUS_STARTED)
8283		bwn_core_start(up_dev);
8284	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8285	sc->sc_curmac = up_dev;
8286
8287	return (0);
8288fail:
8289	sc->sc_curmac = NULL;
8290	return (err);
8291}
8292
8293static void
8294bwn_rf_turnon(struct bwn_mac *mac)
8295{
8296
8297	bwn_mac_suspend(mac);
8298	mac->mac_phy.rf_onoff(mac, 1);
8299	mac->mac_phy.rf_on = 1;
8300	bwn_mac_enable(mac);
8301}
8302
8303static void
8304bwn_rf_turnoff(struct bwn_mac *mac)
8305{
8306
8307	bwn_mac_suspend(mac);
8308	mac->mac_phy.rf_onoff(mac, 0);
8309	mac->mac_phy.rf_on = 0;
8310	bwn_mac_enable(mac);
8311}
8312
8313static void
8314bwn_phy_reset(struct bwn_mac *mac)
8315{
8316	struct bwn_softc *sc = mac->mac_sc;
8317
8318	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8319	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8320	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8321	DELAY(1000);
8322	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8323	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8324	    BWN_TGSLOW_PHYRESET);
8325	DELAY(1000);
8326}
8327
8328static int
8329bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8330{
8331	struct bwn_vap *bvp = BWN_VAP(vap);
8332	struct ieee80211com *ic= vap->iv_ic;
8333	struct ifnet *ifp = ic->ic_ifp;
8334	enum ieee80211_state ostate = vap->iv_state;
8335	struct bwn_softc *sc = ifp->if_softc;
8336	struct bwn_mac *mac = sc->sc_curmac;
8337	int error;
8338
8339	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8340	    ieee80211_state_name[vap->iv_state],
8341	    ieee80211_state_name[nstate]);
8342
8343	error = bvp->bv_newstate(vap, nstate, arg);
8344	if (error != 0)
8345		return (error);
8346
8347	BWN_LOCK(sc);
8348
8349	bwn_led_newstate(mac, nstate);
8350
8351	/*
8352	 * Clear the BSSID when we stop a STA
8353	 */
8354	if (vap->iv_opmode == IEEE80211_M_STA) {
8355		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8356			/*
8357			 * Clear out the BSSID.  If we reassociate to
8358			 * the same AP, this will reinialize things
8359			 * correctly...
8360			 */
8361			if (ic->ic_opmode == IEEE80211_M_STA &&
8362			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8363				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8364				bwn_set_macaddr(mac);
8365			}
8366		}
8367	}
8368
8369	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8370	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8371		/* XXX nothing to do? */
8372	} else if (nstate == IEEE80211_S_RUN) {
8373		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8374		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8375		bwn_set_opmode(mac);
8376		bwn_set_pretbtt(mac);
8377		bwn_spu_setdelay(mac, 0);
8378		bwn_set_macaddr(mac);
8379	}
8380
8381	BWN_UNLOCK(sc);
8382
8383	return (error);
8384}
8385
8386static void
8387bwn_set_pretbtt(struct bwn_mac *mac)
8388{
8389	struct bwn_softc *sc = mac->mac_sc;
8390	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8391	uint16_t pretbtt;
8392
8393	if (ic->ic_opmode == IEEE80211_M_IBSS)
8394		pretbtt = 2;
8395	else
8396		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8397	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8398	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8399}
8400
8401static int
8402bwn_intr(void *arg)
8403{
8404	struct bwn_mac *mac = arg;
8405	struct bwn_softc *sc = mac->mac_sc;
8406	uint32_t reason;
8407
8408	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8409	    (sc->sc_flags & BWN_FLAG_INVALID))
8410		return (FILTER_STRAY);
8411
8412	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8413	if (reason == 0xffffffff)	/* shared IRQ */
8414		return (FILTER_STRAY);
8415	reason &= mac->mac_intr_mask;
8416	if (reason == 0)
8417		return (FILTER_HANDLED);
8418
8419	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8420	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8421	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8422	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8423	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8424	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8425	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8426	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8427	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8428	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8429	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8430
8431	/* Disable interrupts. */
8432	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8433
8434	mac->mac_reason_intr = reason;
8435
8436	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8437	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8438
8439	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8440	return (FILTER_HANDLED);
8441}
8442
8443static void
8444bwn_intrtask(void *arg, int npending)
8445{
8446	struct bwn_mac *mac = arg;
8447	struct bwn_softc *sc = mac->mac_sc;
8448	struct ifnet *ifp = sc->sc_ifp;
8449	uint32_t merged = 0;
8450	int i, tx = 0, rx = 0;
8451
8452	BWN_LOCK(sc);
8453	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8454	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8455		BWN_UNLOCK(sc);
8456		return;
8457	}
8458
8459	for (i = 0; i < N(mac->mac_reason); i++)
8460		merged |= mac->mac_reason[i];
8461
8462	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8463		device_printf(sc->sc_dev, "MAC trans error\n");
8464
8465	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8466		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8467		mac->mac_phy.txerrors--;
8468		if (mac->mac_phy.txerrors == 0) {
8469			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8470			bwn_restart(mac, "PHY TX errors");
8471		}
8472	}
8473
8474	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8475		if (merged & BWN_DMAINTR_FATALMASK) {
8476			device_printf(sc->sc_dev,
8477			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8478			    mac->mac_reason[0], mac->mac_reason[1],
8479			    mac->mac_reason[2], mac->mac_reason[3],
8480			    mac->mac_reason[4], mac->mac_reason[5]);
8481			bwn_restart(mac, "DMA error");
8482			BWN_UNLOCK(sc);
8483			return;
8484		}
8485		if (merged & BWN_DMAINTR_NONFATALMASK) {
8486			device_printf(sc->sc_dev,
8487			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8488			    mac->mac_reason[0], mac->mac_reason[1],
8489			    mac->mac_reason[2], mac->mac_reason[3],
8490			    mac->mac_reason[4], mac->mac_reason[5]);
8491		}
8492	}
8493
8494	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8495		bwn_intr_ucode_debug(mac);
8496	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8497		bwn_intr_tbtt_indication(mac);
8498	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8499		bwn_intr_atim_end(mac);
8500	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8501		bwn_intr_beacon(mac);
8502	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8503		bwn_intr_pmq(mac);
8504	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8505		bwn_intr_noise(mac);
8506
8507	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8508		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8509			bwn_dma_rx(mac->mac_method.dma.rx);
8510			rx = 1;
8511		}
8512	} else
8513		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8514
8515	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8519	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8520
8521	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8522		bwn_intr_txeof(mac);
8523		tx = 1;
8524	}
8525
8526	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8527
8528	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8529		int evt = BWN_LED_EVENT_NONE;
8530
8531		if (tx && rx) {
8532			if (sc->sc_rx_rate > sc->sc_tx_rate)
8533				evt = BWN_LED_EVENT_RX;
8534			else
8535				evt = BWN_LED_EVENT_TX;
8536		} else if (tx) {
8537			evt = BWN_LED_EVENT_TX;
8538		} else if (rx) {
8539			evt = BWN_LED_EVENT_RX;
8540		} else if (rx == 0) {
8541			evt = BWN_LED_EVENT_POLL;
8542		}
8543
8544		if (evt != BWN_LED_EVENT_NONE)
8545			bwn_led_event(mac, evt);
8546       }
8547
8548	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8549		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8550			bwn_start_locked(ifp);
8551	}
8552
8553	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8554	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8555
8556	BWN_UNLOCK(sc);
8557}
8558
8559static void
8560bwn_restart(struct bwn_mac *mac, const char *msg)
8561{
8562	struct bwn_softc *sc = mac->mac_sc;
8563	struct ifnet *ifp = sc->sc_ifp;
8564	struct ieee80211com *ic = ifp->if_l2com;
8565
8566	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8567		return;
8568
8569	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8570	ieee80211_runtask(ic, &mac->mac_hwreset);
8571}
8572
8573static void
8574bwn_intr_ucode_debug(struct bwn_mac *mac)
8575{
8576	struct bwn_softc *sc = mac->mac_sc;
8577	uint16_t reason;
8578
8579	if (mac->mac_fw.opensource == 0)
8580		return;
8581
8582	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8583	switch (reason) {
8584	case BWN_DEBUGINTR_PANIC:
8585		bwn_handle_fwpanic(mac);
8586		break;
8587	case BWN_DEBUGINTR_DUMP_SHM:
8588		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8589		break;
8590	case BWN_DEBUGINTR_DUMP_REGS:
8591		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8592		break;
8593	case BWN_DEBUGINTR_MARKER:
8594		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8595		break;
8596	default:
8597		device_printf(sc->sc_dev,
8598		    "ucode debug unknown reason: %#x\n", reason);
8599	}
8600
8601	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8602	    BWN_DEBUGINTR_ACK);
8603}
8604
8605static void
8606bwn_intr_tbtt_indication(struct bwn_mac *mac)
8607{
8608	struct bwn_softc *sc = mac->mac_sc;
8609	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8610
8611	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8612		bwn_psctl(mac, 0);
8613	if (ic->ic_opmode == IEEE80211_M_IBSS)
8614		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8615}
8616
8617static void
8618bwn_intr_atim_end(struct bwn_mac *mac)
8619{
8620
8621	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8622		BWN_WRITE_4(mac, BWN_MACCMD,
8623		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8624		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8625	}
8626}
8627
8628static void
8629bwn_intr_beacon(struct bwn_mac *mac)
8630{
8631	struct bwn_softc *sc = mac->mac_sc;
8632	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8633	uint32_t cmd, beacon0, beacon1;
8634
8635	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8636	    ic->ic_opmode == IEEE80211_M_MBSS)
8637		return;
8638
8639	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8640
8641	cmd = BWN_READ_4(mac, BWN_MACCMD);
8642	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8643	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8644
8645	if (beacon0 && beacon1) {
8646		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8647		mac->mac_intr_mask |= BWN_INTR_BEACON;
8648		return;
8649	}
8650
8651	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8652		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8653		bwn_load_beacon0(mac);
8654		bwn_load_beacon1(mac);
8655		cmd = BWN_READ_4(mac, BWN_MACCMD);
8656		cmd |= BWN_MACCMD_BEACON0_VALID;
8657		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8658	} else {
8659		if (!beacon0) {
8660			bwn_load_beacon0(mac);
8661			cmd = BWN_READ_4(mac, BWN_MACCMD);
8662			cmd |= BWN_MACCMD_BEACON0_VALID;
8663			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8664		} else if (!beacon1) {
8665			bwn_load_beacon1(mac);
8666			cmd = BWN_READ_4(mac, BWN_MACCMD);
8667			cmd |= BWN_MACCMD_BEACON1_VALID;
8668			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8669		}
8670	}
8671}
8672
8673static void
8674bwn_intr_pmq(struct bwn_mac *mac)
8675{
8676	uint32_t tmp;
8677
8678	while (1) {
8679		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8680		if (!(tmp & 0x00000008))
8681			break;
8682	}
8683	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8684}
8685
8686static void
8687bwn_intr_noise(struct bwn_mac *mac)
8688{
8689	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8690	uint16_t tmp;
8691	uint8_t noise[4];
8692	uint8_t i, j;
8693	int32_t average;
8694
8695	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8696		return;
8697
8698	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8699	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8700	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8701	    noise[3] == 0x7f)
8702		goto new;
8703
8704	KASSERT(mac->mac_noise.noi_nsamples < 8,
8705	    ("%s:%d: fail", __func__, __LINE__));
8706	i = mac->mac_noise.noi_nsamples;
8707	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8708	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8709	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8710	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8711	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8712	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8713	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8714	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8715	mac->mac_noise.noi_nsamples++;
8716	if (mac->mac_noise.noi_nsamples == 8) {
8717		average = 0;
8718		for (i = 0; i < 8; i++) {
8719			for (j = 0; j < 4; j++)
8720				average += mac->mac_noise.noi_samples[i][j];
8721		}
8722		average = (((average / 32) * 125) + 64) / 128;
8723		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8724		if (tmp >= 8)
8725			average += 2;
8726		else
8727			average -= 25;
8728		average -= (tmp == 8) ? 72 : 48;
8729
8730		mac->mac_stats.link_noise = average;
8731		mac->mac_noise.noi_running = 0;
8732		return;
8733	}
8734new:
8735	bwn_noise_gensample(mac);
8736}
8737
8738static int
8739bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8740{
8741	struct bwn_mac *mac = prq->prq_mac;
8742	struct bwn_softc *sc = mac->mac_sc;
8743	unsigned int i;
8744
8745	BWN_ASSERT_LOCKED(sc);
8746
8747	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8748		return (0);
8749
8750	for (i = 0; i < 5000; i++) {
8751		if (bwn_pio_rxeof(prq) == 0)
8752			break;
8753	}
8754	if (i >= 5000)
8755		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8756	return ((i > 0) ? 1 : 0);
8757}
8758
8759static void
8760bwn_dma_rx(struct bwn_dma_ring *dr)
8761{
8762	int slot, curslot;
8763
8764	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8765	curslot = dr->get_curslot(dr);
8766	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8767	    ("%s:%d: fail", __func__, __LINE__));
8768
8769	slot = dr->dr_curslot;
8770	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8771		bwn_dma_rxeof(dr, &slot);
8772
8773	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8774	    BUS_DMASYNC_PREWRITE);
8775
8776	dr->set_curslot(dr, slot);
8777	dr->dr_curslot = slot;
8778}
8779
8780static void
8781bwn_intr_txeof(struct bwn_mac *mac)
8782{
8783	struct bwn_txstatus stat;
8784	uint32_t stat0, stat1;
8785	uint16_t tmp;
8786
8787	BWN_ASSERT_LOCKED(mac->mac_sc);
8788
8789	while (1) {
8790		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8791		if (!(stat0 & 0x00000001))
8792			break;
8793		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8794
8795		stat.cookie = (stat0 >> 16);
8796		stat.seq = (stat1 & 0x0000ffff);
8797		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8798		tmp = (stat0 & 0x0000ffff);
8799		stat.framecnt = ((tmp & 0xf000) >> 12);
8800		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8801		stat.sreason = ((tmp & 0x001c) >> 2);
8802		stat.pm = (tmp & 0x0080) ? 1 : 0;
8803		stat.im = (tmp & 0x0040) ? 1 : 0;
8804		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8805		stat.ack = (tmp & 0x0002) ? 1 : 0;
8806
8807		bwn_handle_txeof(mac, &stat);
8808	}
8809}
8810
8811static void
8812bwn_hwreset(void *arg, int npending)
8813{
8814	struct bwn_mac *mac = arg;
8815	struct bwn_softc *sc = mac->mac_sc;
8816	int error = 0;
8817	int prev_status;
8818
8819	BWN_LOCK(sc);
8820
8821	prev_status = mac->mac_status;
8822	if (prev_status >= BWN_MAC_STATUS_STARTED)
8823		bwn_core_stop(mac);
8824	if (prev_status >= BWN_MAC_STATUS_INITED)
8825		bwn_core_exit(mac);
8826
8827	if (prev_status >= BWN_MAC_STATUS_INITED) {
8828		error = bwn_core_init(mac);
8829		if (error)
8830			goto out;
8831	}
8832	if (prev_status >= BWN_MAC_STATUS_STARTED)
8833		bwn_core_start(mac);
8834out:
8835	if (error) {
8836		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8837		sc->sc_curmac = NULL;
8838	}
8839	BWN_UNLOCK(sc);
8840}
8841
8842static void
8843bwn_handle_fwpanic(struct bwn_mac *mac)
8844{
8845	struct bwn_softc *sc = mac->mac_sc;
8846	uint16_t reason;
8847
8848	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8849	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8850
8851	if (reason == BWN_FWPANIC_RESTART)
8852		bwn_restart(mac, "ucode panic");
8853}
8854
8855static void
8856bwn_load_beacon0(struct bwn_mac *mac)
8857{
8858
8859	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8860}
8861
8862static void
8863bwn_load_beacon1(struct bwn_mac *mac)
8864{
8865
8866	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8867}
8868
8869static uint32_t
8870bwn_jssi_read(struct bwn_mac *mac)
8871{
8872	uint32_t val = 0;
8873
8874	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8875	val <<= 16;
8876	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8877
8878	return (val);
8879}
8880
8881static void
8882bwn_noise_gensample(struct bwn_mac *mac)
8883{
8884	uint32_t jssi = 0x7f7f7f7f;
8885
8886	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8887	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8888	BWN_WRITE_4(mac, BWN_MACCMD,
8889	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8890}
8891
8892static int
8893bwn_dma_freeslot(struct bwn_dma_ring *dr)
8894{
8895	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8896
8897	return (dr->dr_numslots - dr->dr_usedslot);
8898}
8899
8900static int
8901bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8902{
8903	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8904
8905	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8906	    ("%s:%d: fail", __func__, __LINE__));
8907	if (slot == dr->dr_numslots - 1)
8908		return (0);
8909	return (slot + 1);
8910}
8911
8912static void
8913bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8914{
8915	struct bwn_mac *mac = dr->dr_mac;
8916	struct bwn_softc *sc = mac->mac_sc;
8917	struct bwn_dma *dma = &mac->mac_method.dma;
8918	struct bwn_dmadesc_generic *desc;
8919	struct bwn_dmadesc_meta *meta;
8920	struct bwn_rxhdr4 *rxhdr;
8921	struct ifnet *ifp = sc->sc_ifp;
8922	struct mbuf *m;
8923	uint32_t macstat;
8924	int32_t tmp;
8925	int cnt = 0;
8926	uint16_t len;
8927
8928	dr->getdesc(dr, *slot, &desc, &meta);
8929
8930	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8931	m = meta->mt_m;
8932
8933	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8934		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8935		return;
8936	}
8937
8938	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8939	len = le16toh(rxhdr->frame_len);
8940	if (len <= 0) {
8941		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8942		return;
8943	}
8944	if (bwn_dma_check_redzone(dr, m)) {
8945		device_printf(sc->sc_dev, "redzone error.\n");
8946		bwn_dma_set_redzone(dr, m);
8947		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8948		    BUS_DMASYNC_PREWRITE);
8949		return;
8950	}
8951	if (len > dr->dr_rx_bufsize) {
8952		tmp = len;
8953		while (1) {
8954			dr->getdesc(dr, *slot, &desc, &meta);
8955			bwn_dma_set_redzone(dr, meta->mt_m);
8956			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8957			    BUS_DMASYNC_PREWRITE);
8958			*slot = bwn_dma_nextslot(dr, *slot);
8959			cnt++;
8960			tmp -= dr->dr_rx_bufsize;
8961			if (tmp <= 0)
8962				break;
8963		}
8964		device_printf(sc->sc_dev, "too small buffer "
8965		       "(len %u buffer %u dropped %d)\n",
8966		       len, dr->dr_rx_bufsize, cnt);
8967		return;
8968	}
8969	macstat = le32toh(rxhdr->mac_status);
8970	if (macstat & BWN_RX_MAC_FCSERR) {
8971		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8972			device_printf(sc->sc_dev, "RX drop\n");
8973			return;
8974		}
8975	}
8976
8977	m->m_pkthdr.rcvif = ifp;
8978	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8979	m_adj(m, dr->dr_frameoffset);
8980
8981	bwn_rxeof(dr->dr_mac, m, rxhdr);
8982}
8983
8984static void
8985bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8986{
8987	struct bwn_dma_ring *dr;
8988	struct bwn_dmadesc_generic *desc;
8989	struct bwn_dmadesc_meta *meta;
8990	struct bwn_pio_txqueue *tq;
8991	struct bwn_pio_txpkt *tp = NULL;
8992	struct bwn_softc *sc = mac->mac_sc;
8993	struct bwn_stats *stats = &mac->mac_stats;
8994	struct ieee80211_node *ni;
8995	struct ieee80211vap *vap;
8996	int retrycnt = 0, slot;
8997
8998	BWN_ASSERT_LOCKED(mac->mac_sc);
8999
9000	if (status->im)
9001		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9002	if (status->ampdu)
9003		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9004	if (status->rtscnt) {
9005		if (status->rtscnt == 0xf)
9006			stats->rtsfail++;
9007		else
9008			stats->rts++;
9009	}
9010
9011	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9012		if (status->ack) {
9013			dr = bwn_dma_parse_cookie(mac, status,
9014			    status->cookie, &slot);
9015			if (dr == NULL) {
9016				device_printf(sc->sc_dev,
9017				    "failed to parse cookie\n");
9018				return;
9019			}
9020			while (1) {
9021				dr->getdesc(dr, slot, &desc, &meta);
9022				if (meta->mt_islast) {
9023					ni = meta->mt_ni;
9024					vap = ni->ni_vap;
9025					ieee80211_ratectl_tx_complete(vap, ni,
9026					    status->ack ?
9027					      IEEE80211_RATECTL_TX_SUCCESS :
9028					      IEEE80211_RATECTL_TX_FAILURE,
9029					    &retrycnt, 0);
9030					break;
9031				}
9032				slot = bwn_dma_nextslot(dr, slot);
9033			}
9034		}
9035		bwn_dma_handle_txeof(mac, status);
9036	} else {
9037		if (status->ack) {
9038			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9039			if (tq == NULL) {
9040				device_printf(sc->sc_dev,
9041				    "failed to parse cookie\n");
9042				return;
9043			}
9044			ni = tp->tp_ni;
9045			vap = ni->ni_vap;
9046			ieee80211_ratectl_tx_complete(vap, ni,
9047			    status->ack ?
9048			      IEEE80211_RATECTL_TX_SUCCESS :
9049			      IEEE80211_RATECTL_TX_FAILURE,
9050			    &retrycnt, 0);
9051		}
9052		bwn_pio_handle_txeof(mac, status);
9053	}
9054
9055	bwn_phy_txpower_check(mac, 0);
9056}
9057
9058static uint8_t
9059bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9060{
9061	struct bwn_mac *mac = prq->prq_mac;
9062	struct bwn_softc *sc = mac->mac_sc;
9063	struct bwn_rxhdr4 rxhdr;
9064	struct ifnet *ifp = sc->sc_ifp;
9065	struct mbuf *m;
9066	uint32_t ctl32, macstat, v32;
9067	unsigned int i, padding;
9068	uint16_t ctl16, len, totlen, v16;
9069	unsigned char *mp;
9070	char *data;
9071
9072	memset(&rxhdr, 0, sizeof(rxhdr));
9073
9074	if (prq->prq_rev >= 8) {
9075		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9076		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9077			return (0);
9078		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9079		    BWN_PIO8_RXCTL_FRAMEREADY);
9080		for (i = 0; i < 10; i++) {
9081			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9082			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9083				goto ready;
9084			DELAY(10);
9085		}
9086	} else {
9087		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9088		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9089			return (0);
9090		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9091		    BWN_PIO_RXCTL_FRAMEREADY);
9092		for (i = 0; i < 10; i++) {
9093			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9094			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9095				goto ready;
9096			DELAY(10);
9097		}
9098	}
9099	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9100	return (1);
9101ready:
9102	if (prq->prq_rev >= 8)
9103		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9104		    prq->prq_base + BWN_PIO8_RXDATA);
9105	else
9106		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9107		    prq->prq_base + BWN_PIO_RXDATA);
9108	len = le16toh(rxhdr.frame_len);
9109	if (len > 0x700) {
9110		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9111		goto error;
9112	}
9113	if (len == 0) {
9114		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9115		goto error;
9116	}
9117
9118	macstat = le32toh(rxhdr.mac_status);
9119	if (macstat & BWN_RX_MAC_FCSERR) {
9120		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9121			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9122			goto error;
9123		}
9124	}
9125
9126	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9127	totlen = len + padding;
9128	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9129	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9130	if (m == NULL) {
9131		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9132		goto error;
9133	}
9134	mp = mtod(m, unsigned char *);
9135	if (prq->prq_rev >= 8) {
9136		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9137		    prq->prq_base + BWN_PIO8_RXDATA);
9138		if (totlen & 3) {
9139			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9140			data = &(mp[totlen - 1]);
9141			switch (totlen & 3) {
9142			case 3:
9143				*data = (v32 >> 16);
9144				data--;
9145			case 2:
9146				*data = (v32 >> 8);
9147				data--;
9148			case 1:
9149				*data = v32;
9150			}
9151		}
9152	} else {
9153		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9154		    prq->prq_base + BWN_PIO_RXDATA);
9155		if (totlen & 1) {
9156			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9157			mp[totlen - 1] = v16;
9158		}
9159	}
9160
9161	m->m_pkthdr.rcvif = ifp;
9162	m->m_len = m->m_pkthdr.len = totlen;
9163
9164	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9165
9166	return (1);
9167error:
9168	if (prq->prq_rev >= 8)
9169		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9170		    BWN_PIO8_RXCTL_DATAREADY);
9171	else
9172		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9173	return (1);
9174}
9175
9176static int
9177bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9178    struct bwn_dmadesc_meta *meta, int init)
9179{
9180	struct bwn_mac *mac = dr->dr_mac;
9181	struct bwn_dma *dma = &mac->mac_method.dma;
9182	struct bwn_rxhdr4 *hdr;
9183	bus_dmamap_t map;
9184	bus_addr_t paddr;
9185	struct mbuf *m;
9186	int error;
9187
9188	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9189	if (m == NULL) {
9190		error = ENOBUFS;
9191
9192		/*
9193		 * If the NIC is up and running, we need to:
9194		 * - Clear RX buffer's header.
9195		 * - Restore RX descriptor settings.
9196		 */
9197		if (init)
9198			return (error);
9199		else
9200			goto back;
9201	}
9202	m->m_len = m->m_pkthdr.len = MCLBYTES;
9203
9204	bwn_dma_set_redzone(dr, m);
9205
9206	/*
9207	 * Try to load RX buf into temporary DMA map
9208	 */
9209	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9210	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9211	if (error) {
9212		m_freem(m);
9213
9214		/*
9215		 * See the comment above
9216		 */
9217		if (init)
9218			return (error);
9219		else
9220			goto back;
9221	}
9222
9223	if (!init)
9224		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9225	meta->mt_m = m;
9226	meta->mt_paddr = paddr;
9227
9228	/*
9229	 * Swap RX buf's DMA map with the loaded temporary one
9230	 */
9231	map = meta->mt_dmap;
9232	meta->mt_dmap = dr->dr_spare_dmap;
9233	dr->dr_spare_dmap = map;
9234
9235back:
9236	/*
9237	 * Clear RX buf header
9238	 */
9239	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9240	bzero(hdr, sizeof(*hdr));
9241	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9242	    BUS_DMASYNC_PREWRITE);
9243
9244	/*
9245	 * Setup RX buf descriptor
9246	 */
9247	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9248	    sizeof(*hdr), 0, 0, 0);
9249	return (error);
9250}
9251
9252static void
9253bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9254		 bus_size_t mapsz __unused, int error)
9255{
9256
9257	if (!error) {
9258		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9259		*((bus_addr_t *)arg) = seg->ds_addr;
9260	}
9261}
9262
9263static int
9264bwn_hwrate2ieeerate(int rate)
9265{
9266
9267	switch (rate) {
9268	case BWN_CCK_RATE_1MB:
9269		return (2);
9270	case BWN_CCK_RATE_2MB:
9271		return (4);
9272	case BWN_CCK_RATE_5MB:
9273		return (11);
9274	case BWN_CCK_RATE_11MB:
9275		return (22);
9276	case BWN_OFDM_RATE_6MB:
9277		return (12);
9278	case BWN_OFDM_RATE_9MB:
9279		return (18);
9280	case BWN_OFDM_RATE_12MB:
9281		return (24);
9282	case BWN_OFDM_RATE_18MB:
9283		return (36);
9284	case BWN_OFDM_RATE_24MB:
9285		return (48);
9286	case BWN_OFDM_RATE_36MB:
9287		return (72);
9288	case BWN_OFDM_RATE_48MB:
9289		return (96);
9290	case BWN_OFDM_RATE_54MB:
9291		return (108);
9292	default:
9293		printf("Ooops\n");
9294		return (0);
9295	}
9296}
9297
9298static void
9299bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9300{
9301	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9302	struct bwn_plcp6 *plcp;
9303	struct bwn_softc *sc = mac->mac_sc;
9304	struct ieee80211_frame_min *wh;
9305	struct ieee80211_node *ni;
9306	struct ifnet *ifp = sc->sc_ifp;
9307	struct ieee80211com *ic = ifp->if_l2com;
9308	uint32_t macstat;
9309	int padding, rate, rssi = 0, noise = 0, type;
9310	uint16_t phytype, phystat0, phystat3, chanstat;
9311	unsigned char *mp = mtod(m, unsigned char *);
9312	static int rx_mac_dec_rpt = 0;
9313
9314	BWN_ASSERT_LOCKED(sc);
9315
9316	phystat0 = le16toh(rxhdr->phy_status0);
9317	phystat3 = le16toh(rxhdr->phy_status3);
9318	macstat = le32toh(rxhdr->mac_status);
9319	chanstat = le16toh(rxhdr->channel);
9320	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9321
9322	if (macstat & BWN_RX_MAC_FCSERR)
9323		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9324	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9325		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9326	if (macstat & BWN_RX_MAC_DECERR)
9327		goto drop;
9328
9329	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9330	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9331		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9332		    m->m_pkthdr.len);
9333		goto drop;
9334	}
9335	plcp = (struct bwn_plcp6 *)(mp + padding);
9336	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9337	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9338		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9339		    m->m_pkthdr.len);
9340		goto drop;
9341	}
9342	wh = mtod(m, struct ieee80211_frame_min *);
9343
9344	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9345		device_printf(sc->sc_dev,
9346		    "RX decryption attempted (old %d keyidx %#x)\n",
9347		    BWN_ISOLDFMT(mac),
9348		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9349
9350	/* XXX calculating RSSI & noise & antenna */
9351
9352	if (phystat0 & BWN_RX_PHYST0_OFDM)
9353		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9354		    phytype == BWN_PHYTYPE_A);
9355	else
9356		rate = bwn_plcp_get_cckrate(mac, plcp);
9357	if (rate == -1) {
9358		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9359			goto drop;
9360	}
9361	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9362
9363	/* RX radio tap */
9364	if (ieee80211_radiotap_active(ic))
9365		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9366	m_adj(m, -IEEE80211_CRC_LEN);
9367
9368	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9369	noise = mac->mac_stats.link_noise;
9370
9371	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
9372
9373	BWN_UNLOCK(sc);
9374
9375	ni = ieee80211_find_rxnode(ic, wh);
9376	if (ni != NULL) {
9377		type = ieee80211_input(ni, m, rssi, noise);
9378		ieee80211_free_node(ni);
9379	} else
9380		type = ieee80211_input_all(ic, m, rssi, noise);
9381
9382	BWN_LOCK(sc);
9383	return;
9384drop:
9385	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9386}
9387
9388static void
9389bwn_dma_handle_txeof(struct bwn_mac *mac,
9390    const struct bwn_txstatus *status)
9391{
9392	struct bwn_dma *dma = &mac->mac_method.dma;
9393	struct bwn_dma_ring *dr;
9394	struct bwn_dmadesc_generic *desc;
9395	struct bwn_dmadesc_meta *meta;
9396	struct bwn_softc *sc = mac->mac_sc;
9397	struct ieee80211_node *ni;
9398	struct ifnet *ifp = sc->sc_ifp;
9399	struct mbuf *m;
9400	int slot;
9401
9402	BWN_ASSERT_LOCKED(sc);
9403
9404	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9405	if (dr == NULL) {
9406		device_printf(sc->sc_dev, "failed to parse cookie\n");
9407		return;
9408	}
9409	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9410
9411	while (1) {
9412		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9413		    ("%s:%d: fail", __func__, __LINE__));
9414		dr->getdesc(dr, slot, &desc, &meta);
9415
9416		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9417			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9418		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9419			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9420
9421		if (meta->mt_islast) {
9422			KASSERT(meta->mt_m != NULL,
9423			    ("%s:%d: fail", __func__, __LINE__));
9424
9425			ni = meta->mt_ni;
9426			m = meta->mt_m;
9427			if (ni != NULL) {
9428				/*
9429				 * Do any tx complete callback. Note this must
9430				 * be done before releasing the node reference.
9431				 */
9432				if (m->m_flags & M_TXCB)
9433					ieee80211_process_callback(ni, m, 0);
9434				ieee80211_free_node(ni);
9435				meta->mt_ni = NULL;
9436			}
9437			m_freem(m);
9438			meta->mt_m = NULL;
9439		} else {
9440			KASSERT(meta->mt_m == NULL,
9441			    ("%s:%d: fail", __func__, __LINE__));
9442		}
9443
9444		dr->dr_usedslot--;
9445		if (meta->mt_islast) {
9446			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9447			break;
9448		}
9449		slot = bwn_dma_nextslot(dr, slot);
9450	}
9451	sc->sc_watchdog_timer = 0;
9452	if (dr->dr_stop) {
9453		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9454		    ("%s:%d: fail", __func__, __LINE__));
9455		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9456		dr->dr_stop = 0;
9457	}
9458}
9459
9460static void
9461bwn_pio_handle_txeof(struct bwn_mac *mac,
9462    const struct bwn_txstatus *status)
9463{
9464	struct bwn_pio_txqueue *tq;
9465	struct bwn_pio_txpkt *tp = NULL;
9466	struct bwn_softc *sc = mac->mac_sc;
9467	struct ifnet *ifp = sc->sc_ifp;
9468
9469	BWN_ASSERT_LOCKED(sc);
9470
9471	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9472	if (tq == NULL)
9473		return;
9474
9475	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9476	tq->tq_free++;
9477
9478	if (tp->tp_ni != NULL) {
9479		/*
9480		 * Do any tx complete callback.  Note this must
9481		 * be done before releasing the node reference.
9482		 */
9483		if (tp->tp_m->m_flags & M_TXCB)
9484			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9485		ieee80211_free_node(tp->tp_ni);
9486		tp->tp_ni = NULL;
9487	}
9488	m_freem(tp->tp_m);
9489	tp->tp_m = NULL;
9490	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9491
9492	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9493
9494	sc->sc_watchdog_timer = 0;
9495	if (tq->tq_stop) {
9496		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9497		tq->tq_stop = 0;
9498	}
9499}
9500
9501static void
9502bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9503{
9504	struct bwn_softc *sc = mac->mac_sc;
9505	struct bwn_phy *phy = &mac->mac_phy;
9506	struct ifnet *ifp = sc->sc_ifp;
9507	struct ieee80211com *ic = ifp->if_l2com;
9508	unsigned long now;
9509	int result;
9510
9511	BWN_GETTIME(now);
9512
9513	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9514		return;
9515	phy->nexttime = now + 2 * 1000;
9516
9517	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9518	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9519		return;
9520
9521	if (phy->recalc_txpwr != NULL) {
9522		result = phy->recalc_txpwr(mac,
9523		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9524		if (result == BWN_TXPWR_RES_DONE)
9525			return;
9526		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9527		    ("%s: fail", __func__));
9528		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9529
9530		ieee80211_runtask(ic, &mac->mac_txpower);
9531	}
9532}
9533
9534static uint16_t
9535bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9536{
9537
9538	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9539}
9540
9541static uint32_t
9542bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9543{
9544
9545	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9546}
9547
9548static void
9549bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9550{
9551
9552	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9553}
9554
9555static void
9556bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9557{
9558
9559	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9560}
9561
9562static int
9563bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9564{
9565
9566	switch (rate) {
9567	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9568	case 12:
9569		return (BWN_OFDM_RATE_6MB);
9570	case 18:
9571		return (BWN_OFDM_RATE_9MB);
9572	case 24:
9573		return (BWN_OFDM_RATE_12MB);
9574	case 36:
9575		return (BWN_OFDM_RATE_18MB);
9576	case 48:
9577		return (BWN_OFDM_RATE_24MB);
9578	case 72:
9579		return (BWN_OFDM_RATE_36MB);
9580	case 96:
9581		return (BWN_OFDM_RATE_48MB);
9582	case 108:
9583		return (BWN_OFDM_RATE_54MB);
9584	/* CCK rates (NB: not IEEE std, device-specific) */
9585	case 2:
9586		return (BWN_CCK_RATE_1MB);
9587	case 4:
9588		return (BWN_CCK_RATE_2MB);
9589	case 11:
9590		return (BWN_CCK_RATE_5MB);
9591	case 22:
9592		return (BWN_CCK_RATE_11MB);
9593	}
9594
9595	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9596	return (BWN_CCK_RATE_1MB);
9597}
9598
9599static int
9600bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9601    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9602{
9603	const struct bwn_phy *phy = &mac->mac_phy;
9604	struct bwn_softc *sc = mac->mac_sc;
9605	struct ieee80211_frame *wh;
9606	struct ieee80211_frame *protwh;
9607	struct ieee80211_frame_cts *cts;
9608	struct ieee80211_frame_rts *rts;
9609	const struct ieee80211_txparam *tp;
9610	struct ieee80211vap *vap = ni->ni_vap;
9611	struct ifnet *ifp = sc->sc_ifp;
9612	struct ieee80211com *ic = ifp->if_l2com;
9613	struct mbuf *mprot;
9614	unsigned int len;
9615	uint32_t macctl = 0;
9616	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9617	uint16_t phyctl = 0;
9618	uint8_t rate, rate_fb;
9619
9620	wh = mtod(m, struct ieee80211_frame *);
9621	memset(txhdr, 0, sizeof(*txhdr));
9622
9623	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9624	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9625	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9626
9627	/*
9628	 * Find TX rate
9629	 */
9630	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9631	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9632		rate = rate_fb = tp->mgmtrate;
9633	else if (ismcast)
9634		rate = rate_fb = tp->mcastrate;
9635	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9636		rate = rate_fb = tp->ucastrate;
9637	else {
9638		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9639		rate = ni->ni_txrate;
9640
9641		if (rix > 0)
9642			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9643			    IEEE80211_RATE_VAL;
9644		else
9645			rate_fb = rate;
9646	}
9647
9648	sc->sc_tx_rate = rate;
9649
9650	rate = bwn_ieeerate2hwrate(sc, rate);
9651	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9652
9653	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9654	    bwn_plcp_getcck(rate);
9655	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9656	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9657
9658	if ((rate_fb == rate) ||
9659	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9660	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9661		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9662	else
9663		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9664		    m->m_pkthdr.len, rate, isshort);
9665
9666	/* XXX TX encryption */
9667	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9668	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9669	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9670	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9671	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9672	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9673
9674	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9675	    BWN_TX_EFT_FB_CCK;
9676	txhdr->chan = phy->chan;
9677	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9678	    BWN_TX_PHY_ENC_CCK;
9679	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9680	     rate == BWN_CCK_RATE_11MB))
9681		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9682
9683	/* XXX TX antenna selection */
9684
9685	switch (bwn_antenna_sanitize(mac, 0)) {
9686	case 0:
9687		phyctl |= BWN_TX_PHY_ANT01AUTO;
9688		break;
9689	case 1:
9690		phyctl |= BWN_TX_PHY_ANT0;
9691		break;
9692	case 2:
9693		phyctl |= BWN_TX_PHY_ANT1;
9694		break;
9695	case 3:
9696		phyctl |= BWN_TX_PHY_ANT2;
9697		break;
9698	case 4:
9699		phyctl |= BWN_TX_PHY_ANT3;
9700		break;
9701	default:
9702		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9703	}
9704
9705	if (!ismcast)
9706		macctl |= BWN_TX_MAC_ACK;
9707
9708	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9709	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9710	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9711		macctl |= BWN_TX_MAC_LONGFRAME;
9712
9713	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9714		/* XXX RTS rate is always 1MB??? */
9715		rts_rate = BWN_CCK_RATE_1MB;
9716		rts_rate_fb = bwn_get_fbrate(rts_rate);
9717
9718		protdur = ieee80211_compute_duration(ic->ic_rt,
9719		    m->m_pkthdr.len, rate, isshort) +
9720		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9721
9722		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9723			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9724			    (txhdr->body.old.rts_frame) :
9725			    (txhdr->body.new.rts_frame));
9726			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9727			    protdur);
9728			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9729			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9730			    mprot->m_pkthdr.len);
9731			m_freem(mprot);
9732			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9733			len = sizeof(struct ieee80211_frame_cts);
9734		} else {
9735			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9736			    (txhdr->body.old.rts_frame) :
9737			    (txhdr->body.new.rts_frame));
9738			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9739			    isshort);
9740			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9741			    wh->i_addr2, protdur);
9742			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9743			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9744			    mprot->m_pkthdr.len);
9745			m_freem(mprot);
9746			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9747			len = sizeof(struct ieee80211_frame_rts);
9748		}
9749		len += IEEE80211_CRC_LEN;
9750		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9751		    &txhdr->body.old.rts_plcp :
9752		    &txhdr->body.new.rts_plcp), len, rts_rate);
9753		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9754		    rts_rate_fb);
9755
9756		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9757		    (&txhdr->body.old.rts_frame) :
9758		    (&txhdr->body.new.rts_frame));
9759		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9760
9761		if (BWN_ISOFDMRATE(rts_rate)) {
9762			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9763			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9764		} else {
9765			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9766			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9767		}
9768		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9769		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9770	}
9771
9772	if (BWN_ISOLDFMT(mac))
9773		txhdr->body.old.cookie = htole16(cookie);
9774	else
9775		txhdr->body.new.cookie = htole16(cookie);
9776
9777	txhdr->macctl = htole32(macctl);
9778	txhdr->phyctl = htole16(phyctl);
9779
9780	/*
9781	 * TX radio tap
9782	 */
9783	if (ieee80211_radiotap_active_vap(vap)) {
9784		sc->sc_tx_th.wt_flags = 0;
9785		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9786			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9787		if (isshort &&
9788		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9789		     rate == BWN_CCK_RATE_11MB))
9790			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9791		sc->sc_tx_th.wt_rate = rate;
9792
9793		ieee80211_radiotap_tx(vap, m);
9794	}
9795
9796	return (0);
9797}
9798
9799static void
9800bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9801    const uint8_t rate)
9802{
9803	uint32_t d, plen;
9804	uint8_t *raw = plcp->o.raw;
9805
9806	if (BWN_ISOFDMRATE(rate)) {
9807		d = bwn_plcp_getofdm(rate);
9808		KASSERT(!(octets & 0xf000),
9809		    ("%s:%d: fail", __func__, __LINE__));
9810		d |= (octets << 5);
9811		plcp->o.data = htole32(d);
9812	} else {
9813		plen = octets * 16 / rate;
9814		if ((octets * 16 % rate) > 0) {
9815			plen++;
9816			if ((rate == BWN_CCK_RATE_11MB)
9817			    && ((octets * 8 % 11) < 4)) {
9818				raw[1] = 0x84;
9819			} else
9820				raw[1] = 0x04;
9821		} else
9822			raw[1] = 0x04;
9823		plcp->o.data |= htole32(plen << 16);
9824		raw[0] = bwn_plcp_getcck(rate);
9825	}
9826}
9827
9828static uint8_t
9829bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9830{
9831	struct bwn_softc *sc = mac->mac_sc;
9832	uint8_t mask;
9833
9834	if (n == 0)
9835		return (0);
9836	if (mac->mac_phy.gmode)
9837		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9838	else
9839		mask = siba_sprom_get_ant_a(sc->sc_dev);
9840	if (!(mask & (1 << (n - 1))))
9841		return (0);
9842	return (n);
9843}
9844
9845static uint8_t
9846bwn_get_fbrate(uint8_t bitrate)
9847{
9848	switch (bitrate) {
9849	case BWN_CCK_RATE_1MB:
9850		return (BWN_CCK_RATE_1MB);
9851	case BWN_CCK_RATE_2MB:
9852		return (BWN_CCK_RATE_1MB);
9853	case BWN_CCK_RATE_5MB:
9854		return (BWN_CCK_RATE_2MB);
9855	case BWN_CCK_RATE_11MB:
9856		return (BWN_CCK_RATE_5MB);
9857	case BWN_OFDM_RATE_6MB:
9858		return (BWN_CCK_RATE_5MB);
9859	case BWN_OFDM_RATE_9MB:
9860		return (BWN_OFDM_RATE_6MB);
9861	case BWN_OFDM_RATE_12MB:
9862		return (BWN_OFDM_RATE_9MB);
9863	case BWN_OFDM_RATE_18MB:
9864		return (BWN_OFDM_RATE_12MB);
9865	case BWN_OFDM_RATE_24MB:
9866		return (BWN_OFDM_RATE_18MB);
9867	case BWN_OFDM_RATE_36MB:
9868		return (BWN_OFDM_RATE_24MB);
9869	case BWN_OFDM_RATE_48MB:
9870		return (BWN_OFDM_RATE_36MB);
9871	case BWN_OFDM_RATE_54MB:
9872		return (BWN_OFDM_RATE_48MB);
9873	}
9874	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9875	return (0);
9876}
9877
9878static uint32_t
9879bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9880    uint32_t ctl, const void *_data, int len)
9881{
9882	struct bwn_softc *sc = mac->mac_sc;
9883	uint32_t value = 0;
9884	const uint8_t *data = _data;
9885
9886	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9887	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9888	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9889
9890	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9891	    tq->tq_base + BWN_PIO8_TXDATA);
9892	if (len & 3) {
9893		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9894		    BWN_PIO8_TXCTL_24_31);
9895		data = &(data[len - 1]);
9896		switch (len & 3) {
9897		case 3:
9898			ctl |= BWN_PIO8_TXCTL_16_23;
9899			value |= (uint32_t)(*data) << 16;
9900			data--;
9901		case 2:
9902			ctl |= BWN_PIO8_TXCTL_8_15;
9903			value |= (uint32_t)(*data) << 8;
9904			data--;
9905		case 1:
9906			value |= (uint32_t)(*data);
9907		}
9908		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9909		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9910	}
9911
9912	return (ctl);
9913}
9914
9915static void
9916bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9917    uint16_t offset, uint32_t value)
9918{
9919
9920	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9921}
9922
9923static uint16_t
9924bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9925    uint16_t ctl, const void *_data, int len)
9926{
9927	struct bwn_softc *sc = mac->mac_sc;
9928	const uint8_t *data = _data;
9929
9930	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9931	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9932
9933	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9934	    tq->tq_base + BWN_PIO_TXDATA);
9935	if (len & 1) {
9936		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9937		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9938		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9939	}
9940
9941	return (ctl);
9942}
9943
9944static uint16_t
9945bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9946    uint16_t ctl, struct mbuf *m0)
9947{
9948	int i, j = 0;
9949	uint16_t data = 0;
9950	const uint8_t *buf;
9951	struct mbuf *m = m0;
9952
9953	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9954	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9955
9956	for (; m != NULL; m = m->m_next) {
9957		buf = mtod(m, const uint8_t *);
9958		for (i = 0; i < m->m_len; i++) {
9959			if (!((j++) % 2))
9960				data |= buf[i];
9961			else {
9962				data |= (buf[i] << 8);
9963				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9964				data = 0;
9965			}
9966		}
9967	}
9968	if (m0->m_pkthdr.len % 2) {
9969		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9970		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9971		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9972	}
9973
9974	return (ctl);
9975}
9976
9977static void
9978bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9979{
9980
9981	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9982		return;
9983	BWN_WRITE_2(mac, 0x684, 510 + time);
9984	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9985}
9986
9987static struct bwn_dma_ring *
9988bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9989{
9990
9991	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9992		return (mac->mac_method.dma.wme[WME_AC_BE]);
9993
9994	switch (prio) {
9995	case 3:
9996		return (mac->mac_method.dma.wme[WME_AC_VO]);
9997	case 2:
9998		return (mac->mac_method.dma.wme[WME_AC_VI]);
9999	case 0:
10000		return (mac->mac_method.dma.wme[WME_AC_BE]);
10001	case 1:
10002		return (mac->mac_method.dma.wme[WME_AC_BK]);
10003	}
10004	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10005	return (NULL);
10006}
10007
10008static int
10009bwn_dma_getslot(struct bwn_dma_ring *dr)
10010{
10011	int slot;
10012
10013	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10014
10015	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10016	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10017	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10018
10019	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10020	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10021	dr->dr_curslot = slot;
10022	dr->dr_usedslot++;
10023
10024	return (slot);
10025}
10026
10027static int
10028bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10029{
10030	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10031	unsigned int a, b, c, d;
10032	unsigned int avg;
10033	uint32_t tmp;
10034
10035	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10036	a = tmp & 0xff;
10037	b = (tmp >> 8) & 0xff;
10038	c = (tmp >> 16) & 0xff;
10039	d = (tmp >> 24) & 0xff;
10040	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10041	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10042		return (ENOENT);
10043	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10044	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10045	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10046
10047	if (ofdm) {
10048		a = (a + 32) & 0x3f;
10049		b = (b + 32) & 0x3f;
10050		c = (c + 32) & 0x3f;
10051		d = (d + 32) & 0x3f;
10052	}
10053
10054	avg = (a + b + c + d + 2) / 4;
10055	if (ofdm) {
10056		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10057		    & BWN_HF_4DB_CCK_POWERBOOST)
10058			avg = (avg >= 13) ? (avg - 13) : 0;
10059	}
10060	return (avg);
10061}
10062
10063static void
10064bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10065{
10066	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10067	int rfatt = *rfattp;
10068	int bbatt = *bbattp;
10069
10070	while (1) {
10071		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10072			break;
10073		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10074			break;
10075		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10076			break;
10077		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10078			break;
10079		if (bbatt > lo->bbatt.max) {
10080			bbatt -= 4;
10081			rfatt += 1;
10082			continue;
10083		}
10084		if (bbatt < lo->bbatt.min) {
10085			bbatt += 4;
10086			rfatt -= 1;
10087			continue;
10088		}
10089		if (rfatt > lo->rfatt.max) {
10090			rfatt -= 1;
10091			bbatt += 4;
10092			continue;
10093		}
10094		if (rfatt < lo->rfatt.min) {
10095			rfatt += 1;
10096			bbatt -= 4;
10097			continue;
10098		}
10099		break;
10100	}
10101
10102	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10103	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10104}
10105
10106static void
10107bwn_phy_lock(struct bwn_mac *mac)
10108{
10109	struct bwn_softc *sc = mac->mac_sc;
10110	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10111
10112	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10113	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10114
10115	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10116		bwn_psctl(mac, BWN_PS_AWAKE);
10117}
10118
10119static void
10120bwn_phy_unlock(struct bwn_mac *mac)
10121{
10122	struct bwn_softc *sc = mac->mac_sc;
10123	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10124
10125	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10126	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10127
10128	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10129		bwn_psctl(mac, 0);
10130}
10131
10132static void
10133bwn_rf_lock(struct bwn_mac *mac)
10134{
10135
10136	BWN_WRITE_4(mac, BWN_MACCTL,
10137	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10138	BWN_READ_4(mac, BWN_MACCTL);
10139	DELAY(10);
10140}
10141
10142static void
10143bwn_rf_unlock(struct bwn_mac *mac)
10144{
10145
10146	BWN_READ_2(mac, BWN_PHYVER);
10147	BWN_WRITE_4(mac, BWN_MACCTL,
10148	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10149}
10150
10151static struct bwn_pio_txqueue *
10152bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10153    struct bwn_pio_txpkt **pack)
10154{
10155	struct bwn_pio *pio = &mac->mac_method.pio;
10156	struct bwn_pio_txqueue *tq = NULL;
10157	unsigned int index;
10158
10159	switch (cookie & 0xf000) {
10160	case 0x1000:
10161		tq = &pio->wme[WME_AC_BK];
10162		break;
10163	case 0x2000:
10164		tq = &pio->wme[WME_AC_BE];
10165		break;
10166	case 0x3000:
10167		tq = &pio->wme[WME_AC_VI];
10168		break;
10169	case 0x4000:
10170		tq = &pio->wme[WME_AC_VO];
10171		break;
10172	case 0x5000:
10173		tq = &pio->mcast;
10174		break;
10175	}
10176	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10177	if (tq == NULL)
10178		return (NULL);
10179	index = (cookie & 0x0fff);
10180	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10181	if (index >= N(tq->tq_pkts))
10182		return (NULL);
10183	*pack = &tq->tq_pkts[index];
10184	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10185	return (tq);
10186}
10187
10188static void
10189bwn_txpwr(void *arg, int npending)
10190{
10191	struct bwn_mac *mac = arg;
10192	struct bwn_softc *sc = mac->mac_sc;
10193
10194	BWN_LOCK(sc);
10195	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10196	    mac->mac_phy.set_txpwr != NULL)
10197		mac->mac_phy.set_txpwr(mac);
10198	BWN_UNLOCK(sc);
10199}
10200
10201static void
10202bwn_task_15s(struct bwn_mac *mac)
10203{
10204	uint16_t reg;
10205
10206	if (mac->mac_fw.opensource) {
10207		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10208		if (reg) {
10209			bwn_restart(mac, "fw watchdog");
10210			return;
10211		}
10212		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10213	}
10214	if (mac->mac_phy.task_15s)
10215		mac->mac_phy.task_15s(mac);
10216
10217	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10218}
10219
10220static void
10221bwn_task_30s(struct bwn_mac *mac)
10222{
10223
10224	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10225		return;
10226	mac->mac_noise.noi_running = 1;
10227	mac->mac_noise.noi_nsamples = 0;
10228
10229	bwn_noise_gensample(mac);
10230}
10231
10232static void
10233bwn_task_60s(struct bwn_mac *mac)
10234{
10235
10236	if (mac->mac_phy.task_60s)
10237		mac->mac_phy.task_60s(mac);
10238	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10239}
10240
10241static void
10242bwn_tasks(void *arg)
10243{
10244	struct bwn_mac *mac = arg;
10245	struct bwn_softc *sc = mac->mac_sc;
10246
10247	BWN_ASSERT_LOCKED(sc);
10248	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10249		return;
10250
10251	if (mac->mac_task_state % 4 == 0)
10252		bwn_task_60s(mac);
10253	if (mac->mac_task_state % 2 == 0)
10254		bwn_task_30s(mac);
10255	bwn_task_15s(mac);
10256
10257	mac->mac_task_state++;
10258	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10259}
10260
10261static int
10262bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10263{
10264	struct bwn_softc *sc = mac->mac_sc;
10265
10266	KASSERT(a == 0, ("not support APHY\n"));
10267
10268	switch (plcp->o.raw[0] & 0xf) {
10269	case 0xb:
10270		return (BWN_OFDM_RATE_6MB);
10271	case 0xf:
10272		return (BWN_OFDM_RATE_9MB);
10273	case 0xa:
10274		return (BWN_OFDM_RATE_12MB);
10275	case 0xe:
10276		return (BWN_OFDM_RATE_18MB);
10277	case 0x9:
10278		return (BWN_OFDM_RATE_24MB);
10279	case 0xd:
10280		return (BWN_OFDM_RATE_36MB);
10281	case 0x8:
10282		return (BWN_OFDM_RATE_48MB);
10283	case 0xc:
10284		return (BWN_OFDM_RATE_54MB);
10285	}
10286	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10287	    plcp->o.raw[0] & 0xf);
10288	return (-1);
10289}
10290
10291static int
10292bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10293{
10294	struct bwn_softc *sc = mac->mac_sc;
10295
10296	switch (plcp->o.raw[0]) {
10297	case 0x0a:
10298		return (BWN_CCK_RATE_1MB);
10299	case 0x14:
10300		return (BWN_CCK_RATE_2MB);
10301	case 0x37:
10302		return (BWN_CCK_RATE_5MB);
10303	case 0x6e:
10304		return (BWN_CCK_RATE_11MB);
10305	}
10306	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10307	return (-1);
10308}
10309
10310static void
10311bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10312    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10313    int rssi, int noise)
10314{
10315	struct bwn_softc *sc = mac->mac_sc;
10316	const struct ieee80211_frame_min *wh;
10317	uint64_t tsf;
10318	uint16_t low_mactime_now;
10319
10320	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10321		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10322
10323	wh = mtod(m, const struct ieee80211_frame_min *);
10324	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10325		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10326
10327	bwn_tsf_read(mac, &tsf);
10328	low_mactime_now = tsf;
10329	tsf = tsf & ~0xffffULL;
10330	tsf += le16toh(rxhdr->mac_time);
10331	if (low_mactime_now < le16toh(rxhdr->mac_time))
10332		tsf -= 0x10000;
10333
10334	sc->sc_rx_th.wr_tsf = tsf;
10335	sc->sc_rx_th.wr_rate = rate;
10336	sc->sc_rx_th.wr_antsignal = rssi;
10337	sc->sc_rx_th.wr_antnoise = noise;
10338}
10339
10340static void
10341bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10342{
10343	uint32_t low, high;
10344
10345	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10346	    ("%s:%d: fail", __func__, __LINE__));
10347
10348	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10349	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10350	*tsf = high;
10351	*tsf <<= 32;
10352	*tsf |= low;
10353}
10354
10355static int
10356bwn_dma_attach(struct bwn_mac *mac)
10357{
10358	struct bwn_dma *dma = &mac->mac_method.dma;
10359	struct bwn_softc *sc = mac->mac_sc;
10360	bus_addr_t lowaddr = 0;
10361	int error;
10362
10363	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10364		return (0);
10365
10366	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10367
10368	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10369
10370	dma->dmatype = bwn_dma_gettype(mac);
10371	if (dma->dmatype == BWN_DMA_30BIT)
10372		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10373	else if (dma->dmatype == BWN_DMA_32BIT)
10374		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10375	else
10376		lowaddr = BUS_SPACE_MAXADDR;
10377
10378	/*
10379	 * Create top level DMA tag
10380	 */
10381	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10382			       BWN_ALIGN, 0,		/* alignment, bounds */
10383			       lowaddr,			/* lowaddr */
10384			       BUS_SPACE_MAXADDR,	/* highaddr */
10385			       NULL, NULL,		/* filter, filterarg */
10386			       BUS_SPACE_MAXSIZE,	/* maxsize */
10387			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10388			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10389			       0,			/* flags */
10390			       NULL, NULL,		/* lockfunc, lockarg */
10391			       &dma->parent_dtag);
10392	if (error) {
10393		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10394		return (error);
10395	}
10396
10397	/*
10398	 * Create TX/RX mbuf DMA tag
10399	 */
10400	error = bus_dma_tag_create(dma->parent_dtag,
10401				1,
10402				0,
10403				BUS_SPACE_MAXADDR,
10404				BUS_SPACE_MAXADDR,
10405				NULL, NULL,
10406				MCLBYTES,
10407				1,
10408				BUS_SPACE_MAXSIZE_32BIT,
10409				0,
10410				NULL, NULL,
10411				&dma->rxbuf_dtag);
10412	if (error) {
10413		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10414		goto fail0;
10415	}
10416	error = bus_dma_tag_create(dma->parent_dtag,
10417				1,
10418				0,
10419				BUS_SPACE_MAXADDR,
10420				BUS_SPACE_MAXADDR,
10421				NULL, NULL,
10422				MCLBYTES,
10423				1,
10424				BUS_SPACE_MAXSIZE_32BIT,
10425				0,
10426				NULL, NULL,
10427				&dma->txbuf_dtag);
10428	if (error) {
10429		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10430		goto fail1;
10431	}
10432
10433	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10434	if (!dma->wme[WME_AC_BK])
10435		goto fail2;
10436
10437	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10438	if (!dma->wme[WME_AC_BE])
10439		goto fail3;
10440
10441	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10442	if (!dma->wme[WME_AC_VI])
10443		goto fail4;
10444
10445	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10446	if (!dma->wme[WME_AC_VO])
10447		goto fail5;
10448
10449	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10450	if (!dma->mcast)
10451		goto fail6;
10452	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10453	if (!dma->rx)
10454		goto fail7;
10455
10456	return (error);
10457
10458fail7:	bwn_dma_ringfree(&dma->mcast);
10459fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10460fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10461fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10462fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10463fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10464fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10465fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10466	return (error);
10467}
10468
10469static struct bwn_dma_ring *
10470bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10471    uint16_t cookie, int *slot)
10472{
10473	struct bwn_dma *dma = &mac->mac_method.dma;
10474	struct bwn_dma_ring *dr;
10475	struct bwn_softc *sc = mac->mac_sc;
10476
10477	BWN_ASSERT_LOCKED(mac->mac_sc);
10478
10479	switch (cookie & 0xf000) {
10480	case 0x1000:
10481		dr = dma->wme[WME_AC_BK];
10482		break;
10483	case 0x2000:
10484		dr = dma->wme[WME_AC_BE];
10485		break;
10486	case 0x3000:
10487		dr = dma->wme[WME_AC_VI];
10488		break;
10489	case 0x4000:
10490		dr = dma->wme[WME_AC_VO];
10491		break;
10492	case 0x5000:
10493		dr = dma->mcast;
10494		break;
10495	default:
10496		dr = NULL;
10497		KASSERT(0 == 1,
10498		    ("invalid cookie value %d", cookie & 0xf000));
10499	}
10500	*slot = (cookie & 0x0fff);
10501	if (*slot < 0 || *slot >= dr->dr_numslots) {
10502		/*
10503		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10504		 * that it occurs events which have same H/W sequence numbers.
10505		 * When it's occurred just prints a WARNING msgs and ignores.
10506		 */
10507		KASSERT(status->seq == dma->lastseq,
10508		    ("%s:%d: fail", __func__, __LINE__));
10509		device_printf(sc->sc_dev,
10510		    "out of slot ranges (0 < %d < %d)\n", *slot,
10511		    dr->dr_numslots);
10512		return (NULL);
10513	}
10514	dma->lastseq = status->seq;
10515	return (dr);
10516}
10517
10518static void
10519bwn_dma_stop(struct bwn_mac *mac)
10520{
10521	struct bwn_dma *dma;
10522
10523	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10524		return;
10525	dma = &mac->mac_method.dma;
10526
10527	bwn_dma_ringstop(&dma->rx);
10528	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10529	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10530	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10531	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10532	bwn_dma_ringstop(&dma->mcast);
10533}
10534
10535static void
10536bwn_dma_ringstop(struct bwn_dma_ring **dr)
10537{
10538
10539	if (dr == NULL)
10540		return;
10541
10542	bwn_dma_cleanup(*dr);
10543}
10544
10545static void
10546bwn_pio_stop(struct bwn_mac *mac)
10547{
10548	struct bwn_pio *pio;
10549
10550	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10551		return;
10552	pio = &mac->mac_method.pio;
10553
10554	bwn_destroy_queue_tx(&pio->mcast);
10555	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10556	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10557	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10558	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10559}
10560
10561static void
10562bwn_led_attach(struct bwn_mac *mac)
10563{
10564	struct bwn_softc *sc = mac->mac_sc;
10565	const uint8_t *led_act = NULL;
10566	uint16_t val[BWN_LED_MAX];
10567	int i;
10568
10569	sc->sc_led_idle = (2350 * hz) / 1000;
10570	sc->sc_led_blink = 1;
10571
10572	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10573		if (siba_get_pci_subvendor(sc->sc_dev) ==
10574		    bwn_vendor_led_act[i].vid) {
10575			led_act = bwn_vendor_led_act[i].led_act;
10576			break;
10577		}
10578	}
10579	if (led_act == NULL)
10580		led_act = bwn_default_led_act;
10581
10582	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10583	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10584	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10585	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10586
10587	for (i = 0; i < BWN_LED_MAX; ++i) {
10588		struct bwn_led *led = &sc->sc_leds[i];
10589
10590		if (val[i] == 0xff) {
10591			led->led_act = led_act[i];
10592		} else {
10593			if (val[i] & BWN_LED_ACT_LOW)
10594				led->led_flags |= BWN_LED_F_ACTLOW;
10595			led->led_act = val[i] & BWN_LED_ACT_MASK;
10596		}
10597		led->led_mask = (1 << i);
10598
10599		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10600		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10601		    led->led_act == BWN_LED_ACT_BLINK) {
10602			led->led_flags |= BWN_LED_F_BLINK;
10603			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10604				led->led_flags |= BWN_LED_F_POLLABLE;
10605			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10606				led->led_flags |= BWN_LED_F_SLOW;
10607
10608			if (sc->sc_blink_led == NULL) {
10609				sc->sc_blink_led = led;
10610				if (led->led_flags & BWN_LED_F_SLOW)
10611					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10612			}
10613		}
10614
10615		DPRINTF(sc, BWN_DEBUG_LED,
10616		    "%dth led, act %d, lowact %d\n", i,
10617		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10618	}
10619	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10620}
10621
10622static __inline uint16_t
10623bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10624{
10625
10626	if (led->led_flags & BWN_LED_F_ACTLOW)
10627		on = !on;
10628	if (on)
10629		val |= led->led_mask;
10630	else
10631		val &= ~led->led_mask;
10632	return val;
10633}
10634
10635static void
10636bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10637{
10638	struct bwn_softc *sc = mac->mac_sc;
10639	struct ifnet *ifp = sc->sc_ifp;
10640	struct ieee80211com *ic = ifp->if_l2com;
10641	uint16_t val;
10642	int i;
10643
10644	if (nstate == IEEE80211_S_INIT) {
10645		callout_stop(&sc->sc_led_blink_ch);
10646		sc->sc_led_blinking = 0;
10647	}
10648
10649	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10650		return;
10651
10652	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10653	for (i = 0; i < BWN_LED_MAX; ++i) {
10654		struct bwn_led *led = &sc->sc_leds[i];
10655		int on;
10656
10657		if (led->led_act == BWN_LED_ACT_UNKN ||
10658		    led->led_act == BWN_LED_ACT_NULL)
10659			continue;
10660
10661		if ((led->led_flags & BWN_LED_F_BLINK) &&
10662		    nstate != IEEE80211_S_INIT)
10663			continue;
10664
10665		switch (led->led_act) {
10666		case BWN_LED_ACT_ON:    /* Always on */
10667			on = 1;
10668			break;
10669		case BWN_LED_ACT_OFF:   /* Always off */
10670		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10671			on = 0;
10672			break;
10673		default:
10674			on = 1;
10675			switch (nstate) {
10676			case IEEE80211_S_INIT:
10677				on = 0;
10678				break;
10679			case IEEE80211_S_RUN:
10680				if (led->led_act == BWN_LED_ACT_11G &&
10681				    ic->ic_curmode != IEEE80211_MODE_11G)
10682					on = 0;
10683				break;
10684			default:
10685				if (led->led_act == BWN_LED_ACT_ASSOC)
10686					on = 0;
10687				break;
10688			}
10689			break;
10690		}
10691
10692		val = bwn_led_onoff(led, val, on);
10693	}
10694	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10695}
10696
10697static void
10698bwn_led_event(struct bwn_mac *mac, int event)
10699{
10700	struct bwn_softc *sc = mac->mac_sc;
10701	struct bwn_led *led = sc->sc_blink_led;
10702	int rate;
10703
10704	if (event == BWN_LED_EVENT_POLL) {
10705		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10706			return;
10707		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10708			return;
10709	}
10710
10711	sc->sc_led_ticks = ticks;
10712	if (sc->sc_led_blinking)
10713		return;
10714
10715	switch (event) {
10716	case BWN_LED_EVENT_RX:
10717		rate = sc->sc_rx_rate;
10718		break;
10719	case BWN_LED_EVENT_TX:
10720		rate = sc->sc_tx_rate;
10721		break;
10722	case BWN_LED_EVENT_POLL:
10723		rate = 0;
10724		break;
10725	default:
10726		panic("unknown LED event %d\n", event);
10727		break;
10728	}
10729	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10730	    bwn_led_duration[rate].off_dur);
10731}
10732
10733static void
10734bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10735{
10736	struct bwn_softc *sc = mac->mac_sc;
10737	struct bwn_led *led = sc->sc_blink_led;
10738	uint16_t val;
10739
10740	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10741	val = bwn_led_onoff(led, val, 1);
10742	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10743
10744	if (led->led_flags & BWN_LED_F_SLOW) {
10745		BWN_LED_SLOWDOWN(on_dur);
10746		BWN_LED_SLOWDOWN(off_dur);
10747	}
10748
10749	sc->sc_led_blinking = 1;
10750	sc->sc_led_blink_offdur = off_dur;
10751
10752	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10753}
10754
10755static void
10756bwn_led_blink_next(void *arg)
10757{
10758	struct bwn_mac *mac = arg;
10759	struct bwn_softc *sc = mac->mac_sc;
10760	uint16_t val;
10761
10762	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10763	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10764	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10765
10766	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10767	    bwn_led_blink_end, mac);
10768}
10769
10770static void
10771bwn_led_blink_end(void *arg)
10772{
10773	struct bwn_mac *mac = arg;
10774	struct bwn_softc *sc = mac->mac_sc;
10775
10776	sc->sc_led_blinking = 0;
10777}
10778
10779static int
10780bwn_suspend(device_t dev)
10781{
10782	struct bwn_softc *sc = device_get_softc(dev);
10783
10784	bwn_stop(sc, 1);
10785	return (0);
10786}
10787
10788static int
10789bwn_resume(device_t dev)
10790{
10791	struct bwn_softc *sc = device_get_softc(dev);
10792	struct ifnet *ifp = sc->sc_ifp;
10793
10794	if (ifp->if_flags & IFF_UP)
10795		bwn_init(sc);
10796	return (0);
10797}
10798
10799static void
10800bwn_rfswitch(void *arg)
10801{
10802	struct bwn_softc *sc = arg;
10803	struct bwn_mac *mac = sc->sc_curmac;
10804	int cur = 0, prev = 0;
10805
10806	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10807	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10808
10809	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10810		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10811			& BWN_RF_HWENABLED_HI_MASK))
10812			cur = 1;
10813	} else {
10814		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10815		    & BWN_RF_HWENABLED_LO_MASK)
10816			cur = 1;
10817	}
10818
10819	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10820		prev = 1;
10821
10822	if (cur != prev) {
10823		if (cur)
10824			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10825		else
10826			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10827
10828		device_printf(sc->sc_dev,
10829		    "status of RF switch is changed to %s\n",
10830		    cur ? "ON" : "OFF");
10831		if (cur != mac->mac_phy.rf_on) {
10832			if (cur)
10833				bwn_rf_turnon(mac);
10834			else
10835				bwn_rf_turnoff(mac);
10836		}
10837	}
10838
10839	callout_schedule(&sc->sc_rfswitch_ch, hz);
10840}
10841
10842static void
10843bwn_phy_lp_init_pre(struct bwn_mac *mac)
10844{
10845	struct bwn_phy *phy = &mac->mac_phy;
10846	struct bwn_phy_lp *plp = &phy->phy_lp;
10847
10848	plp->plp_antenna = BWN_ANT_DEFAULT;
10849}
10850
10851static int
10852bwn_phy_lp_init(struct bwn_mac *mac)
10853{
10854	static const struct bwn_stxtable tables[] = {
10855		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10856		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10857		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10858		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10859		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10860		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10861		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10862		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10863		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10864		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10865		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10866		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10867		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10868		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10869		{ 2, 11, 0x40, 0, 0x0f }
10870	};
10871	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10872	struct bwn_softc *sc = mac->mac_sc;
10873	const struct bwn_stxtable *st;
10874	struct ifnet *ifp = sc->sc_ifp;
10875	struct ieee80211com *ic = ifp->if_l2com;
10876	int i, error;
10877	uint16_t tmp;
10878
10879	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10880	bwn_phy_lp_bbinit(mac);
10881
10882	/* initialize RF */
10883	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10884	DELAY(1);
10885	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10886	DELAY(1);
10887
10888	if (mac->mac_phy.rf_ver == 0x2062)
10889		bwn_phy_lp_b2062_init(mac);
10890	else {
10891		bwn_phy_lp_b2063_init(mac);
10892
10893		/* synchronize stx table. */
10894		for (i = 0; i < N(tables); i++) {
10895			st = &tables[i];
10896			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10897			tmp >>= st->st_rfshift;
10898			tmp <<= st->st_physhift;
10899			BWN_PHY_SETMASK(mac,
10900			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10901			    ~(st->st_mask << st->st_physhift), tmp);
10902		}
10903
10904		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10905		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10906	}
10907
10908	/* calibrate RC */
10909	if (mac->mac_phy.rev >= 2)
10910		bwn_phy_lp_rxcal_r2(mac);
10911	else if (!plp->plp_rccap) {
10912		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10913			bwn_phy_lp_rccal_r12(mac);
10914	} else
10915		bwn_phy_lp_set_rccap(mac);
10916
10917	error = bwn_phy_lp_switch_channel(mac, 7);
10918	if (error)
10919		device_printf(sc->sc_dev,
10920		    "failed to change channel 7 (%d)\n", error);
10921	bwn_phy_lp_txpctl_init(mac);
10922	bwn_phy_lp_calib(mac);
10923	return (0);
10924}
10925
10926static uint16_t
10927bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10928{
10929
10930	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10931	return (BWN_READ_2(mac, BWN_PHYDATA));
10932}
10933
10934static void
10935bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10936{
10937
10938	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10939	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10940}
10941
10942static void
10943bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10944    uint16_t set)
10945{
10946
10947	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10948	BWN_WRITE_2(mac, BWN_PHYDATA,
10949	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10950}
10951
10952static uint16_t
10953bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10954{
10955
10956	KASSERT(reg != 1, ("unaccessible register %d", reg));
10957	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10958		reg |= 0x100;
10959	if (mac->mac_phy.rev >= 2)
10960		reg |= 0x200;
10961	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10962	return BWN_READ_2(mac, BWN_RFDATALO);
10963}
10964
10965static void
10966bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10967{
10968
10969	KASSERT(reg != 1, ("unaccessible register %d", reg));
10970	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10971	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10972}
10973
10974static void
10975bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10976{
10977
10978	if (on) {
10979		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10980		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10981		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10982		return;
10983	}
10984
10985	if (mac->mac_phy.rev >= 2) {
10986		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10987		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10988		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10989		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10990		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10991		return;
10992	}
10993
10994	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10995	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10996	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10997	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10998}
10999
11000static int
11001bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11002{
11003	struct bwn_phy *phy = &mac->mac_phy;
11004	struct bwn_phy_lp *plp = &phy->phy_lp;
11005	int error;
11006
11007	if (phy->rf_ver == 0x2063) {
11008		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11009		if (error)
11010			return (error);
11011	} else {
11012		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11013		if (error)
11014			return (error);
11015		bwn_phy_lp_set_anafilter(mac, chan);
11016		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11017	}
11018
11019	plp->plp_chan = chan;
11020	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11021	return (0);
11022}
11023
11024static uint32_t
11025bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11026{
11027	struct bwn_softc *sc = mac->mac_sc;
11028	struct ifnet *ifp = sc->sc_ifp;
11029	struct ieee80211com *ic = ifp->if_l2com;
11030
11031	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11032}
11033
11034static void
11035bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11036{
11037	struct bwn_phy *phy = &mac->mac_phy;
11038	struct bwn_phy_lp *plp = &phy->phy_lp;
11039
11040	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11041		return;
11042
11043	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11044	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11045	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11046	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11047	plp->plp_antenna = antenna;
11048}
11049
11050static void
11051bwn_phy_lp_task_60s(struct bwn_mac *mac)
11052{
11053
11054	bwn_phy_lp_calib(mac);
11055}
11056
11057static void
11058bwn_phy_lp_readsprom(struct bwn_mac *mac)
11059{
11060	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11061	struct bwn_softc *sc = mac->mac_sc;
11062	struct ifnet *ifp = sc->sc_ifp;
11063	struct ieee80211com *ic = ifp->if_l2com;
11064
11065	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11066		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11067		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11068		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11069		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11070		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11071		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11072		return;
11073	}
11074
11075	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11076	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11077	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11078	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11079	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11080	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11081	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11082	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11083}
11084
11085static void
11086bwn_phy_lp_bbinit(struct bwn_mac *mac)
11087{
11088
11089	bwn_phy_lp_tblinit(mac);
11090	if (mac->mac_phy.rev >= 2)
11091		bwn_phy_lp_bbinit_r2(mac);
11092	else
11093		bwn_phy_lp_bbinit_r01(mac);
11094}
11095
11096static void
11097bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11098{
11099	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11100	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11101	struct bwn_softc *sc = mac->mac_sc;
11102	struct ifnet *ifp = sc->sc_ifp;
11103	struct ieee80211com *ic = ifp->if_l2com;
11104
11105	bwn_phy_lp_set_txgain(mac,
11106	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11107	bwn_phy_lp_set_bbmult(mac, 150);
11108}
11109
11110static void
11111bwn_phy_lp_calib(struct bwn_mac *mac)
11112{
11113	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11114	struct bwn_softc *sc = mac->mac_sc;
11115	struct ifnet *ifp = sc->sc_ifp;
11116	struct ieee80211com *ic = ifp->if_l2com;
11117	const struct bwn_rxcompco *rc = NULL;
11118	struct bwn_txgain ogain;
11119	int i, omode, oafeovr, orf, obbmult;
11120	uint8_t mode, fc = 0;
11121
11122	if (plp->plp_chanfullcal != plp->plp_chan) {
11123		plp->plp_chanfullcal = plp->plp_chan;
11124		fc = 1;
11125	}
11126
11127	bwn_mac_suspend(mac);
11128
11129	/* BlueTooth Coexistance Override */
11130	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11131	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11132
11133	if (mac->mac_phy.rev >= 2)
11134		bwn_phy_lp_digflt_save(mac);
11135	bwn_phy_lp_get_txpctlmode(mac);
11136	mode = plp->plp_txpctlmode;
11137	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11138	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11139		bwn_phy_lp_bugfix(mac);
11140	if (mac->mac_phy.rev >= 2 && fc == 1) {
11141		bwn_phy_lp_get_txpctlmode(mac);
11142		omode = plp->plp_txpctlmode;
11143		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11144		if (oafeovr)
11145			ogain = bwn_phy_lp_get_txgain(mac);
11146		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11147		obbmult = bwn_phy_lp_get_bbmult(mac);
11148		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11149		if (oafeovr)
11150			bwn_phy_lp_set_txgain(mac, &ogain);
11151		bwn_phy_lp_set_bbmult(mac, obbmult);
11152		bwn_phy_lp_set_txpctlmode(mac, omode);
11153		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11154	}
11155	bwn_phy_lp_set_txpctlmode(mac, mode);
11156	if (mac->mac_phy.rev >= 2)
11157		bwn_phy_lp_digflt_restore(mac);
11158
11159	/* do RX IQ Calculation; assumes that noise is true. */
11160	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11161		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11162			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11163				rc = &bwn_rxcompco_5354[i];
11164		}
11165	} else if (mac->mac_phy.rev >= 2)
11166		rc = &bwn_rxcompco_r2;
11167	else {
11168		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11169			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11170				rc = &bwn_rxcompco_r12[i];
11171		}
11172	}
11173	if (rc == NULL)
11174		goto fail;
11175
11176	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11177	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11178
11179	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11180
11181	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11182		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11183		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11184	} else {
11185		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11186		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11187	}
11188
11189	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11190	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11191	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11192	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11193	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11194	bwn_phy_lp_set_deaf(mac, 0);
11195	/* XXX no checking return value? */
11196	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11197	bwn_phy_lp_clear_deaf(mac, 0);
11198	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11199	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11200	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11201
11202	/* disable RX GAIN override. */
11203	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11204	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11205	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11206	if (mac->mac_phy.rev >= 2) {
11207		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11208		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11209			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11210			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11211		}
11212	} else {
11213		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11214	}
11215
11216	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11217	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11218fail:
11219	bwn_mac_enable(mac);
11220}
11221
11222static void
11223bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11224{
11225
11226	if (on) {
11227		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11228		return;
11229	}
11230
11231	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11232	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11233}
11234
11235static int
11236bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11237{
11238	static const struct bwn_b206x_chan *bc = NULL;
11239	struct bwn_softc *sc = mac->mac_sc;
11240	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11241	    tmp[6];
11242	uint16_t old, scale, tmp16;
11243	int i, div;
11244
11245	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11246		if (bwn_b2063_chantable[i].bc_chan == chan) {
11247			bc = &bwn_b2063_chantable[i];
11248			break;
11249		}
11250	}
11251	if (bc == NULL)
11252		return (EINVAL);
11253
11254	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11255	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11256	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11257	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11258	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11259	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11260	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11261	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11262	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11263	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11264	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11265	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11266
11267	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11268	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11269
11270	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11271	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11272	freqref = freqxtal * 3;
11273	div = (freqxtal <= 26000000 ? 1 : 2);
11274	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11275	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11276		999999) / 1000000) + 1;
11277
11278	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11279	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11280	    0xfff8, timeout >> 2);
11281	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11282	    0xff9f,timeout << 5);
11283	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11284
11285	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11286	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11287	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11288
11289	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11290	    (timeoutref + 1)) - 1;
11291	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11292	    0xf0, count >> 8);
11293	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11294
11295	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11296	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11297	while (tmp[1] >= freqref) {
11298		tmp[0]++;
11299		tmp[1] -= freqref;
11300	}
11301	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11302	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11303	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11304	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11305	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11306
11307	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11308	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11309	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11310	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11311
11312	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11313	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11314
11315	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11316		scale = 1;
11317		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11318	} else {
11319		scale = 0;
11320		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11321	}
11322	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11323	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11324
11325	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11326	    (scale + 1);
11327	if (tmp[5] > 150)
11328		tmp[5] = 0;
11329
11330	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11331	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11332
11333	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11334	if (freqxtal > 26000000)
11335		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11336	else
11337		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11338
11339	if (val[0] == 45)
11340		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11341	else
11342		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11343
11344	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11345	DELAY(1);
11346	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11347
11348	/* VCO Calibration */
11349	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11350	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11351	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11352	DELAY(1);
11353	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11354	DELAY(1);
11355	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11356	DELAY(1);
11357	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11358	DELAY(300);
11359	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11360
11361	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11362	return (0);
11363}
11364
11365static int
11366bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11367{
11368	struct bwn_softc *sc = mac->mac_sc;
11369	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11370	const struct bwn_b206x_chan *bc = NULL;
11371	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11372	uint32_t tmp[9];
11373	int i;
11374
11375	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11376		if (bwn_b2062_chantable[i].bc_chan == chan) {
11377			bc = &bwn_b2062_chantable[i];
11378			break;
11379		}
11380	}
11381
11382	if (bc == NULL)
11383		return (EINVAL);
11384
11385	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11386	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11387	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11388	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11389	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11390	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11391	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11392	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11393	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11394	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11395
11396	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11397	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11398	bwn_phy_lp_b2062_reset_pllbias(mac);
11399	tmp[0] = freqxtal / 1000;
11400	tmp[1] = plp->plp_div * 1000;
11401	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11402	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11403		tmp[2] *= 2;
11404	tmp[3] = 48 * tmp[0];
11405	tmp[5] = tmp[2] / tmp[3];
11406	tmp[6] = tmp[2] % tmp[3];
11407	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11408	tmp[4] = tmp[6] * 0x100;
11409	tmp[5] = tmp[4] / tmp[3];
11410	tmp[6] = tmp[4] % tmp[3];
11411	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11412	tmp[4] = tmp[6] * 0x100;
11413	tmp[5] = tmp[4] / tmp[3];
11414	tmp[6] = tmp[4] % tmp[3];
11415	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11416	tmp[4] = tmp[6] * 0x100;
11417	tmp[5] = tmp[4] / tmp[3];
11418	tmp[6] = tmp[4] % tmp[3];
11419	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11420	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11421	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11422	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11423	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11424	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11425
11426	bwn_phy_lp_b2062_vco_calib(mac);
11427	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11428		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11429		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11430		bwn_phy_lp_b2062_reset_pllbias(mac);
11431		bwn_phy_lp_b2062_vco_calib(mac);
11432		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11433			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11434			return (EIO);
11435		}
11436	}
11437	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11438	return (0);
11439}
11440
11441static void
11442bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11443{
11444	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11445	uint16_t tmp = (channel == 14);
11446
11447	if (mac->mac_phy.rev < 2) {
11448		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11449		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11450			bwn_phy_lp_set_rccap(mac);
11451		return;
11452	}
11453
11454	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11455}
11456
11457static void
11458bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11459{
11460	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11461	struct bwn_softc *sc = mac->mac_sc;
11462	struct ifnet *ifp = sc->sc_ifp;
11463	struct ieee80211com *ic = ifp->if_l2com;
11464	uint16_t iso, tmp[3];
11465
11466	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11467
11468	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11469		iso = plp->plp_txisoband_m;
11470	else if (freq <= 5320)
11471		iso = plp->plp_txisoband_l;
11472	else if (freq <= 5700)
11473		iso = plp->plp_txisoband_m;
11474	else
11475		iso = plp->plp_txisoband_h;
11476
11477	tmp[0] = ((iso - 26) / 12) << 12;
11478	tmp[1] = tmp[0] + 0x1000;
11479	tmp[2] = tmp[0] + 0x2000;
11480
11481	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11482	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11483}
11484
11485static void
11486bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11487{
11488	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11489	int i;
11490	static const uint16_t addr[] = {
11491		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11492		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11493		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11494		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11495		BWN_PHY_OFDM(0xcf),
11496	};
11497	static const uint16_t val[] = {
11498		0xde5e, 0xe832, 0xe331, 0x4d26,
11499		0x0026, 0x1420, 0x0020, 0xfe08,
11500		0x0008,
11501	};
11502
11503	for (i = 0; i < N(addr); i++) {
11504		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11505		BWN_PHY_WRITE(mac, addr[i], val[i]);
11506	}
11507}
11508
11509static void
11510bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11511{
11512	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11513	struct bwn_softc *sc = mac->mac_sc;
11514	uint16_t ctl;
11515
11516	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11517	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11518	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11519		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11520		break;
11521	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11522		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11523		break;
11524	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11525		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11526		break;
11527	default:
11528		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11529		device_printf(sc->sc_dev, "unknown command mode\n");
11530		break;
11531	}
11532}
11533
11534static void
11535bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11536{
11537	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11538	uint16_t ctl;
11539	uint8_t old;
11540
11541	bwn_phy_lp_get_txpctlmode(mac);
11542	old = plp->plp_txpctlmode;
11543	if (old == mode)
11544		return;
11545	plp->plp_txpctlmode = mode;
11546
11547	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11548		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11549		    plp->plp_tssiidx);
11550		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11551		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11552
11553		/* disable TX GAIN override */
11554		if (mac->mac_phy.rev < 2)
11555			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11556		else {
11557			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11558			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11559		}
11560		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11561
11562		plp->plp_txpwridx = -1;
11563	}
11564	if (mac->mac_phy.rev >= 2) {
11565		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11566			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11567		else
11568			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11569	}
11570
11571	/* writes TX Power Control mode */
11572	switch (plp->plp_txpctlmode) {
11573	case BWN_PHYLP_TXPCTL_OFF:
11574		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11575		break;
11576	case BWN_PHYLP_TXPCTL_ON_HW:
11577		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11578		break;
11579	case BWN_PHYLP_TXPCTL_ON_SW:
11580		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11581		break;
11582	default:
11583		ctl = 0;
11584		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11585	}
11586	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11587	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11588}
11589
11590static void
11591bwn_phy_lp_bugfix(struct bwn_mac *mac)
11592{
11593	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11594	struct bwn_softc *sc = mac->mac_sc;
11595	const unsigned int size = 256;
11596	struct bwn_txgain tg;
11597	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11598	uint16_t tssinpt, tssiidx, value[2];
11599	uint8_t mode;
11600	int8_t txpwridx;
11601
11602	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11603	    M_NOWAIT | M_ZERO);
11604	if (tabs == NULL) {
11605		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11606		return;
11607	}
11608
11609	bwn_phy_lp_get_txpctlmode(mac);
11610	mode = plp->plp_txpctlmode;
11611	txpwridx = plp->plp_txpwridx;
11612	tssinpt = plp->plp_tssinpt;
11613	tssiidx = plp->plp_tssiidx;
11614
11615	bwn_tab_read_multi(mac,
11616	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11617	    BWN_TAB_4(7, 0x140), size, tabs);
11618
11619	bwn_phy_lp_tblinit(mac);
11620	bwn_phy_lp_bbinit(mac);
11621	bwn_phy_lp_txpctl_init(mac);
11622	bwn_phy_lp_rf_onoff(mac, 1);
11623	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11624
11625	bwn_tab_write_multi(mac,
11626	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11627	    BWN_TAB_4(7, 0x140), size, tabs);
11628
11629	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11630	plp->plp_tssinpt = tssinpt;
11631	plp->plp_tssiidx = tssiidx;
11632	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11633	if (txpwridx != -1) {
11634		/* set TX power by index */
11635		plp->plp_txpwridx = txpwridx;
11636		bwn_phy_lp_get_txpctlmode(mac);
11637		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11638			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11639		if (mac->mac_phy.rev >= 2) {
11640			rxcomp = bwn_tab_read(mac,
11641			    BWN_TAB_4(7, txpwridx + 320));
11642			txgain = bwn_tab_read(mac,
11643			    BWN_TAB_4(7, txpwridx + 192));
11644			tg.tg_pad = (txgain >> 16) & 0xff;
11645			tg.tg_gm = txgain & 0xff;
11646			tg.tg_pga = (txgain >> 8) & 0xff;
11647			tg.tg_dac = (rxcomp >> 28) & 0xff;
11648			bwn_phy_lp_set_txgain(mac, &tg);
11649		} else {
11650			rxcomp = bwn_tab_read(mac,
11651			    BWN_TAB_4(10, txpwridx + 320));
11652			txgain = bwn_tab_read(mac,
11653			    BWN_TAB_4(10, txpwridx + 192));
11654			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11655			    0xf800, (txgain >> 4) & 0x7fff);
11656			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11657			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11658		}
11659		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11660
11661		/* set TX IQCC */
11662		value[0] = (rxcomp >> 10) & 0x3ff;
11663		value[1] = rxcomp & 0x3ff;
11664		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11665
11666		coeff = bwn_tab_read(mac,
11667		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11668		    BWN_TAB_4(10, txpwridx + 448));
11669		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11670		if (mac->mac_phy.rev >= 2) {
11671			rfpwr = bwn_tab_read(mac,
11672			    BWN_TAB_4(7, txpwridx + 576));
11673			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11674			    rfpwr & 0xffff);
11675		}
11676		bwn_phy_lp_set_txgain_override(mac);
11677	}
11678	if (plp->plp_rccap)
11679		bwn_phy_lp_set_rccap(mac);
11680	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11681	bwn_phy_lp_set_txpctlmode(mac, mode);
11682	free(tabs, M_DEVBUF);
11683}
11684
11685static void
11686bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11687{
11688	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11689	int i;
11690	static const uint16_t addr[] = {
11691		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11692		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11693		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11694		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11695		BWN_PHY_OFDM(0xcf),
11696	};
11697
11698	for (i = 0; i < N(addr); i++)
11699		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11700}
11701
11702static void
11703bwn_phy_lp_tblinit(struct bwn_mac *mac)
11704{
11705	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11706
11707	if (mac->mac_phy.rev < 2) {
11708		bwn_phy_lp_tblinit_r01(mac);
11709		bwn_phy_lp_tblinit_txgain(mac);
11710		bwn_phy_lp_set_gaintbl(mac, freq);
11711		return;
11712	}
11713
11714	bwn_phy_lp_tblinit_r2(mac);
11715	bwn_phy_lp_tblinit_txgain(mac);
11716}
11717
11718struct bwn_wpair {
11719	uint16_t		reg;
11720	uint16_t		value;
11721};
11722
11723struct bwn_smpair {
11724	uint16_t		offset;
11725	uint16_t		mask;
11726	uint16_t		set;
11727};
11728
11729static void
11730bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11731{
11732	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11733	struct bwn_softc *sc = mac->mac_sc;
11734	struct ifnet *ifp = sc->sc_ifp;
11735	struct ieee80211com *ic = ifp->if_l2com;
11736	static const struct bwn_wpair v1[] = {
11737		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11738		{ BWN_PHY_AFE_CTL, 0x8800 },
11739		{ BWN_PHY_AFE_CTL_OVR, 0 },
11740		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11741		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11742		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11743		{ BWN_PHY_OFDM(0xf9), 0 },
11744		{ BWN_PHY_TR_LOOKUP_1, 0 }
11745	};
11746	static const struct bwn_smpair v2[] = {
11747		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11748		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11749		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11750		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11751		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11752	};
11753	static const struct bwn_smpair v3[] = {
11754		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11755		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11756		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11757		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11758		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11759		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11760		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11761		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11762		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11763		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11764
11765	};
11766	int i;
11767
11768	for (i = 0; i < N(v1); i++)
11769		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11770	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11771	for (i = 0; i < N(v2); i++)
11772		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11773
11774	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11775	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11776	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11777	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11778		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11779		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11780	} else {
11781		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11782	}
11783	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11784	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11785	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11786	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11787	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11788	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11789	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11790	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11791	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11792	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11793	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11794	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11795	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11796		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11797		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11798	} else {
11799		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11800		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11801	}
11802	for (i = 0; i < N(v3); i++)
11803		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11804	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11805	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11806		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11807		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11808	}
11809
11810	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11811		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11812		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11813		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11814		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11815		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11816		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11817	} else
11818		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11819
11820	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11821	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11822	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11823	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11824	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11825	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11826	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11827	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11828	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11829
11830	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11831	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11832		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11833		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11834		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11835	}
11836
11837	bwn_phy_lp_digflt_save(mac);
11838}
11839
11840static void
11841bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11842{
11843	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11844	struct bwn_softc *sc = mac->mac_sc;
11845	struct ifnet *ifp = sc->sc_ifp;
11846	struct ieee80211com *ic = ifp->if_l2com;
11847	static const struct bwn_smpair v1[] = {
11848		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11849		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11850		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11851		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11852		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11853		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11854		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11855	};
11856	static const struct bwn_smpair v2[] = {
11857		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11858		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11859		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11860		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11861		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11862		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11863		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11864		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11865		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11866		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11867		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11868		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11869		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11870		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11871		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11872		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11873	};
11874	static const struct bwn_smpair v3[] = {
11875		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11876		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11877		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11878		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11879		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11880		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11881		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11882		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11883	};
11884	static const struct bwn_smpair v4[] = {
11885		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11886		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11887		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11888		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11889		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11890		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11891		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11892		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11893	};
11894	static const struct bwn_smpair v5[] = {
11895		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11896		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11897		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11898		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11899		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11900		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11901		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11902		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11903	};
11904	int i;
11905	uint16_t tmp, tmp2;
11906
11907	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11908	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11909	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11910	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11911	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11912	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11913	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11914	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11915	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11916	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11917	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11918	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11919	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11920	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11921	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11922	for (i = 0; i < N(v1); i++)
11923		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11924	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11925	    0xff00, plp->plp_rxpwroffset);
11926	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11927	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11928	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11929		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11930		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11931		if (mac->mac_phy.rev == 0)
11932			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11933			    0xffcf, 0x0010);
11934		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11935	} else {
11936		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11937		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11938		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11939	}
11940	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11941	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11942	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11943		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11944	else
11945		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11946	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11947	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11948	    0xfff9, (plp->plp_bxarch << 1));
11949	if (mac->mac_phy.rev == 1 &&
11950	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11951		for (i = 0; i < N(v2); i++)
11952			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11953			    v2[i].set);
11954	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11955	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11956	    ((mac->mac_phy.rev == 0) &&
11957	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11958		for (i = 0; i < N(v3); i++)
11959			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11960			    v3[i].set);
11961	} else if (mac->mac_phy.rev == 1 ||
11962		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11963		for (i = 0; i < N(v4); i++)
11964			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11965			    v4[i].set);
11966	} else {
11967		for (i = 0; i < N(v5); i++)
11968			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11969			    v5[i].set);
11970	}
11971	if (mac->mac_phy.rev == 1 &&
11972	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11973		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11974		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11975		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11976		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11977	}
11978	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11979	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11980	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11981		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11982		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11983		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11984		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11985	}
11986	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11987		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11988		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11989		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11990		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11991		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11992		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11993		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11994		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11995	} else {
11996		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11997		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11998	}
11999	if (mac->mac_phy.rev == 1) {
12000		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12001		tmp2 = (tmp & 0x03e0) >> 5;
12002		tmp2 |= tmp2 << 5;
12003		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12004		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12005		tmp2 = (tmp & 0x1f00) >> 8;
12006		tmp2 |= tmp2 << 5;
12007		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12008		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12009		tmp2 = tmp & 0x00ff;
12010		tmp2 |= tmp << 8;
12011		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12012	}
12013}
12014
12015struct bwn_b2062_freq {
12016	uint16_t		freq;
12017	uint8_t			value[6];
12018};
12019
12020static void
12021bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12022{
12023#define	CALC_CTL7(freq, div)						\
12024	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12025#define	CALC_CTL18(freq, div)						\
12026	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12027#define	CALC_CTL19(freq, div)						\
12028	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12029	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12030	struct bwn_softc *sc = mac->mac_sc;
12031	struct ifnet *ifp = sc->sc_ifp;
12032	struct ieee80211com *ic = ifp->if_l2com;
12033	static const struct bwn_b2062_freq freqdata_tab[] = {
12034		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12035		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12036		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12037		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12038		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12039		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12040	};
12041	static const struct bwn_wpair v1[] = {
12042		{ BWN_B2062_N_TXCTL3, 0 },
12043		{ BWN_B2062_N_TXCTL4, 0 },
12044		{ BWN_B2062_N_TXCTL5, 0 },
12045		{ BWN_B2062_N_TXCTL6, 0 },
12046		{ BWN_B2062_N_PDNCTL0, 0x40 },
12047		{ BWN_B2062_N_PDNCTL0, 0 },
12048		{ BWN_B2062_N_CALIB_TS, 0x10 },
12049		{ BWN_B2062_N_CALIB_TS, 0 }
12050	};
12051	const struct bwn_b2062_freq *f = NULL;
12052	uint32_t xtalfreq, ref;
12053	unsigned int i;
12054
12055	bwn_phy_lp_b2062_tblinit(mac);
12056
12057	for (i = 0; i < N(v1); i++)
12058		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12059	if (mac->mac_phy.rev > 0)
12060		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12061		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12062	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12063		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12064	else
12065		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12066
12067	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12068	    ("%s:%d: fail", __func__, __LINE__));
12069	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12070	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12071
12072	if (xtalfreq <= 30000000) {
12073		plp->plp_div = 1;
12074		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12075	} else {
12076		plp->plp_div = 2;
12077		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12078	}
12079
12080	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12081	    CALC_CTL7(xtalfreq, plp->plp_div));
12082	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12083	    CALC_CTL18(xtalfreq, plp->plp_div));
12084	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12085	    CALC_CTL19(xtalfreq, plp->plp_div));
12086
12087	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12088	ref &= 0xffff;
12089	for (i = 0; i < N(freqdata_tab); i++) {
12090		if (ref < freqdata_tab[i].freq) {
12091			f = &freqdata_tab[i];
12092			break;
12093		}
12094	}
12095	if (f == NULL)
12096		f = &freqdata_tab[N(freqdata_tab) - 1];
12097	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12098	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12099	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12100	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12101	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12102	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12103#undef CALC_CTL7
12104#undef CALC_CTL18
12105#undef CALC_CTL19
12106}
12107
12108static void
12109bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12110{
12111
12112	bwn_phy_lp_b2063_tblinit(mac);
12113	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12114	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12115	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12116	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12117	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12118	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12119	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12120	if (mac->mac_phy.rev == 2) {
12121		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12122		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12123		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12124	} else {
12125		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12126		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12127	}
12128}
12129
12130static void
12131bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12132{
12133	struct bwn_softc *sc = mac->mac_sc;
12134	static const struct bwn_wpair v1[] = {
12135		{ BWN_B2063_RX_BB_SP8, 0x0 },
12136		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12137		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12138		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12139		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12140		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12141		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12142		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12143	};
12144	static const struct bwn_wpair v2[] = {
12145		{ BWN_B2063_TX_BB_SP3, 0x0 },
12146		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12147		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12148		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12149		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12150	};
12151	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12152	int i;
12153	uint8_t tmp;
12154
12155	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12156
12157	for (i = 0; i < 2; i++)
12158		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12159	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12160	for (i = 2; i < N(v1); i++)
12161		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12162	for (i = 0; i < 10000; i++) {
12163		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12164			break;
12165		DELAY(1000);
12166	}
12167
12168	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12169		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12170
12171	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12172
12173	for (i = 0; i < N(v2); i++)
12174		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12175	if (freqxtal == 24000000) {
12176		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12177		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12178	} else {
12179		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12180		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12181	}
12182	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12183	for (i = 0; i < 10000; i++) {
12184		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12185			break;
12186		DELAY(1000);
12187	}
12188	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12189		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12190	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12191}
12192
12193static void
12194bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12195{
12196	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12197	struct bwn_softc *sc = mac->mac_sc;
12198	struct bwn_phy_lp_iq_est ie;
12199	struct bwn_txgain tx_gains;
12200	static const uint32_t pwrtbl[21] = {
12201		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12202		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12203		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12204		0x0004c, 0x0002c, 0x0001a,
12205	};
12206	uint32_t npwr, ipwr, sqpwr, tmp;
12207	int loopback, i, j, sum, error;
12208	uint16_t save[7];
12209	uint8_t txo, bbmult, txpctlmode;
12210
12211	error = bwn_phy_lp_switch_channel(mac, 7);
12212	if (error)
12213		device_printf(sc->sc_dev,
12214		    "failed to change channel to 7 (%d)\n", error);
12215	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12216	bbmult = bwn_phy_lp_get_bbmult(mac);
12217	if (txo)
12218		tx_gains = bwn_phy_lp_get_txgain(mac);
12219
12220	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12221	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12222	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12223	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12224	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12225	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12226	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12227
12228	bwn_phy_lp_get_txpctlmode(mac);
12229	txpctlmode = plp->plp_txpctlmode;
12230	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12231
12232	/* disable CRS */
12233	bwn_phy_lp_set_deaf(mac, 1);
12234	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12235	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12236	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12237	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12238	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12239	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12240	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12241	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12242	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12243	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12244	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12245	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12246	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12247	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12248	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12249	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12250	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12251	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12252	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12253	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12254	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12255	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12256	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12257	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12258
12259	loopback = bwn_phy_lp_loopback(mac);
12260	if (loopback == -1)
12261		goto done;
12262	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12263	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12264	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12265	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12266	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12267
12268	tmp = 0;
12269	memset(&ie, 0, sizeof(ie));
12270	for (i = 128; i <= 159; i++) {
12271		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12272		sum = 0;
12273		for (j = 5; j <= 25; j++) {
12274			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12275			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12276				goto done;
12277			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12278			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12279			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12280			    12);
12281			sum += ((ipwr - npwr) * (ipwr - npwr));
12282			if ((i == 128) || (sum < tmp)) {
12283				plp->plp_rccap = i;
12284				tmp = sum;
12285			}
12286		}
12287	}
12288	bwn_phy_lp_ddfs_turnoff(mac);
12289done:
12290	/* restore CRS */
12291	bwn_phy_lp_clear_deaf(mac, 1);
12292	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12293	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12294
12295	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12296	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12297	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12298	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12299	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12300	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12301	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12302
12303	bwn_phy_lp_set_bbmult(mac, bbmult);
12304	if (txo)
12305		bwn_phy_lp_set_txgain(mac, &tx_gains);
12306	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12307	if (plp->plp_rccap)
12308		bwn_phy_lp_set_rccap(mac);
12309}
12310
12311static void
12312bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12313{
12314	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12315	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12316
12317	if (mac->mac_phy.rev == 1)
12318		rc_cap = MIN(rc_cap + 5, 15);
12319
12320	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12321	    MAX(plp->plp_rccap - 4, 0x80));
12322	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12323	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12324	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12325}
12326
12327static uint32_t
12328bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12329{
12330	uint32_t i, q, r;
12331
12332	if (div == 0)
12333		return (0);
12334
12335	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12336		q <<= 1;
12337		if (r << 1 >= div) {
12338			q++;
12339			r = (r << 1) - div;
12340		}
12341	}
12342	if (r << 1 >= div)
12343		q++;
12344	return (q);
12345}
12346
12347static void
12348bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12349{
12350	struct bwn_softc *sc = mac->mac_sc;
12351
12352	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12353	DELAY(20);
12354	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12355		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12356		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12357	} else {
12358		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12359	}
12360	DELAY(5);
12361}
12362
12363static void
12364bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12365{
12366
12367	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12368	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12369	DELAY(200);
12370}
12371
12372static void
12373bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12374{
12375#define	FLAG_A	0x01
12376#define	FLAG_G	0x02
12377	struct bwn_softc *sc = mac->mac_sc;
12378	struct ifnet *ifp = sc->sc_ifp;
12379	struct ieee80211com *ic = ifp->if_l2com;
12380	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12381		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12382		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12383		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12384		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12385		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12386		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12387		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12388		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12389		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12390		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12391		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12392		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12393		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12394		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12399		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12400		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12427		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12428	};
12429	const struct bwn_b206x_rfinit_entry *br;
12430	unsigned int i;
12431
12432	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12433		br = &bwn_b2062_init_tab[i];
12434		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12435			if (br->br_flags & FLAG_G)
12436				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12437		} else {
12438			if (br->br_flags & FLAG_A)
12439				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12440		}
12441	}
12442#undef FLAG_A
12443#undef FLAG_B
12444}
12445
12446static void
12447bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12448{
12449#define	FLAG_A	0x01
12450#define	FLAG_G	0x02
12451	struct bwn_softc *sc = mac->mac_sc;
12452	struct ifnet *ifp = sc->sc_ifp;
12453	struct ieee80211com *ic = ifp->if_l2com;
12454	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12455		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12456		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12457		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12458		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12459		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12460		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12461		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12462		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12463		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12464		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12465		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12466		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12467		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12468		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12469		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12470		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12471		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12472		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12473		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12474		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12475		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12476		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12477		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12478		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12479		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12480		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12482		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12483		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12484		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12485		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12487		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12488		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12491		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12492		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12493		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12494		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12495		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12496		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12497	};
12498	const struct bwn_b206x_rfinit_entry *br;
12499	unsigned int i;
12500
12501	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12502		br = &bwn_b2063_init_tab[i];
12503		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12504			if (br->br_flags & FLAG_G)
12505				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12506		} else {
12507			if (br->br_flags & FLAG_A)
12508				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12509		}
12510	}
12511#undef FLAG_A
12512#undef FLAG_B
12513}
12514
12515static void
12516bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12517    int count, void *_data)
12518{
12519	unsigned int i;
12520	uint32_t offset, type;
12521	uint8_t *data = _data;
12522
12523	type = BWN_TAB_GETTYPE(typenoffset);
12524	offset = BWN_TAB_GETOFFSET(typenoffset);
12525	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12526
12527	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12528
12529	for (i = 0; i < count; i++) {
12530		switch (type) {
12531		case BWN_TAB_8BIT:
12532			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12533			data++;
12534			break;
12535		case BWN_TAB_16BIT:
12536			*((uint16_t *)data) = BWN_PHY_READ(mac,
12537			    BWN_PHY_TABLEDATALO);
12538			data += 2;
12539			break;
12540		case BWN_TAB_32BIT:
12541			*((uint32_t *)data) = BWN_PHY_READ(mac,
12542			    BWN_PHY_TABLEDATAHI);
12543			*((uint32_t *)data) <<= 16;
12544			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12545			    BWN_PHY_TABLEDATALO);
12546			data += 4;
12547			break;
12548		default:
12549			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12550		}
12551	}
12552}
12553
12554static void
12555bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12556    int count, const void *_data)
12557{
12558	uint32_t offset, type, value;
12559	const uint8_t *data = _data;
12560	unsigned int i;
12561
12562	type = BWN_TAB_GETTYPE(typenoffset);
12563	offset = BWN_TAB_GETOFFSET(typenoffset);
12564	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12565
12566	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12567
12568	for (i = 0; i < count; i++) {
12569		switch (type) {
12570		case BWN_TAB_8BIT:
12571			value = *data;
12572			data++;
12573			KASSERT(!(value & ~0xff),
12574			    ("%s:%d: fail", __func__, __LINE__));
12575			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12576			break;
12577		case BWN_TAB_16BIT:
12578			value = *((const uint16_t *)data);
12579			data += 2;
12580			KASSERT(!(value & ~0xffff),
12581			    ("%s:%d: fail", __func__, __LINE__));
12582			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12583			break;
12584		case BWN_TAB_32BIT:
12585			value = *((const uint32_t *)data);
12586			data += 4;
12587			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12588			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12589			break;
12590		default:
12591			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12592		}
12593	}
12594}
12595
12596static struct bwn_txgain
12597bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12598{
12599	struct bwn_txgain tg;
12600	uint16_t tmp;
12601
12602	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12603	if (mac->mac_phy.rev < 2) {
12604		tmp = BWN_PHY_READ(mac,
12605		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12606		tg.tg_gm = tmp & 0x0007;
12607		tg.tg_pga = (tmp & 0x0078) >> 3;
12608		tg.tg_pad = (tmp & 0x780) >> 7;
12609		return (tg);
12610	}
12611
12612	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12613	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12614	tg.tg_gm = tmp & 0xff;
12615	tg.tg_pga = (tmp >> 8) & 0xff;
12616	return (tg);
12617}
12618
12619static uint8_t
12620bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12621{
12622
12623	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12624}
12625
12626static void
12627bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12628{
12629	uint16_t pa;
12630
12631	if (mac->mac_phy.rev < 2) {
12632		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12633		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12634		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12635		bwn_phy_lp_set_txgain_override(mac);
12636		return;
12637	}
12638
12639	pa = bwn_phy_lp_get_pa_gain(mac);
12640	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12641	    (tg->tg_pga << 8) | tg->tg_gm);
12642	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12643	    tg->tg_pad | (pa << 6));
12644	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12645	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12646	    tg->tg_pad | (pa << 8));
12647	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12648	bwn_phy_lp_set_txgain_override(mac);
12649}
12650
12651static void
12652bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12653{
12654
12655	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12656}
12657
12658static void
12659bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12660{
12661	uint16_t trsw = (tx << 1) | rx;
12662
12663	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12664	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12665}
12666
12667static void
12668bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12669{
12670	struct bwn_softc *sc = mac->mac_sc;
12671	struct ifnet *ifp = sc->sc_ifp;
12672	struct ieee80211com *ic = ifp->if_l2com;
12673	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12674
12675	if (mac->mac_phy.rev < 2) {
12676		trsw = gain & 0x1;
12677		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12678		ext_lna = (gain & 2) >> 1;
12679
12680		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12681		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12682		    0xfbff, ext_lna << 10);
12683		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12684		    0xf7ff, ext_lna << 11);
12685		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12686	} else {
12687		low_gain = gain & 0xffff;
12688		high_gain = (gain >> 16) & 0xf;
12689		ext_lna = (gain >> 21) & 0x1;
12690		trsw = ~(gain >> 20) & 0x1;
12691
12692		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12693		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12694		    0xfdff, ext_lna << 9);
12695		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12696		    0xfbff, ext_lna << 10);
12697		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12698		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12699		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12700			tmp = (gain >> 2) & 0x3;
12701			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12702			    0xe7ff, tmp<<11);
12703			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12704			    tmp << 3);
12705		}
12706	}
12707
12708	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12709	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12710	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12711	if (mac->mac_phy.rev >= 2) {
12712		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12713		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12714			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12715			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12716		}
12717		return;
12718	}
12719	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12720}
12721
12722static void
12723bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12724{
12725	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12726
12727	if (user)
12728		plp->plp_crsusr_off = 1;
12729	else
12730		plp->plp_crssys_off = 1;
12731
12732	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12733}
12734
12735static void
12736bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12737{
12738	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12739	struct bwn_softc *sc = mac->mac_sc;
12740	struct ifnet *ifp = sc->sc_ifp;
12741	struct ieee80211com *ic = ifp->if_l2com;
12742
12743	if (user)
12744		plp->plp_crsusr_off = 0;
12745	else
12746		plp->plp_crssys_off = 0;
12747
12748	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12749		return;
12750
12751	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12752		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12753	else
12754		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12755}
12756
12757static unsigned int
12758bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12759{
12760	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12761	static uint8_t sqrt_table[256] = {
12762		10, 14, 17, 20, 22, 24, 26, 28,
12763		30, 31, 33, 34, 36, 37, 38, 40,
12764		41, 42, 43, 44, 45, 46, 47, 48,
12765		50, 50, 51, 52, 53, 54, 55, 56,
12766		57, 58, 59, 60, 60, 61, 62, 63,
12767		64, 64, 65, 66, 67, 67, 68, 69,
12768		70, 70, 71, 72, 72, 73, 74, 74,
12769		75, 76, 76, 77, 78, 78, 79, 80,
12770		80, 81, 81, 82, 83, 83, 84, 84,
12771		85, 86, 86, 87, 87, 88, 88, 89,
12772		90, 90, 91, 91, 92, 92, 93, 93,
12773		94, 94, 95, 95, 96, 96, 97, 97,
12774		98, 98, 99, 100, 100, 100, 101, 101,
12775		102, 102, 103, 103, 104, 104, 105, 105,
12776		106, 106, 107, 107, 108, 108, 109, 109,
12777		110, 110, 110, 111, 111, 112, 112, 113,
12778		113, 114, 114, 114, 115, 115, 116, 116,
12779		117, 117, 117, 118, 118, 119, 119, 120,
12780		120, 120, 121, 121, 122, 122, 122, 123,
12781		123, 124, 124, 124, 125, 125, 126, 126,
12782		126, 127, 127, 128, 128, 128, 129, 129,
12783		130, 130, 130, 131, 131, 131, 132, 132,
12784		133, 133, 133, 134, 134, 134, 135, 135,
12785		136, 136, 136, 137, 137, 137, 138, 138,
12786		138, 139, 139, 140, 140, 140, 141, 141,
12787		141, 142, 142, 142, 143, 143, 143, 144,
12788		144, 144, 145, 145, 145, 146, 146, 146,
12789		147, 147, 147, 148, 148, 148, 149, 149,
12790		150, 150, 150, 150, 151, 151, 151, 152,
12791		152, 152, 153, 153, 153, 154, 154, 154,
12792		155, 155, 155, 156, 156, 156, 157, 157,
12793		157, 158, 158, 158, 159, 159, 159, 160
12794	};
12795
12796	if (x == 0)
12797		return (0);
12798	if (x >= 256) {
12799		unsigned int tmp;
12800
12801		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12802			/* do nothing */ ;
12803		return (tmp);
12804	}
12805	return (sqrt_table[x - 1] / 10);
12806}
12807
12808static int
12809bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12810{
12811#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12812	int _t;								\
12813	_t = _x - 20;							\
12814	if (_t >= 0) {							\
12815		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12816	} else {							\
12817		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12818	}								\
12819} while (0)
12820#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12821	int _t;								\
12822	_t = _x - 11;							\
12823	if (_t >= 0)							\
12824		_v = (_y << (31 - _x)) / (_z >> _t);			\
12825	else								\
12826		_v = (_y << (31 - _x)) / (_z << -_t);			\
12827} while (0)
12828	struct bwn_phy_lp_iq_est ie;
12829	uint16_t v0, v1;
12830	int tmp[2], ret;
12831
12832	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12833	v0 = v1 >> 8;
12834	v1 |= 0xff;
12835
12836	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12837	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12838
12839	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12840	if (ret == 0)
12841		goto done;
12842
12843	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12844		ret = 0;
12845		goto done;
12846	}
12847
12848	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12849	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12850
12851	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12852	v0 = tmp[0] >> 3;
12853	v1 = tmp[1] >> 4;
12854done:
12855	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12856	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12857	return ret;
12858#undef CALC_COEFF
12859#undef CALC_COEFF2
12860}
12861
12862static void
12863bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12864{
12865	static const uint16_t noisescale[] = {
12866		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12867		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12868		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12869		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12870		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12871	};
12872	static const uint16_t crsgainnft[] = {
12873		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12874		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12875		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12876		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12877		0x013d,
12878	};
12879	static const uint16_t filterctl[] = {
12880		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12881		0xff53, 0x0127,
12882	};
12883	static const uint32_t psctl[] = {
12884		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12885		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12886		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12887		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12888		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12889		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12890		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12891		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12892	};
12893	static const uint16_t ofdmcckgain_r0[] = {
12894		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12895		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12896		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12897		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12898		0x755d,
12899	};
12900	static const uint16_t ofdmcckgain_r1[] = {
12901		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12902		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12903		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12904		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12905		0x755d,
12906	};
12907	static const uint16_t gaindelta[] = {
12908		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12909		0x0000,
12910	};
12911	static const uint32_t txpwrctl[] = {
12912		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12913		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12914		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12915		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12916		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12917		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12918		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12919		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12920		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12921		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12922		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12923		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12924		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12925		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12950		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12951		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12952		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12953		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12954		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12955		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12956		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12957		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12958		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12959		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12960		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12961		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12962		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12963		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12964		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12965		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12966		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12967		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12968		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12969		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12970		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12971		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12972		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12973		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12974		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12975		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12976		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12977		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12978		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12979		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12980		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12981		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12982		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12983		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12984		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13000		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13001		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13002		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13003		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13004		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13005		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13006		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13007		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13008		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13009		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13010		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13011		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13012		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13013		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13014		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13015		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13016		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13017		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13018		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13019		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13020		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13021		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13022		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13023		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13024		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13025		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13026		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13027		0x00000702,
13028	};
13029
13030	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13031
13032	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13033	    bwn_tab_sigsq_tbl);
13034	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13035	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13036	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13037	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13038	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13039	    bwn_tab_pllfrac_tbl);
13040	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13041	    bwn_tabl_iqlocal_tbl);
13042	if (mac->mac_phy.rev == 0) {
13043		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13044		    ofdmcckgain_r0);
13045		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13046		    ofdmcckgain_r0);
13047	} else {
13048		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13049		    ofdmcckgain_r1);
13050		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13051		    ofdmcckgain_r1);
13052	}
13053	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13054	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13055}
13056
13057static void
13058bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13059{
13060	struct bwn_softc *sc = mac->mac_sc;
13061	int i;
13062	static const uint16_t noisescale[] = {
13063		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13068		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13069		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13070	};
13071	static const uint32_t filterctl[] = {
13072		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13073		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13074	};
13075	static const uint32_t psctl[] = {
13076		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13077		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13078		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13079		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13080	};
13081	static const uint32_t gainidx[] = {
13082		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13084		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13085		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13086		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13087		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13088		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13089		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13090		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13091		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13092		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13093		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13094		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13095		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13096		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13097		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13099		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13100		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13101		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13102		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13103		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13104		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13105		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13106		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13107		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13108		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13109		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13110		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13111		0x0000001a, 0x64ca55ad, 0x0000001a
13112	};
13113	static const uint16_t auxgainidx[] = {
13114		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13115		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13116		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13117		0x0004, 0x0016
13118	};
13119	static const uint16_t swctl[] = {
13120		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13121		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13122		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13123		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13124		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13125		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13126		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13127		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13128	};
13129	static const uint8_t hf[] = {
13130		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13131		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13132	};
13133	static const uint32_t gainval[] = {
13134		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13135		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13136		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13137		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13138		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13139		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13142		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13143		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13144		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13145		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13146		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13147		0x000000f1, 0x00000000, 0x00000000
13148	};
13149	static const uint16_t gain[] = {
13150		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13151		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13152		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13153		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13154		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13155		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13156		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13160		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13161		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13162	};
13163	static const uint32_t papdeps[] = {
13164		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13165		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13166		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13167		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13168		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13169		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13170		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13171		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13172		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13173		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13174		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13175		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13176		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13177	};
13178	static const uint32_t papdmult[] = {
13179		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13180		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13181		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13182		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13183		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13184		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13185		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13186		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13187		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13188		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13189		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13190		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13191		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13192	};
13193	static const uint32_t gainidx_a0[] = {
13194		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13195		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13196		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13197		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13198		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13199		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13200		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13201		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13202		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13203		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13204		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13205		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13206		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13207	};
13208	static const uint16_t auxgainidx_a0[] = {
13209		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13210		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13211		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13212		0x0002, 0x0014
13213	};
13214	static const uint32_t gainval_a0[] = {
13215		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13216		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13217		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13218		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13219		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13220		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13221		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13222		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13223		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13224		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13225		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13226		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13227		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13228		0x000000f7, 0x00000000, 0x00000000
13229	};
13230	static const uint16_t gain_a0[] = {
13231		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13232		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13233		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13234		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13235		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13236		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13237		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13241		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13242		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13243	};
13244
13245	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13246
13247	for (i = 0; i < 704; i++)
13248		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13249
13250	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13251	    bwn_tab_sigsq_tbl);
13252	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13253	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13254	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13255	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13256	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13257	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13258	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13259	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13260	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13261	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13262	    bwn_tab_pllfrac_tbl);
13263	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13264	    bwn_tabl_iqlocal_tbl);
13265	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13266	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13267
13268	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13269	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13270		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13271		    gainidx_a0);
13272		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13273		    auxgainidx_a0);
13274		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13275		    gainval_a0);
13276		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13277	}
13278}
13279
13280static void
13281bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13282{
13283	struct bwn_softc *sc = mac->mac_sc;
13284	struct ifnet *ifp = sc->sc_ifp;
13285	struct ieee80211com *ic = ifp->if_l2com;
13286	static struct bwn_txgain_entry txgain_r2[] = {
13287		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13288		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13289		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13290		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13291		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13292		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13293		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13294		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13295		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13296		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13297		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13298		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13299		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13300		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13301		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13302		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13303		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13304		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13305		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13306		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13307		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13308		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13309		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13310		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13311		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13312		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13313		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13314		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13315		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13316		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13317		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13318		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13319		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13320		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13321		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13322		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13323		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13324		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13325		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13326		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13327		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13328		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13329		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13330		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13331		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13332		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13333		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13334		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13335		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13336		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13337		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13338		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13339		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13340		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13341		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13342		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13343		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13344		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13345		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13346		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13347		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13348		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13349		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13350		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13351	};
13352	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13353		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13354		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13355		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13356		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13357		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13358		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13359		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13360		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13361		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13362		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13363		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13364		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13365		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13366		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13367		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13368		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13369		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13370		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13371		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13372		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13373		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13374		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13375		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13376		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13377		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13378		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13379		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13380		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13381		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13382		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13383		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13384		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13385		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13386		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13387		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13388		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13389		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13390		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13391		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13392		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13393		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13394		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13395		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13396		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13397		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13398		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13399		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13400		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13401		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13402		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13403		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13404		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13405		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13406		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13407		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13408		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13409		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13410		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13411		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13412		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13413		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13414		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13415		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13416		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13417	};
13418	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13419		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13420		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13421		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13422		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13423		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13424		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13425		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13426		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13427		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13428		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13429		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13430		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13431		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13432		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13433		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13434		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13435		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13436		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13437		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13438		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13439		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13440		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13441		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13442		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13443		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13444		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13445		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13446		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13447		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13448		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13449		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13450		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13451		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13452		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13453		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13454		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13455		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13456		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13457		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13458		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13459		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13460		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13461		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13462		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13463		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13464		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13465		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13466		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13467		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13468		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13469		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13470		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13471		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13472		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13473		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13474		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13475		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13476		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13477		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13478		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13479		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13480		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13481		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13482		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13483	};
13484	static struct bwn_txgain_entry txgain_r0[] = {
13485		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13486		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13487		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13488		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13489		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13490		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13491		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13492		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13493		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13494		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13495		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13496		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13497		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13498		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13499		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13500		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13501		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13502		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13503		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13504		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13505		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13506		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13507		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13508		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13509		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13510		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13511		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13512		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13513		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13514		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13515		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13516		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13517		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13518		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13519		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13520		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13521		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13522		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13523		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13524		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13525		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13526		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13527		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13528		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13529		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13530		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13531		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13532		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13533		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13534		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13535		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13536		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13537		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13538		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13539		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13540		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13541		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13542		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13543		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13544		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13545		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13546		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13547		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13548		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13549	};
13550	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13551		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13552		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13553		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13554		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13555		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13556		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13557		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13558		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13559		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13560		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13561		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13562		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13563		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13564		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13565		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13566		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13567		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13568		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13569		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13570		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13571		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13572		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13573		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13574		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13575		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13576		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13577		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13578		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13579		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13580		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13581		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13582		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13583		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13584		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13585		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13586		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13587		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13588		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13589		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13590		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13591		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13592		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13593		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13594		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13595		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13596		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13597		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13598		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13599		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13600		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13601		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13602		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13603		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13604		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13605		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13606		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13607		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13608		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13609		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13610		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13611		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13612		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13613		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13614		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13615	};
13616	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13617		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13618		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13619		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13620		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13621		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13622		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13623		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13624		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13625		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13626		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13627		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13628		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13629		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13630		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13631		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13632		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13633		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13634		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13635		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13636		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13637		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13638		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13639		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13640		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13641		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13642		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13643		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13644		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13645		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13646		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13647		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13648		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13649		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13650		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13651		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13652		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13653		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13654		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13655		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13656		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13657		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13658		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13659		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13660		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13661		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13662		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13663		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13664		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13665		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13666		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13667		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13668		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13669		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13670		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13671		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13672		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13673		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13674		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13675		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13676		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13677		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13678		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13679		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13680		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13681	};
13682	static struct bwn_txgain_entry txgain_r1[] = {
13683		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13684		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13685		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13686		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13687		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13688		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13689		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13690		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13691		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13692		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13693		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13694		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13695		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13696		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13697		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13698		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13699		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13700		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13701		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13702		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13703		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13704		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13705		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13706		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13707		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13708		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13709		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13710		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13711		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13712		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13713		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13714		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13715		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13716		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13717		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13718		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13719		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13720		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13721		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13722		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13723		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13724		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13725		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13726		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13727		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13728		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13729		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13730		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13731		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13732		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13733		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13734		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13735		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13736		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13737		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13738		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13739		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13740		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13741		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13742		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13743		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13744		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13745		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13746		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13747		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13748		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13749		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13750		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13751		{ 7, 11, 6, 0, 71 }
13752	};
13753	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13754		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13755		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13756		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13757		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13758		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13759		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13760		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13761		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13762		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13763		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13764		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13765		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13766		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13767		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13768		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13769		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13770		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13771		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13772		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13773		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13774		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13775		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13776		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13777		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13778		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13779		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13780		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13781		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13782		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13783		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13784		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13785		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13786		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13787		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13788		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13789		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13790		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13791		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13792		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13793		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13794		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13795		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13796		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13797		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13798		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13799		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13800		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13801		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13802		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13803		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13804		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13805		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13806		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13807		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13808		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13809		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13810		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13811		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13812		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13813		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13814		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13815		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13816		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13817		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13818	};
13819	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13820		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13821		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13822		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13823		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13824		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13825		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13826		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13827		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13828		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13829		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13830		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13831		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13832		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13833		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13834		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13835		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13836		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13837		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13838		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13839		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13840		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13841		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13842		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13843		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13844		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13845		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13846		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13847		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13848		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13849		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13850		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13851		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13852		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13853		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13854		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13855		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13856		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13857		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13858		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13859		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13860		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13861		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13862		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13863		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13864		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13865		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13866		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13867		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13868		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13869		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13870		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13871		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13872		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13873		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13874		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13875		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13876		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13877		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13878		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13879		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13880		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13881		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13882		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13883		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13884	};
13885
13886	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13887		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13888			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13889		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13890			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13891			    txgain_2ghz_r2);
13892		else
13893			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13894			    txgain_5ghz_r2);
13895		return;
13896	}
13897
13898	if (mac->mac_phy.rev == 0) {
13899		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13900		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13901			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13902		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13903			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13904			    txgain_2ghz_r0);
13905		else
13906			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13907			    txgain_5ghz_r0);
13908		return;
13909	}
13910
13911	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13912	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13913		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13914	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13915		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13916	else
13917		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13918}
13919
13920static void
13921bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13922{
13923	uint32_t offset, type;
13924
13925	type = BWN_TAB_GETTYPE(typeoffset);
13926	offset = BWN_TAB_GETOFFSET(typeoffset);
13927	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13928
13929	switch (type) {
13930	case BWN_TAB_8BIT:
13931		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13932		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13933		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13934		break;
13935	case BWN_TAB_16BIT:
13936		KASSERT(!(value & ~0xffff),
13937		    ("%s:%d: fail", __func__, __LINE__));
13938		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13939		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13940		break;
13941	case BWN_TAB_32BIT:
13942		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13943		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13944		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13945		break;
13946	default:
13947		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13948	}
13949}
13950
13951static int
13952bwn_phy_lp_loopback(struct bwn_mac *mac)
13953{
13954	struct bwn_phy_lp_iq_est ie;
13955	int i, index = -1;
13956	uint32_t tmp;
13957
13958	memset(&ie, 0, sizeof(ie));
13959
13960	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13961	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13962	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13963	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13964	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13965	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13966	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13967	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13968	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13969	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13970	for (i = 0; i < 32; i++) {
13971		bwn_phy_lp_set_rxgain_idx(mac, i);
13972		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13973		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13974			continue;
13975		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13976		if ((tmp > 4000) && (tmp < 10000)) {
13977			index = i;
13978			break;
13979		}
13980	}
13981	bwn_phy_lp_ddfs_turnoff(mac);
13982	return (index);
13983}
13984
13985static void
13986bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13987{
13988
13989	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13990}
13991
13992static void
13993bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13994    int incr1, int incr2, int scale_idx)
13995{
13996
13997	bwn_phy_lp_ddfs_turnoff(mac);
13998	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13999	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14000	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14001	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14002	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14003	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14004	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14005	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14006	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14007	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14008}
14009
14010static uint8_t
14011bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14012    struct bwn_phy_lp_iq_est *ie)
14013{
14014	int i;
14015
14016	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14017	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14018	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14019	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14020	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14021
14022	for (i = 0; i < 500; i++) {
14023		if (!(BWN_PHY_READ(mac,
14024		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14025			break;
14026		DELAY(1000);
14027	}
14028	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14029		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14030		return 0;
14031	}
14032
14033	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14034	ie->ie_iqprod <<= 16;
14035	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14036	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14037	ie->ie_ipwr <<= 16;
14038	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14039	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14040	ie->ie_qpwr <<= 16;
14041	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14042
14043	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14044	return 1;
14045}
14046
14047static uint32_t
14048bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14049{
14050	uint32_t offset, type, value;
14051
14052	type = BWN_TAB_GETTYPE(typeoffset);
14053	offset = BWN_TAB_GETOFFSET(typeoffset);
14054	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14055
14056	switch (type) {
14057	case BWN_TAB_8BIT:
14058		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14059		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14060		break;
14061	case BWN_TAB_16BIT:
14062		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14063		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14064		break;
14065	case BWN_TAB_32BIT:
14066		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14067		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14068		value <<= 16;
14069		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14070		break;
14071	default:
14072		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14073		value = 0;
14074	}
14075
14076	return (value);
14077}
14078
14079static void
14080bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14081{
14082
14083	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14084	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14085}
14086
14087static void
14088bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14089{
14090	uint16_t ctl;
14091
14092	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14093	ctl |= dac << 7;
14094	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14095}
14096
14097static void
14098bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14099{
14100
14101	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14102	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14103}
14104
14105static void
14106bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14107{
14108
14109	if (mac->mac_phy.rev < 2)
14110		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14111	else {
14112		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14113		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14114	}
14115	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14116}
14117
14118static uint16_t
14119bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14120{
14121
14122	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14123}
14124
14125static uint8_t
14126bwn_nbits(int32_t val)
14127{
14128	uint32_t tmp;
14129	uint8_t nbits = 0;
14130
14131	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14132		nbits++;
14133	return (nbits);
14134}
14135
14136static void
14137bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14138    struct bwn_txgain_entry *table)
14139{
14140	int i;
14141
14142	for (i = offset; i < count; i++)
14143		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14144}
14145
14146static void
14147bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14148    struct bwn_txgain_entry data)
14149{
14150
14151	if (mac->mac_phy.rev >= 2)
14152		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14153	else
14154		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14155}
14156
14157static void
14158bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14159    struct bwn_txgain_entry te)
14160{
14161	struct bwn_softc *sc = mac->mac_sc;
14162	struct ifnet *ifp = sc->sc_ifp;
14163	struct ieee80211com *ic = ifp->if_l2com;
14164	uint32_t tmp;
14165
14166	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14167
14168	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14169	if (mac->mac_phy.rev >= 3) {
14170		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14171		    (0x10 << 24) : (0x70 << 24));
14172	} else {
14173		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14174		    (0x14 << 24) : (0x7f << 24));
14175	}
14176	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14177	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14178	    te.te_bbmult << 20 | te.te_dac << 28);
14179}
14180
14181static void
14182bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14183    struct bwn_txgain_entry te)
14184{
14185
14186	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14187
14188	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14189	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14190	    te.te_dac);
14191	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14192}
14193
14194static void
14195bwn_sysctl_node(struct bwn_softc *sc)
14196{
14197	device_t dev = sc->sc_dev;
14198	struct bwn_mac *mac;
14199	struct bwn_stats *stats;
14200
14201	/* XXX assume that count of MAC is only 1. */
14202
14203	if ((mac = sc->sc_curmac) == NULL)
14204		return;
14205	stats = &mac->mac_stats;
14206
14207	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14208	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14209	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14210	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14211	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14212	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14213	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14214	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14215	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14216
14217#ifdef BWN_DEBUG
14218	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14219	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14220	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14221#endif
14222}
14223
14224static device_method_t bwn_methods[] = {
14225	/* Device interface */
14226	DEVMETHOD(device_probe,		bwn_probe),
14227	DEVMETHOD(device_attach,	bwn_attach),
14228	DEVMETHOD(device_detach,	bwn_detach),
14229	DEVMETHOD(device_suspend,	bwn_suspend),
14230	DEVMETHOD(device_resume,	bwn_resume),
14231	DEVMETHOD_END
14232};
14233static driver_t bwn_driver = {
14234	"bwn",
14235	bwn_methods,
14236	sizeof(struct bwn_softc)
14237};
14238static devclass_t bwn_devclass;
14239DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14240MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14241MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14242MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14243MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14244