if_bwn.c revision 249800
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 249800 2013-04-23 13:02:57Z eadler $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_phy.h>
71#include <net80211/ieee80211_ratectl.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
77    "Broadcom driver parameters");
78
79/*
80 * Tunable & sysctl variables.
81 */
82
83#ifdef BWN_DEBUG
84static	int bwn_debug = 0;
85SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
86    "Broadcom debugging printfs");
87TUNABLE_INT("hw.bwn.debug", &bwn_debug);
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	/* XXX not right but it's not used anywhere important */
1062	ic->ic_phytype = IEEE80211_T_OFDM;
1063	ic->ic_opmode = IEEE80211_M_STA;
1064	ic->ic_caps =
1065		  IEEE80211_C_STA		/* station mode supported */
1066		| IEEE80211_C_MONITOR		/* monitor mode */
1067		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1068		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1069		| IEEE80211_C_SHSLOT		/* short slot time supported */
1070		| IEEE80211_C_WME		/* WME/WMM supported */
1071		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1072		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1073		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1074		;
1075
1076	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1077
1078	/* call MI attach routine. */
1079	ieee80211_ifattach(ic,
1080	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1082	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1083
1084	ic->ic_headroom = sizeof(struct bwn_txhdr);
1085
1086	/* override default methods */
1087	ic->ic_raw_xmit = bwn_raw_xmit;
1088	ic->ic_updateslot = bwn_updateslot;
1089	ic->ic_update_promisc = bwn_update_promisc;
1090	ic->ic_wme.wme_update = bwn_wme_update;
1091
1092	ic->ic_scan_start = bwn_scan_start;
1093	ic->ic_scan_end = bwn_scan_end;
1094	ic->ic_set_channel = bwn_set_channel;
1095
1096	ic->ic_vap_create = bwn_vap_create;
1097	ic->ic_vap_delete = bwn_vap_delete;
1098
1099	ieee80211_radiotap_attach(ic,
1100	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101	    BWN_TX_RADIOTAP_PRESENT,
1102	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103	    BWN_RX_RADIOTAP_PRESENT);
1104
1105	bwn_sysctl_node(sc);
1106
1107	if (bootverbose)
1108		ieee80211_announce(ic);
1109	return (0);
1110}
1111
1112static void
1113bwn_phy_detach(struct bwn_mac *mac)
1114{
1115
1116	if (mac->mac_phy.detach != NULL)
1117		mac->mac_phy.detach(mac);
1118}
1119
1120static int
1121bwn_detach(device_t dev)
1122{
1123	struct bwn_softc *sc = device_get_softc(dev);
1124	struct bwn_mac *mac = sc->sc_curmac;
1125	struct ifnet *ifp = sc->sc_ifp;
1126	struct ieee80211com *ic = ifp->if_l2com;
1127	int i;
1128
1129	sc->sc_flags |= BWN_FLAG_INVALID;
1130
1131	if (device_is_attached(sc->sc_dev)) {
1132		bwn_stop(sc, 1);
1133		bwn_dma_free(mac);
1134		callout_drain(&sc->sc_led_blink_ch);
1135		callout_drain(&sc->sc_rfswitch_ch);
1136		callout_drain(&sc->sc_task_ch);
1137		callout_drain(&sc->sc_watchdog_ch);
1138		bwn_phy_detach(mac);
1139		if (ifp != NULL) {
1140			ieee80211_draintask(ic, &mac->mac_hwreset);
1141			ieee80211_draintask(ic, &mac->mac_txpower);
1142			ieee80211_ifdetach(ic);
1143			if_free(ifp);
1144		}
1145	}
1146	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147	taskqueue_free(sc->sc_tq);
1148
1149	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150		if (mac->mac_intrhand[i] != NULL) {
1151			bus_teardown_intr(dev, mac->mac_res_irq[i],
1152			    mac->mac_intrhand[i]);
1153			mac->mac_intrhand[i] = NULL;
1154		}
1155	}
1156	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157	if (mac->mac_msi != 0)
1158		pci_release_msi(dev);
1159
1160	BWN_LOCK_DESTROY(sc);
1161	return (0);
1162}
1163
1164static int
1165bwn_attach_pre(struct bwn_softc *sc)
1166{
1167	struct ifnet *ifp;
1168	int error = 0;
1169
1170	BWN_LOCK_INIT(sc);
1171	TAILQ_INIT(&sc->sc_maclist);
1172	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175
1176	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177		taskqueue_thread_enqueue, &sc->sc_tq);
1178	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179		"%s taskq", device_get_nameunit(sc->sc_dev));
1180
1181	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182	if (ifp == NULL) {
1183		device_printf(sc->sc_dev, "can not if_alloc()\n");
1184		error = ENOSPC;
1185		goto fail;
1186	}
1187
1188	/* set these up early for if_printf use */
1189	if_initname(ifp, device_get_name(sc->sc_dev),
1190	    device_get_unit(sc->sc_dev));
1191
1192	ifp->if_softc = sc;
1193	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194	ifp->if_init = bwn_init;
1195	ifp->if_ioctl = bwn_ioctl;
1196	ifp->if_start = bwn_start;
1197	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199	IFQ_SET_READY(&ifp->if_snd);
1200
1201	return (0);
1202
1203fail:	BWN_LOCK_DESTROY(sc);
1204	return (error);
1205}
1206
1207static void
1208bwn_sprom_bugfixes(device_t dev)
1209{
1210#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1211	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1212	 (siba_get_pci_device(dev) == _device) &&			\
1213	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1214	 (siba_get_pci_subdevice(dev) == _subdevice))
1215
1216	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217	    siba_get_pci_subdevice(dev) == 0x4e &&
1218	    siba_get_pci_revid(dev) > 0x40)
1219		siba_sprom_set_bf_lo(dev,
1220		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223		siba_sprom_set_bf_lo(dev,
1224		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233			siba_sprom_set_bf_lo(dev,
1234			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235	}
1236#undef	BWN_ISDEV
1237}
1238
1239static int
1240bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241{
1242#define	IS_RUNNING(ifp) \
1243	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244	struct bwn_softc *sc = ifp->if_softc;
1245	struct ieee80211com *ic = ifp->if_l2com;
1246	struct ifreq *ifr = (struct ifreq *)data;
1247	int error = 0, startall;
1248
1249	switch (cmd) {
1250	case SIOCSIFFLAGS:
1251		startall = 0;
1252		if (IS_RUNNING(ifp)) {
1253			bwn_update_promisc(ifp);
1254		} else if (ifp->if_flags & IFF_UP) {
1255			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256				bwn_init(sc);
1257				startall = 1;
1258			}
1259		} else
1260			bwn_stop(sc, 1);
1261		if (startall)
1262			ieee80211_start_all(ic);
1263		break;
1264	case SIOCGIFMEDIA:
1265		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266		break;
1267	case SIOCGIFADDR:
1268		error = ether_ioctl(ifp, cmd, data);
1269		break;
1270	default:
1271		error = EINVAL;
1272		break;
1273	}
1274	return (error);
1275}
1276
1277static void
1278bwn_start(struct ifnet *ifp)
1279{
1280	struct bwn_softc *sc = ifp->if_softc;
1281
1282	BWN_LOCK(sc);
1283	bwn_start_locked(ifp);
1284	BWN_UNLOCK(sc);
1285}
1286
1287static void
1288bwn_start_locked(struct ifnet *ifp)
1289{
1290	struct bwn_softc *sc = ifp->if_softc;
1291	struct bwn_mac *mac = sc->sc_curmac;
1292	struct ieee80211_frame *wh;
1293	struct ieee80211_node *ni;
1294	struct ieee80211_key *k;
1295	struct mbuf *m;
1296
1297	BWN_ASSERT_LOCKED(sc);
1298
1299	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1301		return;
1302
1303	for (;;) {
1304		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1305		if (m == NULL)
1306			break;
1307
1308		if (bwn_tx_isfull(sc, m))
1309			break;
1310		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311		if (ni == NULL) {
1312			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313			m_freem(m);
1314			ifp->if_oerrors++;
1315			continue;
1316		}
1317		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318		wh = mtod(m, struct ieee80211_frame *);
1319		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320			k = ieee80211_crypto_encap(ni, m);
1321			if (k == NULL) {
1322				ieee80211_free_node(ni);
1323				m_freem(m);
1324				ifp->if_oerrors++;
1325				continue;
1326			}
1327		}
1328		wh = NULL;	/* Catch any invalid use */
1329
1330		if (bwn_tx_start(sc, ni, m) != 0) {
1331			if (ni != NULL)
1332				ieee80211_free_node(ni);
1333			ifp->if_oerrors++;
1334			continue;
1335		}
1336
1337		sc->sc_watchdog_timer = 5;
1338	}
1339}
1340
1341static int
1342bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343{
1344	struct bwn_dma_ring *dr;
1345	struct bwn_mac *mac = sc->sc_curmac;
1346	struct bwn_pio_txqueue *tq;
1347	struct ifnet *ifp = sc->sc_ifp;
1348	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349
1350	BWN_ASSERT_LOCKED(sc);
1351
1352	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354		if (dr->dr_stop == 1 ||
1355		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356			dr->dr_stop = 1;
1357			goto full;
1358		}
1359	} else {
1360		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362		    pktlen > (tq->tq_size - tq->tq_used)) {
1363			tq->tq_stop = 1;
1364			goto full;
1365		}
1366	}
1367	return (0);
1368full:
1369	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371	return (1);
1372}
1373
1374static int
1375bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376{
1377	struct bwn_mac *mac = sc->sc_curmac;
1378	int error;
1379
1380	BWN_ASSERT_LOCKED(sc);
1381
1382	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383		m_freem(m);
1384		return (ENXIO);
1385	}
1386
1387	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389	if (error) {
1390		m_freem(m);
1391		return (error);
1392	}
1393	return (0);
1394}
1395
1396static int
1397bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398{
1399	struct bwn_pio_txpkt *tp;
1400	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401	struct bwn_softc *sc = mac->mac_sc;
1402	struct bwn_txhdr txhdr;
1403	struct mbuf *m_new;
1404	uint32_t ctl32;
1405	int error;
1406	uint16_t ctl16;
1407
1408	BWN_ASSERT_LOCKED(sc);
1409
1410	/* XXX TODO send packets after DTIM */
1411
1412	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413	tp = TAILQ_FIRST(&tq->tq_pktlist);
1414	tp->tp_ni = ni;
1415	tp->tp_m = m;
1416
1417	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418	if (error) {
1419		device_printf(sc->sc_dev, "tx fail\n");
1420		return (error);
1421	}
1422
1423	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425	tq->tq_free--;
1426
1427	if (siba_get_revid(sc->sc_dev) >= 8) {
1428		/*
1429		 * XXX please removes m_defrag(9)
1430		 */
1431		m_new = m_defrag(m, M_NOWAIT);
1432		if (m_new == NULL) {
1433			device_printf(sc->sc_dev,
1434			    "%s: can't defrag TX buffer\n",
1435			    __func__);
1436			return (ENOBUFS);
1437		}
1438		if (m_new->m_next != NULL)
1439			device_printf(sc->sc_dev,
1440			    "TODO: fragmented packets for PIO\n");
1441		tp->tp_m = m_new;
1442
1443		/* send HEADER */
1444		ctl32 = bwn_pio_write_multi_4(mac, tq,
1445		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448		/* send BODY */
1449		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1451		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452		    ctl32 | BWN_PIO8_TXCTL_EOF);
1453	} else {
1454		ctl16 = bwn_pio_write_multi_2(mac, tq,
1455		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460		    ctl16 | BWN_PIO_TXCTL_EOF);
1461	}
1462
1463	return (0);
1464}
1465
1466static struct bwn_pio_txqueue *
1467bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468{
1469
1470	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472
1473	switch (prio) {
1474	case 0:
1475		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476	case 1:
1477		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478	case 2:
1479		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480	case 3:
1481		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482	}
1483	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484	return (NULL);
1485}
1486
1487static int
1488bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489{
1490#define	BWN_GET_TXHDRCACHE(slot)					\
1491	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492	struct bwn_dma *dma = &mac->mac_method.dma;
1493	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494	struct bwn_dmadesc_generic *desc;
1495	struct bwn_dmadesc_meta *mt;
1496	struct bwn_softc *sc = mac->mac_sc;
1497	struct ifnet *ifp = sc->sc_ifp;
1498	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500
1501	BWN_ASSERT_LOCKED(sc);
1502	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503
1504	/* XXX send after DTIM */
1505
1506	slot = bwn_dma_getslot(dr);
1507	dr->getdesc(dr, slot, &desc, &mt);
1508	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509	    ("%s:%d: fail", __func__, __LINE__));
1510
1511	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513	    BWN_DMA_COOKIE(dr, slot));
1514	if (error)
1515		goto fail;
1516	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1519	if (error) {
1520		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521		    __func__, error);
1522		goto fail;
1523	}
1524	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525	    BUS_DMASYNC_PREWRITE);
1526	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528	    BUS_DMASYNC_PREWRITE);
1529
1530	slot = bwn_dma_getslot(dr);
1531	dr->getdesc(dr, slot, &desc, &mt);
1532	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534	mt->mt_m = m;
1535	mt->mt_ni = ni;
1536
1537	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539	if (error && error != EFBIG) {
1540		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541		    __func__, error);
1542		goto fail;
1543	}
1544	if (error) {    /* error == EFBIG */
1545		struct mbuf *m_new;
1546
1547		m_new = m_defrag(m, M_NOWAIT);
1548		if (m_new == NULL) {
1549			if_printf(ifp, "%s: can't defrag TX buffer\n",
1550			    __func__);
1551			error = ENOBUFS;
1552			goto fail;
1553		} else {
1554			m = m_new;
1555		}
1556
1557		mt->mt_m = m;
1558		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560		if (error) {
1561			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562			    __func__, error);
1563			goto fail;
1564		}
1565	}
1566	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569	    BUS_DMASYNC_PREWRITE);
1570
1571	/* XXX send after DTIM */
1572
1573	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574	return (0);
1575fail:
1576	dr->dr_curslot = backup[0];
1577	dr->dr_usedslot = backup[1];
1578	return (error);
1579#undef BWN_GET_TXHDRCACHE
1580}
1581
1582static void
1583bwn_watchdog(void *arg)
1584{
1585	struct bwn_softc *sc = arg;
1586	struct ifnet *ifp = sc->sc_ifp;
1587
1588	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589		if_printf(ifp, "device timeout\n");
1590		ifp->if_oerrors++;
1591	}
1592	callout_schedule(&sc->sc_watchdog_ch, hz);
1593}
1594
1595static int
1596bwn_attach_core(struct bwn_mac *mac)
1597{
1598	struct bwn_softc *sc = mac->mac_sc;
1599	int error, have_bg = 0, have_a = 0;
1600	uint32_t high;
1601
1602	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604
1605	siba_powerup(sc->sc_dev, 0);
1606
1607	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608	bwn_reset_core(mac,
1609	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610	error = bwn_phy_getinfo(mac, high);
1611	if (error)
1612		goto fail;
1613
1614	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619		have_a = have_bg = 0;
1620		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621			have_a = 1;
1622		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1624		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1625			have_bg = 1;
1626		else
1627			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628			    mac->mac_phy.type));
1629	}
1630	/* XXX turns off PHY A because it's not supported */
1631	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1633		have_a = 0;
1634		have_bg = 1;
1635	}
1636
1637	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638		mac->mac_phy.attach = bwn_phy_g_attach;
1639		mac->mac_phy.detach = bwn_phy_g_detach;
1640		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642		mac->mac_phy.init = bwn_phy_g_init;
1643		mac->mac_phy.exit = bwn_phy_g_exit;
1644		mac->mac_phy.phy_read = bwn_phy_g_read;
1645		mac->mac_phy.phy_write = bwn_phy_g_write;
1646		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654		mac->mac_phy.set_im = bwn_phy_g_im;
1655		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661		mac->mac_phy.init = bwn_phy_lp_init;
1662		mac->mac_phy.phy_read = bwn_phy_lp_read;
1663		mac->mac_phy.phy_write = bwn_phy_lp_write;
1664		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673	} else {
1674		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675		    mac->mac_phy.type);
1676		error = ENXIO;
1677		goto fail;
1678	}
1679
1680	mac->mac_phy.gmode = have_bg;
1681	if (mac->mac_phy.attach != NULL) {
1682		error = mac->mac_phy.attach(mac);
1683		if (error) {
1684			device_printf(sc->sc_dev, "failed\n");
1685			goto fail;
1686		}
1687	}
1688
1689	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690
1691	error = bwn_chiptest(mac);
1692	if (error)
1693		goto fail;
1694	error = bwn_setup_channels(mac, have_bg, have_a);
1695	if (error) {
1696		device_printf(sc->sc_dev, "failed to setup channels\n");
1697		goto fail;
1698	}
1699
1700	if (sc->sc_curmac == NULL)
1701		sc->sc_curmac = mac;
1702
1703	error = bwn_dma_attach(mac);
1704	if (error != 0) {
1705		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706		goto fail;
1707	}
1708
1709	mac->mac_phy.switch_analog(mac, 0);
1710
1711	siba_dev_down(sc->sc_dev, 0);
1712fail:
1713	siba_powerdown(sc->sc_dev);
1714	return (error);
1715}
1716
1717static void
1718bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719{
1720	struct bwn_softc *sc = mac->mac_sc;
1721	uint32_t low, ctl;
1722
1723	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724
1725	siba_dev_up(sc->sc_dev, flags);
1726	DELAY(2000);
1727
1728	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729	    ~BWN_TGSLOW_PHYRESET;
1730	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732	DELAY(1000);
1733	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735	DELAY(1000);
1736
1737	if (mac->mac_phy.switch_analog != NULL)
1738		mac->mac_phy.switch_analog(mac, 1);
1739
1740	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741	if (flags & BWN_TGSLOW_SUPPORT_G)
1742		ctl |= BWN_MACCTL_GMODE;
1743	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744}
1745
1746static int
1747bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748{
1749	struct bwn_phy *phy = &mac->mac_phy;
1750	struct bwn_softc *sc = mac->mac_sc;
1751	uint32_t tmp;
1752
1753	/* PHY */
1754	tmp = BWN_READ_2(mac, BWN_PHYVER);
1755	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756	phy->rf_on = 1;
1757	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759	phy->rev = (tmp & BWN_PHYVER_VERSION);
1760	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766		goto unsupphy;
1767
1768	/* RADIO */
1769	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770		if (siba_get_chiprev(sc->sc_dev) == 0)
1771			tmp = 0x3205017f;
1772		else if (siba_get_chiprev(sc->sc_dev) == 1)
1773			tmp = 0x4205017f;
1774		else
1775			tmp = 0x5205017f;
1776	} else {
1777		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781	}
1782	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784	phy->rf_manuf = (tmp & 0x00000fff);
1785	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1786		goto unsupradio;
1787	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791	    (phy->type == BWN_PHYTYPE_N &&
1792	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793	    (phy->type == BWN_PHYTYPE_LP &&
1794	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795		goto unsupradio;
1796
1797	return (0);
1798unsupphy:
1799	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800	    "analog %#x)\n",
1801	    phy->type, phy->rev, phy->analog);
1802	return (ENXIO);
1803unsupradio:
1804	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805	    "rev %#x)\n",
1806	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807	return (ENXIO);
1808}
1809
1810static int
1811bwn_chiptest(struct bwn_mac *mac)
1812{
1813#define	TESTVAL0	0x55aaaa55
1814#define	TESTVAL1	0xaa5555aa
1815	struct bwn_softc *sc = mac->mac_sc;
1816	uint32_t v, backup;
1817
1818	BWN_LOCK(sc);
1819
1820	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821
1822	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824		goto error;
1825	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827		goto error;
1828
1829	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830
1831	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832	    (siba_get_revid(sc->sc_dev) <= 10)) {
1833		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836			goto error;
1837		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838			goto error;
1839	}
1840	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841
1842	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844		goto error;
1845
1846	BWN_UNLOCK(sc);
1847	return (0);
1848error:
1849	BWN_UNLOCK(sc);
1850	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851	return (ENODEV);
1852}
1853
1854#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856
1857static int
1858bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859{
1860	struct bwn_softc *sc = mac->mac_sc;
1861	struct ifnet *ifp = sc->sc_ifp;
1862	struct ieee80211com *ic = ifp->if_l2com;
1863
1864	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865	ic->ic_nchans = 0;
1866
1867	if (have_bg)
1868		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871		if (have_a)
1872			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873			    &ic->ic_nchans, &bwn_chantable_n,
1874			    IEEE80211_CHAN_HTA);
1875	} else {
1876		if (have_a)
1877			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878			    &ic->ic_nchans, &bwn_chantable_a,
1879			    IEEE80211_CHAN_A);
1880	}
1881
1882	mac->mac_phy.supports_2ghz = have_bg;
1883	mac->mac_phy.supports_5ghz = have_a;
1884
1885	return (ic->ic_nchans == 0 ? ENXIO : 0);
1886}
1887
1888static uint32_t
1889bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890{
1891	uint32_t ret;
1892
1893	BWN_ASSERT_LOCKED(mac->mac_sc);
1894
1895	if (way == BWN_SHARED) {
1896		KASSERT((offset & 0x0001) == 0,
1897		    ("%s:%d warn", __func__, __LINE__));
1898		if (offset & 0x0003) {
1899			bwn_shm_ctlword(mac, way, offset >> 2);
1900			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901			ret <<= 16;
1902			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904			goto out;
1905		}
1906		offset >>= 2;
1907	}
1908	bwn_shm_ctlword(mac, way, offset);
1909	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910out:
1911	return (ret);
1912}
1913
1914static uint16_t
1915bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916{
1917	uint16_t ret;
1918
1919	BWN_ASSERT_LOCKED(mac->mac_sc);
1920
1921	if (way == BWN_SHARED) {
1922		KASSERT((offset & 0x0001) == 0,
1923		    ("%s:%d warn", __func__, __LINE__));
1924		if (offset & 0x0003) {
1925			bwn_shm_ctlword(mac, way, offset >> 2);
1926			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927			goto out;
1928		}
1929		offset >>= 2;
1930	}
1931	bwn_shm_ctlword(mac, way, offset);
1932	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933out:
1934
1935	return (ret);
1936}
1937
1938static void
1939bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940    uint16_t offset)
1941{
1942	uint32_t control;
1943
1944	control = way;
1945	control <<= 16;
1946	control |= offset;
1947	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948}
1949
1950static void
1951bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952    uint32_t value)
1953{
1954	BWN_ASSERT_LOCKED(mac->mac_sc);
1955
1956	if (way == BWN_SHARED) {
1957		KASSERT((offset & 0x0001) == 0,
1958		    ("%s:%d warn", __func__, __LINE__));
1959		if (offset & 0x0003) {
1960			bwn_shm_ctlword(mac, way, offset >> 2);
1961			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962				    (value >> 16) & 0xffff);
1963			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965			return;
1966		}
1967		offset >>= 2;
1968	}
1969	bwn_shm_ctlword(mac, way, offset);
1970	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971}
1972
1973static void
1974bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975    uint16_t value)
1976{
1977	BWN_ASSERT_LOCKED(mac->mac_sc);
1978
1979	if (way == BWN_SHARED) {
1980		KASSERT((offset & 0x0001) == 0,
1981		    ("%s:%d warn", __func__, __LINE__));
1982		if (offset & 0x0003) {
1983			bwn_shm_ctlword(mac, way, offset >> 2);
1984			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985			return;
1986		}
1987		offset >>= 2;
1988	}
1989	bwn_shm_ctlword(mac, way, offset);
1990	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991}
1992
1993static void
1994bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995    int txpow)
1996{
1997
1998	c->ic_freq = freq;
1999	c->ic_flags = flags;
2000	c->ic_ieee = ieee;
2001	c->ic_minpower = 0;
2002	c->ic_maxpower = 2 * txpow;
2003	c->ic_maxregpower = txpow;
2004}
2005
2006static void
2007bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008    const struct bwn_channelinfo *ci, int flags)
2009{
2010	struct ieee80211_channel *c;
2011	int i;
2012
2013	c = &chans[*nchans];
2014
2015	for (i = 0; i < ci->nchannels; i++) {
2016		const struct bwn_channel *hc;
2017
2018		hc = &ci->channels[i];
2019		if (*nchans >= maxchans)
2020			break;
2021		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022		c++, (*nchans)++;
2023		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024			/* g channel have a separate b-only entry */
2025			if (*nchans >= maxchans)
2026				break;
2027			c[0] = c[-1];
2028			c[-1].ic_flags = IEEE80211_CHAN_B;
2029			c++, (*nchans)++;
2030		}
2031		if (flags == IEEE80211_CHAN_HTG) {
2032			/* HT g channel have a separate g-only entry */
2033			if (*nchans >= maxchans)
2034				break;
2035			c[-1].ic_flags = IEEE80211_CHAN_G;
2036			c[0] = c[-1];
2037			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2039			c++, (*nchans)++;
2040		}
2041		if (flags == IEEE80211_CHAN_HTA) {
2042			/* HT a channel have a separate a-only entry */
2043			if (*nchans >= maxchans)
2044				break;
2045			c[-1].ic_flags = IEEE80211_CHAN_A;
2046			c[0] = c[-1];
2047			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2049			c++, (*nchans)++;
2050		}
2051	}
2052}
2053
2054static int
2055bwn_phy_g_attach(struct bwn_mac *mac)
2056{
2057	struct bwn_softc *sc = mac->mac_sc;
2058	struct bwn_phy *phy = &mac->mac_phy;
2059	struct bwn_phy_g *pg = &phy->phy_g;
2060	unsigned int i;
2061	int16_t pab0, pab1, pab2;
2062	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063	int8_t bg;
2064
2065	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069
2070	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071		device_printf(sc->sc_dev, "not supported anymore\n");
2072
2073	pg->pg_flags = 0;
2074	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075	    pab2 == -1) {
2076		pg->pg_idletssi = 52;
2077		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078		return (0);
2079	}
2080
2081	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083	if (pg->pg_tssi2dbm == NULL) {
2084		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085		return (ENOMEM);
2086	}
2087	for (i = 0; i < 64; i++) {
2088		int32_t m1, m2, f, q, delta;
2089		int8_t j = 0;
2090
2091		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093		f = 256;
2094
2095		do {
2096			if (j > 15) {
2097				device_printf(sc->sc_dev,
2098				    "failed to generate tssi2dBm\n");
2099				free(pg->pg_tssi2dbm, M_DEVBUF);
2100				return (ENOMEM);
2101			}
2102			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103			    f, 2048);
2104			delta = abs(q - f);
2105			f = q;
2106			j++;
2107		} while (delta >= 2);
2108
2109		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110		    128);
2111	}
2112
2113	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114	return (0);
2115}
2116
2117static void
2118bwn_phy_g_detach(struct bwn_mac *mac)
2119{
2120	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121
2122	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123		free(pg->pg_tssi2dbm, M_DEVBUF);
2124		pg->pg_tssi2dbm = NULL;
2125	}
2126	pg->pg_flags = 0;
2127}
2128
2129static void
2130bwn_phy_g_init_pre(struct bwn_mac *mac)
2131{
2132	struct bwn_phy *phy = &mac->mac_phy;
2133	struct bwn_phy_g *pg = &phy->phy_g;
2134	void *tssi2dbm;
2135	int idletssi;
2136	unsigned int i;
2137
2138	tssi2dbm = pg->pg_tssi2dbm;
2139	idletssi = pg->pg_idletssi;
2140
2141	memset(pg, 0, sizeof(*pg));
2142
2143	pg->pg_tssi2dbm = tssi2dbm;
2144	pg->pg_idletssi = idletssi;
2145
2146	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147
2148	for (i = 0; i < N(pg->pg_nrssi); i++)
2149		pg->pg_nrssi[i] = -1000;
2150	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151		pg->pg_nrssi_lt[i] = i;
2152	pg->pg_lofcal = 0xffff;
2153	pg->pg_initval = 0xffff;
2154	pg->pg_immode = BWN_IMMODE_NONE;
2155	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156	pg->pg_avgtssi = 0xff;
2157
2158	pg->pg_loctl.tx_bias = 0xff;
2159	TAILQ_INIT(&pg->pg_loctl.calib_list);
2160}
2161
2162static int
2163bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164{
2165	struct bwn_phy *phy = &mac->mac_phy;
2166	struct bwn_phy_g *pg = &phy->phy_g;
2167	struct bwn_softc *sc = mac->mac_sc;
2168	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169	static const struct bwn_rfatt rfatt0[] = {
2170		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2171		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172		{ 3, 1 }, { 4, 1 }
2173	};
2174	static const struct bwn_rfatt rfatt1[] = {
2175		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176		{ 14, 1 }
2177	};
2178	static const struct bwn_rfatt rfatt2[] = {
2179		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180		{ 9, 1 }
2181	};
2182	static const struct bwn_bbatt bbatt_0[] = {
2183		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184	};
2185
2186	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187
2188	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189		pg->pg_bbatt.att = 0;
2190	else
2191		pg->pg_bbatt.att = 2;
2192
2193	/* prepare Radio Attenuation */
2194	pg->pg_rfatt.padmix = 0;
2195
2196	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199			pg->pg_rfatt.att = 2;
2200			goto done;
2201		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202			pg->pg_rfatt.att = 3;
2203			goto done;
2204		}
2205	}
2206
2207	if (phy->type == BWN_PHYTYPE_A) {
2208		pg->pg_rfatt.att = 0x60;
2209		goto done;
2210	}
2211
2212	switch (phy->rf_ver) {
2213	case 0x2050:
2214		switch (phy->rf_rev) {
2215		case 0:
2216			pg->pg_rfatt.att = 5;
2217			goto done;
2218		case 1:
2219			if (phy->type == BWN_PHYTYPE_G) {
2220				if (siba_get_pci_subvendor(sc->sc_dev) ==
2221				    SIBA_BOARDVENDOR_BCM &&
2222				    siba_get_pci_subdevice(sc->sc_dev) ==
2223				    SIBA_BOARD_BCM4309G &&
2224				    siba_get_pci_revid(sc->sc_dev) >= 30)
2225					pg->pg_rfatt.att = 3;
2226				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227				    SIBA_BOARDVENDOR_BCM &&
2228				    siba_get_pci_subdevice(sc->sc_dev) ==
2229				    SIBA_BOARD_BU4306)
2230					pg->pg_rfatt.att = 3;
2231				else
2232					pg->pg_rfatt.att = 1;
2233			} else {
2234				if (siba_get_pci_subvendor(sc->sc_dev) ==
2235				    SIBA_BOARDVENDOR_BCM &&
2236				    siba_get_pci_subdevice(sc->sc_dev) ==
2237				    SIBA_BOARD_BCM4309G &&
2238				    siba_get_pci_revid(sc->sc_dev) >= 30)
2239					pg->pg_rfatt.att = 7;
2240				else
2241					pg->pg_rfatt.att = 6;
2242			}
2243			goto done;
2244		case 2:
2245			if (phy->type == BWN_PHYTYPE_G) {
2246				if (siba_get_pci_subvendor(sc->sc_dev) ==
2247				    SIBA_BOARDVENDOR_BCM &&
2248				    siba_get_pci_subdevice(sc->sc_dev) ==
2249				    SIBA_BOARD_BCM4309G &&
2250				    siba_get_pci_revid(sc->sc_dev) >= 30)
2251					pg->pg_rfatt.att = 3;
2252				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253				    SIBA_BOARDVENDOR_BCM &&
2254				    siba_get_pci_subdevice(sc->sc_dev) ==
2255				    SIBA_BOARD_BU4306)
2256					pg->pg_rfatt.att = 5;
2257				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258					pg->pg_rfatt.att = 4;
2259				else
2260					pg->pg_rfatt.att = 3;
2261			} else
2262				pg->pg_rfatt.att = 6;
2263			goto done;
2264		case 3:
2265			pg->pg_rfatt.att = 5;
2266			goto done;
2267		case 4:
2268		case 5:
2269			pg->pg_rfatt.att = 1;
2270			goto done;
2271		case 6:
2272		case 7:
2273			pg->pg_rfatt.att = 5;
2274			goto done;
2275		case 8:
2276			pg->pg_rfatt.att = 0xa;
2277			pg->pg_rfatt.padmix = 1;
2278			goto done;
2279		case 9:
2280		default:
2281			pg->pg_rfatt.att = 5;
2282			goto done;
2283		}
2284		break;
2285	case 0x2053:
2286		switch (phy->rf_rev) {
2287		case 1:
2288			pg->pg_rfatt.att = 6;
2289			goto done;
2290		}
2291		break;
2292	}
2293	pg->pg_rfatt.att = 5;
2294done:
2295	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296
2297	if (!bwn_has_hwpctl(mac)) {
2298		lo->rfatt.array = rfatt0;
2299		lo->rfatt.len = N(rfatt0);
2300		lo->rfatt.min = 0;
2301		lo->rfatt.max = 9;
2302		goto genbbatt;
2303	}
2304	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305		lo->rfatt.array = rfatt1;
2306		lo->rfatt.len = N(rfatt1);
2307		lo->rfatt.min = 0;
2308		lo->rfatt.max = 14;
2309		goto genbbatt;
2310	}
2311	lo->rfatt.array = rfatt2;
2312	lo->rfatt.len = N(rfatt2);
2313	lo->rfatt.min = 0;
2314	lo->rfatt.max = 9;
2315genbbatt:
2316	lo->bbatt.array = bbatt_0;
2317	lo->bbatt.len = N(bbatt_0);
2318	lo->bbatt.min = 0;
2319	lo->bbatt.max = 8;
2320
2321	BWN_READ_4(mac, BWN_MACCTL);
2322	if (phy->rev == 1) {
2323		phy->gmode = 0;
2324		bwn_reset_core(mac, 0);
2325		bwn_phy_g_init_sub(mac);
2326		phy->gmode = 1;
2327		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328	}
2329	return (0);
2330}
2331
2332static uint16_t
2333bwn_phy_g_txctl(struct bwn_mac *mac)
2334{
2335	struct bwn_phy *phy = &mac->mac_phy;
2336
2337	if (phy->rf_ver != 0x2050)
2338		return (0);
2339	if (phy->rf_rev == 1)
2340		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341	if (phy->rf_rev < 6)
2342		return (BWN_TXCTL_PA2DB);
2343	if (phy->rf_rev == 8)
2344		return (BWN_TXCTL_TXMIX);
2345	return (0);
2346}
2347
2348static int
2349bwn_phy_g_init(struct bwn_mac *mac)
2350{
2351
2352	bwn_phy_g_init_sub(mac);
2353	return (0);
2354}
2355
2356static void
2357bwn_phy_g_exit(struct bwn_mac *mac)
2358{
2359	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360	struct bwn_lo_calib *cal, *tmp;
2361
2362	if (lo == NULL)
2363		return;
2364	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365		TAILQ_REMOVE(&lo->calib_list, cal, list);
2366		free(cal, M_DEVBUF);
2367	}
2368}
2369
2370static uint16_t
2371bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372{
2373
2374	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375	return (BWN_READ_2(mac, BWN_PHYDATA));
2376}
2377
2378static void
2379bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380{
2381
2382	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384}
2385
2386static uint16_t
2387bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388{
2389
2390	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392	return (BWN_READ_2(mac, BWN_RFDATALO));
2393}
2394
2395static void
2396bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397{
2398
2399	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402}
2403
2404static int
2405bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406{
2407
2408	return (mac->mac_phy.rev >= 6);
2409}
2410
2411static void
2412bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413{
2414	struct bwn_phy *phy = &mac->mac_phy;
2415	struct bwn_phy_g *pg = &phy->phy_g;
2416	unsigned int channel;
2417	uint16_t rfover, rfoverval;
2418
2419	if (on) {
2420		if (phy->rf_on)
2421			return;
2422
2423		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428			    pg->pg_radioctx_over);
2429			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430			    pg->pg_radioctx_overval);
2431			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432		}
2433		channel = phy->chan;
2434		bwn_phy_g_switch_chan(mac, 6, 1);
2435		bwn_phy_g_switch_chan(mac, channel, 0);
2436		return;
2437	}
2438
2439	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441	pg->pg_radioctx_over = rfover;
2442	pg->pg_radioctx_overval = rfoverval;
2443	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446}
2447
2448static int
2449bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450{
2451
2452	if ((newchan < 1) || (newchan > 14))
2453		return (EINVAL);
2454	bwn_phy_g_switch_chan(mac, newchan, 0);
2455
2456	return (0);
2457}
2458
2459static uint32_t
2460bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461{
2462
2463	return (1);
2464}
2465
2466static void
2467bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468{
2469	struct bwn_phy *phy = &mac->mac_phy;
2470	uint64_t hf;
2471	int autodiv = 0;
2472	uint16_t tmp;
2473
2474	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475		autodiv = 1;
2476
2477	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478	bwn_hf_write(mac, hf);
2479
2480	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2483		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484
2485	if (autodiv) {
2486		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487		if (antenna == BWN_ANTAUTO1)
2488			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489		else
2490			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492	}
2493	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494	if (autodiv)
2495		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496	else
2497		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499	if (phy->rev >= 2) {
2500		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504		    0x15);
2505		if (phy->rev == 2)
2506			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507		else
2508			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510			    8);
2511	}
2512	if (phy->rev >= 6)
2513		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514
2515	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516	bwn_hf_write(mac, hf);
2517}
2518
2519static int
2520bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521{
2522	struct bwn_phy *phy = &mac->mac_phy;
2523	struct bwn_phy_g *pg = &phy->phy_g;
2524
2525	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527
2528	if (phy->rev == 0 || !phy->gmode)
2529		return (ENODEV);
2530
2531	pg->pg_aci_wlan_automatic = 0;
2532	return (0);
2533}
2534
2535static int
2536bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537{
2538	struct bwn_phy *phy = &mac->mac_phy;
2539	struct bwn_phy_g *pg = &phy->phy_g;
2540	struct bwn_softc *sc = mac->mac_sc;
2541	unsigned int tssi;
2542	int cck, ofdm;
2543	int power;
2544	int rfatt, bbatt;
2545	unsigned int max;
2546
2547	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548
2549	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551	if (cck < 0 && ofdm < 0) {
2552		if (ignore_tssi == 0)
2553			return (BWN_TXPWR_RES_DONE);
2554		cck = 0;
2555		ofdm = 0;
2556	}
2557	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558	if (pg->pg_avgtssi != 0xff)
2559		tssi = (tssi + pg->pg_avgtssi) / 2;
2560	pg->pg_avgtssi = tssi;
2561	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562
2563	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565		max -= 3;
2566	if (max >= 120) {
2567		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568		max = 80;
2569		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570	}
2571
2572	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574	     tssi, 0x00), 0x3f)]);
2575	if (power == 0)
2576		return (BWN_TXPWR_RES_DONE);
2577
2578	rfatt = -((power + 7) / 8);
2579	bbatt = (-(power / 2)) - (4 * rfatt);
2580	if ((rfatt == 0) && (bbatt == 0))
2581		return (BWN_TXPWR_RES_DONE);
2582	pg->pg_bbatt_delta = bbatt;
2583	pg->pg_rfatt_delta = rfatt;
2584	return (BWN_TXPWR_RES_NEED_ADJUST);
2585}
2586
2587static void
2588bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589{
2590	struct bwn_phy *phy = &mac->mac_phy;
2591	struct bwn_phy_g *pg = &phy->phy_g;
2592	struct bwn_softc *sc = mac->mac_sc;
2593	int rfatt, bbatt;
2594	uint8_t txctl;
2595
2596	bwn_mac_suspend(mac);
2597
2598	BWN_ASSERT_LOCKED(sc);
2599
2600	bbatt = pg->pg_bbatt.att;
2601	bbatt += pg->pg_bbatt_delta;
2602	rfatt = pg->pg_rfatt.att;
2603	rfatt += pg->pg_rfatt_delta;
2604
2605	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606	txctl = pg->pg_txctl;
2607	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608		if (rfatt <= 1) {
2609			if (txctl == 0) {
2610				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611				rfatt += 2;
2612				bbatt += 2;
2613			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614			    BWN_BFL_PACTRL) {
2615				bbatt += 4 * (rfatt - 2);
2616				rfatt = 2;
2617			}
2618		} else if (rfatt > 4 && txctl) {
2619			txctl = 0;
2620			if (bbatt < 3) {
2621				rfatt -= 3;
2622				bbatt += 2;
2623			} else {
2624				rfatt -= 2;
2625				bbatt -= 2;
2626			}
2627		}
2628	}
2629	pg->pg_txctl = txctl;
2630	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631	pg->pg_rfatt.att = rfatt;
2632	pg->pg_bbatt.att = bbatt;
2633
2634	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635
2636	bwn_phy_lock(mac);
2637	bwn_rf_lock(mac);
2638	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639	    pg->pg_txctl);
2640	bwn_rf_unlock(mac);
2641	bwn_phy_unlock(mac);
2642
2643	bwn_mac_enable(mac);
2644}
2645
2646static void
2647bwn_phy_g_task_15s(struct bwn_mac *mac)
2648{
2649	struct bwn_phy *phy = &mac->mac_phy;
2650	struct bwn_phy_g *pg = &phy->phy_g;
2651	struct bwn_softc *sc = mac->mac_sc;
2652	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653	unsigned long expire, now;
2654	struct bwn_lo_calib *cal, *tmp;
2655	uint8_t expired = 0;
2656
2657	bwn_mac_suspend(mac);
2658
2659	if (lo == NULL)
2660		goto fail;
2661
2662	BWN_GETTIME(now);
2663	if (bwn_has_hwpctl(mac)) {
2664		expire = now - BWN_LO_PWRVEC_EXPIRE;
2665		if (time_before(lo->pwr_vec_read_time, expire)) {
2666			bwn_lo_get_powervector(mac);
2667			bwn_phy_g_dc_lookup_init(mac, 0);
2668		}
2669		goto fail;
2670	}
2671
2672	expire = now - BWN_LO_CALIB_EXPIRE;
2673	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674		if (!time_before(cal->calib_time, expire))
2675			continue;
2676		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679			expired = 1;
2680		}
2681
2682		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684		    cal->ctl.i, cal->ctl.q);
2685
2686		TAILQ_REMOVE(&lo->calib_list, cal, list);
2687		free(cal, M_DEVBUF);
2688	}
2689	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691		    &pg->pg_rfatt);
2692		if (cal == NULL) {
2693			device_printf(sc->sc_dev,
2694			    "failed to recalibrate LO\n");
2695			goto fail;
2696		}
2697		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698		bwn_lo_write(mac, &cal->ctl);
2699	}
2700
2701fail:
2702	bwn_mac_enable(mac);
2703}
2704
2705static void
2706bwn_phy_g_task_60s(struct bwn_mac *mac)
2707{
2708	struct bwn_phy *phy = &mac->mac_phy;
2709	struct bwn_softc *sc = mac->mac_sc;
2710	uint8_t old = phy->chan;
2711
2712	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713		return;
2714
2715	bwn_mac_suspend(mac);
2716	bwn_nrssi_slope_11g(mac);
2717	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719		bwn_switch_channel(mac, old);
2720	}
2721	bwn_mac_enable(mac);
2722}
2723
2724static void
2725bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726{
2727
2728	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729}
2730
2731static int
2732bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733	const struct ieee80211_bpf_params *params)
2734{
2735	struct ieee80211com *ic = ni->ni_ic;
2736	struct ifnet *ifp = ic->ic_ifp;
2737	struct bwn_softc *sc = ifp->if_softc;
2738	struct bwn_mac *mac = sc->sc_curmac;
2739
2740	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742		ieee80211_free_node(ni);
2743		m_freem(m);
2744		return (ENETDOWN);
2745	}
2746
2747	BWN_LOCK(sc);
2748	if (bwn_tx_isfull(sc, m)) {
2749		ieee80211_free_node(ni);
2750		m_freem(m);
2751		ifp->if_oerrors++;
2752		BWN_UNLOCK(sc);
2753		return (ENOBUFS);
2754	}
2755
2756	if (bwn_tx_start(sc, ni, m) != 0) {
2757		if (ni != NULL)
2758			ieee80211_free_node(ni);
2759		ifp->if_oerrors++;
2760	}
2761	sc->sc_watchdog_timer = 5;
2762	BWN_UNLOCK(sc);
2763	return (0);
2764}
2765
2766/*
2767 * Callback from the 802.11 layer to update the slot time
2768 * based on the current setting.  We use it to notify the
2769 * firmware of ERP changes and the f/w takes care of things
2770 * like slot time and preamble.
2771 */
2772static void
2773bwn_updateslot(struct ifnet *ifp)
2774{
2775	struct bwn_softc *sc = ifp->if_softc;
2776	struct ieee80211com *ic = ifp->if_l2com;
2777	struct bwn_mac *mac;
2778
2779	BWN_LOCK(sc);
2780	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781		mac = (struct bwn_mac *)sc->sc_curmac;
2782		bwn_set_slot_time(mac,
2783		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784	}
2785	BWN_UNLOCK(sc);
2786}
2787
2788/*
2789 * Callback from the 802.11 layer after a promiscuous mode change.
2790 * Note this interface does not check the operating mode as this
2791 * is an internal callback and we are expected to honor the current
2792 * state (e.g. this is used for setting the interface in promiscuous
2793 * mode when operating in hostap mode to do ACS).
2794 */
2795static void
2796bwn_update_promisc(struct ifnet *ifp)
2797{
2798	struct bwn_softc *sc = ifp->if_softc;
2799	struct bwn_mac *mac = sc->sc_curmac;
2800
2801	BWN_LOCK(sc);
2802	mac = sc->sc_curmac;
2803	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804		if (ifp->if_flags & IFF_PROMISC)
2805			sc->sc_filters |= BWN_MACCTL_PROMISC;
2806		else
2807			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808		bwn_set_opmode(mac);
2809	}
2810	BWN_UNLOCK(sc);
2811}
2812
2813/*
2814 * Callback from the 802.11 layer to update WME parameters.
2815 */
2816static int
2817bwn_wme_update(struct ieee80211com *ic)
2818{
2819	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820	struct bwn_mac *mac = sc->sc_curmac;
2821	struct wmeParams *wmep;
2822	int i;
2823
2824	BWN_LOCK(sc);
2825	mac = sc->sc_curmac;
2826	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827		bwn_mac_suspend(mac);
2828		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831		}
2832		bwn_mac_enable(mac);
2833	}
2834	BWN_UNLOCK(sc);
2835	return (0);
2836}
2837
2838static void
2839bwn_scan_start(struct ieee80211com *ic)
2840{
2841	struct ifnet *ifp = ic->ic_ifp;
2842	struct bwn_softc *sc = ifp->if_softc;
2843	struct bwn_mac *mac;
2844
2845	BWN_LOCK(sc);
2846	mac = sc->sc_curmac;
2847	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849		bwn_set_opmode(mac);
2850		/* disable CFP update during scan */
2851		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852	}
2853	BWN_UNLOCK(sc);
2854}
2855
2856static void
2857bwn_scan_end(struct ieee80211com *ic)
2858{
2859	struct ifnet *ifp = ic->ic_ifp;
2860	struct bwn_softc *sc = ifp->if_softc;
2861	struct bwn_mac *mac;
2862
2863	BWN_LOCK(sc);
2864	mac = sc->sc_curmac;
2865	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867		bwn_set_opmode(mac);
2868		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869	}
2870	BWN_UNLOCK(sc);
2871}
2872
2873static void
2874bwn_set_channel(struct ieee80211com *ic)
2875{
2876	struct ifnet *ifp = ic->ic_ifp;
2877	struct bwn_softc *sc = ifp->if_softc;
2878	struct bwn_mac *mac = sc->sc_curmac;
2879	struct bwn_phy *phy = &mac->mac_phy;
2880	int chan, error;
2881
2882	BWN_LOCK(sc);
2883
2884	error = bwn_switch_band(sc, ic->ic_curchan);
2885	if (error)
2886		goto fail;
2887	bwn_mac_suspend(mac);
2888	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890	if (chan != phy->chan)
2891		bwn_switch_channel(mac, chan);
2892
2893	/* TX power level */
2894	if (ic->ic_curchan->ic_maxpower != 0 &&
2895	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2896		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898		    BWN_TXPWR_IGNORE_TSSI);
2899	}
2900
2901	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902	if (phy->set_antenna)
2903		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904
2905	if (sc->sc_rf_enabled != phy->rf_on) {
2906		if (sc->sc_rf_enabled) {
2907			bwn_rf_turnon(mac);
2908			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909				device_printf(sc->sc_dev,
2910				    "please turn on the RF switch\n");
2911		} else
2912			bwn_rf_turnoff(mac);
2913	}
2914
2915	bwn_mac_enable(mac);
2916
2917fail:
2918	/*
2919	 * Setup radio tap channel freq and flags
2920	 */
2921	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922		htole16(ic->ic_curchan->ic_freq);
2923	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924		htole16(ic->ic_curchan->ic_flags & 0xffff);
2925
2926	BWN_UNLOCK(sc);
2927}
2928
2929static struct ieee80211vap *
2930bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2931    enum ieee80211_opmode opmode, int flags,
2932    const uint8_t bssid[IEEE80211_ADDR_LEN],
2933    const uint8_t mac0[IEEE80211_ADDR_LEN])
2934{
2935	struct ifnet *ifp = ic->ic_ifp;
2936	struct bwn_softc *sc = ifp->if_softc;
2937	struct ieee80211vap *vap;
2938	struct bwn_vap *bvp;
2939	uint8_t mac[IEEE80211_ADDR_LEN];
2940
2941	IEEE80211_ADDR_COPY(mac, mac0);
2942	switch (opmode) {
2943	case IEEE80211_M_HOSTAP:
2944	case IEEE80211_M_MBSS:
2945	case IEEE80211_M_STA:
2946	case IEEE80211_M_WDS:
2947	case IEEE80211_M_MONITOR:
2948	case IEEE80211_M_IBSS:
2949	case IEEE80211_M_AHDEMO:
2950		break;
2951	default:
2952		return (NULL);
2953	}
2954
2955	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956
2957	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958	    M_80211_VAP, M_NOWAIT | M_ZERO);
2959	if (bvp == NULL) {
2960		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961		return (NULL);
2962	}
2963	vap = &bvp->bv_vap;
2964	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966	/* override with driver methods */
2967	bvp->bv_newstate = vap->iv_newstate;
2968	vap->iv_newstate = bwn_newstate;
2969
2970	/* override max aid so sta's cannot assoc when we're out of sta id's */
2971	vap->iv_max_aid = BWN_STAID_MAX;
2972
2973	ieee80211_ratectl_init(vap);
2974
2975	/* complete setup */
2976	ieee80211_vap_attach(vap, ieee80211_media_change,
2977	    ieee80211_media_status);
2978	return (vap);
2979}
2980
2981static void
2982bwn_vap_delete(struct ieee80211vap *vap)
2983{
2984	struct bwn_vap *bvp = BWN_VAP(vap);
2985
2986	ieee80211_ratectl_deinit(vap);
2987	ieee80211_vap_detach(vap);
2988	free(bvp, M_80211_VAP);
2989}
2990
2991static void
2992bwn_init(void *arg)
2993{
2994	struct bwn_softc *sc = arg;
2995	struct ifnet *ifp = sc->sc_ifp;
2996	struct ieee80211com *ic = ifp->if_l2com;
2997	int error = 0;
2998
2999	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000		__func__, ifp->if_flags);
3001
3002	BWN_LOCK(sc);
3003	error = bwn_init_locked(sc);
3004	BWN_UNLOCK(sc);
3005
3006	if (error == 0)
3007		ieee80211_start_all(ic);	/* start all vap's */
3008}
3009
3010static int
3011bwn_init_locked(struct bwn_softc *sc)
3012{
3013	struct bwn_mac *mac;
3014	struct ifnet *ifp = sc->sc_ifp;
3015	int error;
3016
3017	BWN_ASSERT_LOCKED(sc);
3018
3019	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021	sc->sc_filters = 0;
3022	bwn_wme_clear(sc);
3023	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024	sc->sc_rf_enabled = 1;
3025
3026	mac = sc->sc_curmac;
3027	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028		error = bwn_core_init(mac);
3029		if (error != 0)
3030			return (error);
3031	}
3032	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033		bwn_core_start(mac);
3034
3035	bwn_set_opmode(mac);
3036	bwn_set_pretbtt(mac);
3037	bwn_spu_setdelay(mac, 0);
3038	bwn_set_macaddr(mac);
3039
3040	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043
3044	return (0);
3045}
3046
3047static void
3048bwn_stop(struct bwn_softc *sc, int statechg)
3049{
3050
3051	BWN_LOCK(sc);
3052	bwn_stop_locked(sc, statechg);
3053	BWN_UNLOCK(sc);
3054}
3055
3056static void
3057bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058{
3059	struct bwn_mac *mac = sc->sc_curmac;
3060	struct ifnet *ifp = sc->sc_ifp;
3061
3062	BWN_ASSERT_LOCKED(sc);
3063
3064	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065		/* XXX FIXME opmode not based on VAP */
3066		bwn_set_opmode(mac);
3067		bwn_set_macaddr(mac);
3068	}
3069
3070	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071		bwn_core_stop(mac);
3072
3073	callout_stop(&sc->sc_led_blink_ch);
3074	sc->sc_led_blinking = 0;
3075
3076	bwn_core_exit(mac);
3077	sc->sc_rf_enabled = 0;
3078
3079	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080}
3081
3082static void
3083bwn_wme_clear(struct bwn_softc *sc)
3084{
3085#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3086	struct wmeParams *p;
3087	unsigned int i;
3088
3089	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090	    ("%s:%d: fail", __func__, __LINE__));
3091
3092	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093		p = &(sc->sc_wmeParams[i]);
3094
3095		switch (bwn_wme_shm_offsets[i]) {
3096		case BWN_WME_VOICE:
3097			p->wmep_txopLimit = 0;
3098			p->wmep_aifsn = 2;
3099			/* XXX FIXME: log2(cwmin) */
3100			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102			break;
3103		case BWN_WME_VIDEO:
3104			p->wmep_txopLimit = 0;
3105			p->wmep_aifsn = 2;
3106			/* XXX FIXME: log2(cwmin) */
3107			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109			break;
3110		case BWN_WME_BESTEFFORT:
3111			p->wmep_txopLimit = 0;
3112			p->wmep_aifsn = 3;
3113			/* XXX FIXME: log2(cwmin) */
3114			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116			break;
3117		case BWN_WME_BACKGROUND:
3118			p->wmep_txopLimit = 0;
3119			p->wmep_aifsn = 7;
3120			/* XXX FIXME: log2(cwmin) */
3121			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123			break;
3124		default:
3125			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126		}
3127	}
3128}
3129
3130static int
3131bwn_core_init(struct bwn_mac *mac)
3132{
3133	struct bwn_softc *sc = mac->mac_sc;
3134	uint64_t hf;
3135	int error;
3136
3137	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138	    ("%s:%d: fail", __func__, __LINE__));
3139
3140	siba_powerup(sc->sc_dev, 0);
3141	if (!siba_dev_isup(sc->sc_dev))
3142		bwn_reset_core(mac,
3143		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144
3145	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148	BWN_GETTIME(mac->mac_phy.nexttime);
3149	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151	mac->mac_stats.link_noise = -95;
3152	mac->mac_reason_intr = 0;
3153	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155#ifdef BWN_DEBUG
3156	if (sc->sc_debug & BWN_DEBUG_XMIT)
3157		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158#endif
3159	mac->mac_suspended = 1;
3160	mac->mac_task_state = 0;
3161	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162
3163	mac->mac_phy.init_pre(mac);
3164
3165	siba_pcicore_intr(sc->sc_dev);
3166
3167	siba_fix_imcfglobug(sc->sc_dev);
3168	bwn_bt_disable(mac);
3169	if (mac->mac_phy.prepare_hw) {
3170		error = mac->mac_phy.prepare_hw(mac);
3171		if (error)
3172			goto fail0;
3173	}
3174	error = bwn_chip_init(mac);
3175	if (error)
3176		goto fail0;
3177	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178	    siba_get_revid(sc->sc_dev));
3179	hf = bwn_hf_read(mac);
3180	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184		if (mac->mac_phy.rev == 1)
3185			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186	}
3187	if (mac->mac_phy.rf_ver == 0x2050) {
3188		if (mac->mac_phy.rf_rev < 6)
3189			hf |= BWN_HF_FORCE_VCO_RECALC;
3190		if (mac->mac_phy.rf_rev == 6)
3191			hf |= BWN_HF_4318_TSSI;
3192	}
3193	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199	bwn_hf_write(mac, hf);
3200
3201	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205
3206	bwn_rate_init(mac);
3207	bwn_set_phytxctl(mac);
3208
3209	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212
3213	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214		bwn_pio_init(mac);
3215	else
3216		bwn_dma_init(mac);
3217	bwn_wme_init(mac);
3218	bwn_spu_setdelay(mac, 1);
3219	bwn_bt_enable(mac);
3220
3221	siba_powerup(sc->sc_dev,
3222	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3223	bwn_set_macaddr(mac);
3224	bwn_crypt_init(mac);
3225
3226	/* XXX LED initializatin */
3227
3228	mac->mac_status = BWN_MAC_STATUS_INITED;
3229
3230	return (error);
3231
3232fail0:
3233	siba_powerdown(sc->sc_dev);
3234	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3235	    ("%s:%d: fail", __func__, __LINE__));
3236	return (error);
3237}
3238
3239static void
3240bwn_core_start(struct bwn_mac *mac)
3241{
3242	struct bwn_softc *sc = mac->mac_sc;
3243	uint32_t tmp;
3244
3245	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3246	    ("%s:%d: fail", __func__, __LINE__));
3247
3248	if (siba_get_revid(sc->sc_dev) < 5)
3249		return;
3250
3251	while (1) {
3252		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3253		if (!(tmp & 0x00000001))
3254			break;
3255		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3256	}
3257
3258	bwn_mac_enable(mac);
3259	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3260	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3261
3262	mac->mac_status = BWN_MAC_STATUS_STARTED;
3263}
3264
3265static void
3266bwn_core_exit(struct bwn_mac *mac)
3267{
3268	struct bwn_softc *sc = mac->mac_sc;
3269	uint32_t macctl;
3270
3271	BWN_ASSERT_LOCKED(mac->mac_sc);
3272
3273	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3274	    ("%s:%d: fail", __func__, __LINE__));
3275
3276	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3277		return;
3278	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3279
3280	macctl = BWN_READ_4(mac, BWN_MACCTL);
3281	macctl &= ~BWN_MACCTL_MCODE_RUN;
3282	macctl |= BWN_MACCTL_MCODE_JMP0;
3283	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3284
3285	bwn_dma_stop(mac);
3286	bwn_pio_stop(mac);
3287	bwn_chip_exit(mac);
3288	mac->mac_phy.switch_analog(mac, 0);
3289	siba_dev_down(sc->sc_dev, 0);
3290	siba_powerdown(sc->sc_dev);
3291}
3292
3293static void
3294bwn_bt_disable(struct bwn_mac *mac)
3295{
3296	struct bwn_softc *sc = mac->mac_sc;
3297
3298	(void)sc;
3299	/* XXX do nothing yet */
3300}
3301
3302static int
3303bwn_chip_init(struct bwn_mac *mac)
3304{
3305	struct bwn_softc *sc = mac->mac_sc;
3306	struct bwn_phy *phy = &mac->mac_phy;
3307	uint32_t macctl;
3308	int error;
3309
3310	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3311	if (phy->gmode)
3312		macctl |= BWN_MACCTL_GMODE;
3313	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3314
3315	error = bwn_fw_fillinfo(mac);
3316	if (error)
3317		return (error);
3318	error = bwn_fw_loaducode(mac);
3319	if (error)
3320		return (error);
3321
3322	error = bwn_gpio_init(mac);
3323	if (error)
3324		return (error);
3325
3326	error = bwn_fw_loadinitvals(mac);
3327	if (error) {
3328		siba_gpio_set(sc->sc_dev, 0);
3329		return (error);
3330	}
3331	phy->switch_analog(mac, 1);
3332	error = bwn_phy_init(mac);
3333	if (error) {
3334		siba_gpio_set(sc->sc_dev, 0);
3335		return (error);
3336	}
3337	if (phy->set_im)
3338		phy->set_im(mac, BWN_IMMODE_NONE);
3339	if (phy->set_antenna)
3340		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3341	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3342
3343	if (phy->type == BWN_PHYTYPE_B)
3344		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3345	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3346	if (siba_get_revid(sc->sc_dev) < 5)
3347		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3348
3349	BWN_WRITE_4(mac, BWN_MACCTL,
3350	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3351	BWN_WRITE_4(mac, BWN_MACCTL,
3352	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3353	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3354
3355	bwn_set_opmode(mac);
3356	if (siba_get_revid(sc->sc_dev) < 3) {
3357		BWN_WRITE_2(mac, 0x060e, 0x0000);
3358		BWN_WRITE_2(mac, 0x0610, 0x8000);
3359		BWN_WRITE_2(mac, 0x0604, 0x0000);
3360		BWN_WRITE_2(mac, 0x0606, 0x0200);
3361	} else {
3362		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3363		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3364	}
3365	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3366	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3367	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3368	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3369	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3370	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3371	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3372	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3373	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3374	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3375	return (error);
3376}
3377
3378/* read hostflags */
3379static uint64_t
3380bwn_hf_read(struct bwn_mac *mac)
3381{
3382	uint64_t ret;
3383
3384	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3385	ret <<= 16;
3386	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3387	ret <<= 16;
3388	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3389	return (ret);
3390}
3391
3392static void
3393bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3394{
3395
3396	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3397	    (value & 0x00000000ffffull));
3398	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3399	    (value & 0x0000ffff0000ull) >> 16);
3400	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3401	    (value & 0xffff00000000ULL) >> 32);
3402}
3403
3404static void
3405bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3406{
3407
3408	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3409	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3410}
3411
3412static void
3413bwn_rate_init(struct bwn_mac *mac)
3414{
3415
3416	switch (mac->mac_phy.type) {
3417	case BWN_PHYTYPE_A:
3418	case BWN_PHYTYPE_G:
3419	case BWN_PHYTYPE_LP:
3420	case BWN_PHYTYPE_N:
3421		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3422		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3423		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3424		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3425		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3427		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3428		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3429			break;
3430		/* FALLTHROUGH */
3431	case BWN_PHYTYPE_B:
3432		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3433		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3434		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3435		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3436		break;
3437	default:
3438		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3439	}
3440}
3441
3442static void
3443bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3444{
3445	uint16_t offset;
3446
3447	if (ofdm) {
3448		offset = 0x480;
3449		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3450	} else {
3451		offset = 0x4c0;
3452		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3453	}
3454	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3455	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3456}
3457
3458static uint8_t
3459bwn_plcp_getcck(const uint8_t bitrate)
3460{
3461
3462	switch (bitrate) {
3463	case BWN_CCK_RATE_1MB:
3464		return (0x0a);
3465	case BWN_CCK_RATE_2MB:
3466		return (0x14);
3467	case BWN_CCK_RATE_5MB:
3468		return (0x37);
3469	case BWN_CCK_RATE_11MB:
3470		return (0x6e);
3471	}
3472	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3473	return (0);
3474}
3475
3476static uint8_t
3477bwn_plcp_getofdm(const uint8_t bitrate)
3478{
3479
3480	switch (bitrate) {
3481	case BWN_OFDM_RATE_6MB:
3482		return (0xb);
3483	case BWN_OFDM_RATE_9MB:
3484		return (0xf);
3485	case BWN_OFDM_RATE_12MB:
3486		return (0xa);
3487	case BWN_OFDM_RATE_18MB:
3488		return (0xe);
3489	case BWN_OFDM_RATE_24MB:
3490		return (0x9);
3491	case BWN_OFDM_RATE_36MB:
3492		return (0xd);
3493	case BWN_OFDM_RATE_48MB:
3494		return (0x8);
3495	case BWN_OFDM_RATE_54MB:
3496		return (0xc);
3497	}
3498	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3499	return (0);
3500}
3501
3502static void
3503bwn_set_phytxctl(struct bwn_mac *mac)
3504{
3505	uint16_t ctl;
3506
3507	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3508	    BWN_TX_PHY_TXPWR);
3509	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3510	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3511	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3512}
3513
3514static void
3515bwn_pio_init(struct bwn_mac *mac)
3516{
3517	struct bwn_pio *pio = &mac->mac_method.pio;
3518
3519	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3520	    & ~BWN_MACCTL_BIGENDIAN);
3521	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3522
3523	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3524	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3525	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3526	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3527	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3528	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3529}
3530
3531static void
3532bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3533    int index)
3534{
3535	struct bwn_pio_txpkt *tp;
3536	struct bwn_softc *sc = mac->mac_sc;
3537	unsigned int i;
3538
3539	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3540	tq->tq_index = index;
3541
3542	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3543	if (siba_get_revid(sc->sc_dev) >= 8)
3544		tq->tq_size = 1920;
3545	else {
3546		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3547		tq->tq_size -= 80;
3548	}
3549
3550	TAILQ_INIT(&tq->tq_pktlist);
3551	for (i = 0; i < N(tq->tq_pkts); i++) {
3552		tp = &(tq->tq_pkts[i]);
3553		tp->tp_index = i;
3554		tp->tp_queue = tq;
3555		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3556	}
3557}
3558
3559static uint16_t
3560bwn_pio_idx2base(struct bwn_mac *mac, int index)
3561{
3562	struct bwn_softc *sc = mac->mac_sc;
3563	static const uint16_t bases[] = {
3564		BWN_PIO_BASE0,
3565		BWN_PIO_BASE1,
3566		BWN_PIO_BASE2,
3567		BWN_PIO_BASE3,
3568		BWN_PIO_BASE4,
3569		BWN_PIO_BASE5,
3570		BWN_PIO_BASE6,
3571		BWN_PIO_BASE7,
3572	};
3573	static const uint16_t bases_rev11[] = {
3574		BWN_PIO11_BASE0,
3575		BWN_PIO11_BASE1,
3576		BWN_PIO11_BASE2,
3577		BWN_PIO11_BASE3,
3578		BWN_PIO11_BASE4,
3579		BWN_PIO11_BASE5,
3580	};
3581
3582	if (siba_get_revid(sc->sc_dev) >= 11) {
3583		if (index >= N(bases_rev11))
3584			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3585		return (bases_rev11[index]);
3586	}
3587	if (index >= N(bases))
3588		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589	return (bases[index]);
3590}
3591
3592static void
3593bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3594    int index)
3595{
3596	struct bwn_softc *sc = mac->mac_sc;
3597
3598	prq->prq_mac = mac;
3599	prq->prq_rev = siba_get_revid(sc->sc_dev);
3600	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3601	bwn_dma_rxdirectfifo(mac, index, 1);
3602}
3603
3604static void
3605bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3606{
3607	if (tq == NULL)
3608		return;
3609	bwn_pio_cancel_tx_packets(tq);
3610}
3611
3612static void
3613bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3614{
3615
3616	bwn_destroy_pioqueue_tx(pio);
3617}
3618
3619static uint16_t
3620bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3621    uint16_t offset)
3622{
3623
3624	return (BWN_READ_2(mac, tq->tq_base + offset));
3625}
3626
3627static void
3628bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3629{
3630	uint32_t ctl;
3631	int type;
3632	uint16_t base;
3633
3634	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3635	base = bwn_dma_base(type, idx);
3636	if (type == BWN_DMA_64BIT) {
3637		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3638		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3639		if (enable)
3640			ctl |= BWN_DMA64_RXDIRECTFIFO;
3641		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3642	} else {
3643		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3644		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3645		if (enable)
3646			ctl |= BWN_DMA32_RXDIRECTFIFO;
3647		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3648	}
3649}
3650
3651static uint64_t
3652bwn_dma_mask(struct bwn_mac *mac)
3653{
3654	uint32_t tmp;
3655	uint16_t base;
3656
3657	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3658	if (tmp & SIBA_TGSHIGH_DMA64)
3659		return (BWN_DMA_BIT_MASK(64));
3660	base = bwn_dma_base(0, 0);
3661	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3662	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3663	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3664		return (BWN_DMA_BIT_MASK(32));
3665
3666	return (BWN_DMA_BIT_MASK(30));
3667}
3668
3669static int
3670bwn_dma_mask2type(uint64_t dmamask)
3671{
3672
3673	if (dmamask == BWN_DMA_BIT_MASK(30))
3674		return (BWN_DMA_30BIT);
3675	if (dmamask == BWN_DMA_BIT_MASK(32))
3676		return (BWN_DMA_32BIT);
3677	if (dmamask == BWN_DMA_BIT_MASK(64))
3678		return (BWN_DMA_64BIT);
3679	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3680	return (BWN_DMA_30BIT);
3681}
3682
3683static void
3684bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3685{
3686	struct bwn_pio_txpkt *tp;
3687	unsigned int i;
3688
3689	for (i = 0; i < N(tq->tq_pkts); i++) {
3690		tp = &(tq->tq_pkts[i]);
3691		if (tp->tp_m) {
3692			m_freem(tp->tp_m);
3693			tp->tp_m = NULL;
3694		}
3695	}
3696}
3697
3698static uint16_t
3699bwn_dma_base(int type, int controller_idx)
3700{
3701	static const uint16_t map64[] = {
3702		BWN_DMA64_BASE0,
3703		BWN_DMA64_BASE1,
3704		BWN_DMA64_BASE2,
3705		BWN_DMA64_BASE3,
3706		BWN_DMA64_BASE4,
3707		BWN_DMA64_BASE5,
3708	};
3709	static const uint16_t map32[] = {
3710		BWN_DMA32_BASE0,
3711		BWN_DMA32_BASE1,
3712		BWN_DMA32_BASE2,
3713		BWN_DMA32_BASE3,
3714		BWN_DMA32_BASE4,
3715		BWN_DMA32_BASE5,
3716	};
3717
3718	if (type == BWN_DMA_64BIT) {
3719		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3720		    ("%s:%d: fail", __func__, __LINE__));
3721		return (map64[controller_idx]);
3722	}
3723	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3724	    ("%s:%d: fail", __func__, __LINE__));
3725	return (map32[controller_idx]);
3726}
3727
3728static void
3729bwn_dma_init(struct bwn_mac *mac)
3730{
3731	struct bwn_dma *dma = &mac->mac_method.dma;
3732
3733	/* setup TX DMA channels. */
3734	bwn_dma_setup(dma->wme[WME_AC_BK]);
3735	bwn_dma_setup(dma->wme[WME_AC_BE]);
3736	bwn_dma_setup(dma->wme[WME_AC_VI]);
3737	bwn_dma_setup(dma->wme[WME_AC_VO]);
3738	bwn_dma_setup(dma->mcast);
3739	/* setup RX DMA channel. */
3740	bwn_dma_setup(dma->rx);
3741}
3742
3743static struct bwn_dma_ring *
3744bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3745    int for_tx, int type)
3746{
3747	struct bwn_dma *dma = &mac->mac_method.dma;
3748	struct bwn_dma_ring *dr;
3749	struct bwn_dmadesc_generic *desc;
3750	struct bwn_dmadesc_meta *mt;
3751	struct bwn_softc *sc = mac->mac_sc;
3752	int error, i;
3753
3754	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3755	if (dr == NULL)
3756		goto out;
3757	dr->dr_numslots = BWN_RXRING_SLOTS;
3758	if (for_tx)
3759		dr->dr_numslots = BWN_TXRING_SLOTS;
3760
3761	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3762	    M_DEVBUF, M_NOWAIT | M_ZERO);
3763	if (dr->dr_meta == NULL)
3764		goto fail0;
3765
3766	dr->dr_type = type;
3767	dr->dr_mac = mac;
3768	dr->dr_base = bwn_dma_base(type, controller_index);
3769	dr->dr_index = controller_index;
3770	if (type == BWN_DMA_64BIT) {
3771		dr->getdesc = bwn_dma_64_getdesc;
3772		dr->setdesc = bwn_dma_64_setdesc;
3773		dr->start_transfer = bwn_dma_64_start_transfer;
3774		dr->suspend = bwn_dma_64_suspend;
3775		dr->resume = bwn_dma_64_resume;
3776		dr->get_curslot = bwn_dma_64_get_curslot;
3777		dr->set_curslot = bwn_dma_64_set_curslot;
3778	} else {
3779		dr->getdesc = bwn_dma_32_getdesc;
3780		dr->setdesc = bwn_dma_32_setdesc;
3781		dr->start_transfer = bwn_dma_32_start_transfer;
3782		dr->suspend = bwn_dma_32_suspend;
3783		dr->resume = bwn_dma_32_resume;
3784		dr->get_curslot = bwn_dma_32_get_curslot;
3785		dr->set_curslot = bwn_dma_32_set_curslot;
3786	}
3787	if (for_tx) {
3788		dr->dr_tx = 1;
3789		dr->dr_curslot = -1;
3790	} else {
3791		if (dr->dr_index == 0) {
3792			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3793			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3794		} else
3795			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3796	}
3797
3798	error = bwn_dma_allocringmemory(dr);
3799	if (error)
3800		goto fail2;
3801
3802	if (for_tx) {
3803		/*
3804		 * Assumption: BWN_TXRING_SLOTS can be divided by
3805		 * BWN_TX_SLOTS_PER_FRAME
3806		 */
3807		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3808		    ("%s:%d: fail", __func__, __LINE__));
3809
3810		dr->dr_txhdr_cache =
3811		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3812			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3813		KASSERT(dr->dr_txhdr_cache != NULL,
3814		    ("%s:%d: fail", __func__, __LINE__));
3815
3816		/*
3817		 * Create TX ring DMA stuffs
3818		 */
3819		error = bus_dma_tag_create(dma->parent_dtag,
3820				    BWN_ALIGN, 0,
3821				    BUS_SPACE_MAXADDR,
3822				    BUS_SPACE_MAXADDR,
3823				    NULL, NULL,
3824				    BWN_HDRSIZE(mac),
3825				    1,
3826				    BUS_SPACE_MAXSIZE_32BIT,
3827				    0,
3828				    NULL, NULL,
3829				    &dr->dr_txring_dtag);
3830		if (error) {
3831			device_printf(sc->sc_dev,
3832			    "can't create TX ring DMA tag: TODO frees\n");
3833			goto fail1;
3834		}
3835
3836		for (i = 0; i < dr->dr_numslots; i += 2) {
3837			dr->getdesc(dr, i, &desc, &mt);
3838
3839			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3840			mt->mt_m = NULL;
3841			mt->mt_ni = NULL;
3842			mt->mt_islast = 0;
3843			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3844			    &mt->mt_dmap);
3845			if (error) {
3846				device_printf(sc->sc_dev,
3847				     "can't create RX buf DMA map\n");
3848				goto fail1;
3849			}
3850
3851			dr->getdesc(dr, i + 1, &desc, &mt);
3852
3853			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3854			mt->mt_m = NULL;
3855			mt->mt_ni = NULL;
3856			mt->mt_islast = 1;
3857			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3858			    &mt->mt_dmap);
3859			if (error) {
3860				device_printf(sc->sc_dev,
3861				     "can't create RX buf DMA map\n");
3862				goto fail1;
3863			}
3864		}
3865	} else {
3866		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3867		    &dr->dr_spare_dmap);
3868		if (error) {
3869			device_printf(sc->sc_dev,
3870			    "can't create RX buf DMA map\n");
3871			goto out;		/* XXX wrong! */
3872		}
3873
3874		for (i = 0; i < dr->dr_numslots; i++) {
3875			dr->getdesc(dr, i, &desc, &mt);
3876
3877			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3878			    &mt->mt_dmap);
3879			if (error) {
3880				device_printf(sc->sc_dev,
3881				    "can't create RX buf DMA map\n");
3882				goto out;	/* XXX wrong! */
3883			}
3884			error = bwn_dma_newbuf(dr, desc, mt, 1);
3885			if (error) {
3886				device_printf(sc->sc_dev,
3887				    "failed to allocate RX buf\n");
3888				goto out;	/* XXX wrong! */
3889			}
3890		}
3891
3892		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3893		    BUS_DMASYNC_PREWRITE);
3894
3895		dr->dr_usedslot = dr->dr_numslots;
3896	}
3897
3898      out:
3899	return (dr);
3900
3901fail2:
3902	free(dr->dr_txhdr_cache, M_DEVBUF);
3903fail1:
3904	free(dr->dr_meta, M_DEVBUF);
3905fail0:
3906	free(dr, M_DEVBUF);
3907	return (NULL);
3908}
3909
3910static void
3911bwn_dma_ringfree(struct bwn_dma_ring **dr)
3912{
3913
3914	if (dr == NULL)
3915		return;
3916
3917	bwn_dma_free_descbufs(*dr);
3918	bwn_dma_free_ringmemory(*dr);
3919
3920	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3921	free((*dr)->dr_meta, M_DEVBUF);
3922	free(*dr, M_DEVBUF);
3923
3924	*dr = NULL;
3925}
3926
3927static void
3928bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3929    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3930{
3931	struct bwn_dmadesc32 *desc;
3932
3933	*meta = &(dr->dr_meta[slot]);
3934	desc = dr->dr_ring_descbase;
3935	desc = &(desc[slot]);
3936
3937	*gdesc = (struct bwn_dmadesc_generic *)desc;
3938}
3939
3940static void
3941bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3942    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3943    int start, int end, int irq)
3944{
3945	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3946	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3947	uint32_t addr, addrext, ctl;
3948	int slot;
3949
3950	slot = (int)(&(desc->dma.dma32) - descbase);
3951	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3952	    ("%s:%d: fail", __func__, __LINE__));
3953
3954	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3955	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3956	addr |= siba_dma_translation(sc->sc_dev);
3957	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3958	if (slot == dr->dr_numslots - 1)
3959		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3960	if (start)
3961		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3962	if (end)
3963		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3964	if (irq)
3965		ctl |= BWN_DMA32_DCTL_IRQ;
3966	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3967	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3968
3969	desc->dma.dma32.control = htole32(ctl);
3970	desc->dma.dma32.address = htole32(addr);
3971}
3972
3973static void
3974bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3975{
3976
3977	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3978	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3979}
3980
3981static void
3982bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3983{
3984
3985	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3986	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3987}
3988
3989static void
3990bwn_dma_32_resume(struct bwn_dma_ring *dr)
3991{
3992
3993	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3994	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3995}
3996
3997static int
3998bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3999{
4000	uint32_t val;
4001
4002	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4003	val &= BWN_DMA32_RXDPTR;
4004
4005	return (val / sizeof(struct bwn_dmadesc32));
4006}
4007
4008static void
4009bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4010{
4011
4012	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4013	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4014}
4015
4016static void
4017bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4018    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4019{
4020	struct bwn_dmadesc64 *desc;
4021
4022	*meta = &(dr->dr_meta[slot]);
4023	desc = dr->dr_ring_descbase;
4024	desc = &(desc[slot]);
4025
4026	*gdesc = (struct bwn_dmadesc_generic *)desc;
4027}
4028
4029static void
4030bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4031    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4032    int start, int end, int irq)
4033{
4034	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4035	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4036	int slot;
4037	uint32_t ctl0 = 0, ctl1 = 0;
4038	uint32_t addrlo, addrhi;
4039	uint32_t addrext;
4040
4041	slot = (int)(&(desc->dma.dma64) - descbase);
4042	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4043	    ("%s:%d: fail", __func__, __LINE__));
4044
4045	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4046	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4047	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4048	    30;
4049	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4050	if (slot == dr->dr_numslots - 1)
4051		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4052	if (start)
4053		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4054	if (end)
4055		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4056	if (irq)
4057		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4058	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4059	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4060	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4061
4062	desc->dma.dma64.control0 = htole32(ctl0);
4063	desc->dma.dma64.control1 = htole32(ctl1);
4064	desc->dma.dma64.address_low = htole32(addrlo);
4065	desc->dma.dma64.address_high = htole32(addrhi);
4066}
4067
4068static void
4069bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4070{
4071
4072	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4073	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4074}
4075
4076static void
4077bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4078{
4079
4080	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4081	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4082}
4083
4084static void
4085bwn_dma_64_resume(struct bwn_dma_ring *dr)
4086{
4087
4088	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4089	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4090}
4091
4092static int
4093bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4094{
4095	uint32_t val;
4096
4097	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4098	val &= BWN_DMA64_RXSTATDPTR;
4099
4100	return (val / sizeof(struct bwn_dmadesc64));
4101}
4102
4103static void
4104bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4105{
4106
4107	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4108	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4109}
4110
4111static int
4112bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4113{
4114	struct bwn_mac *mac = dr->dr_mac;
4115	struct bwn_dma *dma = &mac->mac_method.dma;
4116	struct bwn_softc *sc = mac->mac_sc;
4117	int error;
4118
4119	error = bus_dma_tag_create(dma->parent_dtag,
4120			    BWN_ALIGN, 0,
4121			    BUS_SPACE_MAXADDR,
4122			    BUS_SPACE_MAXADDR,
4123			    NULL, NULL,
4124			    BWN_DMA_RINGMEMSIZE,
4125			    1,
4126			    BUS_SPACE_MAXSIZE_32BIT,
4127			    0,
4128			    NULL, NULL,
4129			    &dr->dr_ring_dtag);
4130	if (error) {
4131		device_printf(sc->sc_dev,
4132		    "can't create TX ring DMA tag: TODO frees\n");
4133		return (-1);
4134	}
4135
4136	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4137	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4138	    &dr->dr_ring_dmap);
4139	if (error) {
4140		device_printf(sc->sc_dev,
4141		    "can't allocate DMA mem: TODO frees\n");
4142		return (-1);
4143	}
4144	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4145	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4146	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4147	if (error) {
4148		device_printf(sc->sc_dev,
4149		    "can't load DMA mem: TODO free\n");
4150		return (-1);
4151	}
4152
4153	return (0);
4154}
4155
4156static void
4157bwn_dma_setup(struct bwn_dma_ring *dr)
4158{
4159	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4160	uint64_t ring64;
4161	uint32_t addrext, ring32, value;
4162	uint32_t trans = siba_dma_translation(sc->sc_dev);
4163
4164	if (dr->dr_tx) {
4165		dr->dr_curslot = -1;
4166
4167		if (dr->dr_type == BWN_DMA_64BIT) {
4168			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4169			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4170			    >> 30;
4171			value = BWN_DMA64_TXENABLE;
4172			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4173			    & BWN_DMA64_TXADDREXT_MASK;
4174			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4175			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4176			    (ring64 & 0xffffffff));
4177			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4178			    ((ring64 >> 32) &
4179			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4180		} else {
4181			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4182			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4183			value = BWN_DMA32_TXENABLE;
4184			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4185			    & BWN_DMA32_TXADDREXT_MASK;
4186			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4187			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4188			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4189		}
4190		return;
4191	}
4192
4193	/*
4194	 * set for RX
4195	 */
4196	dr->dr_usedslot = dr->dr_numslots;
4197
4198	if (dr->dr_type == BWN_DMA_64BIT) {
4199		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4200		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4201		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4202		value |= BWN_DMA64_RXENABLE;
4203		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4204		    & BWN_DMA64_RXADDREXT_MASK;
4205		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4206		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4207		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4208		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4209		    | (trans << 1));
4210		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4211		    sizeof(struct bwn_dmadesc64));
4212	} else {
4213		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4214		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4215		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4216		value |= BWN_DMA32_RXENABLE;
4217		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4218		    & BWN_DMA32_RXADDREXT_MASK;
4219		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4220		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4221		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4222		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4223		    sizeof(struct bwn_dmadesc32));
4224	}
4225}
4226
4227static void
4228bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4229{
4230
4231	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4232	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4233	    dr->dr_ring_dmap);
4234}
4235
4236static void
4237bwn_dma_cleanup(struct bwn_dma_ring *dr)
4238{
4239
4240	if (dr->dr_tx) {
4241		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4242		if (dr->dr_type == BWN_DMA_64BIT) {
4243			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4244			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4245		} else
4246			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4247	} else {
4248		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4249		if (dr->dr_type == BWN_DMA_64BIT) {
4250			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4251			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4252		} else
4253			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4254	}
4255}
4256
4257static void
4258bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4259{
4260	struct bwn_dmadesc_generic *desc;
4261	struct bwn_dmadesc_meta *meta;
4262	struct bwn_mac *mac = dr->dr_mac;
4263	struct bwn_dma *dma = &mac->mac_method.dma;
4264	struct bwn_softc *sc = mac->mac_sc;
4265	int i;
4266
4267	if (!dr->dr_usedslot)
4268		return;
4269	for (i = 0; i < dr->dr_numslots; i++) {
4270		dr->getdesc(dr, i, &desc, &meta);
4271
4272		if (meta->mt_m == NULL) {
4273			if (!dr->dr_tx)
4274				device_printf(sc->sc_dev, "%s: not TX?\n",
4275				    __func__);
4276			continue;
4277		}
4278		if (dr->dr_tx) {
4279			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4280				bus_dmamap_unload(dr->dr_txring_dtag,
4281				    meta->mt_dmap);
4282			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4283				bus_dmamap_unload(dma->txbuf_dtag,
4284				    meta->mt_dmap);
4285		} else
4286			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4287		bwn_dma_free_descbuf(dr, meta);
4288	}
4289}
4290
4291static int
4292bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4293    int type)
4294{
4295	struct bwn_softc *sc = mac->mac_sc;
4296	uint32_t value;
4297	int i;
4298	uint16_t offset;
4299
4300	for (i = 0; i < 10; i++) {
4301		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4302		    BWN_DMA32_TXSTATUS;
4303		value = BWN_READ_4(mac, base + offset);
4304		if (type == BWN_DMA_64BIT) {
4305			value &= BWN_DMA64_TXSTAT;
4306			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4307			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4308			    value == BWN_DMA64_TXSTAT_STOPPED)
4309				break;
4310		} else {
4311			value &= BWN_DMA32_TXSTATE;
4312			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4313			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4314			    value == BWN_DMA32_TXSTAT_STOPPED)
4315				break;
4316		}
4317		DELAY(1000);
4318	}
4319	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4320	BWN_WRITE_4(mac, base + offset, 0);
4321	for (i = 0; i < 10; i++) {
4322		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4323						   BWN_DMA32_TXSTATUS;
4324		value = BWN_READ_4(mac, base + offset);
4325		if (type == BWN_DMA_64BIT) {
4326			value &= BWN_DMA64_TXSTAT;
4327			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4328				i = -1;
4329				break;
4330			}
4331		} else {
4332			value &= BWN_DMA32_TXSTATE;
4333			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4334				i = -1;
4335				break;
4336			}
4337		}
4338		DELAY(1000);
4339	}
4340	if (i != -1) {
4341		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4342		return (ENODEV);
4343	}
4344	DELAY(1000);
4345
4346	return (0);
4347}
4348
4349static int
4350bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4351    int type)
4352{
4353	struct bwn_softc *sc = mac->mac_sc;
4354	uint32_t value;
4355	int i;
4356	uint16_t offset;
4357
4358	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4359	BWN_WRITE_4(mac, base + offset, 0);
4360	for (i = 0; i < 10; i++) {
4361		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4362		    BWN_DMA32_RXSTATUS;
4363		value = BWN_READ_4(mac, base + offset);
4364		if (type == BWN_DMA_64BIT) {
4365			value &= BWN_DMA64_RXSTAT;
4366			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4367				i = -1;
4368				break;
4369			}
4370		} else {
4371			value &= BWN_DMA32_RXSTATE;
4372			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4373				i = -1;
4374				break;
4375			}
4376		}
4377		DELAY(1000);
4378	}
4379	if (i != -1) {
4380		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4381		return (ENODEV);
4382	}
4383
4384	return (0);
4385}
4386
4387static void
4388bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4389    struct bwn_dmadesc_meta *meta)
4390{
4391
4392	if (meta->mt_m != NULL) {
4393		m_freem(meta->mt_m);
4394		meta->mt_m = NULL;
4395	}
4396	if (meta->mt_ni != NULL) {
4397		ieee80211_free_node(meta->mt_ni);
4398		meta->mt_ni = NULL;
4399	}
4400}
4401
4402static void
4403bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4404{
4405	struct bwn_rxhdr4 *rxhdr;
4406	unsigned char *frame;
4407
4408	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4409	rxhdr->frame_len = 0;
4410
4411	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4412	    sizeof(struct bwn_plcp6) + 2,
4413	    ("%s:%d: fail", __func__, __LINE__));
4414	frame = mtod(m, char *) + dr->dr_frameoffset;
4415	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4416}
4417
4418static uint8_t
4419bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4420{
4421	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4422
4423	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4424	    == 0xff);
4425}
4426
4427static void
4428bwn_wme_init(struct bwn_mac *mac)
4429{
4430
4431	bwn_wme_load(mac);
4432
4433	/* enable WME support. */
4434	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4435	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4436	    BWN_IFSCTL_USE_EDCF);
4437}
4438
4439static void
4440bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4441{
4442	struct bwn_softc *sc = mac->mac_sc;
4443	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4444	uint16_t delay;	/* microsec */
4445
4446	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4447	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4448		delay = 500;
4449	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4450		delay = max(delay, (uint16_t)2400);
4451
4452	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4453}
4454
4455static void
4456bwn_bt_enable(struct bwn_mac *mac)
4457{
4458	struct bwn_softc *sc = mac->mac_sc;
4459	uint64_t hf;
4460
4461	if (bwn_bluetooth == 0)
4462		return;
4463	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4464		return;
4465	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4466		return;
4467
4468	hf = bwn_hf_read(mac);
4469	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4470		hf |= BWN_HF_BT_COEXISTALT;
4471	else
4472		hf |= BWN_HF_BT_COEXIST;
4473	bwn_hf_write(mac, hf);
4474}
4475
4476static void
4477bwn_set_macaddr(struct bwn_mac *mac)
4478{
4479
4480	bwn_mac_write_bssid(mac);
4481	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4482}
4483
4484static void
4485bwn_clear_keys(struct bwn_mac *mac)
4486{
4487	int i;
4488
4489	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4490		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4491		    ("%s:%d: fail", __func__, __LINE__));
4492
4493		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4494		    NULL, BWN_SEC_KEYSIZE, NULL);
4495		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4496			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4497			    NULL, BWN_SEC_KEYSIZE, NULL);
4498		}
4499		mac->mac_key[i].keyconf = NULL;
4500	}
4501}
4502
4503static void
4504bwn_crypt_init(struct bwn_mac *mac)
4505{
4506	struct bwn_softc *sc = mac->mac_sc;
4507
4508	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4509	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4510	    ("%s:%d: fail", __func__, __LINE__));
4511	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4512	mac->mac_ktp *= 2;
4513	if (siba_get_revid(sc->sc_dev) >= 5)
4514		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4515	bwn_clear_keys(mac);
4516}
4517
4518static void
4519bwn_chip_exit(struct bwn_mac *mac)
4520{
4521	struct bwn_softc *sc = mac->mac_sc;
4522
4523	bwn_phy_exit(mac);
4524	siba_gpio_set(sc->sc_dev, 0);
4525}
4526
4527static int
4528bwn_fw_fillinfo(struct bwn_mac *mac)
4529{
4530	int error;
4531
4532	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4533	if (error == 0)
4534		return (0);
4535	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4536	if (error == 0)
4537		return (0);
4538	return (error);
4539}
4540
4541static int
4542bwn_gpio_init(struct bwn_mac *mac)
4543{
4544	struct bwn_softc *sc = mac->mac_sc;
4545	uint32_t mask = 0x1f, set = 0xf, value;
4546
4547	BWN_WRITE_4(mac, BWN_MACCTL,
4548	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4549	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4550	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4551
4552	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4553		mask |= 0x0060;
4554		set |= 0x0060;
4555	}
4556	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4557		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4558		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4559		mask |= 0x0200;
4560		set |= 0x0200;
4561	}
4562	if (siba_get_revid(sc->sc_dev) >= 2)
4563		mask |= 0x0010;
4564
4565	value = siba_gpio_get(sc->sc_dev);
4566	if (value == -1)
4567		return (0);
4568	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4569
4570	return (0);
4571}
4572
4573static int
4574bwn_fw_loadinitvals(struct bwn_mac *mac)
4575{
4576#define	GETFWOFFSET(fwp, offset)				\
4577	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4578	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4579	const struct bwn_fwhdr *hdr;
4580	struct bwn_fw *fw = &mac->mac_fw;
4581	int error;
4582
4583	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4584	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4585	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4586	if (error)
4587		return (error);
4588	if (fw->initvals_band.fw) {
4589		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4590		error = bwn_fwinitvals_write(mac,
4591		    GETFWOFFSET(fw->initvals_band, hdr_len),
4592		    be32toh(hdr->size),
4593		    fw->initvals_band.fw->datasize - hdr_len);
4594	}
4595	return (error);
4596#undef GETFWOFFSET
4597}
4598
4599static int
4600bwn_phy_init(struct bwn_mac *mac)
4601{
4602	struct bwn_softc *sc = mac->mac_sc;
4603	int error;
4604
4605	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4606	mac->mac_phy.rf_onoff(mac, 1);
4607	error = mac->mac_phy.init(mac);
4608	if (error) {
4609		device_printf(sc->sc_dev, "PHY init failed\n");
4610		goto fail0;
4611	}
4612	error = bwn_switch_channel(mac,
4613	    mac->mac_phy.get_default_chan(mac));
4614	if (error) {
4615		device_printf(sc->sc_dev,
4616		    "failed to switch default channel\n");
4617		goto fail1;
4618	}
4619	return (0);
4620fail1:
4621	if (mac->mac_phy.exit)
4622		mac->mac_phy.exit(mac);
4623fail0:
4624	mac->mac_phy.rf_onoff(mac, 0);
4625
4626	return (error);
4627}
4628
4629static void
4630bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4631{
4632	uint16_t ant;
4633	uint16_t tmp;
4634
4635	ant = bwn_ant2phy(antenna);
4636
4637	/* For ACK/CTS */
4638	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4639	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4640	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4641	/* For Probe Resposes */
4642	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4643	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4645}
4646
4647static void
4648bwn_set_opmode(struct bwn_mac *mac)
4649{
4650	struct bwn_softc *sc = mac->mac_sc;
4651	struct ifnet *ifp = sc->sc_ifp;
4652	struct ieee80211com *ic = ifp->if_l2com;
4653	uint32_t ctl;
4654	uint16_t cfp_pretbtt;
4655
4656	ctl = BWN_READ_4(mac, BWN_MACCTL);
4657	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4658	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4659	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4660	ctl |= BWN_MACCTL_STA;
4661
4662	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4663	    ic->ic_opmode == IEEE80211_M_MBSS)
4664		ctl |= BWN_MACCTL_HOSTAP;
4665	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4666		ctl &= ~BWN_MACCTL_STA;
4667	ctl |= sc->sc_filters;
4668
4669	if (siba_get_revid(sc->sc_dev) <= 4)
4670		ctl |= BWN_MACCTL_PROMISC;
4671
4672	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4673
4674	cfp_pretbtt = 2;
4675	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4676		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4677		    siba_get_chiprev(sc->sc_dev) == 3)
4678			cfp_pretbtt = 100;
4679		else
4680			cfp_pretbtt = 50;
4681	}
4682	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4683}
4684
4685static int
4686bwn_dma_gettype(struct bwn_mac *mac)
4687{
4688	uint32_t tmp;
4689	uint16_t base;
4690
4691	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4692	if (tmp & SIBA_TGSHIGH_DMA64)
4693		return (BWN_DMA_64BIT);
4694	base = bwn_dma_base(0, 0);
4695	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4696	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4697	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4698		return (BWN_DMA_32BIT);
4699
4700	return (BWN_DMA_30BIT);
4701}
4702
4703static void
4704bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4705{
4706	if (!error) {
4707		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4708		*((bus_addr_t *)arg) = seg->ds_addr;
4709	}
4710}
4711
4712static void
4713bwn_phy_g_init_sub(struct bwn_mac *mac)
4714{
4715	struct bwn_phy *phy = &mac->mac_phy;
4716	struct bwn_phy_g *pg = &phy->phy_g;
4717	struct bwn_softc *sc = mac->mac_sc;
4718	uint16_t i, tmp;
4719
4720	if (phy->rev == 1)
4721		bwn_phy_init_b5(mac);
4722	else
4723		bwn_phy_init_b6(mac);
4724
4725	if (phy->rev >= 2 || phy->gmode)
4726		bwn_phy_init_a(mac);
4727
4728	if (phy->rev >= 2) {
4729		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4730		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4731	}
4732	if (phy->rev == 2) {
4733		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4734		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4735	}
4736	if (phy->rev > 5) {
4737		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4738		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739	}
4740	if (phy->gmode || phy->rev >= 2) {
4741		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4742		tmp &= BWN_PHYVER_VERSION;
4743		if (tmp == 3 || tmp == 5) {
4744			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4745			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4746		}
4747		if (tmp == 5) {
4748			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4749			    0x1f00);
4750		}
4751	}
4752	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4753		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4754	if (phy->rf_rev == 8) {
4755		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4756		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4757	}
4758	if (BWN_HAS_LOOPBACK(phy))
4759		bwn_loopback_calcgain(mac);
4760
4761	if (phy->rf_rev != 8) {
4762		if (pg->pg_initval == 0xffff)
4763			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4764		else
4765			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4766	}
4767	bwn_lo_g_init(mac);
4768	if (BWN_HAS_TXMAG(phy)) {
4769		BWN_RF_WRITE(mac, 0x52,
4770		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4771		    | pg->pg_loctl.tx_bias |
4772		    pg->pg_loctl.tx_magn);
4773	} else {
4774		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4775	}
4776	if (phy->rev >= 6) {
4777		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4778		    (pg->pg_loctl.tx_bias << 12));
4779	}
4780	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4781		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4782	else
4783		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4784	if (phy->rev < 2)
4785		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4786	else
4787		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4788	if (phy->gmode || phy->rev >= 2) {
4789		bwn_lo_g_adjust(mac);
4790		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4791	}
4792
4793	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4794		for (i = 0; i < 64; i++) {
4795			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4796			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4797			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4798			    -32), 31));
4799		}
4800		bwn_nrssi_threshold(mac);
4801	} else if (phy->gmode || phy->rev >= 2) {
4802		if (pg->pg_nrssi[0] == -1000) {
4803			KASSERT(pg->pg_nrssi[1] == -1000,
4804			    ("%s:%d: fail", __func__, __LINE__));
4805			bwn_nrssi_slope_11g(mac);
4806		} else
4807			bwn_nrssi_threshold(mac);
4808	}
4809	if (phy->rf_rev == 8)
4810		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4811	bwn_phy_hwpctl_init(mac);
4812	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4813	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4814		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4815		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4816	}
4817}
4818
4819static uint8_t
4820bwn_has_hwpctl(struct bwn_mac *mac)
4821{
4822
4823	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4824		return (0);
4825	return (mac->mac_phy.use_hwpctl(mac));
4826}
4827
4828static void
4829bwn_phy_init_b5(struct bwn_mac *mac)
4830{
4831	struct bwn_phy *phy = &mac->mac_phy;
4832	struct bwn_phy_g *pg = &phy->phy_g;
4833	struct bwn_softc *sc = mac->mac_sc;
4834	uint16_t offset, value;
4835	uint8_t old_channel;
4836
4837	if (phy->analog == 1)
4838		BWN_RF_SET(mac, 0x007a, 0x0050);
4839	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4840	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4841		value = 0x2120;
4842		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4843			BWN_PHY_WRITE(mac, offset, value);
4844			value += 0x202;
4845		}
4846	}
4847	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4848	if (phy->rf_ver == 0x2050)
4849		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4850
4851	if (phy->gmode || phy->rev >= 2) {
4852		if (phy->rf_ver == 0x2050) {
4853			BWN_RF_SET(mac, 0x007a, 0x0020);
4854			BWN_RF_SET(mac, 0x0051, 0x0004);
4855		}
4856		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4857
4858		BWN_PHY_SET(mac, 0x0802, 0x0100);
4859		BWN_PHY_SET(mac, 0x042b, 0x2000);
4860
4861		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4862
4863		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4864		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4865		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4866	}
4867
4868	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4869		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4870
4871	if (phy->analog == 1) {
4872		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4873		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4874		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4875		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4876		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4877	} else
4878		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4879	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4880	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4881
4882	if (phy->analog == 1)
4883		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4884	else
4885		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4886
4887	if (phy->analog == 0)
4888		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4889
4890	old_channel = phy->chan;
4891	bwn_phy_g_switch_chan(mac, 7, 0);
4892
4893	if (phy->rf_ver != 0x2050) {
4894		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4895		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4896	}
4897
4898	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4899	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4900
4901	if (phy->rf_ver == 0x2050) {
4902		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4904	}
4905
4906	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4907	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4908	BWN_RF_SET(mac, 0x007a, 0x0007);
4909
4910	bwn_phy_g_switch_chan(mac, old_channel, 0);
4911	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4912	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4913	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4914
4915	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4916	    pg->pg_txctl);
4917
4918	if (phy->rf_ver == 0x2050)
4919		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4920
4921	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4922}
4923
4924static void
4925bwn_loopback_calcgain(struct bwn_mac *mac)
4926{
4927	struct bwn_phy *phy = &mac->mac_phy;
4928	struct bwn_phy_g *pg = &phy->phy_g;
4929	struct bwn_softc *sc = mac->mac_sc;
4930	uint16_t backup_phy[16] = { 0 };
4931	uint16_t backup_radio[3];
4932	uint16_t backup_bband;
4933	uint16_t i, j, loop_i_max;
4934	uint16_t trsw_rx;
4935	uint16_t loop1_outer_done, loop1_inner_done;
4936
4937	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4938	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4939	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4940	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4941	if (phy->rev != 1) {
4942		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4943		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4944	}
4945	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4946	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4947	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4948	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4949	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4950	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4951	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4952	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4953	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4954	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4955	backup_bband = pg->pg_bbatt.att;
4956	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4957	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4958	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4959
4960	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4961	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4962	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4963	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4964	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4965	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4966	if (phy->rev != 1) {
4967		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4968		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4969		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4970		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4971	}
4972	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4973	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4974	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4975	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4976
4977	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4978	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4979	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4980
4981	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4982	if (phy->rev != 1) {
4983		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4984		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4985	}
4986	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4987
4988	if (phy->rf_rev == 8)
4989		BWN_RF_WRITE(mac, 0x43, 0x000f);
4990	else {
4991		BWN_RF_WRITE(mac, 0x52, 0);
4992		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4993	}
4994	bwn_phy_g_set_bbatt(mac, 11);
4995
4996	if (phy->rev >= 3)
4997		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4998	else
4999		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5000	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5001
5002	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5003	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5004
5005	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5006	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5007
5008	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5009		if (phy->rev >= 7) {
5010			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5011			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5012		}
5013	}
5014	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5015
5016	j = 0;
5017	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5018	for (i = 0; i < loop_i_max; i++) {
5019		for (j = 0; j < 16; j++) {
5020			BWN_RF_WRITE(mac, 0x43, i);
5021			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5022			    (j << 8));
5023			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5024			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5025			DELAY(20);
5026			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5027				goto done0;
5028		}
5029	}
5030done0:
5031	loop1_outer_done = i;
5032	loop1_inner_done = j;
5033	if (j >= 8) {
5034		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5035		trsw_rx = 0x1b;
5036		for (j = j - 8; j < 16; j++) {
5037			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5038			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5039			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5040			DELAY(20);
5041			trsw_rx -= 3;
5042			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5043				goto done1;
5044		}
5045	} else
5046		trsw_rx = 0x18;
5047done1:
5048
5049	if (phy->rev != 1) {
5050		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5051		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5052	}
5053	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5054	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5055	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5056	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5061	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5062
5063	bwn_phy_g_set_bbatt(mac, backup_bband);
5064
5065	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5066	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5067	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5068
5069	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5070	DELAY(10);
5071	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5072	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5073	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5074	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5075
5076	pg->pg_max_lb_gain =
5077	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5078	pg->pg_trsw_rx_gain = trsw_rx * 2;
5079}
5080
5081static uint16_t
5082bwn_rf_init_bcm2050(struct bwn_mac *mac)
5083{
5084	struct bwn_phy *phy = &mac->mac_phy;
5085	uint32_t tmp1 = 0, tmp2 = 0;
5086	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5087	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5088	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5089	static const uint8_t rcc_table[] = {
5090		0x02, 0x03, 0x01, 0x0f,
5091		0x06, 0x07, 0x05, 0x0f,
5092		0x0a, 0x0b, 0x09, 0x0f,
5093		0x0e, 0x0f, 0x0d, 0x0f,
5094	};
5095
5096	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5097	    rfoverval = rfover = cck3 = 0;
5098	radio0 = BWN_RF_READ(mac, 0x43);
5099	radio1 = BWN_RF_READ(mac, 0x51);
5100	radio2 = BWN_RF_READ(mac, 0x52);
5101	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5102	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5103	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5104	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5105
5106	if (phy->type == BWN_PHYTYPE_B) {
5107		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5108		reg0 = BWN_READ_2(mac, 0x3ec);
5109
5110		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5111		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5112	} else if (phy->gmode || phy->rev >= 2) {
5113		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5114		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5115		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5116		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5117		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5118		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5119
5120		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5121		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5122		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5123		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5124		if (BWN_HAS_LOOPBACK(phy)) {
5125			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5126			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5127			if (phy->rev >= 3)
5128				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5129			else
5130				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5131			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5132		}
5133
5134		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5135		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5136			BWN_LPD(0, 1, 1)));
5137		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5138		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5139	}
5140	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5141
5142	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5143	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5144	reg1 = BWN_READ_2(mac, 0x3e6);
5145	reg2 = BWN_READ_2(mac, 0x3f4);
5146
5147	if (phy->analog == 0)
5148		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5149	else {
5150		if (phy->analog >= 2)
5151			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5152		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5153		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5154	}
5155
5156	reg = BWN_RF_READ(mac, 0x60);
5157	index = (reg & 0x001e) >> 1;
5158	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5159
5160	if (phy->type == BWN_PHYTYPE_B)
5161		BWN_RF_WRITE(mac, 0x78, 0x26);
5162	if (phy->gmode || phy->rev >= 2) {
5163		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5164		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5165			BWN_LPD(0, 1, 1)));
5166	}
5167	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5168	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5169	if (phy->gmode || phy->rev >= 2) {
5170		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5171		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5172			BWN_LPD(0, 0, 1)));
5173	}
5174	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5175	BWN_RF_SET(mac, 0x51, 0x0004);
5176	if (phy->rf_rev == 8)
5177		BWN_RF_WRITE(mac, 0x43, 0x1f);
5178	else {
5179		BWN_RF_WRITE(mac, 0x52, 0);
5180		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5181	}
5182	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5183
5184	for (i = 0; i < 16; i++) {
5185		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5186		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5187		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5188		if (phy->gmode || phy->rev >= 2) {
5189			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190			    bwn_rf_2050_rfoverval(mac,
5191				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5192		}
5193		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5194		DELAY(10);
5195		if (phy->gmode || phy->rev >= 2) {
5196			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5197			    bwn_rf_2050_rfoverval(mac,
5198				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5199		}
5200		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5201		DELAY(10);
5202		if (phy->gmode || phy->rev >= 2) {
5203			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5204			    bwn_rf_2050_rfoverval(mac,
5205				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5206		}
5207		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5208		DELAY(20);
5209		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5210		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5211		if (phy->gmode || phy->rev >= 2) {
5212			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5213			    bwn_rf_2050_rfoverval(mac,
5214				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5215		}
5216		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5217	}
5218	DELAY(10);
5219
5220	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5221	tmp1++;
5222	tmp1 >>= 9;
5223
5224	for (i = 0; i < 16; i++) {
5225		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5226		BWN_RF_WRITE(mac, 0x78, radio78);
5227		DELAY(10);
5228		for (j = 0; j < 16; j++) {
5229			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5230			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5231			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5232			if (phy->gmode || phy->rev >= 2) {
5233				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5234				    bwn_rf_2050_rfoverval(mac,
5235					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5236			}
5237			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5238			DELAY(10);
5239			if (phy->gmode || phy->rev >= 2) {
5240				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5241				    bwn_rf_2050_rfoverval(mac,
5242					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5243			}
5244			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5245			DELAY(10);
5246			if (phy->gmode || phy->rev >= 2) {
5247				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5248				    bwn_rf_2050_rfoverval(mac,
5249					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5250			}
5251			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5252			DELAY(10);
5253			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5254			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5255			if (phy->gmode || phy->rev >= 2) {
5256				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257				    bwn_rf_2050_rfoverval(mac,
5258					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5259			}
5260			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5261		}
5262		tmp2++;
5263		tmp2 >>= 8;
5264		if (tmp1 < tmp2)
5265			break;
5266	}
5267
5268	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5269	BWN_RF_WRITE(mac, 0x51, radio1);
5270	BWN_RF_WRITE(mac, 0x52, radio2);
5271	BWN_RF_WRITE(mac, 0x43, radio0);
5272	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5273	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5274	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5275	BWN_WRITE_2(mac, 0x3e6, reg1);
5276	if (phy->analog != 0)
5277		BWN_WRITE_2(mac, 0x3f4, reg2);
5278	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5279	bwn_spu_workaround(mac, phy->chan);
5280	if (phy->type == BWN_PHYTYPE_B) {
5281		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5282		BWN_WRITE_2(mac, 0x3ec, reg0);
5283	} else if (phy->gmode) {
5284		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5285			    BWN_READ_2(mac, BWN_PHY_RADIO)
5286			    & 0x7fff);
5287		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5288		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5289		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5290		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5291			      analogoverval);
5292		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5293		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5294		if (BWN_HAS_LOOPBACK(phy)) {
5295			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5296			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5297		}
5298	}
5299
5300	return ((i > 15) ? radio78 : rcc);
5301}
5302
5303static void
5304bwn_phy_init_b6(struct bwn_mac *mac)
5305{
5306	struct bwn_phy *phy = &mac->mac_phy;
5307	struct bwn_phy_g *pg = &phy->phy_g;
5308	struct bwn_softc *sc = mac->mac_sc;
5309	uint16_t offset, val;
5310	uint8_t old_channel;
5311
5312	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5313	    ("%s:%d: fail", __func__, __LINE__));
5314
5315	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5316	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5317	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5318		BWN_RF_WRITE(mac, 0x51, 0x37);
5319		BWN_RF_WRITE(mac, 0x52, 0x70);
5320		BWN_RF_WRITE(mac, 0x53, 0xb3);
5321		BWN_RF_WRITE(mac, 0x54, 0x9b);
5322		BWN_RF_WRITE(mac, 0x5a, 0x88);
5323		BWN_RF_WRITE(mac, 0x5b, 0x88);
5324		BWN_RF_WRITE(mac, 0x5d, 0x88);
5325		BWN_RF_WRITE(mac, 0x5e, 0x88);
5326		BWN_RF_WRITE(mac, 0x7d, 0x88);
5327		bwn_hf_write(mac,
5328		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5329	}
5330	if (phy->rf_rev == 8) {
5331		BWN_RF_WRITE(mac, 0x51, 0);
5332		BWN_RF_WRITE(mac, 0x52, 0x40);
5333		BWN_RF_WRITE(mac, 0x53, 0xb7);
5334		BWN_RF_WRITE(mac, 0x54, 0x98);
5335		BWN_RF_WRITE(mac, 0x5a, 0x88);
5336		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5337		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5338		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5339			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5340			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5341		} else {
5342			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5343			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5344		}
5345		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5346		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5347		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5348		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5349	}
5350	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5351		BWN_PHY_WRITE(mac, offset, val);
5352		val -= 0x0202;
5353	}
5354	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5355		BWN_PHY_WRITE(mac, offset, val);
5356		val -= 0x0202;
5357	}
5358	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5359		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5360		val += 0x0202;
5361	}
5362	if (phy->type == BWN_PHYTYPE_G) {
5363		BWN_RF_SET(mac, 0x007a, 0x0020);
5364		BWN_RF_SET(mac, 0x0051, 0x0004);
5365		BWN_PHY_SET(mac, 0x0802, 0x0100);
5366		BWN_PHY_SET(mac, 0x042b, 0x2000);
5367		BWN_PHY_WRITE(mac, 0x5b, 0);
5368		BWN_PHY_WRITE(mac, 0x5c, 0);
5369	}
5370
5371	old_channel = phy->chan;
5372	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5373
5374	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5375	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5376	DELAY(40);
5377	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5378		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5379		BWN_RF_WRITE(mac, 0x50, 0x20);
5380	}
5381	if (phy->rf_rev <= 2) {
5382		BWN_RF_WRITE(mac, 0x7c, 0x20);
5383		BWN_RF_WRITE(mac, 0x5a, 0x70);
5384		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5385		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5386	}
5387	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5388
5389	bwn_phy_g_switch_chan(mac, old_channel, 0);
5390
5391	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5392	if (phy->rf_rev >= 6)
5393		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5394	else
5395		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5396	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5397	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5398	    pg->pg_txctl);
5399	if (phy->rf_rev <= 5)
5400		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5401	if (phy->rf_rev <= 2)
5402		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5403
5404	if (phy->analog == 4) {
5405		BWN_WRITE_2(mac, 0x3e4, 9);
5406		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5407	} else
5408		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5409	if (phy->type == BWN_PHYTYPE_B)
5410		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5411	else if (phy->type == BWN_PHYTYPE_G)
5412		BWN_WRITE_2(mac, 0x03e6, 0x0);
5413}
5414
5415static void
5416bwn_phy_init_a(struct bwn_mac *mac)
5417{
5418	struct bwn_phy *phy = &mac->mac_phy;
5419	struct bwn_softc *sc = mac->mac_sc;
5420
5421	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5422	    ("%s:%d: fail", __func__, __LINE__));
5423
5424	if (phy->rev >= 6) {
5425		if (phy->type == BWN_PHYTYPE_A)
5426			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5427		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5428			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5429		else
5430			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5431	}
5432
5433	bwn_wa_init(mac);
5434
5435	if (phy->type == BWN_PHYTYPE_G &&
5436	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5437		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5438}
5439
5440static void
5441bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5442{
5443	int i;
5444
5445	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5446		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5447}
5448
5449static void
5450bwn_wa_agc(struct bwn_mac *mac)
5451{
5452	struct bwn_phy *phy = &mac->mac_phy;
5453
5454	if (phy->rev == 1) {
5455		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5456		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5457		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5463		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5464	} else {
5465		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5466		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5467		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5468		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5469	}
5470
5471	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5472	    0x5700);
5473	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5474	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5475	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5476	BWN_RF_SET(mac, 0x7a, 0x0008);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5478	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5479	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5480	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5481	if (phy->rev == 1)
5482		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5483	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5484	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5485	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5491	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5492	if (phy->rev == 1) {
5493		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5494		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5495	} else {
5496		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5497		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5498		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5499		if (phy->rev >= 6) {
5500			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5501			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5502			    (uint16_t)~0xf000, 0x3000);
5503		}
5504	}
5505	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5506	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5507	if (phy->rev == 1) {
5508		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5509		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5510		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5511		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5512		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5513		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5516	} else {
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5521	}
5522	if (phy->rev >= 6) {
5523		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5524		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5525	}
5526	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5527}
5528
5529static void
5530bwn_wa_grev1(struct bwn_mac *mac)
5531{
5532	struct bwn_phy *phy = &mac->mac_phy;
5533	int i;
5534	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5535	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5536	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5537
5538	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5539
5540	/* init CRSTHRES and ANTDWELL */
5541	if (phy->rev == 1) {
5542		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5543	} else if (phy->rev == 2) {
5544		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5545		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5546		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5547	} else {
5548		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5549		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5550		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5551		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5552	}
5553	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5554	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5555	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5556
5557	/* XXX support PHY-A??? */
5558	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5559		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5560		    bwn_tab_finefreqg[i]);
5561
5562	/* XXX support PHY-A??? */
5563	if (phy->rev == 1)
5564		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5565			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5566			    bwn_tab_noise_g1[i]);
5567	else
5568		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5569			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570			    bwn_tab_noise_g2[i]);
5571
5572
5573	for (i = 0; i < N(bwn_tab_rotor); i++)
5574		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5575		    bwn_tab_rotor[i]);
5576
5577	/* XXX support PHY-A??? */
5578	if (phy->rev >= 6) {
5579		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5580		    BWN_PHY_ENCORE_EN)
5581			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5582		else
5583			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5584	} else
5585		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5586
5587	for (i = 0; i < N(bwn_tab_retard); i++)
5588		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5589		    bwn_tab_retard[i]);
5590
5591	if (phy->rev == 1) {
5592		for (i = 0; i < 16; i++)
5593			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5594			    i, 0x0020);
5595	} else {
5596		for (i = 0; i < 32; i++)
5597			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5598	}
5599
5600	bwn_wa_agc(mac);
5601}
5602
5603static void
5604bwn_wa_grev26789(struct bwn_mac *mac)
5605{
5606	struct bwn_phy *phy = &mac->mac_phy;
5607	int i;
5608	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5609	uint16_t ofdmrev;
5610
5611	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5612
5613	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5614
5615	/* init CRSTHRES and ANTDWELL */
5616	if (phy->rev == 1)
5617		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5618	else if (phy->rev == 2) {
5619		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5620		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5621		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5622	} else {
5623		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5624		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5625		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5626		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5627	}
5628
5629	for (i = 0; i < 64; i++)
5630		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5631
5632	/* XXX support PHY-A??? */
5633	if (phy->rev == 1)
5634		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5635			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5636			    bwn_tab_noise_g1[i]);
5637	else
5638		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5639			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640			    bwn_tab_noise_g2[i]);
5641
5642	/* XXX support PHY-A??? */
5643	if (phy->rev >= 6) {
5644		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5645		    BWN_PHY_ENCORE_EN)
5646			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5647		else
5648			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5649	} else
5650		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5651
5652	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5653		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5654		    bwn_tab_sigmasqr2[i]);
5655
5656	if (phy->rev == 1) {
5657		for (i = 0; i < 16; i++)
5658			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5659			    0x0020);
5660	} else {
5661		for (i = 0; i < 32; i++)
5662			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5663	}
5664
5665	bwn_wa_agc(mac);
5666
5667	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5668	if (ofdmrev > 2) {
5669		if (phy->type == BWN_PHYTYPE_A)
5670			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5671		else
5672			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5673	} else {
5674		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5675		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5676		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5677	}
5678
5679	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5680	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5681}
5682
5683static void
5684bwn_wa_init(struct bwn_mac *mac)
5685{
5686	struct bwn_phy *phy = &mac->mac_phy;
5687	struct bwn_softc *sc = mac->mac_sc;
5688
5689	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5690
5691	switch (phy->rev) {
5692	case 1:
5693		bwn_wa_grev1(mac);
5694		break;
5695	case 2:
5696	case 6:
5697	case 7:
5698	case 8:
5699	case 9:
5700		bwn_wa_grev26789(mac);
5701		break;
5702	default:
5703		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5704	}
5705
5706	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5707	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5708	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5709		if (phy->rev < 2) {
5710			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5711			    0x0002);
5712			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5713			    0x0001);
5714		} else {
5715			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5716			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5717			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5718			     BWN_BFL_EXTLNA) &&
5719			    (phy->rev >= 7)) {
5720				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5721				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5722				    0x0020, 0x0001);
5723				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5724				    0x0021, 0x0001);
5725				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726				    0x0022, 0x0001);
5727				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728				    0x0023, 0x0000);
5729				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730				    0x0000, 0x0000);
5731				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732				    0x0003, 0x0002);
5733			}
5734		}
5735	}
5736	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5737		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5738		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5739	}
5740
5741	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5742	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5743}
5744
5745static void
5746bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5747    uint16_t value)
5748{
5749	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5750	uint16_t addr;
5751
5752	addr = table + offset;
5753	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5754	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5755		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5756		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5757	}
5758	pg->pg_ofdmtab_addr = addr;
5759	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5760}
5761
5762static void
5763bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5764    uint32_t value)
5765{
5766	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5767	uint16_t addr;
5768
5769	addr = table + offset;
5770	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5771	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5772		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5773		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5774	}
5775	pg->pg_ofdmtab_addr = addr;
5776
5777	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5778	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5779}
5780
5781static void
5782bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5783    uint16_t value)
5784{
5785
5786	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5787	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5788}
5789
5790static void
5791bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5792{
5793	struct bwn_phy *phy = &mac->mac_phy;
5794	struct bwn_softc *sc = mac->mac_sc;
5795	unsigned int i, max_loop;
5796	uint16_t value;
5797	uint32_t buffer[5] = {
5798		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5799	};
5800
5801	if (ofdm) {
5802		max_loop = 0x1e;
5803		buffer[0] = 0x000201cc;
5804	} else {
5805		max_loop = 0xfa;
5806		buffer[0] = 0x000b846e;
5807	}
5808
5809	BWN_ASSERT_LOCKED(mac->mac_sc);
5810
5811	for (i = 0; i < 5; i++)
5812		bwn_ram_write(mac, i * 4, buffer[i]);
5813
5814	BWN_WRITE_2(mac, 0x0568, 0x0000);
5815	BWN_WRITE_2(mac, 0x07c0,
5816	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5817	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5818	BWN_WRITE_2(mac, 0x050c, value);
5819	if (phy->type == BWN_PHYTYPE_LP)
5820		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5821	BWN_WRITE_2(mac, 0x0508, 0x0000);
5822	BWN_WRITE_2(mac, 0x050a, 0x0000);
5823	BWN_WRITE_2(mac, 0x054c, 0x0000);
5824	BWN_WRITE_2(mac, 0x056a, 0x0014);
5825	BWN_WRITE_2(mac, 0x0568, 0x0826);
5826	BWN_WRITE_2(mac, 0x0500, 0x0000);
5827	if (phy->type == BWN_PHYTYPE_LP)
5828		BWN_WRITE_2(mac, 0x0502, 0x0050);
5829	else
5830		BWN_WRITE_2(mac, 0x0502, 0x0030);
5831
5832	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5833		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5834	for (i = 0x00; i < max_loop; i++) {
5835		value = BWN_READ_2(mac, 0x050e);
5836		if (value & 0x0080)
5837			break;
5838		DELAY(10);
5839	}
5840	for (i = 0x00; i < 0x0a; i++) {
5841		value = BWN_READ_2(mac, 0x050e);
5842		if (value & 0x0400)
5843			break;
5844		DELAY(10);
5845	}
5846	for (i = 0x00; i < 0x19; i++) {
5847		value = BWN_READ_2(mac, 0x0690);
5848		if (!(value & 0x0100))
5849			break;
5850		DELAY(10);
5851	}
5852	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5853		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5854}
5855
5856static void
5857bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5858{
5859	uint32_t macctl;
5860
5861	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5862
5863	macctl = BWN_READ_4(mac, BWN_MACCTL);
5864	if (macctl & BWN_MACCTL_BIGENDIAN)
5865		printf("TODO: need swap\n");
5866
5867	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5868	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5869	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5870}
5871
5872static void
5873bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5874{
5875	uint16_t value;
5876
5877	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5878	    ("%s:%d: fail", __func__, __LINE__));
5879
5880	value = (uint8_t) (ctl->q);
5881	value |= ((uint8_t) (ctl->i)) << 8;
5882	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5883}
5884
5885static uint16_t
5886bwn_lo_calcfeed(struct bwn_mac *mac,
5887    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5888{
5889	struct bwn_phy *phy = &mac->mac_phy;
5890	struct bwn_softc *sc = mac->mac_sc;
5891	uint16_t rfover;
5892	uint16_t feedthrough;
5893
5894	if (phy->gmode) {
5895		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5896		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5897
5898		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5899		    ("%s:%d: fail", __func__, __LINE__));
5900		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5901		    ("%s:%d: fail", __func__, __LINE__));
5902
5903		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5904
5905		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5906		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5907		    phy->rev > 6)
5908			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5909
5910		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5911		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912		DELAY(10);
5913		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5914		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915		DELAY(10);
5916		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5917		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5918		DELAY(10);
5919		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5920	} else {
5921		pga |= BWN_PHY_PGACTL_UNKNOWN;
5922		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923		DELAY(10);
5924		pga |= BWN_PHY_PGACTL_LOWBANDW;
5925		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926		DELAY(10);
5927		pga |= BWN_PHY_PGACTL_LPF;
5928		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5929	}
5930	DELAY(21);
5931	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5932
5933	return (feedthrough);
5934}
5935
5936static uint16_t
5937bwn_lo_txctl_regtable(struct bwn_mac *mac,
5938    uint16_t *value, uint16_t *pad_mix_gain)
5939{
5940	struct bwn_phy *phy = &mac->mac_phy;
5941	uint16_t reg, v, padmix;
5942
5943	if (phy->type == BWN_PHYTYPE_B) {
5944		v = 0x30;
5945		if (phy->rf_rev <= 5) {
5946			reg = 0x43;
5947			padmix = 0;
5948		} else {
5949			reg = 0x52;
5950			padmix = 5;
5951		}
5952	} else {
5953		if (phy->rev >= 2 && phy->rf_rev == 8) {
5954			reg = 0x43;
5955			v = 0x10;
5956			padmix = 2;
5957		} else {
5958			reg = 0x52;
5959			v = 0x30;
5960			padmix = 5;
5961		}
5962	}
5963	if (value)
5964		*value = v;
5965	if (pad_mix_gain)
5966		*pad_mix_gain = padmix;
5967
5968	return (reg);
5969}
5970
5971static void
5972bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5973{
5974	struct bwn_phy *phy = &mac->mac_phy;
5975	struct bwn_phy_g *pg = &phy->phy_g;
5976	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5977	uint16_t reg, mask;
5978	uint16_t trsw_rx, pga;
5979	uint16_t rf_pctl_reg;
5980
5981	static const uint8_t tx_bias_values[] = {
5982		0x09, 0x08, 0x0a, 0x01, 0x00,
5983		0x02, 0x05, 0x04, 0x06,
5984	};
5985	static const uint8_t tx_magn_values[] = {
5986		0x70, 0x40,
5987	};
5988
5989	if (!BWN_HAS_LOOPBACK(phy)) {
5990		rf_pctl_reg = 6;
5991		trsw_rx = 2;
5992		pga = 0;
5993	} else {
5994		int lb_gain;
5995
5996		trsw_rx = 0;
5997		lb_gain = pg->pg_max_lb_gain / 2;
5998		if (lb_gain > 10) {
5999			rf_pctl_reg = 0;
6000			pga = abs(10 - lb_gain) / 6;
6001			pga = MIN(MAX(pga, 0), 15);
6002		} else {
6003			int cmp_val;
6004			int tmp;
6005
6006			pga = 0;
6007			cmp_val = 0x24;
6008			if ((phy->rev >= 2) &&
6009			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6010				cmp_val = 0x3c;
6011			tmp = lb_gain;
6012			if ((10 - lb_gain) < cmp_val)
6013				tmp = (10 - lb_gain);
6014			if (tmp < 0)
6015				tmp += 6;
6016			else
6017				tmp += 3;
6018			cmp_val /= 4;
6019			tmp /= 4;
6020			if (tmp >= cmp_val)
6021				rf_pctl_reg = cmp_val;
6022			else
6023				rf_pctl_reg = tmp;
6024		}
6025	}
6026	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6027	bwn_phy_g_set_bbatt(mac, 2);
6028
6029	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6030	mask = ~mask;
6031	BWN_RF_MASK(mac, reg, mask);
6032
6033	if (BWN_HAS_TXMAG(phy)) {
6034		int i, j;
6035		int feedthrough;
6036		int min_feedth = 0xffff;
6037		uint8_t tx_magn, tx_bias;
6038
6039		for (i = 0; i < N(tx_magn_values); i++) {
6040			tx_magn = tx_magn_values[i];
6041			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6042			for (j = 0; j < N(tx_bias_values); j++) {
6043				tx_bias = tx_bias_values[j];
6044				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6045				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6046				    trsw_rx);
6047				if (feedthrough < min_feedth) {
6048					lo->tx_bias = tx_bias;
6049					lo->tx_magn = tx_magn;
6050					min_feedth = feedthrough;
6051				}
6052				if (lo->tx_bias == 0)
6053					break;
6054			}
6055			BWN_RF_WRITE(mac, 0x52,
6056					  (BWN_RF_READ(mac, 0x52)
6057					   & 0xff00) | lo->tx_bias | lo->
6058					  tx_magn);
6059		}
6060	} else {
6061		lo->tx_magn = 0;
6062		lo->tx_bias = 0;
6063		BWN_RF_MASK(mac, 0x52, 0xfff0);
6064	}
6065
6066	BWN_GETTIME(lo->txctl_measured_time);
6067}
6068
6069static void
6070bwn_lo_get_powervector(struct bwn_mac *mac)
6071{
6072	struct bwn_phy *phy = &mac->mac_phy;
6073	struct bwn_phy_g *pg = &phy->phy_g;
6074	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6075	int i;
6076	uint64_t tmp;
6077	uint64_t power_vector = 0;
6078
6079	for (i = 0; i < 8; i += 2) {
6080		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6081		power_vector |= (tmp << (i * 8));
6082		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6083	}
6084	if (power_vector)
6085		lo->power_vector = power_vector;
6086
6087	BWN_GETTIME(lo->pwr_vec_read_time);
6088}
6089
6090static void
6091bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6092    int use_trsw_rx)
6093{
6094	struct bwn_phy *phy = &mac->mac_phy;
6095	struct bwn_phy_g *pg = &phy->phy_g;
6096	uint16_t tmp;
6097
6098	if (max_rx_gain < 0)
6099		max_rx_gain = 0;
6100
6101	if (BWN_HAS_LOOPBACK(phy)) {
6102		int trsw_rx = 0;
6103		int trsw_rx_gain;
6104
6105		if (use_trsw_rx) {
6106			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6107			if (max_rx_gain >= trsw_rx_gain) {
6108				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6109				trsw_rx = 0x20;
6110			}
6111		} else
6112			trsw_rx_gain = max_rx_gain;
6113		if (trsw_rx_gain < 9) {
6114			pg->pg_lna_lod_gain = 0;
6115		} else {
6116			pg->pg_lna_lod_gain = 1;
6117			trsw_rx_gain -= 8;
6118		}
6119		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6120		pg->pg_pga_gain = trsw_rx_gain / 3;
6121		if (pg->pg_pga_gain >= 5) {
6122			pg->pg_pga_gain -= 5;
6123			pg->pg_lna_gain = 2;
6124		} else
6125			pg->pg_lna_gain = 0;
6126	} else {
6127		pg->pg_lna_gain = 0;
6128		pg->pg_trsw_rx_gain = 0x20;
6129		if (max_rx_gain >= 0x14) {
6130			pg->pg_lna_lod_gain = 1;
6131			pg->pg_pga_gain = 2;
6132		} else if (max_rx_gain >= 0x12) {
6133			pg->pg_lna_lod_gain = 1;
6134			pg->pg_pga_gain = 1;
6135		} else if (max_rx_gain >= 0xf) {
6136			pg->pg_lna_lod_gain = 1;
6137			pg->pg_pga_gain = 0;
6138		} else {
6139			pg->pg_lna_lod_gain = 0;
6140			pg->pg_pga_gain = 0;
6141		}
6142	}
6143
6144	tmp = BWN_RF_READ(mac, 0x7a);
6145	if (pg->pg_lna_lod_gain == 0)
6146		tmp &= ~0x0008;
6147	else
6148		tmp |= 0x0008;
6149	BWN_RF_WRITE(mac, 0x7a, tmp);
6150}
6151
6152static void
6153bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6154{
6155	struct bwn_phy *phy = &mac->mac_phy;
6156	struct bwn_phy_g *pg = &phy->phy_g;
6157	struct bwn_softc *sc = mac->mac_sc;
6158	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6159	struct timespec ts;
6160	uint16_t tmp;
6161
6162	if (bwn_has_hwpctl(mac)) {
6163		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6164		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6165		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6166		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6167		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6168
6169		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6170		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6171		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6172		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6173	}
6174	if (phy->type == BWN_PHYTYPE_B &&
6175	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6176		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6177		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6178	}
6179	if (phy->rev >= 2) {
6180		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6181		sav->phy_analogoverval =
6182		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6183		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6184		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6185		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6186		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6187		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6188
6189		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6190		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6191		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6192		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6193		if (phy->type == BWN_PHYTYPE_G) {
6194			if ((phy->rev >= 7) &&
6195			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6196			     BWN_BFL_EXTLNA)) {
6197				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6198			} else {
6199				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6200			}
6201		} else {
6202			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6203		}
6204		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6205	}
6206	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6207	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6208	sav->rf0 = BWN_RF_READ(mac, 0x43);
6209	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6210	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6211	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6212	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6213	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6214
6215	if (!BWN_HAS_TXMAG(phy)) {
6216		sav->rf2 = BWN_RF_READ(mac, 0x52);
6217		sav->rf2 &= 0x00f0;
6218	}
6219	if (phy->type == BWN_PHYTYPE_B) {
6220		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6221		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6222		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6223		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6224	} else {
6225		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6226			    | 0x8000);
6227	}
6228	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6229		    & 0xf000);
6230
6231	tmp =
6232	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6233	BWN_PHY_WRITE(mac, tmp, 0x007f);
6234
6235	tmp = sav->phy_syncctl;
6236	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6237	tmp = sav->rf1;
6238	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6239
6240	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6241	if (phy->type == BWN_PHYTYPE_G ||
6242	    (phy->type == BWN_PHYTYPE_B &&
6243	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6244		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6245	} else
6246		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6247	if (phy->rev >= 2)
6248		bwn_dummy_transmission(mac, 0, 1);
6249	bwn_phy_g_switch_chan(mac, 6, 0);
6250	BWN_RF_READ(mac, 0x51);
6251	if (phy->type == BWN_PHYTYPE_G)
6252		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6253
6254	nanouptime(&ts);
6255	if (time_before(lo->txctl_measured_time,
6256	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6257		bwn_lo_measure_txctl_values(mac);
6258
6259	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6260		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6261	else {
6262		if (phy->type == BWN_PHYTYPE_B)
6263			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6264		else
6265			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6266	}
6267}
6268
6269static void
6270bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6271{
6272	struct bwn_phy *phy = &mac->mac_phy;
6273	struct bwn_phy_g *pg = &phy->phy_g;
6274	uint16_t tmp;
6275
6276	if (phy->rev >= 2) {
6277		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6278		tmp = (pg->pg_pga_gain << 8);
6279		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6280		DELAY(5);
6281		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6282		DELAY(2);
6283		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6284	} else {
6285		tmp = (pg->pg_pga_gain | 0xefa0);
6286		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6287	}
6288	if (phy->type == BWN_PHYTYPE_G) {
6289		if (phy->rev >= 3)
6290			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6291		else
6292			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6293		if (phy->rev >= 2)
6294			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6295		else
6296			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6297	}
6298	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6299	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6300	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6301	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6302	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6303	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6304	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6305	if (!BWN_HAS_TXMAG(phy)) {
6306		tmp = sav->rf2;
6307		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6308	}
6309	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6310	if (phy->type == BWN_PHYTYPE_B &&
6311	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6312		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6313		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6314	}
6315	if (phy->rev >= 2) {
6316		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6317		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6318			      sav->phy_analogoverval);
6319		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6320		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6321		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6322		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6323		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6324	}
6325	if (bwn_has_hwpctl(mac)) {
6326		tmp = (sav->phy_lomask & 0xbfff);
6327		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6328		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6329		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6330		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6331		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6332	}
6333	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6334}
6335
6336static int
6337bwn_lo_probe_loctl(struct bwn_mac *mac,
6338    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6339{
6340	struct bwn_phy *phy = &mac->mac_phy;
6341	struct bwn_phy_g *pg = &phy->phy_g;
6342	struct bwn_loctl orig, test;
6343	struct bwn_loctl prev = { -100, -100 };
6344	static const struct bwn_loctl modifiers[] = {
6345		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6346		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6347	};
6348	int begin, end, lower = 0, i;
6349	uint16_t feedth;
6350
6351	if (d->curstate == 0) {
6352		begin = 1;
6353		end = 8;
6354	} else if (d->curstate % 2 == 0) {
6355		begin = d->curstate - 1;
6356		end = d->curstate + 1;
6357	} else {
6358		begin = d->curstate - 2;
6359		end = d->curstate + 2;
6360	}
6361	if (begin < 1)
6362		begin += 8;
6363	if (end > 8)
6364		end -= 8;
6365
6366	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6367	i = begin;
6368	d->curstate = i;
6369	while (1) {
6370		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6371		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6372		test.i += modifiers[i - 1].i * d->multipler;
6373		test.q += modifiers[i - 1].q * d->multipler;
6374		if ((test.i != prev.i || test.q != prev.q) &&
6375		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6376			bwn_lo_write(mac, &test);
6377			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6378			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6379			if (feedth < d->feedth) {
6380				memcpy(probe, &test,
6381				    sizeof(struct bwn_loctl));
6382				lower = 1;
6383				d->feedth = feedth;
6384				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6385					break;
6386			}
6387		}
6388		memcpy(&prev, &test, sizeof(prev));
6389		if (i == end)
6390			break;
6391		if (i == 8)
6392			i = 1;
6393		else
6394			i++;
6395		d->curstate = i;
6396	}
6397
6398	return (lower);
6399}
6400
6401static void
6402bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6403{
6404	struct bwn_phy *phy = &mac->mac_phy;
6405	struct bwn_phy_g *pg = &phy->phy_g;
6406	struct bwn_lo_g_sm d;
6407	struct bwn_loctl probe;
6408	int lower, repeat, cnt = 0;
6409	uint16_t feedth;
6410
6411	d.nmeasure = 0;
6412	d.multipler = 1;
6413	if (BWN_HAS_LOOPBACK(phy))
6414		d.multipler = 3;
6415
6416	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6417	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6418
6419	do {
6420		bwn_lo_write(mac, &d.loctl);
6421		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6422		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6423		if (feedth < 0x258) {
6424			if (feedth >= 0x12c)
6425				*rxgain += 6;
6426			else
6427				*rxgain += 3;
6428			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6429			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6430		}
6431		d.feedth = feedth;
6432		d.curstate = 0;
6433		do {
6434			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6435			    ("%s:%d: fail", __func__, __LINE__));
6436			memcpy(&probe, &d.loctl,
6437			       sizeof(struct bwn_loctl));
6438			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6439			if (!lower)
6440				break;
6441			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6442				break;
6443			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6444			d.nmeasure++;
6445		} while (d.nmeasure < 24);
6446		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6447
6448		if (BWN_HAS_LOOPBACK(phy)) {
6449			if (d.feedth > 0x1194)
6450				*rxgain -= 6;
6451			else if (d.feedth < 0x5dc)
6452				*rxgain += 3;
6453			if (cnt == 0) {
6454				if (d.feedth <= 0x5dc) {
6455					d.multipler = 1;
6456					cnt++;
6457				} else
6458					d.multipler = 2;
6459			} else if (cnt == 2)
6460				d.multipler = 1;
6461		}
6462		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6463	} while (++cnt < repeat);
6464}
6465
6466static struct bwn_lo_calib *
6467bwn_lo_calibset(struct bwn_mac *mac,
6468    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6469{
6470	struct bwn_phy *phy = &mac->mac_phy;
6471	struct bwn_phy_g *pg = &phy->phy_g;
6472	struct bwn_loctl loctl = { 0, 0 };
6473	struct bwn_lo_calib *cal;
6474	struct bwn_lo_g_value sval = { 0 };
6475	int rxgain;
6476	uint16_t pad, reg, value;
6477
6478	sval.old_channel = phy->chan;
6479	bwn_mac_suspend(mac);
6480	bwn_lo_save(mac, &sval);
6481
6482	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6483	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6484	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6485
6486	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6487	if (rfatt->padmix)
6488		rxgain -= pad;
6489	if (BWN_HAS_LOOPBACK(phy))
6490		rxgain += pg->pg_max_lb_gain;
6491	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6492	bwn_phy_g_set_bbatt(mac, bbatt->att);
6493	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6494
6495	bwn_lo_restore(mac, &sval);
6496	bwn_mac_enable(mac);
6497
6498	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6499	if (!cal) {
6500		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6501		return (NULL);
6502	}
6503	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6504	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6505	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6506
6507	BWN_GETTIME(cal->calib_time);
6508
6509	return (cal);
6510}
6511
6512static struct bwn_lo_calib *
6513bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6514    const struct bwn_rfatt *rfatt)
6515{
6516	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6517	struct bwn_lo_calib *c;
6518
6519	TAILQ_FOREACH(c, &lo->calib_list, list) {
6520		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6521			continue;
6522		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6523			continue;
6524		return (c);
6525	}
6526
6527	c = bwn_lo_calibset(mac, bbatt, rfatt);
6528	if (!c)
6529		return (NULL);
6530	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6531
6532	return (c);
6533}
6534
6535static void
6536bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6537{
6538	struct bwn_phy *phy = &mac->mac_phy;
6539	struct bwn_phy_g *pg = &phy->phy_g;
6540	struct bwn_softc *sc = mac->mac_sc;
6541	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6542	const struct bwn_rfatt *rfatt;
6543	const struct bwn_bbatt *bbatt;
6544	uint64_t pvector;
6545	int i;
6546	int rf_offset, bb_offset;
6547	uint8_t changed = 0;
6548
6549	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6550	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6551	    ("%s:%d: fail", __func__, __LINE__));
6552
6553	pvector = lo->power_vector;
6554	if (!update && !pvector)
6555		return;
6556
6557	bwn_mac_suspend(mac);
6558
6559	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6560		struct bwn_lo_calib *cal;
6561		int idx;
6562		uint16_t val;
6563
6564		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6565			continue;
6566		bb_offset = i / lo->rfatt.len;
6567		rf_offset = i % lo->rfatt.len;
6568		bbatt = &(lo->bbatt.array[bb_offset]);
6569		rfatt = &(lo->rfatt.array[rf_offset]);
6570
6571		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6572		if (!cal) {
6573			device_printf(sc->sc_dev, "LO: Could not "
6574			    "calibrate DC table entry\n");
6575			continue;
6576		}
6577		val = (uint8_t)(cal->ctl.q);
6578		val |= ((uint8_t)(cal->ctl.i)) << 4;
6579		free(cal, M_DEVBUF);
6580
6581		idx = i / 2;
6582		if (i % 2)
6583			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6584			    | ((val & 0x00ff) << 8);
6585		else
6586			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6587			    | (val & 0x00ff);
6588		changed = 1;
6589	}
6590	if (changed) {
6591		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6592			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6593	}
6594	bwn_mac_enable(mac);
6595}
6596
6597static void
6598bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6599{
6600
6601	if (!rf->padmix)
6602		return;
6603	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6604		rf->att = 4;
6605}
6606
6607static void
6608bwn_lo_g_adjust(struct bwn_mac *mac)
6609{
6610	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6611	struct bwn_lo_calib *cal;
6612	struct bwn_rfatt rf;
6613
6614	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6615	bwn_lo_fixup_rfatt(&rf);
6616
6617	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6618	if (!cal)
6619		return;
6620	bwn_lo_write(mac, &cal->ctl);
6621}
6622
6623static void
6624bwn_lo_g_init(struct bwn_mac *mac)
6625{
6626
6627	if (!bwn_has_hwpctl(mac))
6628		return;
6629
6630	bwn_lo_get_powervector(mac);
6631	bwn_phy_g_dc_lookup_init(mac, 1);
6632}
6633
6634static void
6635bwn_mac_suspend(struct bwn_mac *mac)
6636{
6637	struct bwn_softc *sc = mac->mac_sc;
6638	int i;
6639	uint32_t tmp;
6640
6641	KASSERT(mac->mac_suspended >= 0,
6642	    ("%s:%d: fail", __func__, __LINE__));
6643
6644	if (mac->mac_suspended == 0) {
6645		bwn_psctl(mac, BWN_PS_AWAKE);
6646		BWN_WRITE_4(mac, BWN_MACCTL,
6647			    BWN_READ_4(mac, BWN_MACCTL)
6648			    & ~BWN_MACCTL_ON);
6649		BWN_READ_4(mac, BWN_MACCTL);
6650		for (i = 35; i; i--) {
6651			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6652			if (tmp & BWN_INTR_MAC_SUSPENDED)
6653				goto out;
6654			DELAY(10);
6655		}
6656		for (i = 40; i; i--) {
6657			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6658			if (tmp & BWN_INTR_MAC_SUSPENDED)
6659				goto out;
6660			DELAY(1000);
6661		}
6662		device_printf(sc->sc_dev, "MAC suspend failed\n");
6663	}
6664out:
6665	mac->mac_suspended++;
6666}
6667
6668static void
6669bwn_mac_enable(struct bwn_mac *mac)
6670{
6671	struct bwn_softc *sc = mac->mac_sc;
6672	uint16_t state;
6673
6674	state = bwn_shm_read_2(mac, BWN_SHARED,
6675	    BWN_SHARED_UCODESTAT);
6676	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6677	    state != BWN_SHARED_UCODESTAT_SLEEP)
6678		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6679
6680	mac->mac_suspended--;
6681	KASSERT(mac->mac_suspended >= 0,
6682	    ("%s:%d: fail", __func__, __LINE__));
6683	if (mac->mac_suspended == 0) {
6684		BWN_WRITE_4(mac, BWN_MACCTL,
6685		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6686		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6687		BWN_READ_4(mac, BWN_MACCTL);
6688		BWN_READ_4(mac, BWN_INTR_REASON);
6689		bwn_psctl(mac, 0);
6690	}
6691}
6692
6693static void
6694bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6695{
6696	struct bwn_softc *sc = mac->mac_sc;
6697	int i;
6698	uint16_t ucstat;
6699
6700	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6701	    ("%s:%d: fail", __func__, __LINE__));
6702	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6703	    ("%s:%d: fail", __func__, __LINE__));
6704
6705	/* XXX forcibly awake and hwps-off */
6706
6707	BWN_WRITE_4(mac, BWN_MACCTL,
6708	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6709	    ~BWN_MACCTL_HWPS);
6710	BWN_READ_4(mac, BWN_MACCTL);
6711	if (siba_get_revid(sc->sc_dev) >= 5) {
6712		for (i = 0; i < 100; i++) {
6713			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6714			    BWN_SHARED_UCODESTAT);
6715			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6716				break;
6717			DELAY(10);
6718		}
6719	}
6720}
6721
6722static int16_t
6723bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6724{
6725
6726	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6727	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6728}
6729
6730static void
6731bwn_nrssi_threshold(struct bwn_mac *mac)
6732{
6733	struct bwn_phy *phy = &mac->mac_phy;
6734	struct bwn_phy_g *pg = &phy->phy_g;
6735	struct bwn_softc *sc = mac->mac_sc;
6736	int32_t a, b;
6737	int16_t tmp16;
6738	uint16_t tmpu16;
6739
6740	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6741
6742	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6743		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6744			a = 0x13;
6745			b = 0x12;
6746		} else {
6747			a = 0xe;
6748			b = 0x11;
6749		}
6750
6751		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6752		a += (pg->pg_nrssi[0] << 6);
6753		a += (a < 32) ? 31 : 32;
6754		a = a >> 6;
6755		a = MIN(MAX(a, -31), 31);
6756
6757		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6758		b += (pg->pg_nrssi[0] << 6);
6759		if (b < 32)
6760			b += 31;
6761		else
6762			b += 32;
6763		b = b >> 6;
6764		b = MIN(MAX(b, -31), 31);
6765
6766		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6767		tmpu16 |= ((uint32_t)b & 0x0000003f);
6768		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6769		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6770		return;
6771	}
6772
6773	tmp16 = bwn_nrssi_read(mac, 0x20);
6774	if (tmp16 >= 0x20)
6775		tmp16 -= 0x40;
6776	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6777}
6778
6779static void
6780bwn_nrssi_slope_11g(struct bwn_mac *mac)
6781{
6782#define	SAVE_RF_MAX		3
6783#define	SAVE_PHY_COMM_MAX	4
6784#define	SAVE_PHY3_MAX		8
6785	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6786		{ 0x7a, 0x52, 0x43 };
6787	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6788		{ 0x15, 0x5a, 0x59, 0x58 };
6789	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6790		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6791		0x0801, 0x0060, 0x0014, 0x0478
6792	};
6793	struct bwn_phy *phy = &mac->mac_phy;
6794	struct bwn_phy_g *pg = &phy->phy_g;
6795	int32_t i, tmp32, phy3_idx = 0;
6796	uint16_t delta, tmp;
6797	uint16_t save_rf[SAVE_RF_MAX];
6798	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6799	uint16_t save_phy3[SAVE_PHY3_MAX];
6800	uint16_t ant_div, phy0, chan_ex;
6801	int16_t nrssi0, nrssi1;
6802
6803	KASSERT(phy->type == BWN_PHYTYPE_G,
6804	    ("%s:%d: fail", __func__, __LINE__));
6805
6806	if (phy->rf_rev >= 9)
6807		return;
6808	if (phy->rf_rev == 8)
6809		bwn_nrssi_offset(mac);
6810
6811	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6812	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6813
6814	/*
6815	 * Save RF/PHY registers for later restoration
6816	 */
6817	ant_div = BWN_READ_2(mac, 0x03e2);
6818	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6819	for (i = 0; i < SAVE_RF_MAX; ++i)
6820		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6821	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6822		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6823
6824	phy0 = BWN_READ_2(mac, BWN_PHY0);
6825	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6826	if (phy->rev >= 3) {
6827		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6828			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6829		BWN_PHY_WRITE(mac, 0x002e, 0);
6830		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6831		switch (phy->rev) {
6832		case 4:
6833		case 6:
6834		case 7:
6835			BWN_PHY_SET(mac, 0x0478, 0x0100);
6836			BWN_PHY_SET(mac, 0x0801, 0x0040);
6837			break;
6838		case 3:
6839		case 5:
6840			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6841			break;
6842		}
6843		BWN_PHY_SET(mac, 0x0060, 0x0040);
6844		BWN_PHY_SET(mac, 0x0014, 0x0200);
6845	}
6846	/*
6847	 * Calculate nrssi0
6848	 */
6849	BWN_RF_SET(mac, 0x007a, 0x0070);
6850	bwn_set_all_gains(mac, 0, 8, 0);
6851	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6852	if (phy->rev >= 2) {
6853		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6854		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6855	}
6856	BWN_RF_SET(mac, 0x007a, 0x0080);
6857	DELAY(20);
6858
6859	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6860	if (nrssi0 >= 0x0020)
6861		nrssi0 -= 0x0040;
6862
6863	/*
6864	 * Calculate nrssi1
6865	 */
6866	BWN_RF_MASK(mac, 0x007a, 0x007f);
6867	if (phy->rev >= 2)
6868		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6869
6870	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6871	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6872	BWN_RF_SET(mac, 0x007a, 0x000f);
6873	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6874	if (phy->rev >= 2) {
6875		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6876		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6877	}
6878
6879	bwn_set_all_gains(mac, 3, 0, 1);
6880	if (phy->rf_rev == 8) {
6881		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6882	} else {
6883		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6884		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6885		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6886		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6887	}
6888	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6889	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6890	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6891	DELAY(20);
6892	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6893
6894	/*
6895	 * Install calculated narrow RSSI values
6896	 */
6897	if (nrssi1 >= 0x0020)
6898		nrssi1 -= 0x0040;
6899	if (nrssi0 == nrssi1)
6900		pg->pg_nrssi_slope = 0x00010000;
6901	else
6902		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6903	if (nrssi0 >= -4) {
6904		pg->pg_nrssi[0] = nrssi1;
6905		pg->pg_nrssi[1] = nrssi0;
6906	}
6907
6908	/*
6909	 * Restore saved RF/PHY registers
6910	 */
6911	if (phy->rev >= 3) {
6912		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6913			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6914			    save_phy3[phy3_idx]);
6915		}
6916	}
6917	if (phy->rev >= 2) {
6918		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6919		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6920	}
6921
6922	for (i = 0; i < SAVE_RF_MAX; ++i)
6923		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6924
6925	BWN_WRITE_2(mac, 0x03e2, ant_div);
6926	BWN_WRITE_2(mac, 0x03e6, phy0);
6927	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6928
6929	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6930		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6931
6932	bwn_spu_workaround(mac, phy->chan);
6933	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6934	bwn_set_original_gains(mac);
6935	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6936	if (phy->rev >= 3) {
6937		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6938			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6939			    save_phy3[phy3_idx]);
6940		}
6941	}
6942
6943	delta = 0x1f - pg->pg_nrssi[0];
6944	for (i = 0; i < 64; i++) {
6945		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6946		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6947		pg->pg_nrssi_lt[i] = tmp32;
6948	}
6949
6950	bwn_nrssi_threshold(mac);
6951#undef SAVE_RF_MAX
6952#undef SAVE_PHY_COMM_MAX
6953#undef SAVE_PHY3_MAX
6954}
6955
6956static void
6957bwn_nrssi_offset(struct bwn_mac *mac)
6958{
6959#define	SAVE_RF_MAX		2
6960#define	SAVE_PHY_COMM_MAX	10
6961#define	SAVE_PHY6_MAX		8
6962	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6963		{ 0x7a, 0x43 };
6964	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6965		0x0001, 0x0811, 0x0812, 0x0814,
6966		0x0815, 0x005a, 0x0059, 0x0058,
6967		0x000a, 0x0003
6968	};
6969	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6970		0x002e, 0x002f, 0x080f, 0x0810,
6971		0x0801, 0x0060, 0x0014, 0x0478
6972	};
6973	struct bwn_phy *phy = &mac->mac_phy;
6974	int i, phy6_idx = 0;
6975	uint16_t save_rf[SAVE_RF_MAX];
6976	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6977	uint16_t save_phy6[SAVE_PHY6_MAX];
6978	int16_t nrssi;
6979	uint16_t saved = 0xffff;
6980
6981	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6982		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6983	for (i = 0; i < SAVE_RF_MAX; ++i)
6984		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6985
6986	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6987	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6988	BWN_PHY_SET(mac, 0x0811, 0x000c);
6989	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6990	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6991	if (phy->rev >= 6) {
6992		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6993			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6994
6995		BWN_PHY_WRITE(mac, 0x002e, 0);
6996		BWN_PHY_WRITE(mac, 0x002f, 0);
6997		BWN_PHY_WRITE(mac, 0x080f, 0);
6998		BWN_PHY_WRITE(mac, 0x0810, 0);
6999		BWN_PHY_SET(mac, 0x0478, 0x0100);
7000		BWN_PHY_SET(mac, 0x0801, 0x0040);
7001		BWN_PHY_SET(mac, 0x0060, 0x0040);
7002		BWN_PHY_SET(mac, 0x0014, 0x0200);
7003	}
7004	BWN_RF_SET(mac, 0x007a, 0x0070);
7005	BWN_RF_SET(mac, 0x007a, 0x0080);
7006	DELAY(30);
7007
7008	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7009	if (nrssi >= 0x20)
7010		nrssi -= 0x40;
7011	if (nrssi == 31) {
7012		for (i = 7; i >= 4; i--) {
7013			BWN_RF_WRITE(mac, 0x007b, i);
7014			DELAY(20);
7015			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7016			    0x003f);
7017			if (nrssi >= 0x20)
7018				nrssi -= 0x40;
7019			if (nrssi < 31 && saved == 0xffff)
7020				saved = i;
7021		}
7022		if (saved == 0xffff)
7023			saved = 4;
7024	} else {
7025		BWN_RF_MASK(mac, 0x007a, 0x007f);
7026		if (phy->rev != 1) {
7027			BWN_PHY_SET(mac, 0x0814, 0x0001);
7028			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7029		}
7030		BWN_PHY_SET(mac, 0x0811, 0x000c);
7031		BWN_PHY_SET(mac, 0x0812, 0x000c);
7032		BWN_PHY_SET(mac, 0x0811, 0x0030);
7033		BWN_PHY_SET(mac, 0x0812, 0x0030);
7034		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7035		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7036		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7037		if (phy->rev == 0)
7038			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7039		else
7040			BWN_PHY_SET(mac, 0x000a, 0x2000);
7041		if (phy->rev != 1) {
7042			BWN_PHY_SET(mac, 0x0814, 0x0004);
7043			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7044		}
7045		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7046		BWN_RF_SET(mac, 0x007a, 0x000f);
7047		bwn_set_all_gains(mac, 3, 0, 1);
7048		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7049		DELAY(30);
7050		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7051		if (nrssi >= 0x20)
7052			nrssi -= 0x40;
7053		if (nrssi == -32) {
7054			for (i = 0; i < 4; i++) {
7055				BWN_RF_WRITE(mac, 0x007b, i);
7056				DELAY(20);
7057				nrssi = (int16_t)((BWN_PHY_READ(mac,
7058				    0x047f) >> 8) & 0x003f);
7059				if (nrssi >= 0x20)
7060					nrssi -= 0x40;
7061				if (nrssi > -31 && saved == 0xffff)
7062					saved = i;
7063			}
7064			if (saved == 0xffff)
7065				saved = 3;
7066		} else
7067			saved = 0;
7068	}
7069	BWN_RF_WRITE(mac, 0x007b, saved);
7070
7071	/*
7072	 * Restore saved RF/PHY registers
7073	 */
7074	if (phy->rev >= 6) {
7075		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7076			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7077			    save_phy6[phy6_idx]);
7078		}
7079	}
7080	if (phy->rev != 1) {
7081		for (i = 3; i < 5; i++)
7082			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7083			    save_phy_comm[i]);
7084	}
7085	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7086		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7087
7088	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7089		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7090
7091	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7092	BWN_PHY_SET(mac, 0x0429, 0x8000);
7093	bwn_set_original_gains(mac);
7094	if (phy->rev >= 6) {
7095		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7096			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7097			    save_phy6[phy6_idx]);
7098		}
7099	}
7100
7101	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7102	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7103	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7104}
7105
7106static void
7107bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7108    int16_t third)
7109{
7110	struct bwn_phy *phy = &mac->mac_phy;
7111	uint16_t i;
7112	uint16_t start = 0x08, end = 0x18;
7113	uint16_t tmp;
7114	uint16_t table;
7115
7116	if (phy->rev <= 1) {
7117		start = 0x10;
7118		end = 0x20;
7119	}
7120
7121	table = BWN_OFDMTAB_GAINX;
7122	if (phy->rev <= 1)
7123		table = BWN_OFDMTAB_GAINX_R1;
7124	for (i = 0; i < 4; i++)
7125		bwn_ofdmtab_write_2(mac, table, i, first);
7126
7127	for (i = start; i < end; i++)
7128		bwn_ofdmtab_write_2(mac, table, i, second);
7129
7130	if (third != -1) {
7131		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7132		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7133		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7134		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7135	}
7136	bwn_dummy_transmission(mac, 0, 1);
7137}
7138
7139static void
7140bwn_set_original_gains(struct bwn_mac *mac)
7141{
7142	struct bwn_phy *phy = &mac->mac_phy;
7143	uint16_t i, tmp;
7144	uint16_t table;
7145	uint16_t start = 0x0008, end = 0x0018;
7146
7147	if (phy->rev <= 1) {
7148		start = 0x0010;
7149		end = 0x0020;
7150	}
7151
7152	table = BWN_OFDMTAB_GAINX;
7153	if (phy->rev <= 1)
7154		table = BWN_OFDMTAB_GAINX_R1;
7155	for (i = 0; i < 4; i++) {
7156		tmp = (i & 0xfffc);
7157		tmp |= (i & 0x0001) << 1;
7158		tmp |= (i & 0x0002) >> 1;
7159
7160		bwn_ofdmtab_write_2(mac, table, i, tmp);
7161	}
7162
7163	for (i = start; i < end; i++)
7164		bwn_ofdmtab_write_2(mac, table, i, i - start);
7165
7166	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7167	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7168	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7169	bwn_dummy_transmission(mac, 0, 1);
7170}
7171
7172static void
7173bwn_phy_hwpctl_init(struct bwn_mac *mac)
7174{
7175	struct bwn_phy *phy = &mac->mac_phy;
7176	struct bwn_phy_g *pg = &phy->phy_g;
7177	struct bwn_rfatt old_rfatt, rfatt;
7178	struct bwn_bbatt old_bbatt, bbatt;
7179	struct bwn_softc *sc = mac->mac_sc;
7180	uint8_t old_txctl = 0;
7181
7182	KASSERT(phy->type == BWN_PHYTYPE_G,
7183	    ("%s:%d: fail", __func__, __LINE__));
7184
7185	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7186	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7187		return;
7188
7189	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7190
7191	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7192
7193	if (!phy->gmode)
7194		return;
7195	bwn_hwpctl_early_init(mac);
7196	if (pg->pg_curtssi == 0) {
7197		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7198			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7199		} else {
7200			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7201			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7202			old_txctl = pg->pg_txctl;
7203
7204			bbatt.att = 11;
7205			if (phy->rf_rev == 8) {
7206				rfatt.att = 15;
7207				rfatt.padmix = 1;
7208			} else {
7209				rfatt.att = 9;
7210				rfatt.padmix = 0;
7211			}
7212			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7213		}
7214		bwn_dummy_transmission(mac, 0, 1);
7215		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7216		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7217			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7218		else
7219			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7220			    &old_rfatt, old_txctl);
7221	}
7222	bwn_hwpctl_init_gphy(mac);
7223
7224	/* clear TSSI */
7225	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7226	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7227	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7228	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7229}
7230
7231static void
7232bwn_hwpctl_early_init(struct bwn_mac *mac)
7233{
7234	struct bwn_phy *phy = &mac->mac_phy;
7235
7236	if (!bwn_has_hwpctl(mac)) {
7237		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7238		return;
7239	}
7240
7241	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7242	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7243	BWN_PHY_SET(mac, 0x047c, 0x0002);
7244	BWN_PHY_SET(mac, 0x047a, 0xf000);
7245	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7246		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7247		BWN_PHY_SET(mac, 0x005d, 0x8000);
7248		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7249		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7250		BWN_PHY_SET(mac, 0x0036, 0x0400);
7251	} else {
7252		BWN_PHY_SET(mac, 0x0036, 0x0200);
7253		BWN_PHY_SET(mac, 0x0036, 0x0400);
7254		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7255		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7256		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7257		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7258		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7259	}
7260}
7261
7262static void
7263bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7264{
7265	struct bwn_phy *phy = &mac->mac_phy;
7266	struct bwn_phy_g *pg = &phy->phy_g;
7267	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7268	int i;
7269	uint16_t nr_written = 0, tmp, value;
7270	uint8_t rf, bb;
7271
7272	if (!bwn_has_hwpctl(mac)) {
7273		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7274		return;
7275	}
7276
7277	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7278	    (pg->pg_idletssi - pg->pg_curtssi));
7279	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7280	    (pg->pg_idletssi - pg->pg_curtssi));
7281
7282	for (i = 0; i < 32; i++)
7283		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7284	for (i = 32; i < 64; i++)
7285		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7286	for (i = 0; i < 64; i += 2) {
7287		value = (uint16_t) pg->pg_tssi2dbm[i];
7288		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7289		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7290	}
7291
7292	for (rf = 0; rf < lo->rfatt.len; rf++) {
7293		for (bb = 0; bb < lo->bbatt.len; bb++) {
7294			if (nr_written >= 0x40)
7295				return;
7296			tmp = lo->bbatt.array[bb].att;
7297			tmp <<= 8;
7298			if (phy->rf_rev == 8)
7299				tmp |= 0x50;
7300			else
7301				tmp |= 0x40;
7302			tmp |= lo->rfatt.array[rf].att;
7303			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7304			nr_written++;
7305		}
7306	}
7307
7308	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7309	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7310
7311	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7312	BWN_PHY_SET(mac, 0x0478, 0x0800);
7313	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7314	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7315
7316	bwn_phy_g_dc_lookup_init(mac, 1);
7317	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7318}
7319
7320static void
7321bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7322{
7323	struct bwn_softc *sc = mac->mac_sc;
7324
7325	if (spu != 0)
7326		bwn_spu_workaround(mac, channel);
7327
7328	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7329
7330	if (channel == 14) {
7331		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7332			bwn_hf_write(mac,
7333			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7334		else
7335			bwn_hf_write(mac,
7336			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7337		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7338		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7339		return;
7340	}
7341
7342	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7343	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7344}
7345
7346static uint16_t
7347bwn_phy_g_chan2freq(uint8_t channel)
7348{
7349	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7350
7351	KASSERT(channel >= 1 && channel <= 14,
7352	    ("%s:%d: fail", __func__, __LINE__));
7353
7354	return (bwn_phy_g_rf_channels[channel - 1]);
7355}
7356
7357static void
7358bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7359    const struct bwn_rfatt *rfatt, uint8_t txctl)
7360{
7361	struct bwn_phy *phy = &mac->mac_phy;
7362	struct bwn_phy_g *pg = &phy->phy_g;
7363	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7364	uint16_t bb, rf;
7365	uint16_t tx_bias, tx_magn;
7366
7367	bb = bbatt->att;
7368	rf = rfatt->att;
7369	tx_bias = lo->tx_bias;
7370	tx_magn = lo->tx_magn;
7371	if (tx_bias == 0xff)
7372		tx_bias = 0;
7373
7374	pg->pg_txctl = txctl;
7375	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7376	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7377	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7378	bwn_phy_g_set_bbatt(mac, bb);
7379	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7380	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7381		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7382	else {
7383		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7384		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7385	}
7386	if (BWN_HAS_TXMAG(phy))
7387		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7388	else
7389		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7390	bwn_lo_g_adjust(mac);
7391}
7392
7393static void
7394bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7395    uint16_t bbatt)
7396{
7397	struct bwn_phy *phy = &mac->mac_phy;
7398
7399	if (phy->analog == 0) {
7400		BWN_WRITE_2(mac, BWN_PHY0,
7401		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7402		return;
7403	}
7404	if (phy->analog > 1) {
7405		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7406		return;
7407	}
7408	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7409}
7410
7411static uint16_t
7412bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7413{
7414	struct bwn_phy *phy = &mac->mac_phy;
7415	struct bwn_phy_g *pg = &phy->phy_g;
7416	struct bwn_softc *sc = mac->mac_sc;
7417	int max_lb_gain;
7418	uint16_t extlna;
7419	uint16_t i;
7420
7421	if (phy->gmode == 0)
7422		return (0);
7423
7424	if (BWN_HAS_LOOPBACK(phy)) {
7425		max_lb_gain = pg->pg_max_lb_gain;
7426		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7427		if (max_lb_gain >= 0x46) {
7428			extlna = 0x3000;
7429			max_lb_gain -= 0x46;
7430		} else if (max_lb_gain >= 0x3a) {
7431			extlna = 0x1000;
7432			max_lb_gain -= 0x3a;
7433		} else if (max_lb_gain >= 0x2e) {
7434			extlna = 0x2000;
7435			max_lb_gain -= 0x2e;
7436		} else {
7437			extlna = 0;
7438			max_lb_gain -= 0x10;
7439		}
7440
7441		for (i = 0; i < 16; i++) {
7442			max_lb_gain -= (i * 6);
7443			if (max_lb_gain < 6)
7444				break;
7445		}
7446
7447		if ((phy->rev < 7) ||
7448		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7449			if (reg == BWN_PHY_RFOVER) {
7450				return (0x1b3);
7451			} else if (reg == BWN_PHY_RFOVERVAL) {
7452				extlna |= (i << 8);
7453				switch (lpd) {
7454				case BWN_LPD(0, 1, 1):
7455					return (0x0f92);
7456				case BWN_LPD(0, 0, 1):
7457				case BWN_LPD(1, 0, 1):
7458					return (0x0092 | extlna);
7459				case BWN_LPD(1, 0, 0):
7460					return (0x0093 | extlna);
7461				}
7462				KASSERT(0 == 1,
7463				    ("%s:%d: fail", __func__, __LINE__));
7464			}
7465			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7466		} else {
7467			if (reg == BWN_PHY_RFOVER)
7468				return (0x9b3);
7469			if (reg == BWN_PHY_RFOVERVAL) {
7470				if (extlna)
7471					extlna |= 0x8000;
7472				extlna |= (i << 8);
7473				switch (lpd) {
7474				case BWN_LPD(0, 1, 1):
7475					return (0x8f92);
7476				case BWN_LPD(0, 0, 1):
7477					return (0x8092 | extlna);
7478				case BWN_LPD(1, 0, 1):
7479					return (0x2092 | extlna);
7480				case BWN_LPD(1, 0, 0):
7481					return (0x2093 | extlna);
7482				}
7483				KASSERT(0 == 1,
7484				    ("%s:%d: fail", __func__, __LINE__));
7485			}
7486			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7487		}
7488		return (0);
7489	}
7490
7491	if ((phy->rev < 7) ||
7492	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7493		if (reg == BWN_PHY_RFOVER) {
7494			return (0x1b3);
7495		} else if (reg == BWN_PHY_RFOVERVAL) {
7496			switch (lpd) {
7497			case BWN_LPD(0, 1, 1):
7498				return (0x0fb2);
7499			case BWN_LPD(0, 0, 1):
7500				return (0x00b2);
7501			case BWN_LPD(1, 0, 1):
7502				return (0x30b2);
7503			case BWN_LPD(1, 0, 0):
7504				return (0x30b3);
7505			}
7506			KASSERT(0 == 1,
7507			    ("%s:%d: fail", __func__, __LINE__));
7508		}
7509		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7510	} else {
7511		if (reg == BWN_PHY_RFOVER) {
7512			return (0x9b3);
7513		} else if (reg == BWN_PHY_RFOVERVAL) {
7514			switch (lpd) {
7515			case BWN_LPD(0, 1, 1):
7516				return (0x8fb2);
7517			case BWN_LPD(0, 0, 1):
7518				return (0x80b2);
7519			case BWN_LPD(1, 0, 1):
7520				return (0x20b2);
7521			case BWN_LPD(1, 0, 0):
7522				return (0x20b3);
7523			}
7524			KASSERT(0 == 1,
7525			    ("%s:%d: fail", __func__, __LINE__));
7526		}
7527		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7528	}
7529	return (0);
7530}
7531
7532static void
7533bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7534{
7535
7536	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7537		return;
7538	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7539	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7540	DELAY(1000);
7541	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7542}
7543
7544static int
7545bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7546{
7547	struct bwn_softc *sc = mac->mac_sc;
7548	struct bwn_fw *fw = &mac->mac_fw;
7549	const uint8_t rev = siba_get_revid(sc->sc_dev);
7550	const char *filename;
7551	uint32_t high;
7552	int error;
7553
7554	/* microcode */
7555	if (rev >= 5 && rev <= 10)
7556		filename = "ucode5";
7557	else if (rev >= 11 && rev <= 12)
7558		filename = "ucode11";
7559	else if (rev == 13)
7560		filename = "ucode13";
7561	else if (rev == 14)
7562		filename = "ucode14";
7563	else if (rev >= 15)
7564		filename = "ucode15";
7565	else {
7566		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7567		bwn_release_firmware(mac);
7568		return (EOPNOTSUPP);
7569	}
7570	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7571	if (error) {
7572		bwn_release_firmware(mac);
7573		return (error);
7574	}
7575
7576	/* PCM */
7577	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7578	if (rev >= 5 && rev <= 10) {
7579		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7580		if (error == ENOENT)
7581			fw->no_pcmfile = 1;
7582		else if (error) {
7583			bwn_release_firmware(mac);
7584			return (error);
7585		}
7586	} else if (rev < 11) {
7587		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7588		return (EOPNOTSUPP);
7589	}
7590
7591	/* initvals */
7592	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7593	switch (mac->mac_phy.type) {
7594	case BWN_PHYTYPE_A:
7595		if (rev < 5 || rev > 10)
7596			goto fail1;
7597		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7598			filename = "a0g1initvals5";
7599		else
7600			filename = "a0g0initvals5";
7601		break;
7602	case BWN_PHYTYPE_G:
7603		if (rev >= 5 && rev <= 10)
7604			filename = "b0g0initvals5";
7605		else if (rev >= 13)
7606			filename = "b0g0initvals13";
7607		else
7608			goto fail1;
7609		break;
7610	case BWN_PHYTYPE_LP:
7611		if (rev == 13)
7612			filename = "lp0initvals13";
7613		else if (rev == 14)
7614			filename = "lp0initvals14";
7615		else if (rev >= 15)
7616			filename = "lp0initvals15";
7617		else
7618			goto fail1;
7619		break;
7620	case BWN_PHYTYPE_N:
7621		if (rev >= 11 && rev <= 12)
7622			filename = "n0initvals11";
7623		else
7624			goto fail1;
7625		break;
7626	default:
7627		goto fail1;
7628	}
7629	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7630	if (error) {
7631		bwn_release_firmware(mac);
7632		return (error);
7633	}
7634
7635	/* bandswitch initvals */
7636	switch (mac->mac_phy.type) {
7637	case BWN_PHYTYPE_A:
7638		if (rev >= 5 && rev <= 10) {
7639			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7640				filename = "a0g1bsinitvals5";
7641			else
7642				filename = "a0g0bsinitvals5";
7643		} else if (rev >= 11)
7644			filename = NULL;
7645		else
7646			goto fail1;
7647		break;
7648	case BWN_PHYTYPE_G:
7649		if (rev >= 5 && rev <= 10)
7650			filename = "b0g0bsinitvals5";
7651		else if (rev >= 11)
7652			filename = NULL;
7653		else
7654			goto fail1;
7655		break;
7656	case BWN_PHYTYPE_LP:
7657		if (rev == 13)
7658			filename = "lp0bsinitvals13";
7659		else if (rev == 14)
7660			filename = "lp0bsinitvals14";
7661		else if (rev >= 15)
7662			filename = "lp0bsinitvals15";
7663		else
7664			goto fail1;
7665		break;
7666	case BWN_PHYTYPE_N:
7667		if (rev >= 11 && rev <= 12)
7668			filename = "n0bsinitvals11";
7669		else
7670			goto fail1;
7671		break;
7672	default:
7673		goto fail1;
7674	}
7675	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7676	if (error) {
7677		bwn_release_firmware(mac);
7678		return (error);
7679	}
7680	return (0);
7681fail1:
7682	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7683	bwn_release_firmware(mac);
7684	return (EOPNOTSUPP);
7685}
7686
7687static int
7688bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7689    const char *name, struct bwn_fwfile *bfw)
7690{
7691	const struct bwn_fwhdr *hdr;
7692	struct bwn_softc *sc = mac->mac_sc;
7693	const struct firmware *fw;
7694	char namebuf[64];
7695
7696	if (name == NULL) {
7697		bwn_do_release_fw(bfw);
7698		return (0);
7699	}
7700	if (bfw->filename != NULL) {
7701		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7702			return (0);
7703		bwn_do_release_fw(bfw);
7704	}
7705
7706	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7707	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7708	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7709	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7710	fw = firmware_get(namebuf);
7711	if (fw == NULL) {
7712		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7713		    namebuf);
7714		return (ENOENT);
7715	}
7716	if (fw->datasize < sizeof(struct bwn_fwhdr))
7717		goto fail;
7718	hdr = (const struct bwn_fwhdr *)(fw->data);
7719	switch (hdr->type) {
7720	case BWN_FWTYPE_UCODE:
7721	case BWN_FWTYPE_PCM:
7722		if (be32toh(hdr->size) !=
7723		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7724			goto fail;
7725		/* FALLTHROUGH */
7726	case BWN_FWTYPE_IV:
7727		if (hdr->ver != 1)
7728			goto fail;
7729		break;
7730	default:
7731		goto fail;
7732	}
7733	bfw->filename = name;
7734	bfw->fw = fw;
7735	bfw->type = type;
7736	return (0);
7737fail:
7738	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7739	if (fw != NULL)
7740		firmware_put(fw, FIRMWARE_UNLOAD);
7741	return (EPROTO);
7742}
7743
7744static void
7745bwn_release_firmware(struct bwn_mac *mac)
7746{
7747
7748	bwn_do_release_fw(&mac->mac_fw.ucode);
7749	bwn_do_release_fw(&mac->mac_fw.pcm);
7750	bwn_do_release_fw(&mac->mac_fw.initvals);
7751	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7752}
7753
7754static void
7755bwn_do_release_fw(struct bwn_fwfile *bfw)
7756{
7757
7758	if (bfw->fw != NULL)
7759		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7760	bfw->fw = NULL;
7761	bfw->filename = NULL;
7762}
7763
7764static int
7765bwn_fw_loaducode(struct bwn_mac *mac)
7766{
7767#define	GETFWOFFSET(fwp, offset)	\
7768	((const uint32_t *)((const char *)fwp.fw->data + offset))
7769#define	GETFWSIZE(fwp, offset)	\
7770	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7771	struct bwn_softc *sc = mac->mac_sc;
7772	const uint32_t *data;
7773	unsigned int i;
7774	uint32_t ctl;
7775	uint16_t date, fwcaps, time;
7776	int error = 0;
7777
7778	ctl = BWN_READ_4(mac, BWN_MACCTL);
7779	ctl |= BWN_MACCTL_MCODE_JMP0;
7780	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7781	    __LINE__));
7782	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7783	for (i = 0; i < 64; i++)
7784		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7785	for (i = 0; i < 4096; i += 2)
7786		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7787
7788	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7789	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7790	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7791	     i++) {
7792		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7793		DELAY(10);
7794	}
7795
7796	if (mac->mac_fw.pcm.fw) {
7797		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7798		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7799		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7800		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7801		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7802		    sizeof(struct bwn_fwhdr)); i++) {
7803			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7804			DELAY(10);
7805		}
7806	}
7807
7808	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7809	BWN_WRITE_4(mac, BWN_MACCTL,
7810	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7811	    BWN_MACCTL_MCODE_RUN);
7812
7813	for (i = 0; i < 21; i++) {
7814		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7815			break;
7816		if (i >= 20) {
7817			device_printf(sc->sc_dev, "ucode timeout\n");
7818			error = ENXIO;
7819			goto error;
7820		}
7821		DELAY(50000);
7822	}
7823	BWN_READ_4(mac, BWN_INTR_REASON);
7824
7825	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7826	if (mac->mac_fw.rev <= 0x128) {
7827		device_printf(sc->sc_dev, "the firmware is too old\n");
7828		error = EOPNOTSUPP;
7829		goto error;
7830	}
7831	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7832	    BWN_SHARED_UCODE_PATCH);
7833	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7834	mac->mac_fw.opensource = (date == 0xffff);
7835	if (bwn_wme != 0)
7836		mac->mac_flags |= BWN_MAC_FLAG_WME;
7837	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7838
7839	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7840	if (mac->mac_fw.opensource == 0) {
7841		device_printf(sc->sc_dev,
7842		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7843		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7844		if (mac->mac_fw.no_pcmfile)
7845			device_printf(sc->sc_dev,
7846			    "no HW crypto acceleration due to pcm5\n");
7847	} else {
7848		mac->mac_fw.patch = time;
7849		fwcaps = bwn_fwcaps_read(mac);
7850		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7851			device_printf(sc->sc_dev,
7852			    "disabling HW crypto acceleration\n");
7853			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7854		}
7855		if (!(fwcaps & BWN_FWCAPS_WME)) {
7856			device_printf(sc->sc_dev, "disabling WME support\n");
7857			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7858		}
7859	}
7860
7861	if (BWN_ISOLDFMT(mac))
7862		device_printf(sc->sc_dev, "using old firmware image\n");
7863
7864	return (0);
7865
7866error:
7867	BWN_WRITE_4(mac, BWN_MACCTL,
7868	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7869	    BWN_MACCTL_MCODE_JMP0);
7870
7871	return (error);
7872#undef GETFWSIZE
7873#undef GETFWOFFSET
7874}
7875
7876/* OpenFirmware only */
7877static uint16_t
7878bwn_fwcaps_read(struct bwn_mac *mac)
7879{
7880
7881	KASSERT(mac->mac_fw.opensource == 1,
7882	    ("%s:%d: fail", __func__, __LINE__));
7883	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7884}
7885
7886static int
7887bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7888    size_t count, size_t array_size)
7889{
7890#define	GET_NEXTIV16(iv)						\
7891	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7892	    sizeof(uint16_t) + sizeof(uint16_t)))
7893#define	GET_NEXTIV32(iv)						\
7894	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7895	    sizeof(uint16_t) + sizeof(uint32_t)))
7896	struct bwn_softc *sc = mac->mac_sc;
7897	const struct bwn_fwinitvals *iv;
7898	uint16_t offset;
7899	size_t i;
7900	uint8_t bit32;
7901
7902	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7903	    ("%s:%d: fail", __func__, __LINE__));
7904	iv = ivals;
7905	for (i = 0; i < count; i++) {
7906		if (array_size < sizeof(iv->offset_size))
7907			goto fail;
7908		array_size -= sizeof(iv->offset_size);
7909		offset = be16toh(iv->offset_size);
7910		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7911		offset &= BWN_FWINITVALS_OFFSET_MASK;
7912		if (offset >= 0x1000)
7913			goto fail;
7914		if (bit32) {
7915			if (array_size < sizeof(iv->data.d32))
7916				goto fail;
7917			array_size -= sizeof(iv->data.d32);
7918			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7919			iv = GET_NEXTIV32(iv);
7920		} else {
7921
7922			if (array_size < sizeof(iv->data.d16))
7923				goto fail;
7924			array_size -= sizeof(iv->data.d16);
7925			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7926
7927			iv = GET_NEXTIV16(iv);
7928		}
7929	}
7930	if (array_size != 0)
7931		goto fail;
7932	return (0);
7933fail:
7934	device_printf(sc->sc_dev, "initvals: invalid format\n");
7935	return (EPROTO);
7936#undef GET_NEXTIV16
7937#undef GET_NEXTIV32
7938}
7939
7940static int
7941bwn_switch_channel(struct bwn_mac *mac, int chan)
7942{
7943	struct bwn_phy *phy = &(mac->mac_phy);
7944	struct bwn_softc *sc = mac->mac_sc;
7945	struct ifnet *ifp = sc->sc_ifp;
7946	struct ieee80211com *ic = ifp->if_l2com;
7947	uint16_t channelcookie, savedcookie;
7948	int error;
7949
7950	if (chan == 0xffff)
7951		chan = phy->get_default_chan(mac);
7952
7953	channelcookie = chan;
7954	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7955		channelcookie |= 0x100;
7956	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7957	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7958	error = phy->switch_channel(mac, chan);
7959	if (error)
7960		goto fail;
7961
7962	mac->mac_phy.chan = chan;
7963	DELAY(8000);
7964	return (0);
7965fail:
7966	device_printf(sc->sc_dev, "failed to switch channel\n");
7967	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7968	return (error);
7969}
7970
7971static uint16_t
7972bwn_ant2phy(int antenna)
7973{
7974
7975	switch (antenna) {
7976	case BWN_ANT0:
7977		return (BWN_TX_PHY_ANT0);
7978	case BWN_ANT1:
7979		return (BWN_TX_PHY_ANT1);
7980	case BWN_ANT2:
7981		return (BWN_TX_PHY_ANT2);
7982	case BWN_ANT3:
7983		return (BWN_TX_PHY_ANT3);
7984	case BWN_ANTAUTO:
7985		return (BWN_TX_PHY_ANT01AUTO);
7986	}
7987	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7988	return (0);
7989}
7990
7991static void
7992bwn_wme_load(struct bwn_mac *mac)
7993{
7994	struct bwn_softc *sc = mac->mac_sc;
7995	int i;
7996
7997	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7998	    ("%s:%d: fail", __func__, __LINE__));
7999
8000	bwn_mac_suspend(mac);
8001	for (i = 0; i < N(sc->sc_wmeParams); i++)
8002		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8003		    bwn_wme_shm_offsets[i]);
8004	bwn_mac_enable(mac);
8005}
8006
8007static void
8008bwn_wme_loadparams(struct bwn_mac *mac,
8009    const struct wmeParams *p, uint16_t shm_offset)
8010{
8011#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8012	struct bwn_softc *sc = mac->mac_sc;
8013	uint16_t params[BWN_NR_WMEPARAMS];
8014	int slot, tmp;
8015	unsigned int i;
8016
8017	slot = BWN_READ_2(mac, BWN_RNG) &
8018	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8019
8020	memset(&params, 0, sizeof(params));
8021
8022	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8023	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8024	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8025
8026	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8027	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8028	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8029	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8030	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8031	params[BWN_WMEPARAM_BSLOTS] = slot;
8032	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8033
8034	for (i = 0; i < N(params); i++) {
8035		if (i == BWN_WMEPARAM_STATUS) {
8036			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8037			    shm_offset + (i * 2));
8038			tmp |= 0x100;
8039			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040			    tmp);
8041		} else {
8042			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8043			    params[i]);
8044		}
8045	}
8046}
8047
8048static void
8049bwn_mac_write_bssid(struct bwn_mac *mac)
8050{
8051	struct bwn_softc *sc = mac->mac_sc;
8052	uint32_t tmp;
8053	int i;
8054	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8055
8056	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8057	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8058	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8059	    IEEE80211_ADDR_LEN);
8060
8061	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8062		tmp = (uint32_t) (mac_bssid[i + 0]);
8063		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8064		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8065		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8066		bwn_ram_write(mac, 0x20 + i, tmp);
8067	}
8068}
8069
8070static void
8071bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8072    const uint8_t *macaddr)
8073{
8074	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8075	uint16_t data;
8076
8077	if (!mac)
8078		macaddr = zero;
8079
8080	offset |= 0x0020;
8081	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8082
8083	data = macaddr[0];
8084	data |= macaddr[1] << 8;
8085	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086	data = macaddr[2];
8087	data |= macaddr[3] << 8;
8088	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089	data = macaddr[4];
8090	data |= macaddr[5] << 8;
8091	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8092}
8093
8094static void
8095bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8096    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8097{
8098	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8099	uint8_t per_sta_keys_start = 8;
8100
8101	if (BWN_SEC_NEWAPI(mac))
8102		per_sta_keys_start = 4;
8103
8104	KASSERT(index < mac->mac_max_nr_keys,
8105	    ("%s:%d: fail", __func__, __LINE__));
8106	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8107	    ("%s:%d: fail", __func__, __LINE__));
8108
8109	if (index >= per_sta_keys_start)
8110		bwn_key_macwrite(mac, index, NULL);
8111	if (key)
8112		memcpy(buf, key, key_len);
8113	bwn_key_write(mac, index, algorithm, buf);
8114	if (index >= per_sta_keys_start)
8115		bwn_key_macwrite(mac, index, mac_addr);
8116
8117	mac->mac_key[index].algorithm = algorithm;
8118}
8119
8120static void
8121bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8122{
8123	struct bwn_softc *sc = mac->mac_sc;
8124	uint32_t addrtmp[2] = { 0, 0 };
8125	uint8_t start = 8;
8126
8127	if (BWN_SEC_NEWAPI(mac))
8128		start = 4;
8129
8130	KASSERT(index >= start,
8131	    ("%s:%d: fail", __func__, __LINE__));
8132	index -= start;
8133
8134	if (addr) {
8135		addrtmp[0] = addr[0];
8136		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8137		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8138		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8139		addrtmp[1] = addr[4];
8140		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8141	}
8142
8143	if (siba_get_revid(sc->sc_dev) >= 5) {
8144		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8145		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8146	} else {
8147		if (index >= 8) {
8148			bwn_shm_write_4(mac, BWN_SHARED,
8149			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8150			bwn_shm_write_2(mac, BWN_SHARED,
8151			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8152		}
8153	}
8154}
8155
8156static void
8157bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8158    const uint8_t *key)
8159{
8160	unsigned int i;
8161	uint32_t offset;
8162	uint16_t kidx, value;
8163
8164	kidx = BWN_SEC_KEY2FW(mac, index);
8165	bwn_shm_write_2(mac, BWN_SHARED,
8166	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8167
8168	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8169	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8170		value = key[i];
8171		value |= (uint16_t)(key[i + 1]) << 8;
8172		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8173	}
8174}
8175
8176static void
8177bwn_phy_exit(struct bwn_mac *mac)
8178{
8179
8180	mac->mac_phy.rf_onoff(mac, 0);
8181	if (mac->mac_phy.exit != NULL)
8182		mac->mac_phy.exit(mac);
8183}
8184
8185static void
8186bwn_dma_free(struct bwn_mac *mac)
8187{
8188	struct bwn_dma *dma;
8189
8190	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8191		return;
8192	dma = &mac->mac_method.dma;
8193
8194	bwn_dma_ringfree(&dma->rx);
8195	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8196	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8197	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8198	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8199	bwn_dma_ringfree(&dma->mcast);
8200}
8201
8202static void
8203bwn_core_stop(struct bwn_mac *mac)
8204{
8205	struct bwn_softc *sc = mac->mac_sc;
8206
8207	BWN_ASSERT_LOCKED(sc);
8208
8209	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8210		return;
8211
8212	callout_stop(&sc->sc_rfswitch_ch);
8213	callout_stop(&sc->sc_task_ch);
8214	callout_stop(&sc->sc_watchdog_ch);
8215	sc->sc_watchdog_timer = 0;
8216	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8217	BWN_READ_4(mac, BWN_INTR_MASK);
8218	bwn_mac_suspend(mac);
8219
8220	mac->mac_status = BWN_MAC_STATUS_INITED;
8221}
8222
8223static int
8224bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8225{
8226	struct bwn_mac *up_dev = NULL;
8227	struct bwn_mac *down_dev;
8228	struct bwn_mac *mac;
8229	int err, status;
8230	uint8_t gmode;
8231
8232	BWN_ASSERT_LOCKED(sc);
8233
8234	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8235		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8236		    mac->mac_phy.supports_2ghz) {
8237			up_dev = mac;
8238			gmode = 1;
8239		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8240		    mac->mac_phy.supports_5ghz) {
8241			up_dev = mac;
8242			gmode = 0;
8243		} else {
8244			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8245			return (EINVAL);
8246		}
8247		if (up_dev != NULL)
8248			break;
8249	}
8250	if (up_dev == NULL) {
8251		device_printf(sc->sc_dev, "Could not find a device\n");
8252		return (ENODEV);
8253	}
8254	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8255		return (0);
8256
8257	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8258	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8259
8260	down_dev = sc->sc_curmac;
8261	status = down_dev->mac_status;
8262	if (status >= BWN_MAC_STATUS_STARTED)
8263		bwn_core_stop(down_dev);
8264	if (status >= BWN_MAC_STATUS_INITED)
8265		bwn_core_exit(down_dev);
8266
8267	if (down_dev != up_dev)
8268		bwn_phy_reset(down_dev);
8269
8270	up_dev->mac_phy.gmode = gmode;
8271	if (status >= BWN_MAC_STATUS_INITED) {
8272		err = bwn_core_init(up_dev);
8273		if (err) {
8274			device_printf(sc->sc_dev,
8275			    "fatal: failed to initialize for %s-GHz\n",
8276			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8277			goto fail;
8278		}
8279	}
8280	if (status >= BWN_MAC_STATUS_STARTED)
8281		bwn_core_start(up_dev);
8282	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8283	sc->sc_curmac = up_dev;
8284
8285	return (0);
8286fail:
8287	sc->sc_curmac = NULL;
8288	return (err);
8289}
8290
8291static void
8292bwn_rf_turnon(struct bwn_mac *mac)
8293{
8294
8295	bwn_mac_suspend(mac);
8296	mac->mac_phy.rf_onoff(mac, 1);
8297	mac->mac_phy.rf_on = 1;
8298	bwn_mac_enable(mac);
8299}
8300
8301static void
8302bwn_rf_turnoff(struct bwn_mac *mac)
8303{
8304
8305	bwn_mac_suspend(mac);
8306	mac->mac_phy.rf_onoff(mac, 0);
8307	mac->mac_phy.rf_on = 0;
8308	bwn_mac_enable(mac);
8309}
8310
8311static void
8312bwn_phy_reset(struct bwn_mac *mac)
8313{
8314	struct bwn_softc *sc = mac->mac_sc;
8315
8316	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8317	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8318	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8319	DELAY(1000);
8320	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8322	    BWN_TGSLOW_PHYRESET);
8323	DELAY(1000);
8324}
8325
8326static int
8327bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8328{
8329	struct bwn_vap *bvp = BWN_VAP(vap);
8330	struct ieee80211com *ic= vap->iv_ic;
8331	struct ifnet *ifp = ic->ic_ifp;
8332	enum ieee80211_state ostate = vap->iv_state;
8333	struct bwn_softc *sc = ifp->if_softc;
8334	struct bwn_mac *mac = sc->sc_curmac;
8335	int error;
8336
8337	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8338	    ieee80211_state_name[vap->iv_state],
8339	    ieee80211_state_name[nstate]);
8340
8341	error = bvp->bv_newstate(vap, nstate, arg);
8342	if (error != 0)
8343		return (error);
8344
8345	BWN_LOCK(sc);
8346
8347	bwn_led_newstate(mac, nstate);
8348
8349	/*
8350	 * Clear the BSSID when we stop a STA
8351	 */
8352	if (vap->iv_opmode == IEEE80211_M_STA) {
8353		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8354			/*
8355			 * Clear out the BSSID.  If we reassociate to
8356			 * the same AP, this will reinialize things
8357			 * correctly...
8358			 */
8359			if (ic->ic_opmode == IEEE80211_M_STA &&
8360			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8361				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8362				bwn_set_macaddr(mac);
8363			}
8364		}
8365	}
8366
8367	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8368	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8369		/* XXX nothing to do? */
8370	} else if (nstate == IEEE80211_S_RUN) {
8371		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8372		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8373		bwn_set_opmode(mac);
8374		bwn_set_pretbtt(mac);
8375		bwn_spu_setdelay(mac, 0);
8376		bwn_set_macaddr(mac);
8377	}
8378
8379	BWN_UNLOCK(sc);
8380
8381	return (error);
8382}
8383
8384static void
8385bwn_set_pretbtt(struct bwn_mac *mac)
8386{
8387	struct bwn_softc *sc = mac->mac_sc;
8388	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8389	uint16_t pretbtt;
8390
8391	if (ic->ic_opmode == IEEE80211_M_IBSS)
8392		pretbtt = 2;
8393	else
8394		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8395	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8396	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8397}
8398
8399static int
8400bwn_intr(void *arg)
8401{
8402	struct bwn_mac *mac = arg;
8403	struct bwn_softc *sc = mac->mac_sc;
8404	uint32_t reason;
8405
8406	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8407	    (sc->sc_flags & BWN_FLAG_INVALID))
8408		return (FILTER_STRAY);
8409
8410	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8411	if (reason == 0xffffffff)	/* shared IRQ */
8412		return (FILTER_STRAY);
8413	reason &= mac->mac_intr_mask;
8414	if (reason == 0)
8415		return (FILTER_HANDLED);
8416
8417	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8418	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8419	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8420	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8421	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8422	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8423	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8424	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8425	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8426	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8427	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8428
8429	/* Disable interrupts. */
8430	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8431
8432	mac->mac_reason_intr = reason;
8433
8434	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8435	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8436
8437	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8438	return (FILTER_HANDLED);
8439}
8440
8441static void
8442bwn_intrtask(void *arg, int npending)
8443{
8444	struct bwn_mac *mac = arg;
8445	struct bwn_softc *sc = mac->mac_sc;
8446	struct ifnet *ifp = sc->sc_ifp;
8447	uint32_t merged = 0;
8448	int i, tx = 0, rx = 0;
8449
8450	BWN_LOCK(sc);
8451	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8452	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8453		BWN_UNLOCK(sc);
8454		return;
8455	}
8456
8457	for (i = 0; i < N(mac->mac_reason); i++)
8458		merged |= mac->mac_reason[i];
8459
8460	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8461		device_printf(sc->sc_dev, "MAC trans error\n");
8462
8463	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8464		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8465		mac->mac_phy.txerrors--;
8466		if (mac->mac_phy.txerrors == 0) {
8467			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8468			bwn_restart(mac, "PHY TX errors");
8469		}
8470	}
8471
8472	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8473		if (merged & BWN_DMAINTR_FATALMASK) {
8474			device_printf(sc->sc_dev,
8475			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8476			    mac->mac_reason[0], mac->mac_reason[1],
8477			    mac->mac_reason[2], mac->mac_reason[3],
8478			    mac->mac_reason[4], mac->mac_reason[5]);
8479			bwn_restart(mac, "DMA error");
8480			BWN_UNLOCK(sc);
8481			return;
8482		}
8483		if (merged & BWN_DMAINTR_NONFATALMASK) {
8484			device_printf(sc->sc_dev,
8485			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8486			    mac->mac_reason[0], mac->mac_reason[1],
8487			    mac->mac_reason[2], mac->mac_reason[3],
8488			    mac->mac_reason[4], mac->mac_reason[5]);
8489		}
8490	}
8491
8492	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8493		bwn_intr_ucode_debug(mac);
8494	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8495		bwn_intr_tbtt_indication(mac);
8496	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8497		bwn_intr_atim_end(mac);
8498	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8499		bwn_intr_beacon(mac);
8500	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8501		bwn_intr_pmq(mac);
8502	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8503		bwn_intr_noise(mac);
8504
8505	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8506		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8507			bwn_dma_rx(mac->mac_method.dma.rx);
8508			rx = 1;
8509		}
8510	} else
8511		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8512
8513	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518
8519	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8520		bwn_intr_txeof(mac);
8521		tx = 1;
8522	}
8523
8524	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8525
8526	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8527		int evt = BWN_LED_EVENT_NONE;
8528
8529		if (tx && rx) {
8530			if (sc->sc_rx_rate > sc->sc_tx_rate)
8531				evt = BWN_LED_EVENT_RX;
8532			else
8533				evt = BWN_LED_EVENT_TX;
8534		} else if (tx) {
8535			evt = BWN_LED_EVENT_TX;
8536		} else if (rx) {
8537			evt = BWN_LED_EVENT_RX;
8538		} else if (rx == 0) {
8539			evt = BWN_LED_EVENT_POLL;
8540		}
8541
8542		if (evt != BWN_LED_EVENT_NONE)
8543			bwn_led_event(mac, evt);
8544       }
8545
8546	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8547		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8548			bwn_start_locked(ifp);
8549	}
8550
8551	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8552	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8553
8554	BWN_UNLOCK(sc);
8555}
8556
8557static void
8558bwn_restart(struct bwn_mac *mac, const char *msg)
8559{
8560	struct bwn_softc *sc = mac->mac_sc;
8561	struct ifnet *ifp = sc->sc_ifp;
8562	struct ieee80211com *ic = ifp->if_l2com;
8563
8564	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8565		return;
8566
8567	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8568	ieee80211_runtask(ic, &mac->mac_hwreset);
8569}
8570
8571static void
8572bwn_intr_ucode_debug(struct bwn_mac *mac)
8573{
8574	struct bwn_softc *sc = mac->mac_sc;
8575	uint16_t reason;
8576
8577	if (mac->mac_fw.opensource == 0)
8578		return;
8579
8580	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8581	switch (reason) {
8582	case BWN_DEBUGINTR_PANIC:
8583		bwn_handle_fwpanic(mac);
8584		break;
8585	case BWN_DEBUGINTR_DUMP_SHM:
8586		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8587		break;
8588	case BWN_DEBUGINTR_DUMP_REGS:
8589		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8590		break;
8591	case BWN_DEBUGINTR_MARKER:
8592		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8593		break;
8594	default:
8595		device_printf(sc->sc_dev,
8596		    "ucode debug unknown reason: %#x\n", reason);
8597	}
8598
8599	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8600	    BWN_DEBUGINTR_ACK);
8601}
8602
8603static void
8604bwn_intr_tbtt_indication(struct bwn_mac *mac)
8605{
8606	struct bwn_softc *sc = mac->mac_sc;
8607	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8608
8609	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8610		bwn_psctl(mac, 0);
8611	if (ic->ic_opmode == IEEE80211_M_IBSS)
8612		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8613}
8614
8615static void
8616bwn_intr_atim_end(struct bwn_mac *mac)
8617{
8618
8619	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8620		BWN_WRITE_4(mac, BWN_MACCMD,
8621		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8622		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8623	}
8624}
8625
8626static void
8627bwn_intr_beacon(struct bwn_mac *mac)
8628{
8629	struct bwn_softc *sc = mac->mac_sc;
8630	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8631	uint32_t cmd, beacon0, beacon1;
8632
8633	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8634	    ic->ic_opmode == IEEE80211_M_MBSS)
8635		return;
8636
8637	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8638
8639	cmd = BWN_READ_4(mac, BWN_MACCMD);
8640	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8641	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8642
8643	if (beacon0 && beacon1) {
8644		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8645		mac->mac_intr_mask |= BWN_INTR_BEACON;
8646		return;
8647	}
8648
8649	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8650		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8651		bwn_load_beacon0(mac);
8652		bwn_load_beacon1(mac);
8653		cmd = BWN_READ_4(mac, BWN_MACCMD);
8654		cmd |= BWN_MACCMD_BEACON0_VALID;
8655		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8656	} else {
8657		if (!beacon0) {
8658			bwn_load_beacon0(mac);
8659			cmd = BWN_READ_4(mac, BWN_MACCMD);
8660			cmd |= BWN_MACCMD_BEACON0_VALID;
8661			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8662		} else if (!beacon1) {
8663			bwn_load_beacon1(mac);
8664			cmd = BWN_READ_4(mac, BWN_MACCMD);
8665			cmd |= BWN_MACCMD_BEACON1_VALID;
8666			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8667		}
8668	}
8669}
8670
8671static void
8672bwn_intr_pmq(struct bwn_mac *mac)
8673{
8674	uint32_t tmp;
8675
8676	while (1) {
8677		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8678		if (!(tmp & 0x00000008))
8679			break;
8680	}
8681	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8682}
8683
8684static void
8685bwn_intr_noise(struct bwn_mac *mac)
8686{
8687	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8688	uint16_t tmp;
8689	uint8_t noise[4];
8690	uint8_t i, j;
8691	int32_t average;
8692
8693	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8694		return;
8695
8696	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8697	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8698	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8699	    noise[3] == 0x7f)
8700		goto new;
8701
8702	KASSERT(mac->mac_noise.noi_nsamples < 8,
8703	    ("%s:%d: fail", __func__, __LINE__));
8704	i = mac->mac_noise.noi_nsamples;
8705	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8706	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8707	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8708	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8709	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8710	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8711	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8712	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8713	mac->mac_noise.noi_nsamples++;
8714	if (mac->mac_noise.noi_nsamples == 8) {
8715		average = 0;
8716		for (i = 0; i < 8; i++) {
8717			for (j = 0; j < 4; j++)
8718				average += mac->mac_noise.noi_samples[i][j];
8719		}
8720		average = (((average / 32) * 125) + 64) / 128;
8721		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8722		if (tmp >= 8)
8723			average += 2;
8724		else
8725			average -= 25;
8726		average -= (tmp == 8) ? 72 : 48;
8727
8728		mac->mac_stats.link_noise = average;
8729		mac->mac_noise.noi_running = 0;
8730		return;
8731	}
8732new:
8733	bwn_noise_gensample(mac);
8734}
8735
8736static int
8737bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8738{
8739	struct bwn_mac *mac = prq->prq_mac;
8740	struct bwn_softc *sc = mac->mac_sc;
8741	unsigned int i;
8742
8743	BWN_ASSERT_LOCKED(sc);
8744
8745	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8746		return (0);
8747
8748	for (i = 0; i < 5000; i++) {
8749		if (bwn_pio_rxeof(prq) == 0)
8750			break;
8751	}
8752	if (i >= 5000)
8753		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8754	return ((i > 0) ? 1 : 0);
8755}
8756
8757static void
8758bwn_dma_rx(struct bwn_dma_ring *dr)
8759{
8760	int slot, curslot;
8761
8762	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8763	curslot = dr->get_curslot(dr);
8764	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8765	    ("%s:%d: fail", __func__, __LINE__));
8766
8767	slot = dr->dr_curslot;
8768	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8769		bwn_dma_rxeof(dr, &slot);
8770
8771	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8772	    BUS_DMASYNC_PREWRITE);
8773
8774	dr->set_curslot(dr, slot);
8775	dr->dr_curslot = slot;
8776}
8777
8778static void
8779bwn_intr_txeof(struct bwn_mac *mac)
8780{
8781	struct bwn_txstatus stat;
8782	uint32_t stat0, stat1;
8783	uint16_t tmp;
8784
8785	BWN_ASSERT_LOCKED(mac->mac_sc);
8786
8787	while (1) {
8788		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8789		if (!(stat0 & 0x00000001))
8790			break;
8791		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8792
8793		stat.cookie = (stat0 >> 16);
8794		stat.seq = (stat1 & 0x0000ffff);
8795		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8796		tmp = (stat0 & 0x0000ffff);
8797		stat.framecnt = ((tmp & 0xf000) >> 12);
8798		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8799		stat.sreason = ((tmp & 0x001c) >> 2);
8800		stat.pm = (tmp & 0x0080) ? 1 : 0;
8801		stat.im = (tmp & 0x0040) ? 1 : 0;
8802		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8803		stat.ack = (tmp & 0x0002) ? 1 : 0;
8804
8805		bwn_handle_txeof(mac, &stat);
8806	}
8807}
8808
8809static void
8810bwn_hwreset(void *arg, int npending)
8811{
8812	struct bwn_mac *mac = arg;
8813	struct bwn_softc *sc = mac->mac_sc;
8814	int error = 0;
8815	int prev_status;
8816
8817	BWN_LOCK(sc);
8818
8819	prev_status = mac->mac_status;
8820	if (prev_status >= BWN_MAC_STATUS_STARTED)
8821		bwn_core_stop(mac);
8822	if (prev_status >= BWN_MAC_STATUS_INITED)
8823		bwn_core_exit(mac);
8824
8825	if (prev_status >= BWN_MAC_STATUS_INITED) {
8826		error = bwn_core_init(mac);
8827		if (error)
8828			goto out;
8829	}
8830	if (prev_status >= BWN_MAC_STATUS_STARTED)
8831		bwn_core_start(mac);
8832out:
8833	if (error) {
8834		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8835		sc->sc_curmac = NULL;
8836	}
8837	BWN_UNLOCK(sc);
8838}
8839
8840static void
8841bwn_handle_fwpanic(struct bwn_mac *mac)
8842{
8843	struct bwn_softc *sc = mac->mac_sc;
8844	uint16_t reason;
8845
8846	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8847	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8848
8849	if (reason == BWN_FWPANIC_RESTART)
8850		bwn_restart(mac, "ucode panic");
8851}
8852
8853static void
8854bwn_load_beacon0(struct bwn_mac *mac)
8855{
8856
8857	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8858}
8859
8860static void
8861bwn_load_beacon1(struct bwn_mac *mac)
8862{
8863
8864	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8865}
8866
8867static uint32_t
8868bwn_jssi_read(struct bwn_mac *mac)
8869{
8870	uint32_t val = 0;
8871
8872	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8873	val <<= 16;
8874	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8875
8876	return (val);
8877}
8878
8879static void
8880bwn_noise_gensample(struct bwn_mac *mac)
8881{
8882	uint32_t jssi = 0x7f7f7f7f;
8883
8884	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8885	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8886	BWN_WRITE_4(mac, BWN_MACCMD,
8887	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8888}
8889
8890static int
8891bwn_dma_freeslot(struct bwn_dma_ring *dr)
8892{
8893	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8894
8895	return (dr->dr_numslots - dr->dr_usedslot);
8896}
8897
8898static int
8899bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8900{
8901	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8902
8903	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8904	    ("%s:%d: fail", __func__, __LINE__));
8905	if (slot == dr->dr_numslots - 1)
8906		return (0);
8907	return (slot + 1);
8908}
8909
8910static void
8911bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8912{
8913	struct bwn_mac *mac = dr->dr_mac;
8914	struct bwn_softc *sc = mac->mac_sc;
8915	struct bwn_dma *dma = &mac->mac_method.dma;
8916	struct bwn_dmadesc_generic *desc;
8917	struct bwn_dmadesc_meta *meta;
8918	struct bwn_rxhdr4 *rxhdr;
8919	struct ifnet *ifp = sc->sc_ifp;
8920	struct mbuf *m;
8921	uint32_t macstat;
8922	int32_t tmp;
8923	int cnt = 0;
8924	uint16_t len;
8925
8926	dr->getdesc(dr, *slot, &desc, &meta);
8927
8928	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8929	m = meta->mt_m;
8930
8931	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8932		ifp->if_ierrors++;
8933		return;
8934	}
8935
8936	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8937	len = le16toh(rxhdr->frame_len);
8938	if (len <= 0) {
8939		ifp->if_ierrors++;
8940		return;
8941	}
8942	if (bwn_dma_check_redzone(dr, m)) {
8943		device_printf(sc->sc_dev, "redzone error.\n");
8944		bwn_dma_set_redzone(dr, m);
8945		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8946		    BUS_DMASYNC_PREWRITE);
8947		return;
8948	}
8949	if (len > dr->dr_rx_bufsize) {
8950		tmp = len;
8951		while (1) {
8952			dr->getdesc(dr, *slot, &desc, &meta);
8953			bwn_dma_set_redzone(dr, meta->mt_m);
8954			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8955			    BUS_DMASYNC_PREWRITE);
8956			*slot = bwn_dma_nextslot(dr, *slot);
8957			cnt++;
8958			tmp -= dr->dr_rx_bufsize;
8959			if (tmp <= 0)
8960				break;
8961		}
8962		device_printf(sc->sc_dev, "too small buffer "
8963		       "(len %u buffer %u dropped %d)\n",
8964		       len, dr->dr_rx_bufsize, cnt);
8965		return;
8966	}
8967	macstat = le32toh(rxhdr->mac_status);
8968	if (macstat & BWN_RX_MAC_FCSERR) {
8969		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8970			device_printf(sc->sc_dev, "RX drop\n");
8971			return;
8972		}
8973	}
8974
8975	m->m_pkthdr.rcvif = ifp;
8976	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8977	m_adj(m, dr->dr_frameoffset);
8978
8979	bwn_rxeof(dr->dr_mac, m, rxhdr);
8980}
8981
8982static void
8983bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8984{
8985	struct bwn_dma_ring *dr;
8986	struct bwn_dmadesc_generic *desc;
8987	struct bwn_dmadesc_meta *meta;
8988	struct bwn_pio_txqueue *tq;
8989	struct bwn_pio_txpkt *tp = NULL;
8990	struct bwn_softc *sc = mac->mac_sc;
8991	struct bwn_stats *stats = &mac->mac_stats;
8992	struct ieee80211_node *ni;
8993	struct ieee80211vap *vap;
8994	int retrycnt = 0, slot;
8995
8996	BWN_ASSERT_LOCKED(mac->mac_sc);
8997
8998	if (status->im)
8999		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9000	if (status->ampdu)
9001		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9002	if (status->rtscnt) {
9003		if (status->rtscnt == 0xf)
9004			stats->rtsfail++;
9005		else
9006			stats->rts++;
9007	}
9008
9009	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9010		if (status->ack) {
9011			dr = bwn_dma_parse_cookie(mac, status,
9012			    status->cookie, &slot);
9013			if (dr == NULL) {
9014				device_printf(sc->sc_dev,
9015				    "failed to parse cookie\n");
9016				return;
9017			}
9018			while (1) {
9019				dr->getdesc(dr, slot, &desc, &meta);
9020				if (meta->mt_islast) {
9021					ni = meta->mt_ni;
9022					vap = ni->ni_vap;
9023					ieee80211_ratectl_tx_complete(vap, ni,
9024					    status->ack ?
9025					      IEEE80211_RATECTL_TX_SUCCESS :
9026					      IEEE80211_RATECTL_TX_FAILURE,
9027					    &retrycnt, 0);
9028					break;
9029				}
9030				slot = bwn_dma_nextslot(dr, slot);
9031			}
9032		}
9033		bwn_dma_handle_txeof(mac, status);
9034	} else {
9035		if (status->ack) {
9036			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9037			if (tq == NULL) {
9038				device_printf(sc->sc_dev,
9039				    "failed to parse cookie\n");
9040				return;
9041			}
9042			ni = tp->tp_ni;
9043			vap = ni->ni_vap;
9044			ieee80211_ratectl_tx_complete(vap, ni,
9045			    status->ack ?
9046			      IEEE80211_RATECTL_TX_SUCCESS :
9047			      IEEE80211_RATECTL_TX_FAILURE,
9048			    &retrycnt, 0);
9049		}
9050		bwn_pio_handle_txeof(mac, status);
9051	}
9052
9053	bwn_phy_txpower_check(mac, 0);
9054}
9055
9056static uint8_t
9057bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9058{
9059	struct bwn_mac *mac = prq->prq_mac;
9060	struct bwn_softc *sc = mac->mac_sc;
9061	struct bwn_rxhdr4 rxhdr;
9062	struct ifnet *ifp = sc->sc_ifp;
9063	struct mbuf *m;
9064	uint32_t ctl32, macstat, v32;
9065	unsigned int i, padding;
9066	uint16_t ctl16, len, totlen, v16;
9067	unsigned char *mp;
9068	char *data;
9069
9070	memset(&rxhdr, 0, sizeof(rxhdr));
9071
9072	if (prq->prq_rev >= 8) {
9073		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9074		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9075			return (0);
9076		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9077		    BWN_PIO8_RXCTL_FRAMEREADY);
9078		for (i = 0; i < 10; i++) {
9079			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9080			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9081				goto ready;
9082			DELAY(10);
9083		}
9084	} else {
9085		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9086		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9087			return (0);
9088		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9089		    BWN_PIO_RXCTL_FRAMEREADY);
9090		for (i = 0; i < 10; i++) {
9091			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9092			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9093				goto ready;
9094			DELAY(10);
9095		}
9096	}
9097	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9098	return (1);
9099ready:
9100	if (prq->prq_rev >= 8)
9101		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102		    prq->prq_base + BWN_PIO8_RXDATA);
9103	else
9104		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9105		    prq->prq_base + BWN_PIO_RXDATA);
9106	len = le16toh(rxhdr.frame_len);
9107	if (len > 0x700) {
9108		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9109		goto error;
9110	}
9111	if (len == 0) {
9112		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9113		goto error;
9114	}
9115
9116	macstat = le32toh(rxhdr.mac_status);
9117	if (macstat & BWN_RX_MAC_FCSERR) {
9118		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9119			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9120			goto error;
9121		}
9122	}
9123
9124	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9125	totlen = len + padding;
9126	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9127	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9128	if (m == NULL) {
9129		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9130		goto error;
9131	}
9132	mp = mtod(m, unsigned char *);
9133	if (prq->prq_rev >= 8) {
9134		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9135		    prq->prq_base + BWN_PIO8_RXDATA);
9136		if (totlen & 3) {
9137			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9138			data = &(mp[totlen - 1]);
9139			switch (totlen & 3) {
9140			case 3:
9141				*data = (v32 >> 16);
9142				data--;
9143			case 2:
9144				*data = (v32 >> 8);
9145				data--;
9146			case 1:
9147				*data = v32;
9148			}
9149		}
9150	} else {
9151		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9152		    prq->prq_base + BWN_PIO_RXDATA);
9153		if (totlen & 1) {
9154			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9155			mp[totlen - 1] = v16;
9156		}
9157	}
9158
9159	m->m_pkthdr.rcvif = ifp;
9160	m->m_len = m->m_pkthdr.len = totlen;
9161
9162	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9163
9164	return (1);
9165error:
9166	if (prq->prq_rev >= 8)
9167		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9168		    BWN_PIO8_RXCTL_DATAREADY);
9169	else
9170		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9171	return (1);
9172}
9173
9174static int
9175bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9176    struct bwn_dmadesc_meta *meta, int init)
9177{
9178	struct bwn_mac *mac = dr->dr_mac;
9179	struct bwn_dma *dma = &mac->mac_method.dma;
9180	struct bwn_rxhdr4 *hdr;
9181	bus_dmamap_t map;
9182	bus_addr_t paddr;
9183	struct mbuf *m;
9184	int error;
9185
9186	paddr = 0;
9187	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9188	if (m == NULL) {
9189		error = ENOBUFS;
9190
9191		/*
9192		 * If the NIC is up and running, we need to:
9193		 * - Clear RX buffer's header.
9194		 * - Restore RX descriptor settings.
9195		 */
9196		if (init)
9197			return (error);
9198		else
9199			goto back;
9200	}
9201	m->m_len = m->m_pkthdr.len = MCLBYTES;
9202
9203	bwn_dma_set_redzone(dr, m);
9204
9205	/*
9206	 * Try to load RX buf into temporary DMA map
9207	 */
9208	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9209	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9210	if (error) {
9211		m_freem(m);
9212
9213		/*
9214		 * See the comment above
9215		 */
9216		if (init)
9217			return (error);
9218		else
9219			goto back;
9220	}
9221
9222	if (!init)
9223		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9224	meta->mt_m = m;
9225	meta->mt_paddr = paddr;
9226
9227	/*
9228	 * Swap RX buf's DMA map with the loaded temporary one
9229	 */
9230	map = meta->mt_dmap;
9231	meta->mt_dmap = dr->dr_spare_dmap;
9232	dr->dr_spare_dmap = map;
9233
9234back:
9235	/*
9236	 * Clear RX buf header
9237	 */
9238	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9239	bzero(hdr, sizeof(*hdr));
9240	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9241	    BUS_DMASYNC_PREWRITE);
9242
9243	/*
9244	 * Setup RX buf descriptor
9245	 */
9246	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9247	    sizeof(*hdr), 0, 0, 0);
9248	return (error);
9249}
9250
9251static void
9252bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9253		 bus_size_t mapsz __unused, int error)
9254{
9255
9256	if (!error) {
9257		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9258		*((bus_addr_t *)arg) = seg->ds_addr;
9259	}
9260}
9261
9262static int
9263bwn_hwrate2ieeerate(int rate)
9264{
9265
9266	switch (rate) {
9267	case BWN_CCK_RATE_1MB:
9268		return (2);
9269	case BWN_CCK_RATE_2MB:
9270		return (4);
9271	case BWN_CCK_RATE_5MB:
9272		return (11);
9273	case BWN_CCK_RATE_11MB:
9274		return (22);
9275	case BWN_OFDM_RATE_6MB:
9276		return (12);
9277	case BWN_OFDM_RATE_9MB:
9278		return (18);
9279	case BWN_OFDM_RATE_12MB:
9280		return (24);
9281	case BWN_OFDM_RATE_18MB:
9282		return (36);
9283	case BWN_OFDM_RATE_24MB:
9284		return (48);
9285	case BWN_OFDM_RATE_36MB:
9286		return (72);
9287	case BWN_OFDM_RATE_48MB:
9288		return (96);
9289	case BWN_OFDM_RATE_54MB:
9290		return (108);
9291	default:
9292		printf("Ooops\n");
9293		return (0);
9294	}
9295}
9296
9297static void
9298bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9299{
9300	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9301	struct bwn_plcp6 *plcp;
9302	struct bwn_softc *sc = mac->mac_sc;
9303	struct ieee80211_frame_min *wh;
9304	struct ieee80211_node *ni;
9305	struct ifnet *ifp = sc->sc_ifp;
9306	struct ieee80211com *ic = ifp->if_l2com;
9307	uint32_t macstat;
9308	int padding, rate, rssi = 0, noise = 0, type;
9309	uint16_t phytype, phystat0, phystat3, chanstat;
9310	unsigned char *mp = mtod(m, unsigned char *);
9311	static int rx_mac_dec_rpt = 0;
9312
9313	BWN_ASSERT_LOCKED(sc);
9314
9315	phystat0 = le16toh(rxhdr->phy_status0);
9316	phystat3 = le16toh(rxhdr->phy_status3);
9317	macstat = le32toh(rxhdr->mac_status);
9318	chanstat = le16toh(rxhdr->channel);
9319	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9320
9321	if (macstat & BWN_RX_MAC_FCSERR)
9322		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9323	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9324		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9325	if (macstat & BWN_RX_MAC_DECERR)
9326		goto drop;
9327
9328	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9329	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9330		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9331		    m->m_pkthdr.len);
9332		goto drop;
9333	}
9334	plcp = (struct bwn_plcp6 *)(mp + padding);
9335	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9336	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9337		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9338		    m->m_pkthdr.len);
9339		goto drop;
9340	}
9341	wh = mtod(m, struct ieee80211_frame_min *);
9342
9343	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9344		device_printf(sc->sc_dev,
9345		    "RX decryption attempted (old %d keyidx %#x)\n",
9346		    BWN_ISOLDFMT(mac),
9347		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9348
9349	/* XXX calculating RSSI & noise & antenna */
9350
9351	if (phystat0 & BWN_RX_PHYST0_OFDM)
9352		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9353		    phytype == BWN_PHYTYPE_A);
9354	else
9355		rate = bwn_plcp_get_cckrate(mac, plcp);
9356	if (rate == -1) {
9357		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9358			goto drop;
9359	}
9360	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9361
9362	/* RX radio tap */
9363	if (ieee80211_radiotap_active(ic))
9364		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9365	m_adj(m, -IEEE80211_CRC_LEN);
9366
9367	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9368	noise = mac->mac_stats.link_noise;
9369
9370	ifp->if_ipackets++;
9371
9372	BWN_UNLOCK(sc);
9373
9374	ni = ieee80211_find_rxnode(ic, wh);
9375	if (ni != NULL) {
9376		type = ieee80211_input(ni, m, rssi, noise);
9377		ieee80211_free_node(ni);
9378	} else
9379		type = ieee80211_input_all(ic, m, rssi, noise);
9380
9381	BWN_LOCK(sc);
9382	return;
9383drop:
9384	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9385}
9386
9387static void
9388bwn_dma_handle_txeof(struct bwn_mac *mac,
9389    const struct bwn_txstatus *status)
9390{
9391	struct bwn_dma *dma = &mac->mac_method.dma;
9392	struct bwn_dma_ring *dr;
9393	struct bwn_dmadesc_generic *desc;
9394	struct bwn_dmadesc_meta *meta;
9395	struct bwn_softc *sc = mac->mac_sc;
9396	struct ieee80211_node *ni;
9397	struct ifnet *ifp = sc->sc_ifp;
9398	struct mbuf *m;
9399	int slot;
9400
9401	BWN_ASSERT_LOCKED(sc);
9402
9403	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9404	if (dr == NULL) {
9405		device_printf(sc->sc_dev, "failed to parse cookie\n");
9406		return;
9407	}
9408	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9409
9410	while (1) {
9411		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9412		    ("%s:%d: fail", __func__, __LINE__));
9413		dr->getdesc(dr, slot, &desc, &meta);
9414
9415		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9416			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9417		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9418			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9419
9420		if (meta->mt_islast) {
9421			KASSERT(meta->mt_m != NULL,
9422			    ("%s:%d: fail", __func__, __LINE__));
9423
9424			ni = meta->mt_ni;
9425			m = meta->mt_m;
9426			if (ni != NULL) {
9427				/*
9428				 * Do any tx complete callback. Note this must
9429				 * be done before releasing the node reference.
9430				 */
9431				if (m->m_flags & M_TXCB)
9432					ieee80211_process_callback(ni, m, 0);
9433				ieee80211_free_node(ni);
9434				meta->mt_ni = NULL;
9435			}
9436			m_freem(m);
9437			meta->mt_m = NULL;
9438		} else {
9439			KASSERT(meta->mt_m == NULL,
9440			    ("%s:%d: fail", __func__, __LINE__));
9441		}
9442
9443		dr->dr_usedslot--;
9444		if (meta->mt_islast) {
9445			ifp->if_opackets++;
9446			break;
9447		}
9448		slot = bwn_dma_nextslot(dr, slot);
9449	}
9450	sc->sc_watchdog_timer = 0;
9451	if (dr->dr_stop) {
9452		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9453		    ("%s:%d: fail", __func__, __LINE__));
9454		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9455		dr->dr_stop = 0;
9456	}
9457}
9458
9459static void
9460bwn_pio_handle_txeof(struct bwn_mac *mac,
9461    const struct bwn_txstatus *status)
9462{
9463	struct bwn_pio_txqueue *tq;
9464	struct bwn_pio_txpkt *tp = NULL;
9465	struct bwn_softc *sc = mac->mac_sc;
9466	struct ifnet *ifp = sc->sc_ifp;
9467
9468	BWN_ASSERT_LOCKED(sc);
9469
9470	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9471	if (tq == NULL)
9472		return;
9473
9474	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9475	tq->tq_free++;
9476
9477	if (tp->tp_ni != NULL) {
9478		/*
9479		 * Do any tx complete callback.  Note this must
9480		 * be done before releasing the node reference.
9481		 */
9482		if (tp->tp_m->m_flags & M_TXCB)
9483			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9484		ieee80211_free_node(tp->tp_ni);
9485		tp->tp_ni = NULL;
9486	}
9487	m_freem(tp->tp_m);
9488	tp->tp_m = NULL;
9489	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9490
9491	ifp->if_opackets++;
9492
9493	sc->sc_watchdog_timer = 0;
9494	if (tq->tq_stop) {
9495		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9496		tq->tq_stop = 0;
9497	}
9498}
9499
9500static void
9501bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9502{
9503	struct bwn_softc *sc = mac->mac_sc;
9504	struct bwn_phy *phy = &mac->mac_phy;
9505	struct ifnet *ifp = sc->sc_ifp;
9506	struct ieee80211com *ic = ifp->if_l2com;
9507	unsigned long now;
9508	int result;
9509
9510	BWN_GETTIME(now);
9511
9512	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9513		return;
9514	phy->nexttime = now + 2 * 1000;
9515
9516	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9517	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9518		return;
9519
9520	if (phy->recalc_txpwr != NULL) {
9521		result = phy->recalc_txpwr(mac,
9522		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9523		if (result == BWN_TXPWR_RES_DONE)
9524			return;
9525		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9526		    ("%s: fail", __func__));
9527		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9528
9529		ieee80211_runtask(ic, &mac->mac_txpower);
9530	}
9531}
9532
9533static uint16_t
9534bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9535{
9536
9537	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9538}
9539
9540static uint32_t
9541bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9542{
9543
9544	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9545}
9546
9547static void
9548bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9549{
9550
9551	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9552}
9553
9554static void
9555bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9556{
9557
9558	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9559}
9560
9561static int
9562bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9563{
9564
9565	switch (rate) {
9566	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9567	case 12:
9568		return (BWN_OFDM_RATE_6MB);
9569	case 18:
9570		return (BWN_OFDM_RATE_9MB);
9571	case 24:
9572		return (BWN_OFDM_RATE_12MB);
9573	case 36:
9574		return (BWN_OFDM_RATE_18MB);
9575	case 48:
9576		return (BWN_OFDM_RATE_24MB);
9577	case 72:
9578		return (BWN_OFDM_RATE_36MB);
9579	case 96:
9580		return (BWN_OFDM_RATE_48MB);
9581	case 108:
9582		return (BWN_OFDM_RATE_54MB);
9583	/* CCK rates (NB: not IEEE std, device-specific) */
9584	case 2:
9585		return (BWN_CCK_RATE_1MB);
9586	case 4:
9587		return (BWN_CCK_RATE_2MB);
9588	case 11:
9589		return (BWN_CCK_RATE_5MB);
9590	case 22:
9591		return (BWN_CCK_RATE_11MB);
9592	}
9593
9594	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9595	return (BWN_CCK_RATE_1MB);
9596}
9597
9598static int
9599bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9600    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9601{
9602	const struct bwn_phy *phy = &mac->mac_phy;
9603	struct bwn_softc *sc = mac->mac_sc;
9604	struct ieee80211_frame *wh;
9605	struct ieee80211_frame *protwh;
9606	struct ieee80211_frame_cts *cts;
9607	struct ieee80211_frame_rts *rts;
9608	const struct ieee80211_txparam *tp;
9609	struct ieee80211vap *vap = ni->ni_vap;
9610	struct ifnet *ifp = sc->sc_ifp;
9611	struct ieee80211com *ic = ifp->if_l2com;
9612	struct mbuf *mprot;
9613	unsigned int len;
9614	uint32_t macctl = 0;
9615	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9616	uint16_t phyctl = 0;
9617	uint8_t rate, rate_fb;
9618
9619	wh = mtod(m, struct ieee80211_frame *);
9620	memset(txhdr, 0, sizeof(*txhdr));
9621
9622	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9623	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9624	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9625
9626	/*
9627	 * Find TX rate
9628	 */
9629	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9630	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9631		rate = rate_fb = tp->mgmtrate;
9632	else if (ismcast)
9633		rate = rate_fb = tp->mcastrate;
9634	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9635		rate = rate_fb = tp->ucastrate;
9636	else {
9637		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9638		rate = ni->ni_txrate;
9639
9640		if (rix > 0)
9641			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9642			    IEEE80211_RATE_VAL;
9643		else
9644			rate_fb = rate;
9645	}
9646
9647	sc->sc_tx_rate = rate;
9648
9649	rate = bwn_ieeerate2hwrate(sc, rate);
9650	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9651
9652	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9653	    bwn_plcp_getcck(rate);
9654	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9655	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9656
9657	if ((rate_fb == rate) ||
9658	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9659	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9660		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9661	else
9662		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9663		    m->m_pkthdr.len, rate, isshort);
9664
9665	/* XXX TX encryption */
9666	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9667	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9668	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9669	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9670	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9671	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9672
9673	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9674	    BWN_TX_EFT_FB_CCK;
9675	txhdr->chan = phy->chan;
9676	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9677	    BWN_TX_PHY_ENC_CCK;
9678	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9679	     rate == BWN_CCK_RATE_11MB))
9680		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9681
9682	/* XXX TX antenna selection */
9683
9684	switch (bwn_antenna_sanitize(mac, 0)) {
9685	case 0:
9686		phyctl |= BWN_TX_PHY_ANT01AUTO;
9687		break;
9688	case 1:
9689		phyctl |= BWN_TX_PHY_ANT0;
9690		break;
9691	case 2:
9692		phyctl |= BWN_TX_PHY_ANT1;
9693		break;
9694	case 3:
9695		phyctl |= BWN_TX_PHY_ANT2;
9696		break;
9697	case 4:
9698		phyctl |= BWN_TX_PHY_ANT3;
9699		break;
9700	default:
9701		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9702	}
9703
9704	if (!ismcast)
9705		macctl |= BWN_TX_MAC_ACK;
9706
9707	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9708	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9709	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9710		macctl |= BWN_TX_MAC_LONGFRAME;
9711
9712	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9713		/* XXX RTS rate is always 1MB??? */
9714		rts_rate = BWN_CCK_RATE_1MB;
9715		rts_rate_fb = bwn_get_fbrate(rts_rate);
9716
9717		protdur = ieee80211_compute_duration(ic->ic_rt,
9718		    m->m_pkthdr.len, rate, isshort) +
9719		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9720
9721		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9722			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9723			    (txhdr->body.old.rts_frame) :
9724			    (txhdr->body.new.rts_frame));
9725			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9726			    protdur);
9727			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9728			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9729			    mprot->m_pkthdr.len);
9730			m_freem(mprot);
9731			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9732			len = sizeof(struct ieee80211_frame_cts);
9733		} else {
9734			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9735			    (txhdr->body.old.rts_frame) :
9736			    (txhdr->body.new.rts_frame));
9737			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9738			    isshort);
9739			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9740			    wh->i_addr2, protdur);
9741			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9742			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9743			    mprot->m_pkthdr.len);
9744			m_freem(mprot);
9745			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9746			len = sizeof(struct ieee80211_frame_rts);
9747		}
9748		len += IEEE80211_CRC_LEN;
9749		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9750		    &txhdr->body.old.rts_plcp :
9751		    &txhdr->body.new.rts_plcp), len, rts_rate);
9752		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9753		    rts_rate_fb);
9754
9755		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9756		    (&txhdr->body.old.rts_frame) :
9757		    (&txhdr->body.new.rts_frame));
9758		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9759
9760		if (BWN_ISOFDMRATE(rts_rate)) {
9761			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9762			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9763		} else {
9764			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9765			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9766		}
9767		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9768		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9769	}
9770
9771	if (BWN_ISOLDFMT(mac))
9772		txhdr->body.old.cookie = htole16(cookie);
9773	else
9774		txhdr->body.new.cookie = htole16(cookie);
9775
9776	txhdr->macctl = htole32(macctl);
9777	txhdr->phyctl = htole16(phyctl);
9778
9779	/*
9780	 * TX radio tap
9781	 */
9782	if (ieee80211_radiotap_active_vap(vap)) {
9783		sc->sc_tx_th.wt_flags = 0;
9784		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9785			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9786		if (isshort &&
9787		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9788		     rate == BWN_CCK_RATE_11MB))
9789			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9790		sc->sc_tx_th.wt_rate = rate;
9791
9792		ieee80211_radiotap_tx(vap, m);
9793	}
9794
9795	return (0);
9796}
9797
9798static void
9799bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9800    const uint8_t rate)
9801{
9802	uint32_t d, plen;
9803	uint8_t *raw = plcp->o.raw;
9804
9805	if (BWN_ISOFDMRATE(rate)) {
9806		d = bwn_plcp_getofdm(rate);
9807		KASSERT(!(octets & 0xf000),
9808		    ("%s:%d: fail", __func__, __LINE__));
9809		d |= (octets << 5);
9810		plcp->o.data = htole32(d);
9811	} else {
9812		plen = octets * 16 / rate;
9813		if ((octets * 16 % rate) > 0) {
9814			plen++;
9815			if ((rate == BWN_CCK_RATE_11MB)
9816			    && ((octets * 8 % 11) < 4)) {
9817				raw[1] = 0x84;
9818			} else
9819				raw[1] = 0x04;
9820		} else
9821			raw[1] = 0x04;
9822		plcp->o.data |= htole32(plen << 16);
9823		raw[0] = bwn_plcp_getcck(rate);
9824	}
9825}
9826
9827static uint8_t
9828bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9829{
9830	struct bwn_softc *sc = mac->mac_sc;
9831	uint8_t mask;
9832
9833	if (n == 0)
9834		return (0);
9835	if (mac->mac_phy.gmode)
9836		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9837	else
9838		mask = siba_sprom_get_ant_a(sc->sc_dev);
9839	if (!(mask & (1 << (n - 1))))
9840		return (0);
9841	return (n);
9842}
9843
9844static uint8_t
9845bwn_get_fbrate(uint8_t bitrate)
9846{
9847	switch (bitrate) {
9848	case BWN_CCK_RATE_1MB:
9849		return (BWN_CCK_RATE_1MB);
9850	case BWN_CCK_RATE_2MB:
9851		return (BWN_CCK_RATE_1MB);
9852	case BWN_CCK_RATE_5MB:
9853		return (BWN_CCK_RATE_2MB);
9854	case BWN_CCK_RATE_11MB:
9855		return (BWN_CCK_RATE_5MB);
9856	case BWN_OFDM_RATE_6MB:
9857		return (BWN_CCK_RATE_5MB);
9858	case BWN_OFDM_RATE_9MB:
9859		return (BWN_OFDM_RATE_6MB);
9860	case BWN_OFDM_RATE_12MB:
9861		return (BWN_OFDM_RATE_9MB);
9862	case BWN_OFDM_RATE_18MB:
9863		return (BWN_OFDM_RATE_12MB);
9864	case BWN_OFDM_RATE_24MB:
9865		return (BWN_OFDM_RATE_18MB);
9866	case BWN_OFDM_RATE_36MB:
9867		return (BWN_OFDM_RATE_24MB);
9868	case BWN_OFDM_RATE_48MB:
9869		return (BWN_OFDM_RATE_36MB);
9870	case BWN_OFDM_RATE_54MB:
9871		return (BWN_OFDM_RATE_48MB);
9872	}
9873	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9874	return (0);
9875}
9876
9877static uint32_t
9878bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9879    uint32_t ctl, const void *_data, int len)
9880{
9881	struct bwn_softc *sc = mac->mac_sc;
9882	uint32_t value = 0;
9883	const uint8_t *data = _data;
9884
9885	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9886	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9887	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9888
9889	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9890	    tq->tq_base + BWN_PIO8_TXDATA);
9891	if (len & 3) {
9892		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9893		    BWN_PIO8_TXCTL_24_31);
9894		data = &(data[len - 1]);
9895		switch (len & 3) {
9896		case 3:
9897			ctl |= BWN_PIO8_TXCTL_16_23;
9898			value |= (uint32_t)(*data) << 16;
9899			data--;
9900		case 2:
9901			ctl |= BWN_PIO8_TXCTL_8_15;
9902			value |= (uint32_t)(*data) << 8;
9903			data--;
9904		case 1:
9905			value |= (uint32_t)(*data);
9906		}
9907		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9908		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9909	}
9910
9911	return (ctl);
9912}
9913
9914static void
9915bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9916    uint16_t offset, uint32_t value)
9917{
9918
9919	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9920}
9921
9922static uint16_t
9923bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9924    uint16_t ctl, const void *_data, int len)
9925{
9926	struct bwn_softc *sc = mac->mac_sc;
9927	const uint8_t *data = _data;
9928
9929	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9930	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9931
9932	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9933	    tq->tq_base + BWN_PIO_TXDATA);
9934	if (len & 1) {
9935		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9936		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9937		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9938	}
9939
9940	return (ctl);
9941}
9942
9943static uint16_t
9944bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9945    uint16_t ctl, struct mbuf *m0)
9946{
9947	int i, j = 0;
9948	uint16_t data = 0;
9949	const uint8_t *buf;
9950	struct mbuf *m = m0;
9951
9952	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9953	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9954
9955	for (; m != NULL; m = m->m_next) {
9956		buf = mtod(m, const uint8_t *);
9957		for (i = 0; i < m->m_len; i++) {
9958			if (!((j++) % 2))
9959				data |= buf[i];
9960			else {
9961				data |= (buf[i] << 8);
9962				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9963				data = 0;
9964			}
9965		}
9966	}
9967	if (m0->m_pkthdr.len % 2) {
9968		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9969		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9970		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9971	}
9972
9973	return (ctl);
9974}
9975
9976static void
9977bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9978{
9979
9980	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9981		return;
9982	BWN_WRITE_2(mac, 0x684, 510 + time);
9983	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9984}
9985
9986static struct bwn_dma_ring *
9987bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9988{
9989
9990	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9991		return (mac->mac_method.dma.wme[WME_AC_BE]);
9992
9993	switch (prio) {
9994	case 3:
9995		return (mac->mac_method.dma.wme[WME_AC_VO]);
9996	case 2:
9997		return (mac->mac_method.dma.wme[WME_AC_VI]);
9998	case 0:
9999		return (mac->mac_method.dma.wme[WME_AC_BE]);
10000	case 1:
10001		return (mac->mac_method.dma.wme[WME_AC_BK]);
10002	}
10003	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10004	return (NULL);
10005}
10006
10007static int
10008bwn_dma_getslot(struct bwn_dma_ring *dr)
10009{
10010	int slot;
10011
10012	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10013
10014	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10015	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10016	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10017
10018	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10019	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10020	dr->dr_curslot = slot;
10021	dr->dr_usedslot++;
10022
10023	return (slot);
10024}
10025
10026static int
10027bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10028{
10029	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10030	unsigned int a, b, c, d;
10031	unsigned int avg;
10032	uint32_t tmp;
10033
10034	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10035	a = tmp & 0xff;
10036	b = (tmp >> 8) & 0xff;
10037	c = (tmp >> 16) & 0xff;
10038	d = (tmp >> 24) & 0xff;
10039	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10040	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10041		return (ENOENT);
10042	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10043	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10044	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10045
10046	if (ofdm) {
10047		a = (a + 32) & 0x3f;
10048		b = (b + 32) & 0x3f;
10049		c = (c + 32) & 0x3f;
10050		d = (d + 32) & 0x3f;
10051	}
10052
10053	avg = (a + b + c + d + 2) / 4;
10054	if (ofdm) {
10055		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10056		    & BWN_HF_4DB_CCK_POWERBOOST)
10057			avg = (avg >= 13) ? (avg - 13) : 0;
10058	}
10059	return (avg);
10060}
10061
10062static void
10063bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10064{
10065	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10066	int rfatt = *rfattp;
10067	int bbatt = *bbattp;
10068
10069	while (1) {
10070		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10071			break;
10072		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10073			break;
10074		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10075			break;
10076		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10077			break;
10078		if (bbatt > lo->bbatt.max) {
10079			bbatt -= 4;
10080			rfatt += 1;
10081			continue;
10082		}
10083		if (bbatt < lo->bbatt.min) {
10084			bbatt += 4;
10085			rfatt -= 1;
10086			continue;
10087		}
10088		if (rfatt > lo->rfatt.max) {
10089			rfatt -= 1;
10090			bbatt += 4;
10091			continue;
10092		}
10093		if (rfatt < lo->rfatt.min) {
10094			rfatt += 1;
10095			bbatt -= 4;
10096			continue;
10097		}
10098		break;
10099	}
10100
10101	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10102	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10103}
10104
10105static void
10106bwn_phy_lock(struct bwn_mac *mac)
10107{
10108	struct bwn_softc *sc = mac->mac_sc;
10109	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10110
10111	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10112	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10113
10114	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10115		bwn_psctl(mac, BWN_PS_AWAKE);
10116}
10117
10118static void
10119bwn_phy_unlock(struct bwn_mac *mac)
10120{
10121	struct bwn_softc *sc = mac->mac_sc;
10122	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10123
10124	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10125	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10126
10127	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10128		bwn_psctl(mac, 0);
10129}
10130
10131static void
10132bwn_rf_lock(struct bwn_mac *mac)
10133{
10134
10135	BWN_WRITE_4(mac, BWN_MACCTL,
10136	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10137	BWN_READ_4(mac, BWN_MACCTL);
10138	DELAY(10);
10139}
10140
10141static void
10142bwn_rf_unlock(struct bwn_mac *mac)
10143{
10144
10145	BWN_READ_2(mac, BWN_PHYVER);
10146	BWN_WRITE_4(mac, BWN_MACCTL,
10147	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10148}
10149
10150static struct bwn_pio_txqueue *
10151bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10152    struct bwn_pio_txpkt **pack)
10153{
10154	struct bwn_pio *pio = &mac->mac_method.pio;
10155	struct bwn_pio_txqueue *tq = NULL;
10156	unsigned int index;
10157
10158	switch (cookie & 0xf000) {
10159	case 0x1000:
10160		tq = &pio->wme[WME_AC_BK];
10161		break;
10162	case 0x2000:
10163		tq = &pio->wme[WME_AC_BE];
10164		break;
10165	case 0x3000:
10166		tq = &pio->wme[WME_AC_VI];
10167		break;
10168	case 0x4000:
10169		tq = &pio->wme[WME_AC_VO];
10170		break;
10171	case 0x5000:
10172		tq = &pio->mcast;
10173		break;
10174	}
10175	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10176	if (tq == NULL)
10177		return (NULL);
10178	index = (cookie & 0x0fff);
10179	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10180	if (index >= N(tq->tq_pkts))
10181		return (NULL);
10182	*pack = &tq->tq_pkts[index];
10183	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10184	return (tq);
10185}
10186
10187static void
10188bwn_txpwr(void *arg, int npending)
10189{
10190	struct bwn_mac *mac = arg;
10191	struct bwn_softc *sc = mac->mac_sc;
10192
10193	BWN_LOCK(sc);
10194	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10195	    mac->mac_phy.set_txpwr != NULL)
10196		mac->mac_phy.set_txpwr(mac);
10197	BWN_UNLOCK(sc);
10198}
10199
10200static void
10201bwn_task_15s(struct bwn_mac *mac)
10202{
10203	uint16_t reg;
10204
10205	if (mac->mac_fw.opensource) {
10206		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10207		if (reg) {
10208			bwn_restart(mac, "fw watchdog");
10209			return;
10210		}
10211		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10212	}
10213	if (mac->mac_phy.task_15s)
10214		mac->mac_phy.task_15s(mac);
10215
10216	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10217}
10218
10219static void
10220bwn_task_30s(struct bwn_mac *mac)
10221{
10222
10223	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10224		return;
10225	mac->mac_noise.noi_running = 1;
10226	mac->mac_noise.noi_nsamples = 0;
10227
10228	bwn_noise_gensample(mac);
10229}
10230
10231static void
10232bwn_task_60s(struct bwn_mac *mac)
10233{
10234
10235	if (mac->mac_phy.task_60s)
10236		mac->mac_phy.task_60s(mac);
10237	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10238}
10239
10240static void
10241bwn_tasks(void *arg)
10242{
10243	struct bwn_mac *mac = arg;
10244	struct bwn_softc *sc = mac->mac_sc;
10245
10246	BWN_ASSERT_LOCKED(sc);
10247	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10248		return;
10249
10250	if (mac->mac_task_state % 4 == 0)
10251		bwn_task_60s(mac);
10252	if (mac->mac_task_state % 2 == 0)
10253		bwn_task_30s(mac);
10254	bwn_task_15s(mac);
10255
10256	mac->mac_task_state++;
10257	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10258}
10259
10260static int
10261bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10262{
10263	struct bwn_softc *sc = mac->mac_sc;
10264
10265	KASSERT(a == 0, ("not support APHY\n"));
10266
10267	switch (plcp->o.raw[0] & 0xf) {
10268	case 0xb:
10269		return (BWN_OFDM_RATE_6MB);
10270	case 0xf:
10271		return (BWN_OFDM_RATE_9MB);
10272	case 0xa:
10273		return (BWN_OFDM_RATE_12MB);
10274	case 0xe:
10275		return (BWN_OFDM_RATE_18MB);
10276	case 0x9:
10277		return (BWN_OFDM_RATE_24MB);
10278	case 0xd:
10279		return (BWN_OFDM_RATE_36MB);
10280	case 0x8:
10281		return (BWN_OFDM_RATE_48MB);
10282	case 0xc:
10283		return (BWN_OFDM_RATE_54MB);
10284	}
10285	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10286	    plcp->o.raw[0] & 0xf);
10287	return (-1);
10288}
10289
10290static int
10291bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10292{
10293	struct bwn_softc *sc = mac->mac_sc;
10294
10295	switch (plcp->o.raw[0]) {
10296	case 0x0a:
10297		return (BWN_CCK_RATE_1MB);
10298	case 0x14:
10299		return (BWN_CCK_RATE_2MB);
10300	case 0x37:
10301		return (BWN_CCK_RATE_5MB);
10302	case 0x6e:
10303		return (BWN_CCK_RATE_11MB);
10304	}
10305	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10306	return (-1);
10307}
10308
10309static void
10310bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10311    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10312    int rssi, int noise)
10313{
10314	struct bwn_softc *sc = mac->mac_sc;
10315	const struct ieee80211_frame_min *wh;
10316	uint64_t tsf;
10317	uint16_t low_mactime_now;
10318
10319	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10320		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10321
10322	wh = mtod(m, const struct ieee80211_frame_min *);
10323	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10324		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10325
10326	bwn_tsf_read(mac, &tsf);
10327	low_mactime_now = tsf;
10328	tsf = tsf & ~0xffffULL;
10329	tsf += le16toh(rxhdr->mac_time);
10330	if (low_mactime_now < le16toh(rxhdr->mac_time))
10331		tsf -= 0x10000;
10332
10333	sc->sc_rx_th.wr_tsf = tsf;
10334	sc->sc_rx_th.wr_rate = rate;
10335	sc->sc_rx_th.wr_antsignal = rssi;
10336	sc->sc_rx_th.wr_antnoise = noise;
10337}
10338
10339static void
10340bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10341{
10342	uint32_t low, high;
10343
10344	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10345	    ("%s:%d: fail", __func__, __LINE__));
10346
10347	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10348	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10349	*tsf = high;
10350	*tsf <<= 32;
10351	*tsf |= low;
10352}
10353
10354static int
10355bwn_dma_attach(struct bwn_mac *mac)
10356{
10357	struct bwn_dma *dma = &mac->mac_method.dma;
10358	struct bwn_softc *sc = mac->mac_sc;
10359	bus_addr_t lowaddr = 0;
10360	int error;
10361
10362	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10363		return (0);
10364
10365	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10366
10367	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10368
10369	dma->dmatype = bwn_dma_gettype(mac);
10370	if (dma->dmatype == BWN_DMA_30BIT)
10371		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10372	else if (dma->dmatype == BWN_DMA_32BIT)
10373		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10374	else
10375		lowaddr = BUS_SPACE_MAXADDR;
10376
10377	/*
10378	 * Create top level DMA tag
10379	 */
10380	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10381			       BWN_ALIGN, 0,		/* alignment, bounds */
10382			       lowaddr,			/* lowaddr */
10383			       BUS_SPACE_MAXADDR,	/* highaddr */
10384			       NULL, NULL,		/* filter, filterarg */
10385			       MAXBSIZE,		/* maxsize */
10386			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10387			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10388			       0,			/* flags */
10389			       NULL, NULL,		/* lockfunc, lockarg */
10390			       &dma->parent_dtag);
10391	if (error) {
10392		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10393		return (error);
10394	}
10395
10396	/*
10397	 * Create TX/RX mbuf DMA tag
10398	 */
10399	error = bus_dma_tag_create(dma->parent_dtag,
10400				1,
10401				0,
10402				BUS_SPACE_MAXADDR,
10403				BUS_SPACE_MAXADDR,
10404				NULL, NULL,
10405				MCLBYTES,
10406				1,
10407				BUS_SPACE_MAXSIZE_32BIT,
10408				0,
10409				NULL, NULL,
10410				&dma->rxbuf_dtag);
10411	if (error) {
10412		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10413		goto fail0;
10414	}
10415	error = bus_dma_tag_create(dma->parent_dtag,
10416				1,
10417				0,
10418				BUS_SPACE_MAXADDR,
10419				BUS_SPACE_MAXADDR,
10420				NULL, NULL,
10421				MCLBYTES,
10422				1,
10423				BUS_SPACE_MAXSIZE_32BIT,
10424				0,
10425				NULL, NULL,
10426				&dma->txbuf_dtag);
10427	if (error) {
10428		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10429		goto fail1;
10430	}
10431
10432	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10433	if (!dma->wme[WME_AC_BK])
10434		goto fail2;
10435
10436	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10437	if (!dma->wme[WME_AC_BE])
10438		goto fail3;
10439
10440	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10441	if (!dma->wme[WME_AC_VI])
10442		goto fail4;
10443
10444	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10445	if (!dma->wme[WME_AC_VO])
10446		goto fail5;
10447
10448	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10449	if (!dma->mcast)
10450		goto fail6;
10451	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10452	if (!dma->rx)
10453		goto fail7;
10454
10455	return (error);
10456
10457fail7:	bwn_dma_ringfree(&dma->mcast);
10458fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10459fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10460fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10461fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10462fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10463fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10464fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10465	return (error);
10466}
10467
10468static struct bwn_dma_ring *
10469bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10470    uint16_t cookie, int *slot)
10471{
10472	struct bwn_dma *dma = &mac->mac_method.dma;
10473	struct bwn_dma_ring *dr;
10474	struct bwn_softc *sc = mac->mac_sc;
10475
10476	BWN_ASSERT_LOCKED(mac->mac_sc);
10477
10478	switch (cookie & 0xf000) {
10479	case 0x1000:
10480		dr = dma->wme[WME_AC_BK];
10481		break;
10482	case 0x2000:
10483		dr = dma->wme[WME_AC_BE];
10484		break;
10485	case 0x3000:
10486		dr = dma->wme[WME_AC_VI];
10487		break;
10488	case 0x4000:
10489		dr = dma->wme[WME_AC_VO];
10490		break;
10491	case 0x5000:
10492		dr = dma->mcast;
10493		break;
10494	default:
10495		dr = NULL;
10496		KASSERT(0 == 1,
10497		    ("invalid cookie value %d", cookie & 0xf000));
10498	}
10499	*slot = (cookie & 0x0fff);
10500	if (*slot < 0 || *slot >= dr->dr_numslots) {
10501		/*
10502		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10503		 * that it occurs events which have same H/W sequence numbers.
10504		 * When it's occurred just prints a WARNING msgs and ignores.
10505		 */
10506		KASSERT(status->seq == dma->lastseq,
10507		    ("%s:%d: fail", __func__, __LINE__));
10508		device_printf(sc->sc_dev,
10509		    "out of slot ranges (0 < %d < %d)\n", *slot,
10510		    dr->dr_numslots);
10511		return (NULL);
10512	}
10513	dma->lastseq = status->seq;
10514	return (dr);
10515}
10516
10517static void
10518bwn_dma_stop(struct bwn_mac *mac)
10519{
10520	struct bwn_dma *dma;
10521
10522	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10523		return;
10524	dma = &mac->mac_method.dma;
10525
10526	bwn_dma_ringstop(&dma->rx);
10527	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10528	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10529	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10530	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10531	bwn_dma_ringstop(&dma->mcast);
10532}
10533
10534static void
10535bwn_dma_ringstop(struct bwn_dma_ring **dr)
10536{
10537
10538	if (dr == NULL)
10539		return;
10540
10541	bwn_dma_cleanup(*dr);
10542}
10543
10544static void
10545bwn_pio_stop(struct bwn_mac *mac)
10546{
10547	struct bwn_pio *pio;
10548
10549	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10550		return;
10551	pio = &mac->mac_method.pio;
10552
10553	bwn_destroy_queue_tx(&pio->mcast);
10554	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10555	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10556	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10557	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10558}
10559
10560static void
10561bwn_led_attach(struct bwn_mac *mac)
10562{
10563	struct bwn_softc *sc = mac->mac_sc;
10564	const uint8_t *led_act = NULL;
10565	uint16_t val[BWN_LED_MAX];
10566	int i;
10567
10568	sc->sc_led_idle = (2350 * hz) / 1000;
10569	sc->sc_led_blink = 1;
10570
10571	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10572		if (siba_get_pci_subvendor(sc->sc_dev) ==
10573		    bwn_vendor_led_act[i].vid) {
10574			led_act = bwn_vendor_led_act[i].led_act;
10575			break;
10576		}
10577	}
10578	if (led_act == NULL)
10579		led_act = bwn_default_led_act;
10580
10581	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10582	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10583	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10584	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10585
10586	for (i = 0; i < BWN_LED_MAX; ++i) {
10587		struct bwn_led *led = &sc->sc_leds[i];
10588
10589		if (val[i] == 0xff) {
10590			led->led_act = led_act[i];
10591		} else {
10592			if (val[i] & BWN_LED_ACT_LOW)
10593				led->led_flags |= BWN_LED_F_ACTLOW;
10594			led->led_act = val[i] & BWN_LED_ACT_MASK;
10595		}
10596		led->led_mask = (1 << i);
10597
10598		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10599		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10600		    led->led_act == BWN_LED_ACT_BLINK) {
10601			led->led_flags |= BWN_LED_F_BLINK;
10602			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10603				led->led_flags |= BWN_LED_F_POLLABLE;
10604			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10605				led->led_flags |= BWN_LED_F_SLOW;
10606
10607			if (sc->sc_blink_led == NULL) {
10608				sc->sc_blink_led = led;
10609				if (led->led_flags & BWN_LED_F_SLOW)
10610					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10611			}
10612		}
10613
10614		DPRINTF(sc, BWN_DEBUG_LED,
10615		    "%dth led, act %d, lowact %d\n", i,
10616		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10617	}
10618	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10619}
10620
10621static __inline uint16_t
10622bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10623{
10624
10625	if (led->led_flags & BWN_LED_F_ACTLOW)
10626		on = !on;
10627	if (on)
10628		val |= led->led_mask;
10629	else
10630		val &= ~led->led_mask;
10631	return val;
10632}
10633
10634static void
10635bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10636{
10637	struct bwn_softc *sc = mac->mac_sc;
10638	struct ifnet *ifp = sc->sc_ifp;
10639	struct ieee80211com *ic = ifp->if_l2com;
10640	uint16_t val;
10641	int i;
10642
10643	if (nstate == IEEE80211_S_INIT) {
10644		callout_stop(&sc->sc_led_blink_ch);
10645		sc->sc_led_blinking = 0;
10646	}
10647
10648	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10649		return;
10650
10651	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10652	for (i = 0; i < BWN_LED_MAX; ++i) {
10653		struct bwn_led *led = &sc->sc_leds[i];
10654		int on;
10655
10656		if (led->led_act == BWN_LED_ACT_UNKN ||
10657		    led->led_act == BWN_LED_ACT_NULL)
10658			continue;
10659
10660		if ((led->led_flags & BWN_LED_F_BLINK) &&
10661		    nstate != IEEE80211_S_INIT)
10662			continue;
10663
10664		switch (led->led_act) {
10665		case BWN_LED_ACT_ON:    /* Always on */
10666			on = 1;
10667			break;
10668		case BWN_LED_ACT_OFF:   /* Always off */
10669		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10670			on = 0;
10671			break;
10672		default:
10673			on = 1;
10674			switch (nstate) {
10675			case IEEE80211_S_INIT:
10676				on = 0;
10677				break;
10678			case IEEE80211_S_RUN:
10679				if (led->led_act == BWN_LED_ACT_11G &&
10680				    ic->ic_curmode != IEEE80211_MODE_11G)
10681					on = 0;
10682				break;
10683			default:
10684				if (led->led_act == BWN_LED_ACT_ASSOC)
10685					on = 0;
10686				break;
10687			}
10688			break;
10689		}
10690
10691		val = bwn_led_onoff(led, val, on);
10692	}
10693	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10694}
10695
10696static void
10697bwn_led_event(struct bwn_mac *mac, int event)
10698{
10699	struct bwn_softc *sc = mac->mac_sc;
10700	struct bwn_led *led = sc->sc_blink_led;
10701	int rate;
10702
10703	if (event == BWN_LED_EVENT_POLL) {
10704		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10705			return;
10706		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10707			return;
10708	}
10709
10710	sc->sc_led_ticks = ticks;
10711	if (sc->sc_led_blinking)
10712		return;
10713
10714	switch (event) {
10715	case BWN_LED_EVENT_RX:
10716		rate = sc->sc_rx_rate;
10717		break;
10718	case BWN_LED_EVENT_TX:
10719		rate = sc->sc_tx_rate;
10720		break;
10721	case BWN_LED_EVENT_POLL:
10722		rate = 0;
10723		break;
10724	default:
10725		panic("unknown LED event %d\n", event);
10726		break;
10727	}
10728	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10729	    bwn_led_duration[rate].off_dur);
10730}
10731
10732static void
10733bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10734{
10735	struct bwn_softc *sc = mac->mac_sc;
10736	struct bwn_led *led = sc->sc_blink_led;
10737	uint16_t val;
10738
10739	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10740	val = bwn_led_onoff(led, val, 1);
10741	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10742
10743	if (led->led_flags & BWN_LED_F_SLOW) {
10744		BWN_LED_SLOWDOWN(on_dur);
10745		BWN_LED_SLOWDOWN(off_dur);
10746	}
10747
10748	sc->sc_led_blinking = 1;
10749	sc->sc_led_blink_offdur = off_dur;
10750
10751	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10752}
10753
10754static void
10755bwn_led_blink_next(void *arg)
10756{
10757	struct bwn_mac *mac = arg;
10758	struct bwn_softc *sc = mac->mac_sc;
10759	uint16_t val;
10760
10761	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10762	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10763	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10764
10765	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10766	    bwn_led_blink_end, mac);
10767}
10768
10769static void
10770bwn_led_blink_end(void *arg)
10771{
10772	struct bwn_mac *mac = arg;
10773	struct bwn_softc *sc = mac->mac_sc;
10774
10775	sc->sc_led_blinking = 0;
10776}
10777
10778static int
10779bwn_suspend(device_t dev)
10780{
10781	struct bwn_softc *sc = device_get_softc(dev);
10782
10783	bwn_stop(sc, 1);
10784	return (0);
10785}
10786
10787static int
10788bwn_resume(device_t dev)
10789{
10790	struct bwn_softc *sc = device_get_softc(dev);
10791	struct ifnet *ifp = sc->sc_ifp;
10792
10793	if (ifp->if_flags & IFF_UP)
10794		bwn_init(sc);
10795	return (0);
10796}
10797
10798static void
10799bwn_rfswitch(void *arg)
10800{
10801	struct bwn_softc *sc = arg;
10802	struct bwn_mac *mac = sc->sc_curmac;
10803	int cur = 0, prev = 0;
10804
10805	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10806	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10807
10808	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10809		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10810			& BWN_RF_HWENABLED_HI_MASK))
10811			cur = 1;
10812	} else {
10813		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10814		    & BWN_RF_HWENABLED_LO_MASK)
10815			cur = 1;
10816	}
10817
10818	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10819		prev = 1;
10820
10821	if (cur != prev) {
10822		if (cur)
10823			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10824		else
10825			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10826
10827		device_printf(sc->sc_dev,
10828		    "status of RF switch is changed to %s\n",
10829		    cur ? "ON" : "OFF");
10830		if (cur != mac->mac_phy.rf_on) {
10831			if (cur)
10832				bwn_rf_turnon(mac);
10833			else
10834				bwn_rf_turnoff(mac);
10835		}
10836	}
10837
10838	callout_schedule(&sc->sc_rfswitch_ch, hz);
10839}
10840
10841static void
10842bwn_phy_lp_init_pre(struct bwn_mac *mac)
10843{
10844	struct bwn_phy *phy = &mac->mac_phy;
10845	struct bwn_phy_lp *plp = &phy->phy_lp;
10846
10847	plp->plp_antenna = BWN_ANT_DEFAULT;
10848}
10849
10850static int
10851bwn_phy_lp_init(struct bwn_mac *mac)
10852{
10853	static const struct bwn_stxtable tables[] = {
10854		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10855		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10856		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10857		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10858		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10859		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10860		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10861		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10862		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10863		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10864		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10865		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10866		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10867		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10868		{ 2, 11, 0x40, 0, 0x0f }
10869	};
10870	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10871	struct bwn_softc *sc = mac->mac_sc;
10872	const struct bwn_stxtable *st;
10873	struct ifnet *ifp = sc->sc_ifp;
10874	struct ieee80211com *ic = ifp->if_l2com;
10875	int i, error;
10876	uint16_t tmp;
10877
10878	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10879	bwn_phy_lp_bbinit(mac);
10880
10881	/* initialize RF */
10882	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10883	DELAY(1);
10884	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10885	DELAY(1);
10886
10887	if (mac->mac_phy.rf_ver == 0x2062)
10888		bwn_phy_lp_b2062_init(mac);
10889	else {
10890		bwn_phy_lp_b2063_init(mac);
10891
10892		/* synchronize stx table. */
10893		for (i = 0; i < N(tables); i++) {
10894			st = &tables[i];
10895			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10896			tmp >>= st->st_rfshift;
10897			tmp <<= st->st_physhift;
10898			BWN_PHY_SETMASK(mac,
10899			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10900			    ~(st->st_mask << st->st_physhift), tmp);
10901		}
10902
10903		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10904		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10905	}
10906
10907	/* calibrate RC */
10908	if (mac->mac_phy.rev >= 2)
10909		bwn_phy_lp_rxcal_r2(mac);
10910	else if (!plp->plp_rccap) {
10911		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10912			bwn_phy_lp_rccal_r12(mac);
10913	} else
10914		bwn_phy_lp_set_rccap(mac);
10915
10916	error = bwn_phy_lp_switch_channel(mac, 7);
10917	if (error)
10918		device_printf(sc->sc_dev,
10919		    "failed to change channel 7 (%d)\n", error);
10920	bwn_phy_lp_txpctl_init(mac);
10921	bwn_phy_lp_calib(mac);
10922	return (0);
10923}
10924
10925static uint16_t
10926bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10927{
10928
10929	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10930	return (BWN_READ_2(mac, BWN_PHYDATA));
10931}
10932
10933static void
10934bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10935{
10936
10937	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10938	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10939}
10940
10941static void
10942bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10943    uint16_t set)
10944{
10945
10946	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10947	BWN_WRITE_2(mac, BWN_PHYDATA,
10948	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10949}
10950
10951static uint16_t
10952bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10953{
10954
10955	KASSERT(reg != 1, ("unaccessible register %d", reg));
10956	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10957		reg |= 0x100;
10958	if (mac->mac_phy.rev >= 2)
10959		reg |= 0x200;
10960	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10961	return BWN_READ_2(mac, BWN_RFDATALO);
10962}
10963
10964static void
10965bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10966{
10967
10968	KASSERT(reg != 1, ("unaccessible register %d", reg));
10969	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10970	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10971}
10972
10973static void
10974bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10975{
10976
10977	if (on) {
10978		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10979		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10980		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10981		return;
10982	}
10983
10984	if (mac->mac_phy.rev >= 2) {
10985		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10986		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10987		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10988		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10989		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10990		return;
10991	}
10992
10993	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10994	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10995	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10996	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10997}
10998
10999static int
11000bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11001{
11002	struct bwn_phy *phy = &mac->mac_phy;
11003	struct bwn_phy_lp *plp = &phy->phy_lp;
11004	int error;
11005
11006	if (phy->rf_ver == 0x2063) {
11007		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11008		if (error)
11009			return (error);
11010	} else {
11011		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11012		if (error)
11013			return (error);
11014		bwn_phy_lp_set_anafilter(mac, chan);
11015		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11016	}
11017
11018	plp->plp_chan = chan;
11019	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11020	return (0);
11021}
11022
11023static uint32_t
11024bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11025{
11026	struct bwn_softc *sc = mac->mac_sc;
11027	struct ifnet *ifp = sc->sc_ifp;
11028	struct ieee80211com *ic = ifp->if_l2com;
11029
11030	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11031}
11032
11033static void
11034bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11035{
11036	struct bwn_phy *phy = &mac->mac_phy;
11037	struct bwn_phy_lp *plp = &phy->phy_lp;
11038
11039	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11040		return;
11041
11042	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11043	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11044	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11045	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11046	plp->plp_antenna = antenna;
11047}
11048
11049static void
11050bwn_phy_lp_task_60s(struct bwn_mac *mac)
11051{
11052
11053	bwn_phy_lp_calib(mac);
11054}
11055
11056static void
11057bwn_phy_lp_readsprom(struct bwn_mac *mac)
11058{
11059	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11060	struct bwn_softc *sc = mac->mac_sc;
11061	struct ifnet *ifp = sc->sc_ifp;
11062	struct ieee80211com *ic = ifp->if_l2com;
11063
11064	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11065		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11066		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11067		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11068		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11069		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11070		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11071		return;
11072	}
11073
11074	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11075	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11076	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11077	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11078	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11079	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11080	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11081	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11082}
11083
11084static void
11085bwn_phy_lp_bbinit(struct bwn_mac *mac)
11086{
11087
11088	bwn_phy_lp_tblinit(mac);
11089	if (mac->mac_phy.rev >= 2)
11090		bwn_phy_lp_bbinit_r2(mac);
11091	else
11092		bwn_phy_lp_bbinit_r01(mac);
11093}
11094
11095static void
11096bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11097{
11098	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11099	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11100	struct bwn_softc *sc = mac->mac_sc;
11101	struct ifnet *ifp = sc->sc_ifp;
11102	struct ieee80211com *ic = ifp->if_l2com;
11103
11104	bwn_phy_lp_set_txgain(mac,
11105	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11106	bwn_phy_lp_set_bbmult(mac, 150);
11107}
11108
11109static void
11110bwn_phy_lp_calib(struct bwn_mac *mac)
11111{
11112	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11113	struct bwn_softc *sc = mac->mac_sc;
11114	struct ifnet *ifp = sc->sc_ifp;
11115	struct ieee80211com *ic = ifp->if_l2com;
11116	const struct bwn_rxcompco *rc = NULL;
11117	struct bwn_txgain ogain;
11118	int i, omode, oafeovr, orf, obbmult;
11119	uint8_t mode, fc = 0;
11120
11121	if (plp->plp_chanfullcal != plp->plp_chan) {
11122		plp->plp_chanfullcal = plp->plp_chan;
11123		fc = 1;
11124	}
11125
11126	bwn_mac_suspend(mac);
11127
11128	/* BlueTooth Coexistance Override */
11129	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11130	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11131
11132	if (mac->mac_phy.rev >= 2)
11133		bwn_phy_lp_digflt_save(mac);
11134	bwn_phy_lp_get_txpctlmode(mac);
11135	mode = plp->plp_txpctlmode;
11136	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11137	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11138		bwn_phy_lp_bugfix(mac);
11139	if (mac->mac_phy.rev >= 2 && fc == 1) {
11140		bwn_phy_lp_get_txpctlmode(mac);
11141		omode = plp->plp_txpctlmode;
11142		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11143		if (oafeovr)
11144			ogain = bwn_phy_lp_get_txgain(mac);
11145		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11146		obbmult = bwn_phy_lp_get_bbmult(mac);
11147		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11148		if (oafeovr)
11149			bwn_phy_lp_set_txgain(mac, &ogain);
11150		bwn_phy_lp_set_bbmult(mac, obbmult);
11151		bwn_phy_lp_set_txpctlmode(mac, omode);
11152		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11153	}
11154	bwn_phy_lp_set_txpctlmode(mac, mode);
11155	if (mac->mac_phy.rev >= 2)
11156		bwn_phy_lp_digflt_restore(mac);
11157
11158	/* do RX IQ Calculation; assumes that noise is true. */
11159	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11160		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11161			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11162				rc = &bwn_rxcompco_5354[i];
11163		}
11164	} else if (mac->mac_phy.rev >= 2)
11165		rc = &bwn_rxcompco_r2;
11166	else {
11167		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11168			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11169				rc = &bwn_rxcompco_r12[i];
11170		}
11171	}
11172	if (rc == NULL)
11173		goto fail;
11174
11175	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11176	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11177
11178	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11179
11180	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11181		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11182		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11183	} else {
11184		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11185		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11186	}
11187
11188	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11189	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11190	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11191	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11192	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11193	bwn_phy_lp_set_deaf(mac, 0);
11194	/* XXX no checking return value? */
11195	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11196	bwn_phy_lp_clear_deaf(mac, 0);
11197	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11198	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11199	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11200
11201	/* disable RX GAIN override. */
11202	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11203	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11204	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11205	if (mac->mac_phy.rev >= 2) {
11206		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11207		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11208			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11209			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11210		}
11211	} else {
11212		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11213	}
11214
11215	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11216	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11217fail:
11218	bwn_mac_enable(mac);
11219}
11220
11221static void
11222bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11223{
11224
11225	if (on) {
11226		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11227		return;
11228	}
11229
11230	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11231	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11232}
11233
11234static int
11235bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11236{
11237	static const struct bwn_b206x_chan *bc = NULL;
11238	struct bwn_softc *sc = mac->mac_sc;
11239	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11240	    tmp[6];
11241	uint16_t old, scale, tmp16;
11242	int i, div;
11243
11244	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11245		if (bwn_b2063_chantable[i].bc_chan == chan) {
11246			bc = &bwn_b2063_chantable[i];
11247			break;
11248		}
11249	}
11250	if (bc == NULL)
11251		return (EINVAL);
11252
11253	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11254	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11255	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11256	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11257	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11258	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11259	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11260	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11261	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11262	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11263	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11264	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11265
11266	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11267	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11268
11269	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11270	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11271	freqref = freqxtal * 3;
11272	div = (freqxtal <= 26000000 ? 1 : 2);
11273	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11274	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11275		999999) / 1000000) + 1;
11276
11277	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11278	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11279	    0xfff8, timeout >> 2);
11280	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11281	    0xff9f,timeout << 5);
11282	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11283
11284	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11285	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11286	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11287
11288	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11289	    (timeoutref + 1)) - 1;
11290	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11291	    0xf0, count >> 8);
11292	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11293
11294	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11295	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11296	while (tmp[1] >= freqref) {
11297		tmp[0]++;
11298		tmp[1] -= freqref;
11299	}
11300	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11301	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11302	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11303	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11304	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11305
11306	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11307	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11308	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11309	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11310
11311	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11312	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11313
11314	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11315		scale = 1;
11316		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11317	} else {
11318		scale = 0;
11319		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11320	}
11321	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11322	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11323
11324	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11325	    (scale + 1);
11326	if (tmp[5] > 150)
11327		tmp[5] = 0;
11328
11329	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11330	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11331
11332	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11333	if (freqxtal > 26000000)
11334		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11335	else
11336		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11337
11338	if (val[0] == 45)
11339		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11340	else
11341		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11342
11343	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11344	DELAY(1);
11345	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11346
11347	/* VCO Calibration */
11348	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11349	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11351	DELAY(1);
11352	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11353	DELAY(1);
11354	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11355	DELAY(1);
11356	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11357	DELAY(300);
11358	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11359
11360	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11361	return (0);
11362}
11363
11364static int
11365bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11366{
11367	struct bwn_softc *sc = mac->mac_sc;
11368	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11369	const struct bwn_b206x_chan *bc = NULL;
11370	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11371	uint32_t tmp[9];
11372	int i;
11373
11374	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11375		if (bwn_b2062_chantable[i].bc_chan == chan) {
11376			bc = &bwn_b2062_chantable[i];
11377			break;
11378		}
11379	}
11380
11381	if (bc == NULL)
11382		return (EINVAL);
11383
11384	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11385	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11386	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11387	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11388	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11389	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11390	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11391	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11392	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11393	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11394
11395	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11396	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11397	bwn_phy_lp_b2062_reset_pllbias(mac);
11398	tmp[0] = freqxtal / 1000;
11399	tmp[1] = plp->plp_div * 1000;
11400	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11401	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11402		tmp[2] *= 2;
11403	tmp[3] = 48 * tmp[0];
11404	tmp[5] = tmp[2] / tmp[3];
11405	tmp[6] = tmp[2] % tmp[3];
11406	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11407	tmp[4] = tmp[6] * 0x100;
11408	tmp[5] = tmp[4] / tmp[3];
11409	tmp[6] = tmp[4] % tmp[3];
11410	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11411	tmp[4] = tmp[6] * 0x100;
11412	tmp[5] = tmp[4] / tmp[3];
11413	tmp[6] = tmp[4] % tmp[3];
11414	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11415	tmp[4] = tmp[6] * 0x100;
11416	tmp[5] = tmp[4] / tmp[3];
11417	tmp[6] = tmp[4] % tmp[3];
11418	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11419	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11420	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11421	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11422	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11423	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11424
11425	bwn_phy_lp_b2062_vco_calib(mac);
11426	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11427		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11428		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11429		bwn_phy_lp_b2062_reset_pllbias(mac);
11430		bwn_phy_lp_b2062_vco_calib(mac);
11431		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11432			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11433			return (EIO);
11434		}
11435	}
11436	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11437	return (0);
11438}
11439
11440static void
11441bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11442{
11443	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11444	uint16_t tmp = (channel == 14);
11445
11446	if (mac->mac_phy.rev < 2) {
11447		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11448		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11449			bwn_phy_lp_set_rccap(mac);
11450		return;
11451	}
11452
11453	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11454}
11455
11456static void
11457bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11458{
11459	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11460	struct bwn_softc *sc = mac->mac_sc;
11461	struct ifnet *ifp = sc->sc_ifp;
11462	struct ieee80211com *ic = ifp->if_l2com;
11463	uint16_t iso, tmp[3];
11464
11465	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11466
11467	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11468		iso = plp->plp_txisoband_m;
11469	else if (freq <= 5320)
11470		iso = plp->plp_txisoband_l;
11471	else if (freq <= 5700)
11472		iso = plp->plp_txisoband_m;
11473	else
11474		iso = plp->plp_txisoband_h;
11475
11476	tmp[0] = ((iso - 26) / 12) << 12;
11477	tmp[1] = tmp[0] + 0x1000;
11478	tmp[2] = tmp[0] + 0x2000;
11479
11480	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11481	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11482}
11483
11484static void
11485bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11486{
11487	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11488	int i;
11489	static const uint16_t addr[] = {
11490		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11491		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11492		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11493		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11494		BWN_PHY_OFDM(0xcf),
11495	};
11496	static const uint16_t val[] = {
11497		0xde5e, 0xe832, 0xe331, 0x4d26,
11498		0x0026, 0x1420, 0x0020, 0xfe08,
11499		0x0008,
11500	};
11501
11502	for (i = 0; i < N(addr); i++) {
11503		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11504		BWN_PHY_WRITE(mac, addr[i], val[i]);
11505	}
11506}
11507
11508static void
11509bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11510{
11511	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11512	struct bwn_softc *sc = mac->mac_sc;
11513	uint16_t ctl;
11514
11515	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11516	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11517	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11518		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11519		break;
11520	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11521		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11522		break;
11523	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11524		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11525		break;
11526	default:
11527		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11528		device_printf(sc->sc_dev, "unknown command mode\n");
11529		break;
11530	}
11531}
11532
11533static void
11534bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11535{
11536	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11537	uint16_t ctl;
11538	uint8_t old;
11539
11540	bwn_phy_lp_get_txpctlmode(mac);
11541	old = plp->plp_txpctlmode;
11542	if (old == mode)
11543		return;
11544	plp->plp_txpctlmode = mode;
11545
11546	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11547		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11548		    plp->plp_tssiidx);
11549		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11550		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11551
11552		/* disable TX GAIN override */
11553		if (mac->mac_phy.rev < 2)
11554			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11555		else {
11556			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11557			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11558		}
11559		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11560
11561		plp->plp_txpwridx = -1;
11562	}
11563	if (mac->mac_phy.rev >= 2) {
11564		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11565			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11566		else
11567			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11568	}
11569
11570	/* writes TX Power Control mode */
11571	switch (plp->plp_txpctlmode) {
11572	case BWN_PHYLP_TXPCTL_OFF:
11573		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11574		break;
11575	case BWN_PHYLP_TXPCTL_ON_HW:
11576		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11577		break;
11578	case BWN_PHYLP_TXPCTL_ON_SW:
11579		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11580		break;
11581	default:
11582		ctl = 0;
11583		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11584	}
11585	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11586	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11587}
11588
11589static void
11590bwn_phy_lp_bugfix(struct bwn_mac *mac)
11591{
11592	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11593	struct bwn_softc *sc = mac->mac_sc;
11594	const unsigned int size = 256;
11595	struct bwn_txgain tg;
11596	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11597	uint16_t tssinpt, tssiidx, value[2];
11598	uint8_t mode;
11599	int8_t txpwridx;
11600
11601	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11602	    M_NOWAIT | M_ZERO);
11603	if (tabs == NULL) {
11604		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11605		return;
11606	}
11607
11608	bwn_phy_lp_get_txpctlmode(mac);
11609	mode = plp->plp_txpctlmode;
11610	txpwridx = plp->plp_txpwridx;
11611	tssinpt = plp->plp_tssinpt;
11612	tssiidx = plp->plp_tssiidx;
11613
11614	bwn_tab_read_multi(mac,
11615	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11616	    BWN_TAB_4(7, 0x140), size, tabs);
11617
11618	bwn_phy_lp_tblinit(mac);
11619	bwn_phy_lp_bbinit(mac);
11620	bwn_phy_lp_txpctl_init(mac);
11621	bwn_phy_lp_rf_onoff(mac, 1);
11622	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11623
11624	bwn_tab_write_multi(mac,
11625	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11626	    BWN_TAB_4(7, 0x140), size, tabs);
11627
11628	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11629	plp->plp_tssinpt = tssinpt;
11630	plp->plp_tssiidx = tssiidx;
11631	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11632	if (txpwridx != -1) {
11633		/* set TX power by index */
11634		plp->plp_txpwridx = txpwridx;
11635		bwn_phy_lp_get_txpctlmode(mac);
11636		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11637			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11638		if (mac->mac_phy.rev >= 2) {
11639			rxcomp = bwn_tab_read(mac,
11640			    BWN_TAB_4(7, txpwridx + 320));
11641			txgain = bwn_tab_read(mac,
11642			    BWN_TAB_4(7, txpwridx + 192));
11643			tg.tg_pad = (txgain >> 16) & 0xff;
11644			tg.tg_gm = txgain & 0xff;
11645			tg.tg_pga = (txgain >> 8) & 0xff;
11646			tg.tg_dac = (rxcomp >> 28) & 0xff;
11647			bwn_phy_lp_set_txgain(mac, &tg);
11648		} else {
11649			rxcomp = bwn_tab_read(mac,
11650			    BWN_TAB_4(10, txpwridx + 320));
11651			txgain = bwn_tab_read(mac,
11652			    BWN_TAB_4(10, txpwridx + 192));
11653			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11654			    0xf800, (txgain >> 4) & 0x7fff);
11655			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11656			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11657		}
11658		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11659
11660		/* set TX IQCC */
11661		value[0] = (rxcomp >> 10) & 0x3ff;
11662		value[1] = rxcomp & 0x3ff;
11663		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11664
11665		coeff = bwn_tab_read(mac,
11666		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11667		    BWN_TAB_4(10, txpwridx + 448));
11668		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11669		if (mac->mac_phy.rev >= 2) {
11670			rfpwr = bwn_tab_read(mac,
11671			    BWN_TAB_4(7, txpwridx + 576));
11672			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11673			    rfpwr & 0xffff);
11674		}
11675		bwn_phy_lp_set_txgain_override(mac);
11676	}
11677	if (plp->plp_rccap)
11678		bwn_phy_lp_set_rccap(mac);
11679	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11680	bwn_phy_lp_set_txpctlmode(mac, mode);
11681	free(tabs, M_DEVBUF);
11682}
11683
11684static void
11685bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11686{
11687	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11688	int i;
11689	static const uint16_t addr[] = {
11690		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11691		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11692		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11693		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11694		BWN_PHY_OFDM(0xcf),
11695	};
11696
11697	for (i = 0; i < N(addr); i++)
11698		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11699}
11700
11701static void
11702bwn_phy_lp_tblinit(struct bwn_mac *mac)
11703{
11704	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11705
11706	if (mac->mac_phy.rev < 2) {
11707		bwn_phy_lp_tblinit_r01(mac);
11708		bwn_phy_lp_tblinit_txgain(mac);
11709		bwn_phy_lp_set_gaintbl(mac, freq);
11710		return;
11711	}
11712
11713	bwn_phy_lp_tblinit_r2(mac);
11714	bwn_phy_lp_tblinit_txgain(mac);
11715}
11716
11717struct bwn_wpair {
11718	uint16_t		reg;
11719	uint16_t		value;
11720};
11721
11722struct bwn_smpair {
11723	uint16_t		offset;
11724	uint16_t		mask;
11725	uint16_t		set;
11726};
11727
11728static void
11729bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11730{
11731	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11732	struct bwn_softc *sc = mac->mac_sc;
11733	struct ifnet *ifp = sc->sc_ifp;
11734	struct ieee80211com *ic = ifp->if_l2com;
11735	static const struct bwn_wpair v1[] = {
11736		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11737		{ BWN_PHY_AFE_CTL, 0x8800 },
11738		{ BWN_PHY_AFE_CTL_OVR, 0 },
11739		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11740		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11741		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11742		{ BWN_PHY_OFDM(0xf9), 0 },
11743		{ BWN_PHY_TR_LOOKUP_1, 0 }
11744	};
11745	static const struct bwn_smpair v2[] = {
11746		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11747		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11748		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11749		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11750		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11751	};
11752	static const struct bwn_smpair v3[] = {
11753		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11754		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11755		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11756		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11757		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11758		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11759		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11760		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11761		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11762		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11763
11764	};
11765	int i;
11766
11767	for (i = 0; i < N(v1); i++)
11768		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11769	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11770	for (i = 0; i < N(v2); i++)
11771		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11772
11773	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11774	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11775	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11776	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11777		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11778		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11779	} else {
11780		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11781	}
11782	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11783	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11784	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11785	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11786	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11787	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11788	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11789	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11790	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11791	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11792	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11793	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11794	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11795		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11796		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11797	} else {
11798		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11799		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11800	}
11801	for (i = 0; i < N(v3); i++)
11802		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11803	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11804	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11805		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11806		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11807	}
11808
11809	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11810		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11811		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11812		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11813		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11814		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11815		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11816	} else
11817		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11818
11819	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11820	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11821	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11822	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11823	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11824	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11825	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11826	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11827	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11828
11829	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11830	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11831		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11832		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11833		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11834	}
11835
11836	bwn_phy_lp_digflt_save(mac);
11837}
11838
11839static void
11840bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11841{
11842	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11843	struct bwn_softc *sc = mac->mac_sc;
11844	struct ifnet *ifp = sc->sc_ifp;
11845	struct ieee80211com *ic = ifp->if_l2com;
11846	static const struct bwn_smpair v1[] = {
11847		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11848		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11849		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11850		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11851		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11852		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11853		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11854	};
11855	static const struct bwn_smpair v2[] = {
11856		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11857		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11858		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11859		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11860		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11861		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11862		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11863		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11864		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11865		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11866		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11867		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11868		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11869		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11870		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11871		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11872	};
11873	static const struct bwn_smpair v3[] = {
11874		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11875		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11876		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11877		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11878		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11879		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11880		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11881		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11882	};
11883	static const struct bwn_smpair v4[] = {
11884		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11885		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11886		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11887		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11888		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11889		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11890		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11891		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11892	};
11893	static const struct bwn_smpair v5[] = {
11894		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11895		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11896		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11897		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11898		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11899		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11900		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11901		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11902	};
11903	int i;
11904	uint16_t tmp, tmp2;
11905
11906	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11907	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11908	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11909	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11910	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11911	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11912	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11913	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11914	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11915	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11916	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11917	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11918	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11919	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11920	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11921	for (i = 0; i < N(v1); i++)
11922		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11923	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11924	    0xff00, plp->plp_rxpwroffset);
11925	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11926	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11927	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11928		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11929		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11930		if (mac->mac_phy.rev == 0)
11931			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11932			    0xffcf, 0x0010);
11933		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11934	} else {
11935		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11936		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11937		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11938	}
11939	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11940	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11941	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11942		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11943	else
11944		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11945	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11946	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11947	    0xfff9, (plp->plp_bxarch << 1));
11948	if (mac->mac_phy.rev == 1 &&
11949	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11950		for (i = 0; i < N(v2); i++)
11951			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11952			    v2[i].set);
11953	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11954	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11955	    ((mac->mac_phy.rev == 0) &&
11956	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11957		for (i = 0; i < N(v3); i++)
11958			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11959			    v3[i].set);
11960	} else if (mac->mac_phy.rev == 1 ||
11961		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11962		for (i = 0; i < N(v4); i++)
11963			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11964			    v4[i].set);
11965	} else {
11966		for (i = 0; i < N(v5); i++)
11967			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11968			    v5[i].set);
11969	}
11970	if (mac->mac_phy.rev == 1 &&
11971	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11972		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11973		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11974		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11975		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11976	}
11977	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11978	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11979	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11980		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11981		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11982		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11983		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11984	}
11985	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11986		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11987		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11988		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11989		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11990		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11991		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11992		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11993		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11994	} else {
11995		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11996		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11997	}
11998	if (mac->mac_phy.rev == 1) {
11999		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12000		tmp2 = (tmp & 0x03e0) >> 5;
12001		tmp2 |= tmp2 << 5;
12002		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12003		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12004		tmp2 = (tmp & 0x1f00) >> 8;
12005		tmp2 |= tmp2 << 5;
12006		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12007		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12008		tmp2 = tmp & 0x00ff;
12009		tmp2 |= tmp << 8;
12010		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12011	}
12012}
12013
12014struct bwn_b2062_freq {
12015	uint16_t		freq;
12016	uint8_t			value[6];
12017};
12018
12019static void
12020bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12021{
12022#define	CALC_CTL7(freq, div)						\
12023	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12024#define	CALC_CTL18(freq, div)						\
12025	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12026#define	CALC_CTL19(freq, div)						\
12027	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12028	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12029	struct bwn_softc *sc = mac->mac_sc;
12030	struct ifnet *ifp = sc->sc_ifp;
12031	struct ieee80211com *ic = ifp->if_l2com;
12032	static const struct bwn_b2062_freq freqdata_tab[] = {
12033		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12034		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12035		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12036		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12037		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12038		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12039	};
12040	static const struct bwn_wpair v1[] = {
12041		{ BWN_B2062_N_TXCTL3, 0 },
12042		{ BWN_B2062_N_TXCTL4, 0 },
12043		{ BWN_B2062_N_TXCTL5, 0 },
12044		{ BWN_B2062_N_TXCTL6, 0 },
12045		{ BWN_B2062_N_PDNCTL0, 0x40 },
12046		{ BWN_B2062_N_PDNCTL0, 0 },
12047		{ BWN_B2062_N_CALIB_TS, 0x10 },
12048		{ BWN_B2062_N_CALIB_TS, 0 }
12049	};
12050	const struct bwn_b2062_freq *f = NULL;
12051	uint32_t xtalfreq, ref;
12052	unsigned int i;
12053
12054	bwn_phy_lp_b2062_tblinit(mac);
12055
12056	for (i = 0; i < N(v1); i++)
12057		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12058	if (mac->mac_phy.rev > 0)
12059		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12060		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12061	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12062		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12063	else
12064		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12065
12066	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12067	    ("%s:%d: fail", __func__, __LINE__));
12068	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12069	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12070
12071	if (xtalfreq <= 30000000) {
12072		plp->plp_div = 1;
12073		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12074	} else {
12075		plp->plp_div = 2;
12076		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12077	}
12078
12079	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12080	    CALC_CTL7(xtalfreq, plp->plp_div));
12081	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12082	    CALC_CTL18(xtalfreq, plp->plp_div));
12083	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12084	    CALC_CTL19(xtalfreq, plp->plp_div));
12085
12086	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12087	ref &= 0xffff;
12088	for (i = 0; i < N(freqdata_tab); i++) {
12089		if (ref < freqdata_tab[i].freq) {
12090			f = &freqdata_tab[i];
12091			break;
12092		}
12093	}
12094	if (f == NULL)
12095		f = &freqdata_tab[N(freqdata_tab) - 1];
12096	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12097	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12098	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12099	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12100	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12101	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12102#undef CALC_CTL7
12103#undef CALC_CTL18
12104#undef CALC_CTL19
12105}
12106
12107static void
12108bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12109{
12110
12111	bwn_phy_lp_b2063_tblinit(mac);
12112	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12113	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12114	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12115	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12116	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12117	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12118	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12119	if (mac->mac_phy.rev == 2) {
12120		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12121		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12122		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12123	} else {
12124		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12125		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12126	}
12127}
12128
12129static void
12130bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12131{
12132	struct bwn_softc *sc = mac->mac_sc;
12133	static const struct bwn_wpair v1[] = {
12134		{ BWN_B2063_RX_BB_SP8, 0x0 },
12135		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12136		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12137		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12138		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12139		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12140		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12141		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12142	};
12143	static const struct bwn_wpair v2[] = {
12144		{ BWN_B2063_TX_BB_SP3, 0x0 },
12145		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12146		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12147		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12148		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12149	};
12150	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12151	int i;
12152	uint8_t tmp;
12153
12154	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12155
12156	for (i = 0; i < 2; i++)
12157		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12158	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12159	for (i = 2; i < N(v1); i++)
12160		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12161	for (i = 0; i < 10000; i++) {
12162		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12163			break;
12164		DELAY(1000);
12165	}
12166
12167	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12168		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12169
12170	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12171
12172	for (i = 0; i < N(v2); i++)
12173		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12174	if (freqxtal == 24000000) {
12175		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12176		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12177	} else {
12178		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12179		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12180	}
12181	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12182	for (i = 0; i < 10000; i++) {
12183		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12184			break;
12185		DELAY(1000);
12186	}
12187	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12188		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12189	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12190}
12191
12192static void
12193bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12194{
12195	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12196	struct bwn_softc *sc = mac->mac_sc;
12197	struct bwn_phy_lp_iq_est ie;
12198	struct bwn_txgain tx_gains;
12199	static const uint32_t pwrtbl[21] = {
12200		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12201		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12202		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12203		0x0004c, 0x0002c, 0x0001a,
12204	};
12205	uint32_t npwr, ipwr, sqpwr, tmp;
12206	int loopback, i, j, sum, error;
12207	uint16_t save[7];
12208	uint8_t txo, bbmult, txpctlmode;
12209
12210	error = bwn_phy_lp_switch_channel(mac, 7);
12211	if (error)
12212		device_printf(sc->sc_dev,
12213		    "failed to change channel to 7 (%d)\n", error);
12214	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12215	bbmult = bwn_phy_lp_get_bbmult(mac);
12216	if (txo)
12217		tx_gains = bwn_phy_lp_get_txgain(mac);
12218
12219	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12220	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12221	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12222	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12223	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12224	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12225	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12226
12227	bwn_phy_lp_get_txpctlmode(mac);
12228	txpctlmode = plp->plp_txpctlmode;
12229	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12230
12231	/* disable CRS */
12232	bwn_phy_lp_set_deaf(mac, 1);
12233	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12234	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12235	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12236	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12237	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12238	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12239	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12240	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12241	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12242	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12243	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12244	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12245	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12246	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12247	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12248	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12249	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12250	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12251	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12252	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12253	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12254	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12255	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12256	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12257
12258	loopback = bwn_phy_lp_loopback(mac);
12259	if (loopback == -1)
12260		goto done;
12261	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12262	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12263	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12264	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12265	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12266
12267	tmp = 0;
12268	memset(&ie, 0, sizeof(ie));
12269	for (i = 128; i <= 159; i++) {
12270		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12271		sum = 0;
12272		for (j = 5; j <= 25; j++) {
12273			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12274			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12275				goto done;
12276			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12277			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12278			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12279			    12);
12280			sum += ((ipwr - npwr) * (ipwr - npwr));
12281			if ((i == 128) || (sum < tmp)) {
12282				plp->plp_rccap = i;
12283				tmp = sum;
12284			}
12285		}
12286	}
12287	bwn_phy_lp_ddfs_turnoff(mac);
12288done:
12289	/* restore CRS */
12290	bwn_phy_lp_clear_deaf(mac, 1);
12291	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12292	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12293
12294	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12295	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12296	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12297	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12298	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12299	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12300	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12301
12302	bwn_phy_lp_set_bbmult(mac, bbmult);
12303	if (txo)
12304		bwn_phy_lp_set_txgain(mac, &tx_gains);
12305	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12306	if (plp->plp_rccap)
12307		bwn_phy_lp_set_rccap(mac);
12308}
12309
12310static void
12311bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12312{
12313	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12314	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12315
12316	if (mac->mac_phy.rev == 1)
12317		rc_cap = MIN(rc_cap + 5, 15);
12318
12319	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12320	    MAX(plp->plp_rccap - 4, 0x80));
12321	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12322	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12323	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12324}
12325
12326static uint32_t
12327bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12328{
12329	uint32_t i, q, r;
12330
12331	if (div == 0)
12332		return (0);
12333
12334	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12335		q <<= 1;
12336		if (r << 1 >= div) {
12337			q++;
12338			r = (r << 1) - div;
12339		}
12340	}
12341	if (r << 1 >= div)
12342		q++;
12343	return (q);
12344}
12345
12346static void
12347bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12348{
12349	struct bwn_softc *sc = mac->mac_sc;
12350
12351	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12352	DELAY(20);
12353	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12354		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12355		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12356	} else {
12357		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12358	}
12359	DELAY(5);
12360}
12361
12362static void
12363bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12364{
12365
12366	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12367	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12368	DELAY(200);
12369}
12370
12371static void
12372bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12373{
12374#define	FLAG_A	0x01
12375#define	FLAG_G	0x02
12376	struct bwn_softc *sc = mac->mac_sc;
12377	struct ifnet *ifp = sc->sc_ifp;
12378	struct ieee80211com *ic = ifp->if_l2com;
12379	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12380		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12381		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12382		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12383		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12384		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12385		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12386		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12387		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12388		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12389		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12390		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12391		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12392		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12393		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12394		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12399		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12400		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12427	};
12428	const struct bwn_b206x_rfinit_entry *br;
12429	unsigned int i;
12430
12431	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12432		br = &bwn_b2062_init_tab[i];
12433		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12434			if (br->br_flags & FLAG_G)
12435				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12436		} else {
12437			if (br->br_flags & FLAG_A)
12438				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12439		}
12440	}
12441#undef FLAG_A
12442#undef FLAG_B
12443}
12444
12445static void
12446bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12447{
12448#define	FLAG_A	0x01
12449#define	FLAG_G	0x02
12450	struct bwn_softc *sc = mac->mac_sc;
12451	struct ifnet *ifp = sc->sc_ifp;
12452	struct ieee80211com *ic = ifp->if_l2com;
12453	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12454		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12455		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12456		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12457		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12458		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12459		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12460		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12461		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12462		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12463		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12464		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12465		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12466		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12467		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12468		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12469		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12470		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12471		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12472		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12473		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12474		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12475		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12476		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12477		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12478		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12479		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12480		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12482		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12483		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12484		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12485		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12487		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12488		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12491		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12492		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12493		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12494		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12495		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12496	};
12497	const struct bwn_b206x_rfinit_entry *br;
12498	unsigned int i;
12499
12500	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12501		br = &bwn_b2063_init_tab[i];
12502		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12503			if (br->br_flags & FLAG_G)
12504				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12505		} else {
12506			if (br->br_flags & FLAG_A)
12507				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12508		}
12509	}
12510#undef FLAG_A
12511#undef FLAG_B
12512}
12513
12514static void
12515bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12516    int count, void *_data)
12517{
12518	unsigned int i;
12519	uint32_t offset, type;
12520	uint8_t *data = _data;
12521
12522	type = BWN_TAB_GETTYPE(typenoffset);
12523	offset = BWN_TAB_GETOFFSET(typenoffset);
12524	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12525
12526	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12527
12528	for (i = 0; i < count; i++) {
12529		switch (type) {
12530		case BWN_TAB_8BIT:
12531			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12532			data++;
12533			break;
12534		case BWN_TAB_16BIT:
12535			*((uint16_t *)data) = BWN_PHY_READ(mac,
12536			    BWN_PHY_TABLEDATALO);
12537			data += 2;
12538			break;
12539		case BWN_TAB_32BIT:
12540			*((uint32_t *)data) = BWN_PHY_READ(mac,
12541			    BWN_PHY_TABLEDATAHI);
12542			*((uint32_t *)data) <<= 16;
12543			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12544			    BWN_PHY_TABLEDATALO);
12545			data += 4;
12546			break;
12547		default:
12548			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12549		}
12550	}
12551}
12552
12553static void
12554bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12555    int count, const void *_data)
12556{
12557	uint32_t offset, type, value;
12558	const uint8_t *data = _data;
12559	unsigned int i;
12560
12561	type = BWN_TAB_GETTYPE(typenoffset);
12562	offset = BWN_TAB_GETOFFSET(typenoffset);
12563	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12564
12565	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12566
12567	for (i = 0; i < count; i++) {
12568		switch (type) {
12569		case BWN_TAB_8BIT:
12570			value = *data;
12571			data++;
12572			KASSERT(!(value & ~0xff),
12573			    ("%s:%d: fail", __func__, __LINE__));
12574			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12575			break;
12576		case BWN_TAB_16BIT:
12577			value = *((const uint16_t *)data);
12578			data += 2;
12579			KASSERT(!(value & ~0xffff),
12580			    ("%s:%d: fail", __func__, __LINE__));
12581			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12582			break;
12583		case BWN_TAB_32BIT:
12584			value = *((const uint32_t *)data);
12585			data += 4;
12586			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12587			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12588			break;
12589		default:
12590			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12591		}
12592	}
12593}
12594
12595static struct bwn_txgain
12596bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12597{
12598	struct bwn_txgain tg;
12599	uint16_t tmp;
12600
12601	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12602	if (mac->mac_phy.rev < 2) {
12603		tmp = BWN_PHY_READ(mac,
12604		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12605		tg.tg_gm = tmp & 0x0007;
12606		tg.tg_pga = (tmp & 0x0078) >> 3;
12607		tg.tg_pad = (tmp & 0x780) >> 7;
12608		return (tg);
12609	}
12610
12611	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12612	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12613	tg.tg_gm = tmp & 0xff;
12614	tg.tg_pga = (tmp >> 8) & 0xff;
12615	return (tg);
12616}
12617
12618static uint8_t
12619bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12620{
12621
12622	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12623}
12624
12625static void
12626bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12627{
12628	uint16_t pa;
12629
12630	if (mac->mac_phy.rev < 2) {
12631		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12632		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12633		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12634		bwn_phy_lp_set_txgain_override(mac);
12635		return;
12636	}
12637
12638	pa = bwn_phy_lp_get_pa_gain(mac);
12639	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12640	    (tg->tg_pga << 8) | tg->tg_gm);
12641	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12642	    tg->tg_pad | (pa << 6));
12643	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12644	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12645	    tg->tg_pad | (pa << 8));
12646	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12647	bwn_phy_lp_set_txgain_override(mac);
12648}
12649
12650static void
12651bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12652{
12653
12654	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12655}
12656
12657static void
12658bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12659{
12660	uint16_t trsw = (tx << 1) | rx;
12661
12662	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12663	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12664}
12665
12666static void
12667bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12668{
12669	struct bwn_softc *sc = mac->mac_sc;
12670	struct ifnet *ifp = sc->sc_ifp;
12671	struct ieee80211com *ic = ifp->if_l2com;
12672	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12673
12674	if (mac->mac_phy.rev < 2) {
12675		trsw = gain & 0x1;
12676		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12677		ext_lna = (gain & 2) >> 1;
12678
12679		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12680		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12681		    0xfbff, ext_lna << 10);
12682		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12683		    0xf7ff, ext_lna << 11);
12684		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12685	} else {
12686		low_gain = gain & 0xffff;
12687		high_gain = (gain >> 16) & 0xf;
12688		ext_lna = (gain >> 21) & 0x1;
12689		trsw = ~(gain >> 20) & 0x1;
12690
12691		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12692		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12693		    0xfdff, ext_lna << 9);
12694		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12695		    0xfbff, ext_lna << 10);
12696		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12697		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12698		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12699			tmp = (gain >> 2) & 0x3;
12700			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12701			    0xe7ff, tmp<<11);
12702			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12703			    tmp << 3);
12704		}
12705	}
12706
12707	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12708	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12709	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12710	if (mac->mac_phy.rev >= 2) {
12711		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12712		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12713			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12714			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12715		}
12716		return;
12717	}
12718	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12719}
12720
12721static void
12722bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12723{
12724	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12725
12726	if (user)
12727		plp->plp_crsusr_off = 1;
12728	else
12729		plp->plp_crssys_off = 1;
12730
12731	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12732}
12733
12734static void
12735bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12736{
12737	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12738	struct bwn_softc *sc = mac->mac_sc;
12739	struct ifnet *ifp = sc->sc_ifp;
12740	struct ieee80211com *ic = ifp->if_l2com;
12741
12742	if (user)
12743		plp->plp_crsusr_off = 0;
12744	else
12745		plp->plp_crssys_off = 0;
12746
12747	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12748		return;
12749
12750	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12751		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12752	else
12753		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12754}
12755
12756static unsigned int
12757bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12758{
12759	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12760	static uint8_t sqrt_table[256] = {
12761		10, 14, 17, 20, 22, 24, 26, 28,
12762		30, 31, 33, 34, 36, 37, 38, 40,
12763		41, 42, 43, 44, 45, 46, 47, 48,
12764		50, 50, 51, 52, 53, 54, 55, 56,
12765		57, 58, 59, 60, 60, 61, 62, 63,
12766		64, 64, 65, 66, 67, 67, 68, 69,
12767		70, 70, 71, 72, 72, 73, 74, 74,
12768		75, 76, 76, 77, 78, 78, 79, 80,
12769		80, 81, 81, 82, 83, 83, 84, 84,
12770		85, 86, 86, 87, 87, 88, 88, 89,
12771		90, 90, 91, 91, 92, 92, 93, 93,
12772		94, 94, 95, 95, 96, 96, 97, 97,
12773		98, 98, 99, 100, 100, 100, 101, 101,
12774		102, 102, 103, 103, 104, 104, 105, 105,
12775		106, 106, 107, 107, 108, 108, 109, 109,
12776		110, 110, 110, 111, 111, 112, 112, 113,
12777		113, 114, 114, 114, 115, 115, 116, 116,
12778		117, 117, 117, 118, 118, 119, 119, 120,
12779		120, 120, 121, 121, 122, 122, 122, 123,
12780		123, 124, 124, 124, 125, 125, 126, 126,
12781		126, 127, 127, 128, 128, 128, 129, 129,
12782		130, 130, 130, 131, 131, 131, 132, 132,
12783		133, 133, 133, 134, 134, 134, 135, 135,
12784		136, 136, 136, 137, 137, 137, 138, 138,
12785		138, 139, 139, 140, 140, 140, 141, 141,
12786		141, 142, 142, 142, 143, 143, 143, 144,
12787		144, 144, 145, 145, 145, 146, 146, 146,
12788		147, 147, 147, 148, 148, 148, 149, 149,
12789		150, 150, 150, 150, 151, 151, 151, 152,
12790		152, 152, 153, 153, 153, 154, 154, 154,
12791		155, 155, 155, 156, 156, 156, 157, 157,
12792		157, 158, 158, 158, 159, 159, 159, 160
12793	};
12794
12795	if (x == 0)
12796		return (0);
12797	if (x >= 256) {
12798		unsigned int tmp;
12799
12800		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12801			/* do nothing */ ;
12802		return (tmp);
12803	}
12804	return (sqrt_table[x - 1] / 10);
12805}
12806
12807static int
12808bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12809{
12810#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12811	int _t;								\
12812	_t = _x - 20;							\
12813	if (_t >= 0) {							\
12814		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12815	} else {							\
12816		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12817	}								\
12818} while (0)
12819#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12820	int _t;								\
12821	_t = _x - 11;							\
12822	if (_t >= 0)							\
12823		_v = (_y << (31 - _x)) / (_z >> _t);			\
12824	else								\
12825		_v = (_y << (31 - _x)) / (_z << -_t);			\
12826} while (0)
12827	struct bwn_phy_lp_iq_est ie;
12828	uint16_t v0, v1;
12829	int tmp[2], ret;
12830
12831	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12832	v0 = v1 >> 8;
12833	v1 |= 0xff;
12834
12835	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12836	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12837
12838	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12839	if (ret == 0)
12840		goto done;
12841
12842	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12843		ret = 0;
12844		goto done;
12845	}
12846
12847	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12848	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12849
12850	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12851	v0 = tmp[0] >> 3;
12852	v1 = tmp[1] >> 4;
12853done:
12854	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12855	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12856	return ret;
12857#undef CALC_COEFF
12858#undef CALC_COEFF2
12859}
12860
12861static void
12862bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12863{
12864	static const uint16_t noisescale[] = {
12865		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12866		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12867		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12868		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12869		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12870	};
12871	static const uint16_t crsgainnft[] = {
12872		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12873		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12874		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12875		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12876		0x013d,
12877	};
12878	static const uint16_t filterctl[] = {
12879		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12880		0xff53, 0x0127,
12881	};
12882	static const uint32_t psctl[] = {
12883		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12884		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12885		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12886		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12887		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12888		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12889		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12890		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12891	};
12892	static const uint16_t ofdmcckgain_r0[] = {
12893		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12894		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12895		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12896		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12897		0x755d,
12898	};
12899	static const uint16_t ofdmcckgain_r1[] = {
12900		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12901		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12902		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12903		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12904		0x755d,
12905	};
12906	static const uint16_t gaindelta[] = {
12907		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12908		0x0000,
12909	};
12910	static const uint32_t txpwrctl[] = {
12911		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12912		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12913		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12914		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12915		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12916		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12917		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12918		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12919		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12920		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12921		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12922		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12923		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12924		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12950		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12951		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12952		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12953		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12954		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12955		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12956		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12957		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12958		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12959		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12960		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12961		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12962		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12963		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12964		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12965		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12966		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12967		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12968		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12969		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12970		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12971		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12972		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12973		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12974		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12975		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12976		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12977		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12978		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12979		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12980		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12981		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12982		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12983		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12984		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12985		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12986		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12987		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12988		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12989		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12990		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12991		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12992		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12993		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12994		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12995		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12996		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12997		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12998		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12999		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13000		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13001		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13002		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13003		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13004		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13005		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13006		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13007		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13008		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13009		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13010		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13011		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13012		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13013		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13014		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13015		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13016		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13017		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13018		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13019		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13020		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13021		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13022		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13023		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13024		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13025		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13026		0x00000702,
13027	};
13028
13029	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13030
13031	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13032	    bwn_tab_sigsq_tbl);
13033	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13034	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13035	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13036	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13037	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13038	    bwn_tab_pllfrac_tbl);
13039	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13040	    bwn_tabl_iqlocal_tbl);
13041	if (mac->mac_phy.rev == 0) {
13042		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13043		    ofdmcckgain_r0);
13044		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13045		    ofdmcckgain_r0);
13046	} else {
13047		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13048		    ofdmcckgain_r1);
13049		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13050		    ofdmcckgain_r1);
13051	}
13052	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13053	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13054}
13055
13056static void
13057bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13058{
13059	struct bwn_softc *sc = mac->mac_sc;
13060	int i;
13061	static const uint16_t noisescale[] = {
13062		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13068		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13069	};
13070	static const uint32_t filterctl[] = {
13071		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13072		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13073	};
13074	static const uint32_t psctl[] = {
13075		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13076		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13077		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13078		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13079	};
13080	static const uint32_t gainidx[] = {
13081		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13084		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13085		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13086		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13087		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13088		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13089		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13090		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13091		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13092		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13093		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13094		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13095		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13096		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13099		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13100		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13101		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13102		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13103		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13104		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13105		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13106		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13107		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13108		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13109		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13110		0x0000001a, 0x64ca55ad, 0x0000001a
13111	};
13112	static const uint16_t auxgainidx[] = {
13113		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13114		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13115		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13116		0x0004, 0x0016
13117	};
13118	static const uint16_t swctl[] = {
13119		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13121		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13122		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13123		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13124		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13125		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13126		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13127	};
13128	static const uint8_t hf[] = {
13129		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13130		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13131	};
13132	static const uint32_t gainval[] = {
13133		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13134		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13135		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13136		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13137		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13138		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13139		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13142		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13143		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13144		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13145		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13146		0x000000f1, 0x00000000, 0x00000000
13147	};
13148	static const uint16_t gain[] = {
13149		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13150		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13151		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13152		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13153		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13154		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13155		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13160		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13161	};
13162	static const uint32_t papdeps[] = {
13163		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13164		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13165		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13166		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13167		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13168		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13169		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13170		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13171		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13172		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13173		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13174		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13175		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13176	};
13177	static const uint32_t papdmult[] = {
13178		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13179		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13180		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13181		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13182		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13183		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13184		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13185		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13186		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13187		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13188		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13189		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13190		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13191	};
13192	static const uint32_t gainidx_a0[] = {
13193		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13194		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13195		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13196		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13197		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13198		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13199		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13200		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13201		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13202		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13203		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13204		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13205		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13206	};
13207	static const uint16_t auxgainidx_a0[] = {
13208		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13209		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13210		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13211		0x0002, 0x0014
13212	};
13213	static const uint32_t gainval_a0[] = {
13214		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13215		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13216		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13217		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13218		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13219		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13220		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13221		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13222		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13223		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13224		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13225		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13226		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13227		0x000000f7, 0x00000000, 0x00000000
13228	};
13229	static const uint16_t gain_a0[] = {
13230		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13231		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13232		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13233		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13234		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13235		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13236		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13241		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13242	};
13243
13244	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13245
13246	for (i = 0; i < 704; i++)
13247		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13248
13249	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13250	    bwn_tab_sigsq_tbl);
13251	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13252	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13253	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13254	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13255	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13256	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13257	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13258	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13259	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13260	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13261	    bwn_tab_pllfrac_tbl);
13262	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13263	    bwn_tabl_iqlocal_tbl);
13264	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13265	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13266
13267	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13268	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13269		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13270		    gainidx_a0);
13271		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13272		    auxgainidx_a0);
13273		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13274		    gainval_a0);
13275		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13276	}
13277}
13278
13279static void
13280bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13281{
13282	struct bwn_softc *sc = mac->mac_sc;
13283	struct ifnet *ifp = sc->sc_ifp;
13284	struct ieee80211com *ic = ifp->if_l2com;
13285	static struct bwn_txgain_entry txgain_r2[] = {
13286		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13287		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13288		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13289		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13290		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13291		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13292		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13293		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13294		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13295		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13296		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13297		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13298		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13299		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13300		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13301		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13302		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13303		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13304		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13305		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13306		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13307		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13308		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13309		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13310		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13311		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13312		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13313		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13314		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13315		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13316		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13317		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13318		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13319		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13320		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13321		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13322		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13323		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13324		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13325		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13326		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13327		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13328		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13329		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13330		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13331		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13332		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13333		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13334		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13335		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13336		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13337		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13338		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13339		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13340		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13341		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13342		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13343		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13344		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13345		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13346		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13347		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13348		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13349		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13350	};
13351	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13352		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13353		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13354		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13355		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13356		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13357		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13358		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13359		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13360		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13361		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13362		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13363		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13364		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13365		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13366		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13367		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13368		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13369		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13370		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13371		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13372		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13373		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13374		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13375		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13376		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13377		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13378		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13379		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13380		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13381		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13382		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13383		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13384		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13385		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13386		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13387		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13388		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13389		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13390		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13391		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13392		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13393		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13394		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13395		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13396		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13397		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13398		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13399		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13400		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13401		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13402		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13403		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13404		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13405		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13406		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13407		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13408		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13409		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13410		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13411		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13412		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13413		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13414		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13415		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13416	};
13417	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13418		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13419		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13420		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13421		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13422		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13423		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13424		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13425		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13426		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13427		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13428		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13429		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13430		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13431		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13432		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13433		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13434		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13435		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13436		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13437		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13438		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13439		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13440		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13441		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13442		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13443		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13444		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13445		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13446		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13447		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13448		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13449		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13450		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13451		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13452		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13453		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13454		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13455		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13456		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13457		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13458		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13459		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13460		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13461		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13462		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13463		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13464		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13465		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13466		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13467		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13468		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13469		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13470		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13471		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13472		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13473		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13474		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13475		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13476		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13477		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13478		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13479		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13480		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13481		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13482	};
13483	static struct bwn_txgain_entry txgain_r0[] = {
13484		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13485		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13486		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13487		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13488		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13489		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13490		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13491		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13492		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13493		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13494		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13495		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13496		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13497		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13498		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13499		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13500		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13501		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13502		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13503		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13504		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13505		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13506		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13507		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13508		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13509		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13510		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13511		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13512		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13513		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13514		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13515		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13516		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13517		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13518		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13519		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13520		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13521		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13522		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13523		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13524		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13525		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13526		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13527		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13528		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13529		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13530		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13531		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13532		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13533		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13534		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13535		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13536		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13537		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13538		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13539		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13540		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13541		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13542		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13543		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13544		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13545		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13546		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13547		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13548	};
13549	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13550		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13551		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13552		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13553		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13554		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13555		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13556		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13557		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13558		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13559		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13560		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13561		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13562		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13563		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13564		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13565		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13566		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13567		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13568		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13569		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13570		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13571		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13572		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13573		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13574		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13575		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13576		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13577		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13578		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13579		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13580		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13581		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13582		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13583		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13584		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13585		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13586		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13587		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13588		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13589		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13590		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13591		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13592		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13593		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13594		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13595		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13596		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13597		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13598		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13599		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13600		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13601		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13602		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13603		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13604		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13605		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13606		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13607		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13608		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13609		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13610		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13611		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13612		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13613		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13614	};
13615	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13616		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13617		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13618		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13619		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13620		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13621		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13622		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13623		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13624		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13625		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13626		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13627		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13628		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13629		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13630		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13631		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13632		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13633		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13634		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13635		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13636		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13637		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13638		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13639		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13640		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13641		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13642		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13643		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13644		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13645		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13646		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13647		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13648		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13649		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13650		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13651		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13652		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13653		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13654		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13655		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13656		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13657		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13658		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13659		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13660		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13661		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13662		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13663		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13664		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13665		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13666		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13667		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13668		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13669		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13670		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13671		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13672		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13673		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13674		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13675		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13676		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13677		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13678		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13679		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13680	};
13681	static struct bwn_txgain_entry txgain_r1[] = {
13682		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13683		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13684		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13685		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13686		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13687		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13688		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13689		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13690		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13691		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13692		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13693		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13694		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13695		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13696		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13697		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13698		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13699		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13700		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13701		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13702		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13703		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13704		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13705		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13706		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13707		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13708		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13709		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13710		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13711		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13712		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13713		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13714		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13715		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13716		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13717		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13718		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13719		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13720		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13721		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13722		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13723		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13724		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13725		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13726		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13727		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13728		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13729		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13730		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13731		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13732		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13733		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13734		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13735		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13736		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13737		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13738		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13739		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13740		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13741		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13742		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13743		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13744		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13745		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13746		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13747		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13748		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13749		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13750		{ 7, 11, 6, 0, 71 }
13751	};
13752	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13753		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13754		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13755		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13756		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13757		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13758		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13759		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13760		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13761		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13762		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13763		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13764		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13765		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13766		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13767		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13768		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13769		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13770		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13771		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13772		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13773		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13774		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13775		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13776		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13777		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13778		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13779		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13780		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13781		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13782		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13783		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13784		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13785		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13786		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13787		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13788		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13789		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13790		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13791		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13792		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13793		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13794		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13795		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13796		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13797		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13798		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13799		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13800		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13801		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13802		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13803		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13804		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13805		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13806		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13807		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13808		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13809		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13810		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13811		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13812		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13813		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13814		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13815		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13816		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13817	};
13818	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13819		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13820		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13821		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13822		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13823		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13824		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13825		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13826		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13827		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13828		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13829		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13830		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13831		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13832		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13833		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13834		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13835		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13836		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13837		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13838		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13839		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13840		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13841		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13842		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13843		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13844		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13845		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13846		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13847		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13848		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13849		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13850		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13851		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13852		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13853		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13854		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13855		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13856		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13857		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13858		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13859		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13860		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13861		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13862		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13863		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13864		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13865		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13866		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13867		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13868		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13869		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13870		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13871		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13872		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13873		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13874		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13875		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13876		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13877		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13878		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13879		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13880		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13881		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13882		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13883	};
13884
13885	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13886		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13887			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13888		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13889			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13890			    txgain_2ghz_r2);
13891		else
13892			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13893			    txgain_5ghz_r2);
13894		return;
13895	}
13896
13897	if (mac->mac_phy.rev == 0) {
13898		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13899		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13900			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13901		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13902			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13903			    txgain_2ghz_r0);
13904		else
13905			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13906			    txgain_5ghz_r0);
13907		return;
13908	}
13909
13910	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13911	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13912		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13913	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13914		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13915	else
13916		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13917}
13918
13919static void
13920bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13921{
13922	uint32_t offset, type;
13923
13924	type = BWN_TAB_GETTYPE(typeoffset);
13925	offset = BWN_TAB_GETOFFSET(typeoffset);
13926	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13927
13928	switch (type) {
13929	case BWN_TAB_8BIT:
13930		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13931		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13932		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13933		break;
13934	case BWN_TAB_16BIT:
13935		KASSERT(!(value & ~0xffff),
13936		    ("%s:%d: fail", __func__, __LINE__));
13937		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13938		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13939		break;
13940	case BWN_TAB_32BIT:
13941		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13942		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13943		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13944		break;
13945	default:
13946		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13947	}
13948}
13949
13950static int
13951bwn_phy_lp_loopback(struct bwn_mac *mac)
13952{
13953	struct bwn_phy_lp_iq_est ie;
13954	int i, index = -1;
13955	uint32_t tmp;
13956
13957	memset(&ie, 0, sizeof(ie));
13958
13959	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13960	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13961	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13962	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13963	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13964	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13965	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13966	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13967	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13968	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13969	for (i = 0; i < 32; i++) {
13970		bwn_phy_lp_set_rxgain_idx(mac, i);
13971		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13972		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13973			continue;
13974		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13975		if ((tmp > 4000) && (tmp < 10000)) {
13976			index = i;
13977			break;
13978		}
13979	}
13980	bwn_phy_lp_ddfs_turnoff(mac);
13981	return (index);
13982}
13983
13984static void
13985bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13986{
13987
13988	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13989}
13990
13991static void
13992bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13993    int incr1, int incr2, int scale_idx)
13994{
13995
13996	bwn_phy_lp_ddfs_turnoff(mac);
13997	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13998	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13999	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14000	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14001	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14002	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14003	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14004	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14005	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14006	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14007}
14008
14009static uint8_t
14010bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14011    struct bwn_phy_lp_iq_est *ie)
14012{
14013	int i;
14014
14015	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14016	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14017	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14018	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14019	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14020
14021	for (i = 0; i < 500; i++) {
14022		if (!(BWN_PHY_READ(mac,
14023		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14024			break;
14025		DELAY(1000);
14026	}
14027	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14028		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14029		return 0;
14030	}
14031
14032	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14033	ie->ie_iqprod <<= 16;
14034	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14035	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14036	ie->ie_ipwr <<= 16;
14037	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14038	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14039	ie->ie_qpwr <<= 16;
14040	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14041
14042	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14043	return 1;
14044}
14045
14046static uint32_t
14047bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14048{
14049	uint32_t offset, type, value;
14050
14051	type = BWN_TAB_GETTYPE(typeoffset);
14052	offset = BWN_TAB_GETOFFSET(typeoffset);
14053	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14054
14055	switch (type) {
14056	case BWN_TAB_8BIT:
14057		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14058		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14059		break;
14060	case BWN_TAB_16BIT:
14061		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14062		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14063		break;
14064	case BWN_TAB_32BIT:
14065		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14066		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14067		value <<= 16;
14068		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14069		break;
14070	default:
14071		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14072		value = 0;
14073	}
14074
14075	return (value);
14076}
14077
14078static void
14079bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14080{
14081
14082	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14083	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14084}
14085
14086static void
14087bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14088{
14089	uint16_t ctl;
14090
14091	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14092	ctl |= dac << 7;
14093	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14094}
14095
14096static void
14097bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14098{
14099
14100	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14101	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14102}
14103
14104static void
14105bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14106{
14107
14108	if (mac->mac_phy.rev < 2)
14109		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14110	else {
14111		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14112		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14113	}
14114	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14115}
14116
14117static uint16_t
14118bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14119{
14120
14121	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14122}
14123
14124static uint8_t
14125bwn_nbits(int32_t val)
14126{
14127	uint32_t tmp;
14128	uint8_t nbits = 0;
14129
14130	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14131		nbits++;
14132	return (nbits);
14133}
14134
14135static void
14136bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14137    struct bwn_txgain_entry *table)
14138{
14139	int i;
14140
14141	for (i = offset; i < count; i++)
14142		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14143}
14144
14145static void
14146bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14147    struct bwn_txgain_entry data)
14148{
14149
14150	if (mac->mac_phy.rev >= 2)
14151		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14152	else
14153		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14154}
14155
14156static void
14157bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14158    struct bwn_txgain_entry te)
14159{
14160	struct bwn_softc *sc = mac->mac_sc;
14161	struct ifnet *ifp = sc->sc_ifp;
14162	struct ieee80211com *ic = ifp->if_l2com;
14163	uint32_t tmp;
14164
14165	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14166
14167	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14168	if (mac->mac_phy.rev >= 3) {
14169		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14170		    (0x10 << 24) : (0x70 << 24));
14171	} else {
14172		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14173		    (0x14 << 24) : (0x7f << 24));
14174	}
14175	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14176	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14177	    te.te_bbmult << 20 | te.te_dac << 28);
14178}
14179
14180static void
14181bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14182    struct bwn_txgain_entry te)
14183{
14184
14185	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14186
14187	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14188	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14189	    te.te_dac);
14190	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14191}
14192
14193static void
14194bwn_sysctl_node(struct bwn_softc *sc)
14195{
14196	device_t dev = sc->sc_dev;
14197	struct bwn_mac *mac;
14198	struct bwn_stats *stats;
14199
14200	/* XXX assume that count of MAC is only 1. */
14201
14202	if ((mac = sc->sc_curmac) == NULL)
14203		return;
14204	stats = &mac->mac_stats;
14205
14206	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14207	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14208	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14209	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14210	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14211	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14212	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14213	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14214	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14215
14216#ifdef BWN_DEBUG
14217	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14218	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14219	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14220#endif
14221}
14222
14223static device_method_t bwn_methods[] = {
14224	/* Device interface */
14225	DEVMETHOD(device_probe,		bwn_probe),
14226	DEVMETHOD(device_attach,	bwn_attach),
14227	DEVMETHOD(device_detach,	bwn_detach),
14228	DEVMETHOD(device_suspend,	bwn_suspend),
14229	DEVMETHOD(device_resume,	bwn_resume),
14230	DEVMETHOD_END
14231};
14232static driver_t bwn_driver = {
14233	"bwn",
14234	bwn_methods,
14235	sizeof(struct bwn_softc)
14236};
14237static devclass_t bwn_devclass;
14238DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14239MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14240MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14241MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14242MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14243