if_bwn.c revision 285436
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 285436 2015-07-13 05:13:39Z adrian $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_var.h>
56#include <net/if_arp.h>
57#include <net/if_dl.h>
58#include <net/if_llc.h>
59#include <net/if_media.h>
60#include <net/if_types.h>
61
62#include <dev/pci/pcivar.h>
63#include <dev/pci/pcireg.h>
64#include <dev/siba/siba_ids.h>
65#include <dev/siba/sibareg.h>
66#include <dev/siba/sibavar.h>
67
68#include <net80211/ieee80211_var.h>
69#include <net80211/ieee80211_radiotap.h>
70#include <net80211/ieee80211_regdomain.h>
71#include <net80211/ieee80211_phy.h>
72#include <net80211/ieee80211_ratectl.h>
73
74#include <dev/bwn/if_bwnreg.h>
75#include <dev/bwn/if_bwnvar.h>
76
77static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
78    "Broadcom driver parameters");
79
80/*
81 * Tunable & sysctl variables.
82 */
83
84#ifdef BWN_DEBUG
85static	int bwn_debug = 0;
86SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
87    "Broadcom debugging printfs");
88enum {
89	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107	BWN_DEBUG_ANY		= 0xffffffff
108};
109#define	DPRINTF(sc, m, fmt, ...) do {			\
110	if (sc->sc_debug & (m))				\
111		printf(fmt, __VA_ARGS__);		\
112} while (0)
113#else
114#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115#endif
116
117static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119    "uses Bad Frames Preemption");
120static int	bwn_bluetooth = 1;
121SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122    "turns on Bluetooth Coexistence");
123static int	bwn_hwpctl = 0;
124SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125    "uses H/W power control");
126static int	bwn_msi_disable = 0;		/* MSI disabled  */
127TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128static int	bwn_usedma = 1;
129SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130    "uses DMA");
131TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132static int	bwn_wme = 1;
133SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134    "uses WME support");
135
136static int	bwn_attach_pre(struct bwn_softc *);
137static int	bwn_attach_post(struct bwn_softc *);
138static void	bwn_sprom_bugfixes(device_t);
139static void	bwn_init(void *);
140static int	bwn_init_locked(struct bwn_softc *);
141static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
142static void	bwn_start(struct ifnet *);
143static int	bwn_attach_core(struct bwn_mac *);
144static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145static int	bwn_phy_getinfo(struct bwn_mac *, int);
146static int	bwn_chiptest(struct bwn_mac *);
147static int	bwn_setup_channels(struct bwn_mac *, int, int);
148static int	bwn_phy_g_attach(struct bwn_mac *);
149static void	bwn_phy_g_detach(struct bwn_mac *);
150static void	bwn_phy_g_init_pre(struct bwn_mac *);
151static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152static int	bwn_phy_g_init(struct bwn_mac *);
153static void	bwn_phy_g_exit(struct bwn_mac *);
154static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156		    uint16_t);
157static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159		    uint16_t);
160static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165static int	bwn_phy_g_im(struct bwn_mac *, int);
166static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168static void	bwn_phy_g_task_15s(struct bwn_mac *);
169static void	bwn_phy_g_task_60s(struct bwn_mac *);
170static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174		    uint16_t);
175static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177		    uint32_t);
178static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179		    uint16_t);
180static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181		    const struct bwn_channelinfo *, int);
182static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183		    const struct ieee80211_bpf_params *);
184static void	bwn_updateslot(struct ieee80211com *);
185static void	bwn_update_promisc(struct ieee80211com *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static void	bwn_wme_clear(struct bwn_softc *);
189static void	bwn_wme_load(struct bwn_mac *);
190static void	bwn_wme_loadparams(struct bwn_mac *,
191		    const struct wmeParams *, uint16_t);
192static void	bwn_scan_start(struct ieee80211com *);
193static void	bwn_scan_end(struct ieee80211com *);
194static void	bwn_set_channel(struct ieee80211com *);
195static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197		    const uint8_t [IEEE80211_ADDR_LEN],
198		    const uint8_t [IEEE80211_ADDR_LEN]);
199static void	bwn_vap_delete(struct ieee80211vap *);
200static void	bwn_stop(struct bwn_softc *, int);
201static void	bwn_stop_locked(struct bwn_softc *, int);
202static int	bwn_core_init(struct bwn_mac *);
203static void	bwn_core_start(struct bwn_mac *);
204static void	bwn_core_exit(struct bwn_mac *);
205static void	bwn_bt_disable(struct bwn_mac *);
206static int	bwn_chip_init(struct bwn_mac *);
207static uint64_t	bwn_hf_read(struct bwn_mac *);
208static void	bwn_hf_write(struct bwn_mac *, uint64_t);
209static void	bwn_set_txretry(struct bwn_mac *, int, int);
210static void	bwn_rate_init(struct bwn_mac *);
211static void	bwn_set_phytxctl(struct bwn_mac *);
212static void	bwn_spu_setdelay(struct bwn_mac *, int);
213static void	bwn_bt_enable(struct bwn_mac *);
214static void	bwn_set_macaddr(struct bwn_mac *);
215static void	bwn_crypt_init(struct bwn_mac *);
216static void	bwn_chip_exit(struct bwn_mac *);
217static int	bwn_fw_fillinfo(struct bwn_mac *);
218static int	bwn_fw_loaducode(struct bwn_mac *);
219static int	bwn_gpio_init(struct bwn_mac *);
220static int	bwn_fw_loadinitvals(struct bwn_mac *);
221static int	bwn_phy_init(struct bwn_mac *);
222static void	bwn_set_txantenna(struct bwn_mac *, int);
223static void	bwn_set_opmode(struct bwn_mac *);
224static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
225static uint8_t	bwn_plcp_getcck(const uint8_t);
226static uint8_t	bwn_plcp_getofdm(const uint8_t);
227static void	bwn_pio_init(struct bwn_mac *);
228static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
229static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230		    int);
231static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
232		    struct bwn_pio_rxqueue *, int);
233static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235		    uint16_t);
236static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
238static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239static void	bwn_pio_handle_txeof(struct bwn_mac *,
240		    const struct bwn_txstatus *);
241static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244		    uint16_t);
245static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246		    uint32_t);
247static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248		    struct mbuf *);
249static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
251		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
252static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253		    uint16_t, uint32_t);
254static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
255		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
256static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
257		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259		    uint16_t, struct bwn_pio_txpkt **);
260static void	bwn_dma_init(struct bwn_mac *);
261static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262static int	bwn_dma_mask2type(uint64_t);
263static uint64_t	bwn_dma_mask(struct bwn_mac *);
264static uint16_t	bwn_dma_base(int, int);
265static void	bwn_dma_ringfree(struct bwn_dma_ring **);
266static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
267		    int, struct bwn_dmadesc_generic **,
268		    struct bwn_dmadesc_meta **);
269static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
270		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271		    int, int);
272static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
274static void	bwn_dma_32_resume(struct bwn_dma_ring *);
275static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
278		    int, struct bwn_dmadesc_generic **,
279		    struct bwn_dmadesc_meta **);
280static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
281		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282		    int, int);
283static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
285static void	bwn_dma_64_resume(struct bwn_dma_ring *);
286static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
289static void	bwn_dma_setup(struct bwn_dma_ring *);
290static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291static void	bwn_dma_cleanup(struct bwn_dma_ring *);
292static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
293static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294static void	bwn_dma_rx(struct bwn_dma_ring *);
295static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
297		    struct bwn_dmadesc_meta *);
298static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299static int	bwn_dma_gettype(struct bwn_mac *);
300static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301static int	bwn_dma_freeslot(struct bwn_dma_ring *);
302static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
303static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304static int	bwn_dma_newbuf(struct bwn_dma_ring *,
305		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306		    int);
307static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308		    bus_size_t, int);
309static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310static void	bwn_dma_handle_txeof(struct bwn_mac *,
311		    const struct bwn_txstatus *);
312static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313		    struct mbuf *);
314static int	bwn_dma_getslot(struct bwn_dma_ring *);
315static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316		    uint8_t);
317static int	bwn_dma_attach(struct bwn_mac *);
318static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319		    int, int, int);
320static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321		    const struct bwn_txstatus *, uint16_t, int *);
322static void	bwn_dma_free(struct bwn_mac *);
323static void	bwn_phy_g_init_sub(struct bwn_mac *);
324static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
325static void	bwn_phy_init_b5(struct bwn_mac *);
326static void	bwn_phy_init_b6(struct bwn_mac *);
327static void	bwn_phy_init_a(struct bwn_mac *);
328static void	bwn_loopback_calcgain(struct bwn_mac *);
329static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
330static void	bwn_lo_g_init(struct bwn_mac *);
331static void	bwn_lo_g_adjust(struct bwn_mac *);
332static void	bwn_lo_get_powervector(struct bwn_mac *);
333static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334		    const struct bwn_bbatt *, const struct bwn_rfatt *);
335static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336static void	bwn_phy_hwpctl_init(struct bwn_mac *);
337static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339		    const struct bwn_bbatt *, const struct bwn_rfatt *,
340		    uint8_t);
341static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
344static void	bwn_wa_init(struct bwn_mac *);
345static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346		    uint16_t);
347static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
348static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349		    uint32_t);
350static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351		    uint16_t);
352static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353static void	bwn_mac_suspend(struct bwn_mac *);
354static void	bwn_mac_enable(struct bwn_mac *);
355static void	bwn_psctl(struct bwn_mac *, uint32_t);
356static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
357static void	bwn_nrssi_offset(struct bwn_mac *);
358static void	bwn_nrssi_threshold(struct bwn_mac *);
359static void	bwn_nrssi_slope_11g(struct bwn_mac *);
360static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361		    int16_t);
362static void	bwn_set_original_gains(struct bwn_mac *);
363static void	bwn_hwpctl_early_init(struct bwn_mac *);
364static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
365static uint16_t	bwn_phy_g_chan2freq(uint8_t);
366static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368		    const char *, struct bwn_fwfile *);
369static void	bwn_release_firmware(struct bwn_mac *);
370static void	bwn_do_release_fw(struct bwn_fwfile *);
371static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
372static int	bwn_fwinitvals_write(struct bwn_mac *,
373		    const struct bwn_fwinitvals *, size_t, size_t);
374static int	bwn_switch_channel(struct bwn_mac *, int);
375static uint16_t	bwn_ant2phy(int);
376static void	bwn_mac_write_bssid(struct bwn_mac *);
377static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378		    const uint8_t *);
379static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380		    const uint8_t *, size_t, const uint8_t *);
381static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
382		    const uint8_t *);
383static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384		    const uint8_t *);
385static void	bwn_phy_exit(struct bwn_mac *);
386static void	bwn_core_stop(struct bwn_mac *);
387static int	bwn_switch_band(struct bwn_softc *,
388		    struct ieee80211_channel *);
389static void	bwn_phy_reset(struct bwn_mac *);
390static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391static void	bwn_set_pretbtt(struct bwn_mac *);
392static int	bwn_intr(void *);
393static void	bwn_intrtask(void *, int);
394static void	bwn_restart(struct bwn_mac *, const char *);
395static void	bwn_intr_ucode_debug(struct bwn_mac *);
396static void	bwn_intr_tbtt_indication(struct bwn_mac *);
397static void	bwn_intr_atim_end(struct bwn_mac *);
398static void	bwn_intr_beacon(struct bwn_mac *);
399static void	bwn_intr_pmq(struct bwn_mac *);
400static void	bwn_intr_noise(struct bwn_mac *);
401static void	bwn_intr_txeof(struct bwn_mac *);
402static void	bwn_hwreset(void *, int);
403static void	bwn_handle_fwpanic(struct bwn_mac *);
404static void	bwn_load_beacon0(struct bwn_mac *);
405static void	bwn_load_beacon1(struct bwn_mac *);
406static uint32_t	bwn_jssi_read(struct bwn_mac *);
407static void	bwn_noise_gensample(struct bwn_mac *);
408static void	bwn_handle_txeof(struct bwn_mac *,
409		    const struct bwn_txstatus *);
410static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
412static void	bwn_start_locked(struct ifnet *);
413static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414		    struct mbuf *);
415static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416static int	bwn_set_txhdr(struct bwn_mac *,
417		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418		    uint16_t);
419static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420		    const uint8_t);
421static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422static uint8_t	bwn_get_fbrate(uint8_t);
423static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425static void	bwn_phy_lock(struct bwn_mac *);
426static void	bwn_phy_unlock(struct bwn_mac *);
427static void	bwn_rf_lock(struct bwn_mac *);
428static void	bwn_rf_unlock(struct bwn_mac *);
429static void	bwn_txpwr(void *, int);
430static void	bwn_tasks(void *);
431static void	bwn_task_15s(struct bwn_mac *);
432static void	bwn_task_30s(struct bwn_mac *);
433static void	bwn_task_60s(struct bwn_mac *);
434static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435		    uint8_t);
436static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439		    int, int);
440static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
441static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
443static void	bwn_watchdog(void *);
444static void	bwn_dma_stop(struct bwn_mac *);
445static void	bwn_pio_stop(struct bwn_mac *);
446static void	bwn_dma_ringstop(struct bwn_dma_ring **);
447static void	bwn_led_attach(struct bwn_mac *);
448static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449static void	bwn_led_event(struct bwn_mac *, int);
450static void	bwn_led_blink_start(struct bwn_mac *, int, int);
451static void	bwn_led_blink_next(void *);
452static void	bwn_led_blink_end(void *);
453static void	bwn_rfswitch(void *);
454static void	bwn_rf_turnon(struct bwn_mac *);
455static void	bwn_rf_turnoff(struct bwn_mac *);
456static void	bwn_phy_lp_init_pre(struct bwn_mac *);
457static int	bwn_phy_lp_init(struct bwn_mac *);
458static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461		    uint16_t);
462static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
467static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468static void	bwn_phy_lp_task_60s(struct bwn_mac *);
469static void	bwn_phy_lp_readsprom(struct bwn_mac *);
470static void	bwn_phy_lp_bbinit(struct bwn_mac *);
471static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
472static void	bwn_phy_lp_calib(struct bwn_mac *);
473static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
479static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481static void	bwn_phy_lp_bugfix(struct bwn_mac *);
482static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
483static void	bwn_phy_lp_tblinit(struct bwn_mac *);
484static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
487static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
488static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
490static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
491static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495		    const void *);
496static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497static struct bwn_txgain
498		bwn_phy_lp_get_txgain(struct bwn_mac *);
499static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
500static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513static int	bwn_phy_lp_loopback(struct bwn_mac *);
514static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516		    int);
517static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518		    struct bwn_phy_lp_iq_est *);
519static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
521static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525static uint8_t	bwn_nbits(int32_t);
526static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527		    struct bwn_txgain_entry *);
528static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529		    struct bwn_txgain_entry);
530static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531		    struct bwn_txgain_entry);
532static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533		    struct bwn_txgain_entry);
534static void	bwn_sysctl_node(struct bwn_softc *);
535
536static struct resource_spec bwn_res_spec_legacy[] = {
537	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
538	{ -1,			0,		0 }
539};
540
541static struct resource_spec bwn_res_spec_msi[] = {
542	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
543	{ -1,			0,		0 }
544};
545
546static const struct bwn_channelinfo bwn_chantable_bg = {
547	.channels = {
548		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
549		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
550		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
551		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552		{ 2472, 13, 30 }, { 2484, 14, 30 } },
553	.nchannels = 14
554};
555
556static const struct bwn_channelinfo bwn_chantable_a = {
557	.channels = {
558		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
559		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
560		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
561		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
562		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570		{ 6080, 216, 30 } },
571	.nchannels = 37
572};
573
574static const struct bwn_channelinfo bwn_chantable_n = {
575	.channels = {
576		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
577		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
578		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
579		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
580		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
581		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
582		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
583		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
584		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
585		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
586		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
587		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612		{ 6130, 226, 30 }, { 6140, 228, 30 } },
613	.nchannels = 110
614};
615
616static const uint8_t bwn_b2063_chantable_data[33][12] = {
617	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650};
651
652static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653	{ 1, 2412, bwn_b2063_chantable_data[0] },
654	{ 2, 2417, bwn_b2063_chantable_data[0] },
655	{ 3, 2422, bwn_b2063_chantable_data[0] },
656	{ 4, 2427, bwn_b2063_chantable_data[1] },
657	{ 5, 2432, bwn_b2063_chantable_data[1] },
658	{ 6, 2437, bwn_b2063_chantable_data[1] },
659	{ 7, 2442, bwn_b2063_chantable_data[1] },
660	{ 8, 2447, bwn_b2063_chantable_data[1] },
661	{ 9, 2452, bwn_b2063_chantable_data[2] },
662	{ 10, 2457, bwn_b2063_chantable_data[2] },
663	{ 11, 2462, bwn_b2063_chantable_data[3] },
664	{ 12, 2467, bwn_b2063_chantable_data[3] },
665	{ 13, 2472, bwn_b2063_chantable_data[3] },
666	{ 14, 2484, bwn_b2063_chantable_data[4] },
667	{ 34, 5170, bwn_b2063_chantable_data[5] },
668	{ 36, 5180, bwn_b2063_chantable_data[6] },
669	{ 38, 5190, bwn_b2063_chantable_data[7] },
670	{ 40, 5200, bwn_b2063_chantable_data[8] },
671	{ 42, 5210, bwn_b2063_chantable_data[9] },
672	{ 44, 5220, bwn_b2063_chantable_data[10] },
673	{ 46, 5230, bwn_b2063_chantable_data[11] },
674	{ 48, 5240, bwn_b2063_chantable_data[12] },
675	{ 52, 5260, bwn_b2063_chantable_data[13] },
676	{ 56, 5280, bwn_b2063_chantable_data[14] },
677	{ 60, 5300, bwn_b2063_chantable_data[14] },
678	{ 64, 5320, bwn_b2063_chantable_data[15] },
679	{ 100, 5500, bwn_b2063_chantable_data[16] },
680	{ 104, 5520, bwn_b2063_chantable_data[17] },
681	{ 108, 5540, bwn_b2063_chantable_data[18] },
682	{ 112, 5560, bwn_b2063_chantable_data[19] },
683	{ 116, 5580, bwn_b2063_chantable_data[20] },
684	{ 120, 5600, bwn_b2063_chantable_data[21] },
685	{ 124, 5620, bwn_b2063_chantable_data[21] },
686	{ 128, 5640, bwn_b2063_chantable_data[22] },
687	{ 132, 5660, bwn_b2063_chantable_data[22] },
688	{ 136, 5680, bwn_b2063_chantable_data[22] },
689	{ 140, 5700, bwn_b2063_chantable_data[23] },
690	{ 149, 5745, bwn_b2063_chantable_data[23] },
691	{ 153, 5765, bwn_b2063_chantable_data[23] },
692	{ 157, 5785, bwn_b2063_chantable_data[23] },
693	{ 161, 5805, bwn_b2063_chantable_data[23] },
694	{ 165, 5825, bwn_b2063_chantable_data[23] },
695	{ 184, 4920, bwn_b2063_chantable_data[24] },
696	{ 188, 4940, bwn_b2063_chantable_data[25] },
697	{ 192, 4960, bwn_b2063_chantable_data[26] },
698	{ 196, 4980, bwn_b2063_chantable_data[27] },
699	{ 200, 5000, bwn_b2063_chantable_data[28] },
700	{ 204, 5020, bwn_b2063_chantable_data[29] },
701	{ 208, 5040, bwn_b2063_chantable_data[30] },
702	{ 212, 5060, bwn_b2063_chantable_data[31] },
703	{ 216, 5080, bwn_b2063_chantable_data[32] }
704};
705
706static const uint8_t bwn_b2062_chantable_data[22][12] = {
707	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729};
730
731static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732	{ 1, 2412, bwn_b2062_chantable_data[0] },
733	{ 2, 2417, bwn_b2062_chantable_data[0] },
734	{ 3, 2422, bwn_b2062_chantable_data[0] },
735	{ 4, 2427, bwn_b2062_chantable_data[0] },
736	{ 5, 2432, bwn_b2062_chantable_data[0] },
737	{ 6, 2437, bwn_b2062_chantable_data[0] },
738	{ 7, 2442, bwn_b2062_chantable_data[0] },
739	{ 8, 2447, bwn_b2062_chantable_data[0] },
740	{ 9, 2452, bwn_b2062_chantable_data[0] },
741	{ 10, 2457, bwn_b2062_chantable_data[0] },
742	{ 11, 2462, bwn_b2062_chantable_data[0] },
743	{ 12, 2467, bwn_b2062_chantable_data[0] },
744	{ 13, 2472, bwn_b2062_chantable_data[0] },
745	{ 14, 2484, bwn_b2062_chantable_data[0] },
746	{ 34, 5170, bwn_b2062_chantable_data[1] },
747	{ 38, 5190, bwn_b2062_chantable_data[2] },
748	{ 42, 5210, bwn_b2062_chantable_data[2] },
749	{ 46, 5230, bwn_b2062_chantable_data[3] },
750	{ 36, 5180, bwn_b2062_chantable_data[4] },
751	{ 40, 5200, bwn_b2062_chantable_data[5] },
752	{ 44, 5220, bwn_b2062_chantable_data[6] },
753	{ 48, 5240, bwn_b2062_chantable_data[3] },
754	{ 52, 5260, bwn_b2062_chantable_data[3] },
755	{ 56, 5280, bwn_b2062_chantable_data[3] },
756	{ 60, 5300, bwn_b2062_chantable_data[7] },
757	{ 64, 5320, bwn_b2062_chantable_data[8] },
758	{ 100, 5500, bwn_b2062_chantable_data[9] },
759	{ 104, 5520, bwn_b2062_chantable_data[10] },
760	{ 108, 5540, bwn_b2062_chantable_data[10] },
761	{ 112, 5560, bwn_b2062_chantable_data[10] },
762	{ 116, 5580, bwn_b2062_chantable_data[11] },
763	{ 120, 5600, bwn_b2062_chantable_data[12] },
764	{ 124, 5620, bwn_b2062_chantable_data[12] },
765	{ 128, 5640, bwn_b2062_chantable_data[12] },
766	{ 132, 5660, bwn_b2062_chantable_data[12] },
767	{ 136, 5680, bwn_b2062_chantable_data[12] },
768	{ 140, 5700, bwn_b2062_chantable_data[12] },
769	{ 149, 5745, bwn_b2062_chantable_data[12] },
770	{ 153, 5765, bwn_b2062_chantable_data[12] },
771	{ 157, 5785, bwn_b2062_chantable_data[12] },
772	{ 161, 5805, bwn_b2062_chantable_data[12] },
773	{ 165, 5825, bwn_b2062_chantable_data[12] },
774	{ 184, 4920, bwn_b2062_chantable_data[13] },
775	{ 188, 4940, bwn_b2062_chantable_data[14] },
776	{ 192, 4960, bwn_b2062_chantable_data[15] },
777	{ 196, 4980, bwn_b2062_chantable_data[16] },
778	{ 200, 5000, bwn_b2062_chantable_data[17] },
779	{ 204, 5020, bwn_b2062_chantable_data[18] },
780	{ 208, 5040, bwn_b2062_chantable_data[19] },
781	{ 212, 5060, bwn_b2062_chantable_data[20] },
782	{ 216, 5080, bwn_b2062_chantable_data[21] }
783};
784
785/* for LP PHY */
786static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
788	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
789	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790	{ 13, -66, 13 }, { 14, -66, 13 },
791};
792
793/* for LP PHY */
794static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
796	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
797	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
798	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
799	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
800	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
801	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
805	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
806	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808};
809
810static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811
812static const uint8_t bwn_tab_sigsq_tbl[] = {
813	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819};
820
821static const uint8_t bwn_tab_pllfrac_tbl[] = {
822	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824};
825
826static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839};
840
841static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847
848#define	VENDOR_LED_ACT(vendor)				\
849{							\
850	.vid = PCI_VENDOR_##vendor,			\
851	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
852}
853
854static const struct {
855	uint16_t	vid;
856	uint8_t		led_act[BWN_LED_MAX];
857} bwn_vendor_led_act[] = {
858	VENDOR_LED_ACT(COMPAQ),
859	VENDOR_LED_ACT(ASUSTEK)
860};
861
862static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863	{ BWN_VENDOR_LED_ACT_DEFAULT };
864
865#undef VENDOR_LED_ACT
866
867static const struct {
868	int		on_dur;
869	int		off_dur;
870} bwn_led_duration[109] = {
871	[0]	= { 400, 100 },
872	[2]	= { 150, 75 },
873	[4]	= { 90, 45 },
874	[11]	= { 66, 34 },
875	[12]	= { 53, 26 },
876	[18]	= { 42, 21 },
877	[22]	= { 35, 17 },
878	[24]	= { 32, 16 },
879	[36]	= { 21, 10 },
880	[48]	= { 16, 8 },
881	[72]	= { 11, 5 },
882	[96]	= { 9, 4 },
883	[108]	= { 7, 3 }
884};
885
886static const uint16_t bwn_wme_shm_offsets[] = {
887	[0] = BWN_WME_BESTEFFORT,
888	[1] = BWN_WME_BACKGROUND,
889	[2] = BWN_WME_VOICE,
890	[3] = BWN_WME_VIDEO,
891};
892
893static const struct siba_devid bwn_devs[] = {
894	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903};
904
905static int
906bwn_probe(device_t dev)
907{
908	int i;
909
910	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912		    siba_get_device(dev) == bwn_devs[i].sd_device &&
913		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
914			return (BUS_PROBE_DEFAULT);
915	}
916
917	return (ENXIO);
918}
919
920static int
921bwn_attach(device_t dev)
922{
923	struct bwn_mac *mac;
924	struct bwn_softc *sc = device_get_softc(dev);
925	int error, i, msic, reg;
926
927	sc->sc_dev = dev;
928#ifdef BWN_DEBUG
929	sc->sc_debug = bwn_debug;
930#endif
931
932	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933		error = bwn_attach_pre(sc);
934		if (error != 0)
935			return (error);
936		bwn_sprom_bugfixes(dev);
937		sc->sc_flags |= BWN_FLAG_ATTACHED;
938	}
939
940	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941		if (siba_get_pci_device(dev) != 0x4313 &&
942		    siba_get_pci_device(dev) != 0x431a &&
943		    siba_get_pci_device(dev) != 0x4321) {
944			device_printf(sc->sc_dev,
945			    "skip 802.11 cores\n");
946			return (ENODEV);
947		}
948	}
949
950	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951	    M_NOWAIT | M_ZERO);
952	if (mac == NULL)
953		return (ENOMEM);
954	mac->mac_sc = sc;
955	mac->mac_status = BWN_MAC_STATUS_UNINIT;
956	if (bwn_bfp != 0)
957		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958
959	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962
963	error = bwn_attach_core(mac);
964	if (error)
965		goto fail0;
966	bwn_led_attach(mac);
967
968	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973	    mac->mac_phy.rf_rev);
974	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975		device_printf(sc->sc_dev, "DMA (%d bits)\n",
976		    mac->mac_method.dma.dmatype);
977	else
978		device_printf(sc->sc_dev, "PIO\n");
979
980	/*
981	 * setup PCI resources and interrupt.
982	 */
983	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
984		msic = pci_msi_count(dev);
985		if (bootverbose)
986			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987	} else
988		msic = 0;
989
990	mac->mac_intr_spec = bwn_res_spec_legacy;
991	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992		if (pci_alloc_msi(dev, &msic) == 0) {
993			device_printf(sc->sc_dev,
994			    "Using %d MSI messages\n", msic);
995			mac->mac_intr_spec = bwn_res_spec_msi;
996			mac->mac_msi = 1;
997		}
998	}
999
1000	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001	    mac->mac_res_irq);
1002	if (error) {
1003		device_printf(sc->sc_dev,
1004		    "couldn't allocate IRQ resources (%d)\n", error);
1005		goto fail1;
1006	}
1007
1008	if (mac->mac_msi == 0)
1009		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011		    &mac->mac_intrhand[0]);
1012	else {
1013		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016			    &mac->mac_intrhand[i]);
1017			if (error != 0) {
1018				device_printf(sc->sc_dev,
1019				    "couldn't setup interrupt (%d)\n", error);
1020				break;
1021			}
1022		}
1023	}
1024
1025	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026
1027	/*
1028	 * calls attach-post routine
1029	 */
1030	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031		bwn_attach_post(sc);
1032
1033	return (0);
1034fail1:
1035	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036		pci_release_msi(dev);
1037fail0:
1038	free(mac, M_DEVBUF);
1039	return (error);
1040}
1041
1042static int
1043bwn_is_valid_ether_addr(uint8_t *addr)
1044{
1045	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046
1047	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048		return (FALSE);
1049
1050	return (TRUE);
1051}
1052
1053static int
1054bwn_attach_post(struct bwn_softc *sc)
1055{
1056	struct ieee80211com *ic;
1057	struct ifnet *ifp = sc->sc_ifp;
1058
1059	ic = ifp->if_l2com;
1060	ic->ic_ifp = ifp;
1061	ic->ic_softc = sc;
1062	ic->ic_name = device_get_nameunit(sc->sc_dev);
1063	/* XXX not right but it's not used anywhere important */
1064	ic->ic_phytype = IEEE80211_T_OFDM;
1065	ic->ic_opmode = IEEE80211_M_STA;
1066	ic->ic_caps =
1067		  IEEE80211_C_STA		/* station mode supported */
1068		| IEEE80211_C_MONITOR		/* monitor mode */
1069		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1070		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1071		| IEEE80211_C_SHSLOT		/* short slot time supported */
1072		| IEEE80211_C_WME		/* WME/WMM supported */
1073		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1074		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1075		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1076		;
1077
1078	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1079
1080	/* call MI attach routine. */
1081	ieee80211_ifattach(ic,
1082	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1083	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1084	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1085
1086	ic->ic_headroom = sizeof(struct bwn_txhdr);
1087
1088	/* override default methods */
1089	ic->ic_raw_xmit = bwn_raw_xmit;
1090	ic->ic_updateslot = bwn_updateslot;
1091	ic->ic_update_promisc = bwn_update_promisc;
1092	ic->ic_wme.wme_update = bwn_wme_update;
1093
1094	ic->ic_scan_start = bwn_scan_start;
1095	ic->ic_scan_end = bwn_scan_end;
1096	ic->ic_set_channel = bwn_set_channel;
1097
1098	ic->ic_vap_create = bwn_vap_create;
1099	ic->ic_vap_delete = bwn_vap_delete;
1100
1101	ieee80211_radiotap_attach(ic,
1102	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1103	    BWN_TX_RADIOTAP_PRESENT,
1104	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1105	    BWN_RX_RADIOTAP_PRESENT);
1106
1107	bwn_sysctl_node(sc);
1108
1109	if (bootverbose)
1110		ieee80211_announce(ic);
1111	return (0);
1112}
1113
1114static void
1115bwn_phy_detach(struct bwn_mac *mac)
1116{
1117
1118	if (mac->mac_phy.detach != NULL)
1119		mac->mac_phy.detach(mac);
1120}
1121
1122static int
1123bwn_detach(device_t dev)
1124{
1125	struct bwn_softc *sc = device_get_softc(dev);
1126	struct bwn_mac *mac = sc->sc_curmac;
1127	struct ifnet *ifp = sc->sc_ifp;
1128	struct ieee80211com *ic = ifp->if_l2com;
1129	int i;
1130
1131	sc->sc_flags |= BWN_FLAG_INVALID;
1132
1133	if (device_is_attached(sc->sc_dev)) {
1134		bwn_stop(sc, 1);
1135		bwn_dma_free(mac);
1136		callout_drain(&sc->sc_led_blink_ch);
1137		callout_drain(&sc->sc_rfswitch_ch);
1138		callout_drain(&sc->sc_task_ch);
1139		callout_drain(&sc->sc_watchdog_ch);
1140		bwn_phy_detach(mac);
1141		if (ifp != NULL) {
1142			ieee80211_draintask(ic, &mac->mac_hwreset);
1143			ieee80211_draintask(ic, &mac->mac_txpower);
1144			ieee80211_ifdetach(ic);
1145			if_free(ifp);
1146		}
1147	}
1148	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1149	taskqueue_free(sc->sc_tq);
1150
1151	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1152		if (mac->mac_intrhand[i] != NULL) {
1153			bus_teardown_intr(dev, mac->mac_res_irq[i],
1154			    mac->mac_intrhand[i]);
1155			mac->mac_intrhand[i] = NULL;
1156		}
1157	}
1158	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1159	if (mac->mac_msi != 0)
1160		pci_release_msi(dev);
1161
1162	BWN_LOCK_DESTROY(sc);
1163	return (0);
1164}
1165
1166static int
1167bwn_attach_pre(struct bwn_softc *sc)
1168{
1169	struct ifnet *ifp;
1170	int error = 0;
1171
1172	BWN_LOCK_INIT(sc);
1173	TAILQ_INIT(&sc->sc_maclist);
1174	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1175	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1176	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1177
1178	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1179		taskqueue_thread_enqueue, &sc->sc_tq);
1180	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1181		"%s taskq", device_get_nameunit(sc->sc_dev));
1182
1183	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1184	if (ifp == NULL) {
1185		device_printf(sc->sc_dev, "can not if_alloc()\n");
1186		error = ENOSPC;
1187		goto fail;
1188	}
1189
1190	/* set these up early for if_printf use */
1191	if_initname(ifp, device_get_name(sc->sc_dev),
1192	    device_get_unit(sc->sc_dev));
1193
1194	ifp->if_softc = sc;
1195	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1196	ifp->if_init = bwn_init;
1197	ifp->if_ioctl = bwn_ioctl;
1198	ifp->if_start = bwn_start;
1199	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1200	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1201	IFQ_SET_READY(&ifp->if_snd);
1202
1203	return (0);
1204
1205fail:	BWN_LOCK_DESTROY(sc);
1206	return (error);
1207}
1208
1209static void
1210bwn_sprom_bugfixes(device_t dev)
1211{
1212#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1213	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1214	 (siba_get_pci_device(dev) == _device) &&			\
1215	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1216	 (siba_get_pci_subdevice(dev) == _subdevice))
1217
1218	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1219	    siba_get_pci_subdevice(dev) == 0x4e &&
1220	    siba_get_pci_revid(dev) > 0x40)
1221		siba_sprom_set_bf_lo(dev,
1222		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1223	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1224	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1225		siba_sprom_set_bf_lo(dev,
1226		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1227	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1228		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1232		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1233		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1234		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1235			siba_sprom_set_bf_lo(dev,
1236			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1237	}
1238#undef	BWN_ISDEV
1239}
1240
1241static int
1242bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1243{
1244#define	IS_RUNNING(ifp) \
1245	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1246	struct bwn_softc *sc = ifp->if_softc;
1247	struct ieee80211com *ic = ifp->if_l2com;
1248	struct ifreq *ifr = (struct ifreq *)data;
1249	int error = 0, startall;
1250
1251	switch (cmd) {
1252	case SIOCSIFFLAGS:
1253		startall = 0;
1254		if (IS_RUNNING(ifp)) {
1255			bwn_update_promisc(ic);
1256		} else if (ifp->if_flags & IFF_UP) {
1257			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1258				bwn_init(sc);
1259				startall = 1;
1260			}
1261		} else
1262			bwn_stop(sc, 1);
1263		if (startall)
1264			ieee80211_start_all(ic);
1265		break;
1266	case SIOCGIFMEDIA:
1267		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1268		break;
1269	case SIOCGIFADDR:
1270		error = ether_ioctl(ifp, cmd, data);
1271		break;
1272	default:
1273		error = EINVAL;
1274		break;
1275	}
1276	return (error);
1277}
1278
1279static void
1280bwn_start(struct ifnet *ifp)
1281{
1282	struct bwn_softc *sc = ifp->if_softc;
1283
1284	BWN_LOCK(sc);
1285	bwn_start_locked(ifp);
1286	BWN_UNLOCK(sc);
1287}
1288
1289static void
1290bwn_start_locked(struct ifnet *ifp)
1291{
1292	struct bwn_softc *sc = ifp->if_softc;
1293	struct bwn_mac *mac = sc->sc_curmac;
1294	struct ieee80211_frame *wh;
1295	struct ieee80211_node *ni;
1296	struct ieee80211_key *k;
1297	struct mbuf *m;
1298
1299	BWN_ASSERT_LOCKED(sc);
1300
1301	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1302	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1303		return;
1304
1305	for (;;) {
1306		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1307		if (m == NULL)
1308			break;
1309
1310		if (bwn_tx_isfull(sc, m))
1311			break;
1312		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1313		if (ni == NULL) {
1314			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1315			m_freem(m);
1316			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1317			continue;
1318		}
1319		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1320		wh = mtod(m, struct ieee80211_frame *);
1321		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1322			k = ieee80211_crypto_encap(ni, m);
1323			if (k == NULL) {
1324				ieee80211_free_node(ni);
1325				m_freem(m);
1326				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1327				continue;
1328			}
1329		}
1330		wh = NULL;	/* Catch any invalid use */
1331
1332		if (bwn_tx_start(sc, ni, m) != 0) {
1333			if (ni != NULL)
1334				ieee80211_free_node(ni);
1335			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1336			continue;
1337		}
1338
1339		sc->sc_watchdog_timer = 5;
1340	}
1341}
1342
1343static int
1344bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1345{
1346	struct bwn_dma_ring *dr;
1347	struct bwn_mac *mac = sc->sc_curmac;
1348	struct bwn_pio_txqueue *tq;
1349	struct ifnet *ifp = sc->sc_ifp;
1350	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1351
1352	BWN_ASSERT_LOCKED(sc);
1353
1354	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1355		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1356		if (dr->dr_stop == 1 ||
1357		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1358			dr->dr_stop = 1;
1359			goto full;
1360		}
1361	} else {
1362		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1363		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1364		    pktlen > (tq->tq_size - tq->tq_used)) {
1365			tq->tq_stop = 1;
1366			goto full;
1367		}
1368	}
1369	return (0);
1370full:
1371	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1372	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1373	return (1);
1374}
1375
1376static int
1377bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1378{
1379	struct bwn_mac *mac = sc->sc_curmac;
1380	int error;
1381
1382	BWN_ASSERT_LOCKED(sc);
1383
1384	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1385		m_freem(m);
1386		return (ENXIO);
1387	}
1388
1389	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1390	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1391	if (error) {
1392		m_freem(m);
1393		return (error);
1394	}
1395	return (0);
1396}
1397
1398static int
1399bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1400{
1401	struct bwn_pio_txpkt *tp;
1402	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1403	struct bwn_softc *sc = mac->mac_sc;
1404	struct bwn_txhdr txhdr;
1405	struct mbuf *m_new;
1406	uint32_t ctl32;
1407	int error;
1408	uint16_t ctl16;
1409
1410	BWN_ASSERT_LOCKED(sc);
1411
1412	/* XXX TODO send packets after DTIM */
1413
1414	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1415	tp = TAILQ_FIRST(&tq->tq_pktlist);
1416	tp->tp_ni = ni;
1417	tp->tp_m = m;
1418
1419	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1420	if (error) {
1421		device_printf(sc->sc_dev, "tx fail\n");
1422		return (error);
1423	}
1424
1425	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1426	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1427	tq->tq_free--;
1428
1429	if (siba_get_revid(sc->sc_dev) >= 8) {
1430		/*
1431		 * XXX please removes m_defrag(9)
1432		 */
1433		m_new = m_defrag(m, M_NOWAIT);
1434		if (m_new == NULL) {
1435			device_printf(sc->sc_dev,
1436			    "%s: can't defrag TX buffer\n",
1437			    __func__);
1438			return (ENOBUFS);
1439		}
1440		if (m_new->m_next != NULL)
1441			device_printf(sc->sc_dev,
1442			    "TODO: fragmented packets for PIO\n");
1443		tp->tp_m = m_new;
1444
1445		/* send HEADER */
1446		ctl32 = bwn_pio_write_multi_4(mac, tq,
1447		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1448			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1449		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1450		/* send BODY */
1451		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1452		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1453		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1454		    ctl32 | BWN_PIO8_TXCTL_EOF);
1455	} else {
1456		ctl16 = bwn_pio_write_multi_2(mac, tq,
1457		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1458			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1459		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1460		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1461		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1462		    ctl16 | BWN_PIO_TXCTL_EOF);
1463	}
1464
1465	return (0);
1466}
1467
1468static struct bwn_pio_txqueue *
1469bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1470{
1471
1472	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1473		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1474
1475	switch (prio) {
1476	case 0:
1477		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478	case 1:
1479		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1480	case 2:
1481		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1482	case 3:
1483		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1484	}
1485	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1486	return (NULL);
1487}
1488
1489static int
1490bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1491{
1492#define	BWN_GET_TXHDRCACHE(slot)					\
1493	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1494	struct bwn_dma *dma = &mac->mac_method.dma;
1495	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1496	struct bwn_dmadesc_generic *desc;
1497	struct bwn_dmadesc_meta *mt;
1498	struct bwn_softc *sc = mac->mac_sc;
1499	struct ifnet *ifp = sc->sc_ifp;
1500	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1501	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1502
1503	BWN_ASSERT_LOCKED(sc);
1504	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1505
1506	/* XXX send after DTIM */
1507
1508	slot = bwn_dma_getslot(dr);
1509	dr->getdesc(dr, slot, &desc, &mt);
1510	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1511	    ("%s:%d: fail", __func__, __LINE__));
1512
1513	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1514	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1515	    BWN_DMA_COOKIE(dr, slot));
1516	if (error)
1517		goto fail;
1518	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1519	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1520	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1521	if (error) {
1522		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1523		    __func__, error);
1524		goto fail;
1525	}
1526	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1527	    BUS_DMASYNC_PREWRITE);
1528	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1529	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1530	    BUS_DMASYNC_PREWRITE);
1531
1532	slot = bwn_dma_getslot(dr);
1533	dr->getdesc(dr, slot, &desc, &mt);
1534	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1535	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1536	mt->mt_m = m;
1537	mt->mt_ni = ni;
1538
1539	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1540	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1541	if (error && error != EFBIG) {
1542		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1543		    __func__, error);
1544		goto fail;
1545	}
1546	if (error) {    /* error == EFBIG */
1547		struct mbuf *m_new;
1548
1549		m_new = m_defrag(m, M_NOWAIT);
1550		if (m_new == NULL) {
1551			if_printf(ifp, "%s: can't defrag TX buffer\n",
1552			    __func__);
1553			error = ENOBUFS;
1554			goto fail;
1555		} else {
1556			m = m_new;
1557		}
1558
1559		mt->mt_m = m;
1560		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1561		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1562		if (error) {
1563			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1564			    __func__, error);
1565			goto fail;
1566		}
1567	}
1568	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1569	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1570	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1571	    BUS_DMASYNC_PREWRITE);
1572
1573	/* XXX send after DTIM */
1574
1575	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1576	return (0);
1577fail:
1578	dr->dr_curslot = backup[0];
1579	dr->dr_usedslot = backup[1];
1580	return (error);
1581#undef BWN_GET_TXHDRCACHE
1582}
1583
1584static void
1585bwn_watchdog(void *arg)
1586{
1587	struct bwn_softc *sc = arg;
1588	struct ifnet *ifp = sc->sc_ifp;
1589
1590	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1591		if_printf(ifp, "device timeout\n");
1592		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1593	}
1594	callout_schedule(&sc->sc_watchdog_ch, hz);
1595}
1596
1597static int
1598bwn_attach_core(struct bwn_mac *mac)
1599{
1600	struct bwn_softc *sc = mac->mac_sc;
1601	int error, have_bg = 0, have_a = 0;
1602	uint32_t high;
1603
1604	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1605	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1606
1607	siba_powerup(sc->sc_dev, 0);
1608
1609	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1610	bwn_reset_core(mac,
1611	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1612	error = bwn_phy_getinfo(mac, high);
1613	if (error)
1614		goto fail;
1615
1616	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1617	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1618	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1619	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1620	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1621		have_a = have_bg = 0;
1622		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1623			have_a = 1;
1624		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1625		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1626		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1627			have_bg = 1;
1628		else
1629			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1630			    mac->mac_phy.type));
1631	}
1632	/* XXX turns off PHY A because it's not supported */
1633	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1634	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1635		have_a = 0;
1636		have_bg = 1;
1637	}
1638
1639	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1640		mac->mac_phy.attach = bwn_phy_g_attach;
1641		mac->mac_phy.detach = bwn_phy_g_detach;
1642		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1643		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1644		mac->mac_phy.init = bwn_phy_g_init;
1645		mac->mac_phy.exit = bwn_phy_g_exit;
1646		mac->mac_phy.phy_read = bwn_phy_g_read;
1647		mac->mac_phy.phy_write = bwn_phy_g_write;
1648		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1649		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1650		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1651		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1652		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1653		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1654		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1655		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1656		mac->mac_phy.set_im = bwn_phy_g_im;
1657		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1658		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1659		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1660		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1661	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1662		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1663		mac->mac_phy.init = bwn_phy_lp_init;
1664		mac->mac_phy.phy_read = bwn_phy_lp_read;
1665		mac->mac_phy.phy_write = bwn_phy_lp_write;
1666		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1667		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1668		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1669		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1670		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1671		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1672		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1673		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1674		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1675	} else {
1676		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1677		    mac->mac_phy.type);
1678		error = ENXIO;
1679		goto fail;
1680	}
1681
1682	mac->mac_phy.gmode = have_bg;
1683	if (mac->mac_phy.attach != NULL) {
1684		error = mac->mac_phy.attach(mac);
1685		if (error) {
1686			device_printf(sc->sc_dev, "failed\n");
1687			goto fail;
1688		}
1689	}
1690
1691	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1692
1693	error = bwn_chiptest(mac);
1694	if (error)
1695		goto fail;
1696	error = bwn_setup_channels(mac, have_bg, have_a);
1697	if (error) {
1698		device_printf(sc->sc_dev, "failed to setup channels\n");
1699		goto fail;
1700	}
1701
1702	if (sc->sc_curmac == NULL)
1703		sc->sc_curmac = mac;
1704
1705	error = bwn_dma_attach(mac);
1706	if (error != 0) {
1707		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1708		goto fail;
1709	}
1710
1711	mac->mac_phy.switch_analog(mac, 0);
1712
1713	siba_dev_down(sc->sc_dev, 0);
1714fail:
1715	siba_powerdown(sc->sc_dev);
1716	return (error);
1717}
1718
1719static void
1720bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1721{
1722	struct bwn_softc *sc = mac->mac_sc;
1723	uint32_t low, ctl;
1724
1725	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1726
1727	siba_dev_up(sc->sc_dev, flags);
1728	DELAY(2000);
1729
1730	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1731	    ~BWN_TGSLOW_PHYRESET;
1732	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1733	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734	DELAY(1000);
1735	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1736	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1737	DELAY(1000);
1738
1739	if (mac->mac_phy.switch_analog != NULL)
1740		mac->mac_phy.switch_analog(mac, 1);
1741
1742	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1743	if (flags & BWN_TGSLOW_SUPPORT_G)
1744		ctl |= BWN_MACCTL_GMODE;
1745	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1746}
1747
1748static int
1749bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1750{
1751	struct bwn_phy *phy = &mac->mac_phy;
1752	struct bwn_softc *sc = mac->mac_sc;
1753	uint32_t tmp;
1754
1755	/* PHY */
1756	tmp = BWN_READ_2(mac, BWN_PHYVER);
1757	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1758	phy->rf_on = 1;
1759	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1760	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1761	phy->rev = (tmp & BWN_PHYVER_VERSION);
1762	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1763	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1764		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1765	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1766	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1767	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1768		goto unsupphy;
1769
1770	/* RADIO */
1771	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1772		if (siba_get_chiprev(sc->sc_dev) == 0)
1773			tmp = 0x3205017f;
1774		else if (siba_get_chiprev(sc->sc_dev) == 1)
1775			tmp = 0x4205017f;
1776		else
1777			tmp = 0x5205017f;
1778	} else {
1779		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1781		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1782		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1783	}
1784	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1785	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1786	phy->rf_manuf = (tmp & 0x00000fff);
1787	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1788		goto unsupradio;
1789	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1790	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1791	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1792	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1793	    (phy->type == BWN_PHYTYPE_N &&
1794	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1795	    (phy->type == BWN_PHYTYPE_LP &&
1796	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1797		goto unsupradio;
1798
1799	return (0);
1800unsupphy:
1801	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1802	    "analog %#x)\n",
1803	    phy->type, phy->rev, phy->analog);
1804	return (ENXIO);
1805unsupradio:
1806	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1807	    "rev %#x)\n",
1808	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1809	return (ENXIO);
1810}
1811
1812static int
1813bwn_chiptest(struct bwn_mac *mac)
1814{
1815#define	TESTVAL0	0x55aaaa55
1816#define	TESTVAL1	0xaa5555aa
1817	struct bwn_softc *sc = mac->mac_sc;
1818	uint32_t v, backup;
1819
1820	BWN_LOCK(sc);
1821
1822	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1823
1824	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1825	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1826		goto error;
1827	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1828	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1829		goto error;
1830
1831	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1832
1833	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1834	    (siba_get_revid(sc->sc_dev) <= 10)) {
1835		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1836		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1837		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1838			goto error;
1839		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1840			goto error;
1841	}
1842	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1843
1844	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1845	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1846		goto error;
1847
1848	BWN_UNLOCK(sc);
1849	return (0);
1850error:
1851	BWN_UNLOCK(sc);
1852	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1853	return (ENODEV);
1854}
1855
1856#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1857#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1858
1859static int
1860bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1861{
1862	struct bwn_softc *sc = mac->mac_sc;
1863	struct ifnet *ifp = sc->sc_ifp;
1864	struct ieee80211com *ic = ifp->if_l2com;
1865
1866	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1867	ic->ic_nchans = 0;
1868
1869	if (have_bg)
1870		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1871		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1872	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1873		if (have_a)
1874			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875			    &ic->ic_nchans, &bwn_chantable_n,
1876			    IEEE80211_CHAN_HTA);
1877	} else {
1878		if (have_a)
1879			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1880			    &ic->ic_nchans, &bwn_chantable_a,
1881			    IEEE80211_CHAN_A);
1882	}
1883
1884	mac->mac_phy.supports_2ghz = have_bg;
1885	mac->mac_phy.supports_5ghz = have_a;
1886
1887	return (ic->ic_nchans == 0 ? ENXIO : 0);
1888}
1889
1890static uint32_t
1891bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1892{
1893	uint32_t ret;
1894
1895	BWN_ASSERT_LOCKED(mac->mac_sc);
1896
1897	if (way == BWN_SHARED) {
1898		KASSERT((offset & 0x0001) == 0,
1899		    ("%s:%d warn", __func__, __LINE__));
1900		if (offset & 0x0003) {
1901			bwn_shm_ctlword(mac, way, offset >> 2);
1902			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1903			ret <<= 16;
1904			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1905			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1906			goto out;
1907		}
1908		offset >>= 2;
1909	}
1910	bwn_shm_ctlword(mac, way, offset);
1911	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1912out:
1913	return (ret);
1914}
1915
1916static uint16_t
1917bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1918{
1919	uint16_t ret;
1920
1921	BWN_ASSERT_LOCKED(mac->mac_sc);
1922
1923	if (way == BWN_SHARED) {
1924		KASSERT((offset & 0x0001) == 0,
1925		    ("%s:%d warn", __func__, __LINE__));
1926		if (offset & 0x0003) {
1927			bwn_shm_ctlword(mac, way, offset >> 2);
1928			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1929			goto out;
1930		}
1931		offset >>= 2;
1932	}
1933	bwn_shm_ctlword(mac, way, offset);
1934	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1935out:
1936
1937	return (ret);
1938}
1939
1940static void
1941bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1942    uint16_t offset)
1943{
1944	uint32_t control;
1945
1946	control = way;
1947	control <<= 16;
1948	control |= offset;
1949	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1950}
1951
1952static void
1953bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1954    uint32_t value)
1955{
1956	BWN_ASSERT_LOCKED(mac->mac_sc);
1957
1958	if (way == BWN_SHARED) {
1959		KASSERT((offset & 0x0001) == 0,
1960		    ("%s:%d warn", __func__, __LINE__));
1961		if (offset & 0x0003) {
1962			bwn_shm_ctlword(mac, way, offset >> 2);
1963			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1964				    (value >> 16) & 0xffff);
1965			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1966			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1967			return;
1968		}
1969		offset >>= 2;
1970	}
1971	bwn_shm_ctlword(mac, way, offset);
1972	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1973}
1974
1975static void
1976bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1977    uint16_t value)
1978{
1979	BWN_ASSERT_LOCKED(mac->mac_sc);
1980
1981	if (way == BWN_SHARED) {
1982		KASSERT((offset & 0x0001) == 0,
1983		    ("%s:%d warn", __func__, __LINE__));
1984		if (offset & 0x0003) {
1985			bwn_shm_ctlword(mac, way, offset >> 2);
1986			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1987			return;
1988		}
1989		offset >>= 2;
1990	}
1991	bwn_shm_ctlword(mac, way, offset);
1992	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1993}
1994
1995static void
1996bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1997    int txpow)
1998{
1999
2000	c->ic_freq = freq;
2001	c->ic_flags = flags;
2002	c->ic_ieee = ieee;
2003	c->ic_minpower = 0;
2004	c->ic_maxpower = 2 * txpow;
2005	c->ic_maxregpower = txpow;
2006}
2007
2008static void
2009bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2010    const struct bwn_channelinfo *ci, int flags)
2011{
2012	struct ieee80211_channel *c;
2013	int i;
2014
2015	c = &chans[*nchans];
2016
2017	for (i = 0; i < ci->nchannels; i++) {
2018		const struct bwn_channel *hc;
2019
2020		hc = &ci->channels[i];
2021		if (*nchans >= maxchans)
2022			break;
2023		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2024		c++, (*nchans)++;
2025		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2026			/* g channel have a separate b-only entry */
2027			if (*nchans >= maxchans)
2028				break;
2029			c[0] = c[-1];
2030			c[-1].ic_flags = IEEE80211_CHAN_B;
2031			c++, (*nchans)++;
2032		}
2033		if (flags == IEEE80211_CHAN_HTG) {
2034			/* HT g channel have a separate g-only entry */
2035			if (*nchans >= maxchans)
2036				break;
2037			c[-1].ic_flags = IEEE80211_CHAN_G;
2038			c[0] = c[-1];
2039			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2040			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2041			c++, (*nchans)++;
2042		}
2043		if (flags == IEEE80211_CHAN_HTA) {
2044			/* HT a channel have a separate a-only entry */
2045			if (*nchans >= maxchans)
2046				break;
2047			c[-1].ic_flags = IEEE80211_CHAN_A;
2048			c[0] = c[-1];
2049			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2050			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2051			c++, (*nchans)++;
2052		}
2053	}
2054}
2055
2056static int
2057bwn_phy_g_attach(struct bwn_mac *mac)
2058{
2059	struct bwn_softc *sc = mac->mac_sc;
2060	struct bwn_phy *phy = &mac->mac_phy;
2061	struct bwn_phy_g *pg = &phy->phy_g;
2062	unsigned int i;
2063	int16_t pab0, pab1, pab2;
2064	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2065	int8_t bg;
2066
2067	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2068	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2069	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2070	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2071
2072	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2073		device_printf(sc->sc_dev, "not supported anymore\n");
2074
2075	pg->pg_flags = 0;
2076	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2077	    pab2 == -1) {
2078		pg->pg_idletssi = 52;
2079		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2080		return (0);
2081	}
2082
2083	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2084	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2085	if (pg->pg_tssi2dbm == NULL) {
2086		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2087		return (ENOMEM);
2088	}
2089	for (i = 0; i < 64; i++) {
2090		int32_t m1, m2, f, q, delta;
2091		int8_t j = 0;
2092
2093		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2094		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2095		f = 256;
2096
2097		do {
2098			if (j > 15) {
2099				device_printf(sc->sc_dev,
2100				    "failed to generate tssi2dBm\n");
2101				free(pg->pg_tssi2dbm, M_DEVBUF);
2102				return (ENOMEM);
2103			}
2104			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2105			    f, 2048);
2106			delta = abs(q - f);
2107			f = q;
2108			j++;
2109		} while (delta >= 2);
2110
2111		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2112		    128);
2113	}
2114
2115	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2116	return (0);
2117}
2118
2119static void
2120bwn_phy_g_detach(struct bwn_mac *mac)
2121{
2122	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2123
2124	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2125		free(pg->pg_tssi2dbm, M_DEVBUF);
2126		pg->pg_tssi2dbm = NULL;
2127	}
2128	pg->pg_flags = 0;
2129}
2130
2131static void
2132bwn_phy_g_init_pre(struct bwn_mac *mac)
2133{
2134	struct bwn_phy *phy = &mac->mac_phy;
2135	struct bwn_phy_g *pg = &phy->phy_g;
2136	void *tssi2dbm;
2137	int idletssi;
2138	unsigned int i;
2139
2140	tssi2dbm = pg->pg_tssi2dbm;
2141	idletssi = pg->pg_idletssi;
2142
2143	memset(pg, 0, sizeof(*pg));
2144
2145	pg->pg_tssi2dbm = tssi2dbm;
2146	pg->pg_idletssi = idletssi;
2147
2148	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2149
2150	for (i = 0; i < N(pg->pg_nrssi); i++)
2151		pg->pg_nrssi[i] = -1000;
2152	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2153		pg->pg_nrssi_lt[i] = i;
2154	pg->pg_lofcal = 0xffff;
2155	pg->pg_initval = 0xffff;
2156	pg->pg_immode = BWN_IMMODE_NONE;
2157	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2158	pg->pg_avgtssi = 0xff;
2159
2160	pg->pg_loctl.tx_bias = 0xff;
2161	TAILQ_INIT(&pg->pg_loctl.calib_list);
2162}
2163
2164static int
2165bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2166{
2167	struct bwn_phy *phy = &mac->mac_phy;
2168	struct bwn_phy_g *pg = &phy->phy_g;
2169	struct bwn_softc *sc = mac->mac_sc;
2170	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2171	static const struct bwn_rfatt rfatt0[] = {
2172		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2173		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2174		{ 3, 1 }, { 4, 1 }
2175	};
2176	static const struct bwn_rfatt rfatt1[] = {
2177		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2178		{ 14, 1 }
2179	};
2180	static const struct bwn_rfatt rfatt2[] = {
2181		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2182		{ 9, 1 }
2183	};
2184	static const struct bwn_bbatt bbatt_0[] = {
2185		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2186	};
2187
2188	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2189
2190	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2191		pg->pg_bbatt.att = 0;
2192	else
2193		pg->pg_bbatt.att = 2;
2194
2195	/* prepare Radio Attenuation */
2196	pg->pg_rfatt.padmix = 0;
2197
2198	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2199	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2200		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2201			pg->pg_rfatt.att = 2;
2202			goto done;
2203		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2204			pg->pg_rfatt.att = 3;
2205			goto done;
2206		}
2207	}
2208
2209	if (phy->type == BWN_PHYTYPE_A) {
2210		pg->pg_rfatt.att = 0x60;
2211		goto done;
2212	}
2213
2214	switch (phy->rf_ver) {
2215	case 0x2050:
2216		switch (phy->rf_rev) {
2217		case 0:
2218			pg->pg_rfatt.att = 5;
2219			goto done;
2220		case 1:
2221			if (phy->type == BWN_PHYTYPE_G) {
2222				if (siba_get_pci_subvendor(sc->sc_dev) ==
2223				    SIBA_BOARDVENDOR_BCM &&
2224				    siba_get_pci_subdevice(sc->sc_dev) ==
2225				    SIBA_BOARD_BCM4309G &&
2226				    siba_get_pci_revid(sc->sc_dev) >= 30)
2227					pg->pg_rfatt.att = 3;
2228				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2229				    SIBA_BOARDVENDOR_BCM &&
2230				    siba_get_pci_subdevice(sc->sc_dev) ==
2231				    SIBA_BOARD_BU4306)
2232					pg->pg_rfatt.att = 3;
2233				else
2234					pg->pg_rfatt.att = 1;
2235			} else {
2236				if (siba_get_pci_subvendor(sc->sc_dev) ==
2237				    SIBA_BOARDVENDOR_BCM &&
2238				    siba_get_pci_subdevice(sc->sc_dev) ==
2239				    SIBA_BOARD_BCM4309G &&
2240				    siba_get_pci_revid(sc->sc_dev) >= 30)
2241					pg->pg_rfatt.att = 7;
2242				else
2243					pg->pg_rfatt.att = 6;
2244			}
2245			goto done;
2246		case 2:
2247			if (phy->type == BWN_PHYTYPE_G) {
2248				if (siba_get_pci_subvendor(sc->sc_dev) ==
2249				    SIBA_BOARDVENDOR_BCM &&
2250				    siba_get_pci_subdevice(sc->sc_dev) ==
2251				    SIBA_BOARD_BCM4309G &&
2252				    siba_get_pci_revid(sc->sc_dev) >= 30)
2253					pg->pg_rfatt.att = 3;
2254				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2255				    SIBA_BOARDVENDOR_BCM &&
2256				    siba_get_pci_subdevice(sc->sc_dev) ==
2257				    SIBA_BOARD_BU4306)
2258					pg->pg_rfatt.att = 5;
2259				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2260					pg->pg_rfatt.att = 4;
2261				else
2262					pg->pg_rfatt.att = 3;
2263			} else
2264				pg->pg_rfatt.att = 6;
2265			goto done;
2266		case 3:
2267			pg->pg_rfatt.att = 5;
2268			goto done;
2269		case 4:
2270		case 5:
2271			pg->pg_rfatt.att = 1;
2272			goto done;
2273		case 6:
2274		case 7:
2275			pg->pg_rfatt.att = 5;
2276			goto done;
2277		case 8:
2278			pg->pg_rfatt.att = 0xa;
2279			pg->pg_rfatt.padmix = 1;
2280			goto done;
2281		case 9:
2282		default:
2283			pg->pg_rfatt.att = 5;
2284			goto done;
2285		}
2286		break;
2287	case 0x2053:
2288		switch (phy->rf_rev) {
2289		case 1:
2290			pg->pg_rfatt.att = 6;
2291			goto done;
2292		}
2293		break;
2294	}
2295	pg->pg_rfatt.att = 5;
2296done:
2297	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2298
2299	if (!bwn_has_hwpctl(mac)) {
2300		lo->rfatt.array = rfatt0;
2301		lo->rfatt.len = N(rfatt0);
2302		lo->rfatt.min = 0;
2303		lo->rfatt.max = 9;
2304		goto genbbatt;
2305	}
2306	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2307		lo->rfatt.array = rfatt1;
2308		lo->rfatt.len = N(rfatt1);
2309		lo->rfatt.min = 0;
2310		lo->rfatt.max = 14;
2311		goto genbbatt;
2312	}
2313	lo->rfatt.array = rfatt2;
2314	lo->rfatt.len = N(rfatt2);
2315	lo->rfatt.min = 0;
2316	lo->rfatt.max = 9;
2317genbbatt:
2318	lo->bbatt.array = bbatt_0;
2319	lo->bbatt.len = N(bbatt_0);
2320	lo->bbatt.min = 0;
2321	lo->bbatt.max = 8;
2322
2323	BWN_READ_4(mac, BWN_MACCTL);
2324	if (phy->rev == 1) {
2325		phy->gmode = 0;
2326		bwn_reset_core(mac, 0);
2327		bwn_phy_g_init_sub(mac);
2328		phy->gmode = 1;
2329		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2330	}
2331	return (0);
2332}
2333
2334static uint16_t
2335bwn_phy_g_txctl(struct bwn_mac *mac)
2336{
2337	struct bwn_phy *phy = &mac->mac_phy;
2338
2339	if (phy->rf_ver != 0x2050)
2340		return (0);
2341	if (phy->rf_rev == 1)
2342		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2343	if (phy->rf_rev < 6)
2344		return (BWN_TXCTL_PA2DB);
2345	if (phy->rf_rev == 8)
2346		return (BWN_TXCTL_TXMIX);
2347	return (0);
2348}
2349
2350static int
2351bwn_phy_g_init(struct bwn_mac *mac)
2352{
2353
2354	bwn_phy_g_init_sub(mac);
2355	return (0);
2356}
2357
2358static void
2359bwn_phy_g_exit(struct bwn_mac *mac)
2360{
2361	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2362	struct bwn_lo_calib *cal, *tmp;
2363
2364	if (lo == NULL)
2365		return;
2366	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2367		TAILQ_REMOVE(&lo->calib_list, cal, list);
2368		free(cal, M_DEVBUF);
2369	}
2370}
2371
2372static uint16_t
2373bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2374{
2375
2376	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2377	return (BWN_READ_2(mac, BWN_PHYDATA));
2378}
2379
2380static void
2381bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2382{
2383
2384	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2385	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2386}
2387
2388static uint16_t
2389bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2390{
2391
2392	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2393	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2394	return (BWN_READ_2(mac, BWN_RFDATALO));
2395}
2396
2397static void
2398bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2399{
2400
2401	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2402	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2403	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2404}
2405
2406static int
2407bwn_phy_g_hwpctl(struct bwn_mac *mac)
2408{
2409
2410	return (mac->mac_phy.rev >= 6);
2411}
2412
2413static void
2414bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2415{
2416	struct bwn_phy *phy = &mac->mac_phy;
2417	struct bwn_phy_g *pg = &phy->phy_g;
2418	unsigned int channel;
2419	uint16_t rfover, rfoverval;
2420
2421	if (on) {
2422		if (phy->rf_on)
2423			return;
2424
2425		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2426		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2427		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2428		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2429			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2430			    pg->pg_radioctx_over);
2431			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2432			    pg->pg_radioctx_overval);
2433			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2434		}
2435		channel = phy->chan;
2436		bwn_phy_g_switch_chan(mac, 6, 1);
2437		bwn_phy_g_switch_chan(mac, channel, 0);
2438		return;
2439	}
2440
2441	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2442	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2443	pg->pg_radioctx_over = rfover;
2444	pg->pg_radioctx_overval = rfoverval;
2445	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2446	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2447	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2448}
2449
2450static int
2451bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2452{
2453
2454	if ((newchan < 1) || (newchan > 14))
2455		return (EINVAL);
2456	bwn_phy_g_switch_chan(mac, newchan, 0);
2457
2458	return (0);
2459}
2460
2461static uint32_t
2462bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2463{
2464
2465	return (1);
2466}
2467
2468static void
2469bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2470{
2471	struct bwn_phy *phy = &mac->mac_phy;
2472	uint64_t hf;
2473	int autodiv = 0;
2474	uint16_t tmp;
2475
2476	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2477		autodiv = 1;
2478
2479	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2480	bwn_hf_write(mac, hf);
2481
2482	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2483	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2484	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2485		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2486
2487	if (autodiv) {
2488		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2489		if (antenna == BWN_ANTAUTO1)
2490			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2491		else
2492			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2493		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2494	}
2495	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2496	if (autodiv)
2497		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2498	else
2499		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2500	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2501	if (phy->rev >= 2) {
2502		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2503		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2504		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2505		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2506		    0x15);
2507		if (phy->rev == 2)
2508			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2509		else
2510			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2511			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2512			    8);
2513	}
2514	if (phy->rev >= 6)
2515		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2516
2517	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2518	bwn_hf_write(mac, hf);
2519}
2520
2521static int
2522bwn_phy_g_im(struct bwn_mac *mac, int mode)
2523{
2524	struct bwn_phy *phy = &mac->mac_phy;
2525	struct bwn_phy_g *pg = &phy->phy_g;
2526
2527	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2528	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2529
2530	if (phy->rev == 0 || !phy->gmode)
2531		return (ENODEV);
2532
2533	pg->pg_aci_wlan_automatic = 0;
2534	return (0);
2535}
2536
2537static int
2538bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2539{
2540	struct bwn_phy *phy = &mac->mac_phy;
2541	struct bwn_phy_g *pg = &phy->phy_g;
2542	struct bwn_softc *sc = mac->mac_sc;
2543	unsigned int tssi;
2544	int cck, ofdm;
2545	int power;
2546	int rfatt, bbatt;
2547	unsigned int max;
2548
2549	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2550
2551	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2552	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2553	if (cck < 0 && ofdm < 0) {
2554		if (ignore_tssi == 0)
2555			return (BWN_TXPWR_RES_DONE);
2556		cck = 0;
2557		ofdm = 0;
2558	}
2559	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2560	if (pg->pg_avgtssi != 0xff)
2561		tssi = (tssi + pg->pg_avgtssi) / 2;
2562	pg->pg_avgtssi = tssi;
2563	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2564
2565	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2566	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2567		max -= 3;
2568	if (max >= 120) {
2569		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2570		max = 80;
2571		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2572	}
2573
2574	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2575	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2576	     tssi, 0x00), 0x3f)]);
2577	if (power == 0)
2578		return (BWN_TXPWR_RES_DONE);
2579
2580	rfatt = -((power + 7) / 8);
2581	bbatt = (-(power / 2)) - (4 * rfatt);
2582	if ((rfatt == 0) && (bbatt == 0))
2583		return (BWN_TXPWR_RES_DONE);
2584	pg->pg_bbatt_delta = bbatt;
2585	pg->pg_rfatt_delta = rfatt;
2586	return (BWN_TXPWR_RES_NEED_ADJUST);
2587}
2588
2589static void
2590bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2591{
2592	struct bwn_phy *phy = &mac->mac_phy;
2593	struct bwn_phy_g *pg = &phy->phy_g;
2594	struct bwn_softc *sc = mac->mac_sc;
2595	int rfatt, bbatt;
2596	uint8_t txctl;
2597
2598	bwn_mac_suspend(mac);
2599
2600	BWN_ASSERT_LOCKED(sc);
2601
2602	bbatt = pg->pg_bbatt.att;
2603	bbatt += pg->pg_bbatt_delta;
2604	rfatt = pg->pg_rfatt.att;
2605	rfatt += pg->pg_rfatt_delta;
2606
2607	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2608	txctl = pg->pg_txctl;
2609	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2610		if (rfatt <= 1) {
2611			if (txctl == 0) {
2612				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2613				rfatt += 2;
2614				bbatt += 2;
2615			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2616			    BWN_BFL_PACTRL) {
2617				bbatt += 4 * (rfatt - 2);
2618				rfatt = 2;
2619			}
2620		} else if (rfatt > 4 && txctl) {
2621			txctl = 0;
2622			if (bbatt < 3) {
2623				rfatt -= 3;
2624				bbatt += 2;
2625			} else {
2626				rfatt -= 2;
2627				bbatt -= 2;
2628			}
2629		}
2630	}
2631	pg->pg_txctl = txctl;
2632	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2633	pg->pg_rfatt.att = rfatt;
2634	pg->pg_bbatt.att = bbatt;
2635
2636	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2637
2638	bwn_phy_lock(mac);
2639	bwn_rf_lock(mac);
2640	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2641	    pg->pg_txctl);
2642	bwn_rf_unlock(mac);
2643	bwn_phy_unlock(mac);
2644
2645	bwn_mac_enable(mac);
2646}
2647
2648static void
2649bwn_phy_g_task_15s(struct bwn_mac *mac)
2650{
2651	struct bwn_phy *phy = &mac->mac_phy;
2652	struct bwn_phy_g *pg = &phy->phy_g;
2653	struct bwn_softc *sc = mac->mac_sc;
2654	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2655	unsigned long expire, now;
2656	struct bwn_lo_calib *cal, *tmp;
2657	uint8_t expired = 0;
2658
2659	bwn_mac_suspend(mac);
2660
2661	if (lo == NULL)
2662		goto fail;
2663
2664	BWN_GETTIME(now);
2665	if (bwn_has_hwpctl(mac)) {
2666		expire = now - BWN_LO_PWRVEC_EXPIRE;
2667		if (time_before(lo->pwr_vec_read_time, expire)) {
2668			bwn_lo_get_powervector(mac);
2669			bwn_phy_g_dc_lookup_init(mac, 0);
2670		}
2671		goto fail;
2672	}
2673
2674	expire = now - BWN_LO_CALIB_EXPIRE;
2675	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2676		if (!time_before(cal->calib_time, expire))
2677			continue;
2678		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2679		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2680			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2681			expired = 1;
2682		}
2683
2684		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2685		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2686		    cal->ctl.i, cal->ctl.q);
2687
2688		TAILQ_REMOVE(&lo->calib_list, cal, list);
2689		free(cal, M_DEVBUF);
2690	}
2691	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2692		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2693		    &pg->pg_rfatt);
2694		if (cal == NULL) {
2695			device_printf(sc->sc_dev,
2696			    "failed to recalibrate LO\n");
2697			goto fail;
2698		}
2699		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2700		bwn_lo_write(mac, &cal->ctl);
2701	}
2702
2703fail:
2704	bwn_mac_enable(mac);
2705}
2706
2707static void
2708bwn_phy_g_task_60s(struct bwn_mac *mac)
2709{
2710	struct bwn_phy *phy = &mac->mac_phy;
2711	struct bwn_softc *sc = mac->mac_sc;
2712	uint8_t old = phy->chan;
2713
2714	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2715		return;
2716
2717	bwn_mac_suspend(mac);
2718	bwn_nrssi_slope_11g(mac);
2719	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2720		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2721		bwn_switch_channel(mac, old);
2722	}
2723	bwn_mac_enable(mac);
2724}
2725
2726static void
2727bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2728{
2729
2730	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2731}
2732
2733static int
2734bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2735	const struct ieee80211_bpf_params *params)
2736{
2737	struct ieee80211com *ic = ni->ni_ic;
2738	struct ifnet *ifp = ic->ic_ifp;
2739	struct bwn_softc *sc = ifp->if_softc;
2740	struct bwn_mac *mac = sc->sc_curmac;
2741
2742	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2743	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2744		ieee80211_free_node(ni);
2745		m_freem(m);
2746		return (ENETDOWN);
2747	}
2748
2749	BWN_LOCK(sc);
2750	if (bwn_tx_isfull(sc, m)) {
2751		ieee80211_free_node(ni);
2752		m_freem(m);
2753		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2754		BWN_UNLOCK(sc);
2755		return (ENOBUFS);
2756	}
2757
2758	if (bwn_tx_start(sc, ni, m) != 0) {
2759		if (ni != NULL)
2760			ieee80211_free_node(ni);
2761		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2762	}
2763	sc->sc_watchdog_timer = 5;
2764	BWN_UNLOCK(sc);
2765	return (0);
2766}
2767
2768/*
2769 * Callback from the 802.11 layer to update the slot time
2770 * based on the current setting.  We use it to notify the
2771 * firmware of ERP changes and the f/w takes care of things
2772 * like slot time and preamble.
2773 */
2774static void
2775bwn_updateslot(struct ieee80211com *ic)
2776{
2777	struct bwn_softc *sc = ic->ic_softc;
2778	struct bwn_mac *mac;
2779
2780	BWN_LOCK(sc);
2781	if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
2782		mac = (struct bwn_mac *)sc->sc_curmac;
2783		bwn_set_slot_time(mac,
2784		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2785	}
2786	BWN_UNLOCK(sc);
2787}
2788
2789/*
2790 * Callback from the 802.11 layer after a promiscuous mode change.
2791 * Note this interface does not check the operating mode as this
2792 * is an internal callback and we are expected to honor the current
2793 * state (e.g. this is used for setting the interface in promiscuous
2794 * mode when operating in hostap mode to do ACS).
2795 */
2796static void
2797bwn_update_promisc(struct ieee80211com *ic)
2798{
2799	struct bwn_softc *sc = ic->ic_softc;
2800	struct bwn_mac *mac = sc->sc_curmac;
2801
2802	BWN_LOCK(sc);
2803	mac = sc->sc_curmac;
2804	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2805		if (ic->ic_ifp->if_flags & IFF_PROMISC)
2806			sc->sc_filters |= BWN_MACCTL_PROMISC;
2807		else
2808			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2809		bwn_set_opmode(mac);
2810	}
2811	BWN_UNLOCK(sc);
2812}
2813
2814/*
2815 * Callback from the 802.11 layer to update WME parameters.
2816 */
2817static int
2818bwn_wme_update(struct ieee80211com *ic)
2819{
2820	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2821	struct bwn_mac *mac = sc->sc_curmac;
2822	struct wmeParams *wmep;
2823	int i;
2824
2825	BWN_LOCK(sc);
2826	mac = sc->sc_curmac;
2827	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2828		bwn_mac_suspend(mac);
2829		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2830			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2831			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2832		}
2833		bwn_mac_enable(mac);
2834	}
2835	BWN_UNLOCK(sc);
2836	return (0);
2837}
2838
2839static void
2840bwn_scan_start(struct ieee80211com *ic)
2841{
2842	struct ifnet *ifp = ic->ic_ifp;
2843	struct bwn_softc *sc = ifp->if_softc;
2844	struct bwn_mac *mac;
2845
2846	BWN_LOCK(sc);
2847	mac = sc->sc_curmac;
2848	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2849		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2850		bwn_set_opmode(mac);
2851		/* disable CFP update during scan */
2852		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2853	}
2854	BWN_UNLOCK(sc);
2855}
2856
2857static void
2858bwn_scan_end(struct ieee80211com *ic)
2859{
2860	struct ifnet *ifp = ic->ic_ifp;
2861	struct bwn_softc *sc = ifp->if_softc;
2862	struct bwn_mac *mac;
2863
2864	BWN_LOCK(sc);
2865	mac = sc->sc_curmac;
2866	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2867		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2868		bwn_set_opmode(mac);
2869		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2870	}
2871	BWN_UNLOCK(sc);
2872}
2873
2874static void
2875bwn_set_channel(struct ieee80211com *ic)
2876{
2877	struct ifnet *ifp = ic->ic_ifp;
2878	struct bwn_softc *sc = ifp->if_softc;
2879	struct bwn_mac *mac = sc->sc_curmac;
2880	struct bwn_phy *phy = &mac->mac_phy;
2881	int chan, error;
2882
2883	BWN_LOCK(sc);
2884
2885	error = bwn_switch_band(sc, ic->ic_curchan);
2886	if (error)
2887		goto fail;
2888	bwn_mac_suspend(mac);
2889	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2890	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2891	if (chan != phy->chan)
2892		bwn_switch_channel(mac, chan);
2893
2894	/* TX power level */
2895	if (ic->ic_curchan->ic_maxpower != 0 &&
2896	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2897		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2898		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2899		    BWN_TXPWR_IGNORE_TSSI);
2900	}
2901
2902	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2903	if (phy->set_antenna)
2904		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2905
2906	if (sc->sc_rf_enabled != phy->rf_on) {
2907		if (sc->sc_rf_enabled) {
2908			bwn_rf_turnon(mac);
2909			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2910				device_printf(sc->sc_dev,
2911				    "please turn on the RF switch\n");
2912		} else
2913			bwn_rf_turnoff(mac);
2914	}
2915
2916	bwn_mac_enable(mac);
2917
2918fail:
2919	/*
2920	 * Setup radio tap channel freq and flags
2921	 */
2922	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2923		htole16(ic->ic_curchan->ic_freq);
2924	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2925		htole16(ic->ic_curchan->ic_flags & 0xffff);
2926
2927	BWN_UNLOCK(sc);
2928}
2929
2930static struct ieee80211vap *
2931bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2932    enum ieee80211_opmode opmode, int flags,
2933    const uint8_t bssid[IEEE80211_ADDR_LEN],
2934    const uint8_t mac0[IEEE80211_ADDR_LEN])
2935{
2936	struct ifnet *ifp = ic->ic_ifp;
2937	struct bwn_softc *sc = ifp->if_softc;
2938	struct ieee80211vap *vap;
2939	struct bwn_vap *bvp;
2940	uint8_t mac[IEEE80211_ADDR_LEN];
2941
2942	IEEE80211_ADDR_COPY(mac, mac0);
2943	switch (opmode) {
2944	case IEEE80211_M_HOSTAP:
2945	case IEEE80211_M_MBSS:
2946	case IEEE80211_M_STA:
2947	case IEEE80211_M_WDS:
2948	case IEEE80211_M_MONITOR:
2949	case IEEE80211_M_IBSS:
2950	case IEEE80211_M_AHDEMO:
2951		break;
2952	default:
2953		return (NULL);
2954	}
2955
2956	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2957
2958	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2959	    M_80211_VAP, M_NOWAIT | M_ZERO);
2960	if (bvp == NULL) {
2961		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2962		return (NULL);
2963	}
2964	vap = &bvp->bv_vap;
2965	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2966	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2967	/* override with driver methods */
2968	bvp->bv_newstate = vap->iv_newstate;
2969	vap->iv_newstate = bwn_newstate;
2970
2971	/* override max aid so sta's cannot assoc when we're out of sta id's */
2972	vap->iv_max_aid = BWN_STAID_MAX;
2973
2974	ieee80211_ratectl_init(vap);
2975
2976	/* complete setup */
2977	ieee80211_vap_attach(vap, ieee80211_media_change,
2978	    ieee80211_media_status);
2979	return (vap);
2980}
2981
2982static void
2983bwn_vap_delete(struct ieee80211vap *vap)
2984{
2985	struct bwn_vap *bvp = BWN_VAP(vap);
2986
2987	ieee80211_ratectl_deinit(vap);
2988	ieee80211_vap_detach(vap);
2989	free(bvp, M_80211_VAP);
2990}
2991
2992static void
2993bwn_init(void *arg)
2994{
2995	struct bwn_softc *sc = arg;
2996	struct ifnet *ifp = sc->sc_ifp;
2997	struct ieee80211com *ic = ifp->if_l2com;
2998	int error = 0;
2999
3000	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3001		__func__, ifp->if_flags);
3002
3003	BWN_LOCK(sc);
3004	error = bwn_init_locked(sc);
3005	BWN_UNLOCK(sc);
3006
3007	if (error == 0)
3008		ieee80211_start_all(ic);	/* start all vap's */
3009}
3010
3011static int
3012bwn_init_locked(struct bwn_softc *sc)
3013{
3014	struct bwn_mac *mac;
3015	struct ifnet *ifp = sc->sc_ifp;
3016	int error;
3017
3018	BWN_ASSERT_LOCKED(sc);
3019
3020	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3021	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3022	sc->sc_filters = 0;
3023	bwn_wme_clear(sc);
3024	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3025	sc->sc_rf_enabled = 1;
3026
3027	mac = sc->sc_curmac;
3028	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3029		error = bwn_core_init(mac);
3030		if (error != 0)
3031			return (error);
3032	}
3033	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3034		bwn_core_start(mac);
3035
3036	bwn_set_opmode(mac);
3037	bwn_set_pretbtt(mac);
3038	bwn_spu_setdelay(mac, 0);
3039	bwn_set_macaddr(mac);
3040
3041	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3042	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3043	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3044
3045	return (0);
3046}
3047
3048static void
3049bwn_stop(struct bwn_softc *sc, int statechg)
3050{
3051
3052	BWN_LOCK(sc);
3053	bwn_stop_locked(sc, statechg);
3054	BWN_UNLOCK(sc);
3055}
3056
3057static void
3058bwn_stop_locked(struct bwn_softc *sc, int statechg)
3059{
3060	struct bwn_mac *mac = sc->sc_curmac;
3061	struct ifnet *ifp = sc->sc_ifp;
3062
3063	BWN_ASSERT_LOCKED(sc);
3064
3065	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3066		/* XXX FIXME opmode not based on VAP */
3067		bwn_set_opmode(mac);
3068		bwn_set_macaddr(mac);
3069	}
3070
3071	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3072		bwn_core_stop(mac);
3073
3074	callout_stop(&sc->sc_led_blink_ch);
3075	sc->sc_led_blinking = 0;
3076
3077	bwn_core_exit(mac);
3078	sc->sc_rf_enabled = 0;
3079
3080	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3081}
3082
3083static void
3084bwn_wme_clear(struct bwn_softc *sc)
3085{
3086#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3087	struct wmeParams *p;
3088	unsigned int i;
3089
3090	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3091	    ("%s:%d: fail", __func__, __LINE__));
3092
3093	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3094		p = &(sc->sc_wmeParams[i]);
3095
3096		switch (bwn_wme_shm_offsets[i]) {
3097		case BWN_WME_VOICE:
3098			p->wmep_txopLimit = 0;
3099			p->wmep_aifsn = 2;
3100			/* XXX FIXME: log2(cwmin) */
3101			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3102			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3103			break;
3104		case BWN_WME_VIDEO:
3105			p->wmep_txopLimit = 0;
3106			p->wmep_aifsn = 2;
3107			/* XXX FIXME: log2(cwmin) */
3108			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3109			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3110			break;
3111		case BWN_WME_BESTEFFORT:
3112			p->wmep_txopLimit = 0;
3113			p->wmep_aifsn = 3;
3114			/* XXX FIXME: log2(cwmin) */
3115			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3116			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3117			break;
3118		case BWN_WME_BACKGROUND:
3119			p->wmep_txopLimit = 0;
3120			p->wmep_aifsn = 7;
3121			/* XXX FIXME: log2(cwmin) */
3122			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3123			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3124			break;
3125		default:
3126			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3127		}
3128	}
3129}
3130
3131static int
3132bwn_core_init(struct bwn_mac *mac)
3133{
3134	struct bwn_softc *sc = mac->mac_sc;
3135	uint64_t hf;
3136	int error;
3137
3138	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3139	    ("%s:%d: fail", __func__, __LINE__));
3140
3141	siba_powerup(sc->sc_dev, 0);
3142	if (!siba_dev_isup(sc->sc_dev))
3143		bwn_reset_core(mac,
3144		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3145
3146	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3147	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3148	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3149	BWN_GETTIME(mac->mac_phy.nexttime);
3150	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3151	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3152	mac->mac_stats.link_noise = -95;
3153	mac->mac_reason_intr = 0;
3154	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3155	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3156#ifdef BWN_DEBUG
3157	if (sc->sc_debug & BWN_DEBUG_XMIT)
3158		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3159#endif
3160	mac->mac_suspended = 1;
3161	mac->mac_task_state = 0;
3162	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3163
3164	mac->mac_phy.init_pre(mac);
3165
3166	siba_pcicore_intr(sc->sc_dev);
3167
3168	siba_fix_imcfglobug(sc->sc_dev);
3169	bwn_bt_disable(mac);
3170	if (mac->mac_phy.prepare_hw) {
3171		error = mac->mac_phy.prepare_hw(mac);
3172		if (error)
3173			goto fail0;
3174	}
3175	error = bwn_chip_init(mac);
3176	if (error)
3177		goto fail0;
3178	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3179	    siba_get_revid(sc->sc_dev));
3180	hf = bwn_hf_read(mac);
3181	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3182		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3183		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3184			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3185		if (mac->mac_phy.rev == 1)
3186			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3187	}
3188	if (mac->mac_phy.rf_ver == 0x2050) {
3189		if (mac->mac_phy.rf_rev < 6)
3190			hf |= BWN_HF_FORCE_VCO_RECALC;
3191		if (mac->mac_phy.rf_rev == 6)
3192			hf |= BWN_HF_4318_TSSI;
3193	}
3194	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3195		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3196	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3197	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3198		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3199	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3200	bwn_hf_write(mac, hf);
3201
3202	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3203	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3204	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3205	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3206
3207	bwn_rate_init(mac);
3208	bwn_set_phytxctl(mac);
3209
3210	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3211	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3212	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3213
3214	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3215		bwn_pio_init(mac);
3216	else
3217		bwn_dma_init(mac);
3218	bwn_wme_init(mac);
3219	bwn_spu_setdelay(mac, 1);
3220	bwn_bt_enable(mac);
3221
3222	siba_powerup(sc->sc_dev,
3223	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3224	bwn_set_macaddr(mac);
3225	bwn_crypt_init(mac);
3226
3227	/* XXX LED initializatin */
3228
3229	mac->mac_status = BWN_MAC_STATUS_INITED;
3230
3231	return (error);
3232
3233fail0:
3234	siba_powerdown(sc->sc_dev);
3235	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3236	    ("%s:%d: fail", __func__, __LINE__));
3237	return (error);
3238}
3239
3240static void
3241bwn_core_start(struct bwn_mac *mac)
3242{
3243	struct bwn_softc *sc = mac->mac_sc;
3244	uint32_t tmp;
3245
3246	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3247	    ("%s:%d: fail", __func__, __LINE__));
3248
3249	if (siba_get_revid(sc->sc_dev) < 5)
3250		return;
3251
3252	while (1) {
3253		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3254		if (!(tmp & 0x00000001))
3255			break;
3256		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3257	}
3258
3259	bwn_mac_enable(mac);
3260	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3261	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3262
3263	mac->mac_status = BWN_MAC_STATUS_STARTED;
3264}
3265
3266static void
3267bwn_core_exit(struct bwn_mac *mac)
3268{
3269	struct bwn_softc *sc = mac->mac_sc;
3270	uint32_t macctl;
3271
3272	BWN_ASSERT_LOCKED(mac->mac_sc);
3273
3274	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3275	    ("%s:%d: fail", __func__, __LINE__));
3276
3277	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3278		return;
3279	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3280
3281	macctl = BWN_READ_4(mac, BWN_MACCTL);
3282	macctl &= ~BWN_MACCTL_MCODE_RUN;
3283	macctl |= BWN_MACCTL_MCODE_JMP0;
3284	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3285
3286	bwn_dma_stop(mac);
3287	bwn_pio_stop(mac);
3288	bwn_chip_exit(mac);
3289	mac->mac_phy.switch_analog(mac, 0);
3290	siba_dev_down(sc->sc_dev, 0);
3291	siba_powerdown(sc->sc_dev);
3292}
3293
3294static void
3295bwn_bt_disable(struct bwn_mac *mac)
3296{
3297	struct bwn_softc *sc = mac->mac_sc;
3298
3299	(void)sc;
3300	/* XXX do nothing yet */
3301}
3302
3303static int
3304bwn_chip_init(struct bwn_mac *mac)
3305{
3306	struct bwn_softc *sc = mac->mac_sc;
3307	struct bwn_phy *phy = &mac->mac_phy;
3308	uint32_t macctl;
3309	int error;
3310
3311	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3312	if (phy->gmode)
3313		macctl |= BWN_MACCTL_GMODE;
3314	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3315
3316	error = bwn_fw_fillinfo(mac);
3317	if (error)
3318		return (error);
3319	error = bwn_fw_loaducode(mac);
3320	if (error)
3321		return (error);
3322
3323	error = bwn_gpio_init(mac);
3324	if (error)
3325		return (error);
3326
3327	error = bwn_fw_loadinitvals(mac);
3328	if (error) {
3329		siba_gpio_set(sc->sc_dev, 0);
3330		return (error);
3331	}
3332	phy->switch_analog(mac, 1);
3333	error = bwn_phy_init(mac);
3334	if (error) {
3335		siba_gpio_set(sc->sc_dev, 0);
3336		return (error);
3337	}
3338	if (phy->set_im)
3339		phy->set_im(mac, BWN_IMMODE_NONE);
3340	if (phy->set_antenna)
3341		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3342	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3343
3344	if (phy->type == BWN_PHYTYPE_B)
3345		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3346	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3347	if (siba_get_revid(sc->sc_dev) < 5)
3348		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3349
3350	BWN_WRITE_4(mac, BWN_MACCTL,
3351	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3352	BWN_WRITE_4(mac, BWN_MACCTL,
3353	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3354	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3355
3356	bwn_set_opmode(mac);
3357	if (siba_get_revid(sc->sc_dev) < 3) {
3358		BWN_WRITE_2(mac, 0x060e, 0x0000);
3359		BWN_WRITE_2(mac, 0x0610, 0x8000);
3360		BWN_WRITE_2(mac, 0x0604, 0x0000);
3361		BWN_WRITE_2(mac, 0x0606, 0x0200);
3362	} else {
3363		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3364		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3365	}
3366	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3367	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3368	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3369	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3370	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3371	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3372	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3373	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3374	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3375	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3376	return (error);
3377}
3378
3379/* read hostflags */
3380static uint64_t
3381bwn_hf_read(struct bwn_mac *mac)
3382{
3383	uint64_t ret;
3384
3385	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3386	ret <<= 16;
3387	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3388	ret <<= 16;
3389	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3390	return (ret);
3391}
3392
3393static void
3394bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3395{
3396
3397	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3398	    (value & 0x00000000ffffull));
3399	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3400	    (value & 0x0000ffff0000ull) >> 16);
3401	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3402	    (value & 0xffff00000000ULL) >> 32);
3403}
3404
3405static void
3406bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3407{
3408
3409	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3410	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3411}
3412
3413static void
3414bwn_rate_init(struct bwn_mac *mac)
3415{
3416
3417	switch (mac->mac_phy.type) {
3418	case BWN_PHYTYPE_A:
3419	case BWN_PHYTYPE_G:
3420	case BWN_PHYTYPE_LP:
3421	case BWN_PHYTYPE_N:
3422		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3423		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3424		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3425		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3427		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3428		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3429		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3430			break;
3431		/* FALLTHROUGH */
3432	case BWN_PHYTYPE_B:
3433		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3434		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3435		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3436		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3437		break;
3438	default:
3439		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3440	}
3441}
3442
3443static void
3444bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3445{
3446	uint16_t offset;
3447
3448	if (ofdm) {
3449		offset = 0x480;
3450		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3451	} else {
3452		offset = 0x4c0;
3453		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3454	}
3455	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3456	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3457}
3458
3459static uint8_t
3460bwn_plcp_getcck(const uint8_t bitrate)
3461{
3462
3463	switch (bitrate) {
3464	case BWN_CCK_RATE_1MB:
3465		return (0x0a);
3466	case BWN_CCK_RATE_2MB:
3467		return (0x14);
3468	case BWN_CCK_RATE_5MB:
3469		return (0x37);
3470	case BWN_CCK_RATE_11MB:
3471		return (0x6e);
3472	}
3473	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3474	return (0);
3475}
3476
3477static uint8_t
3478bwn_plcp_getofdm(const uint8_t bitrate)
3479{
3480
3481	switch (bitrate) {
3482	case BWN_OFDM_RATE_6MB:
3483		return (0xb);
3484	case BWN_OFDM_RATE_9MB:
3485		return (0xf);
3486	case BWN_OFDM_RATE_12MB:
3487		return (0xa);
3488	case BWN_OFDM_RATE_18MB:
3489		return (0xe);
3490	case BWN_OFDM_RATE_24MB:
3491		return (0x9);
3492	case BWN_OFDM_RATE_36MB:
3493		return (0xd);
3494	case BWN_OFDM_RATE_48MB:
3495		return (0x8);
3496	case BWN_OFDM_RATE_54MB:
3497		return (0xc);
3498	}
3499	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3500	return (0);
3501}
3502
3503static void
3504bwn_set_phytxctl(struct bwn_mac *mac)
3505{
3506	uint16_t ctl;
3507
3508	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3509	    BWN_TX_PHY_TXPWR);
3510	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3511	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3512	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3513}
3514
3515static void
3516bwn_pio_init(struct bwn_mac *mac)
3517{
3518	struct bwn_pio *pio = &mac->mac_method.pio;
3519
3520	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3521	    & ~BWN_MACCTL_BIGENDIAN);
3522	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3523
3524	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3525	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3526	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3527	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3528	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3529	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3530}
3531
3532static void
3533bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3534    int index)
3535{
3536	struct bwn_pio_txpkt *tp;
3537	struct bwn_softc *sc = mac->mac_sc;
3538	unsigned int i;
3539
3540	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3541	tq->tq_index = index;
3542
3543	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3544	if (siba_get_revid(sc->sc_dev) >= 8)
3545		tq->tq_size = 1920;
3546	else {
3547		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3548		tq->tq_size -= 80;
3549	}
3550
3551	TAILQ_INIT(&tq->tq_pktlist);
3552	for (i = 0; i < N(tq->tq_pkts); i++) {
3553		tp = &(tq->tq_pkts[i]);
3554		tp->tp_index = i;
3555		tp->tp_queue = tq;
3556		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3557	}
3558}
3559
3560static uint16_t
3561bwn_pio_idx2base(struct bwn_mac *mac, int index)
3562{
3563	struct bwn_softc *sc = mac->mac_sc;
3564	static const uint16_t bases[] = {
3565		BWN_PIO_BASE0,
3566		BWN_PIO_BASE1,
3567		BWN_PIO_BASE2,
3568		BWN_PIO_BASE3,
3569		BWN_PIO_BASE4,
3570		BWN_PIO_BASE5,
3571		BWN_PIO_BASE6,
3572		BWN_PIO_BASE7,
3573	};
3574	static const uint16_t bases_rev11[] = {
3575		BWN_PIO11_BASE0,
3576		BWN_PIO11_BASE1,
3577		BWN_PIO11_BASE2,
3578		BWN_PIO11_BASE3,
3579		BWN_PIO11_BASE4,
3580		BWN_PIO11_BASE5,
3581	};
3582
3583	if (siba_get_revid(sc->sc_dev) >= 11) {
3584		if (index >= N(bases_rev11))
3585			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3586		return (bases_rev11[index]);
3587	}
3588	if (index >= N(bases))
3589		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3590	return (bases[index]);
3591}
3592
3593static void
3594bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3595    int index)
3596{
3597	struct bwn_softc *sc = mac->mac_sc;
3598
3599	prq->prq_mac = mac;
3600	prq->prq_rev = siba_get_revid(sc->sc_dev);
3601	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3602	bwn_dma_rxdirectfifo(mac, index, 1);
3603}
3604
3605static void
3606bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3607{
3608	if (tq == NULL)
3609		return;
3610	bwn_pio_cancel_tx_packets(tq);
3611}
3612
3613static void
3614bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3615{
3616
3617	bwn_destroy_pioqueue_tx(pio);
3618}
3619
3620static uint16_t
3621bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3622    uint16_t offset)
3623{
3624
3625	return (BWN_READ_2(mac, tq->tq_base + offset));
3626}
3627
3628static void
3629bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3630{
3631	uint32_t ctl;
3632	int type;
3633	uint16_t base;
3634
3635	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3636	base = bwn_dma_base(type, idx);
3637	if (type == BWN_DMA_64BIT) {
3638		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3639		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3640		if (enable)
3641			ctl |= BWN_DMA64_RXDIRECTFIFO;
3642		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3643	} else {
3644		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3645		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3646		if (enable)
3647			ctl |= BWN_DMA32_RXDIRECTFIFO;
3648		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3649	}
3650}
3651
3652static uint64_t
3653bwn_dma_mask(struct bwn_mac *mac)
3654{
3655	uint32_t tmp;
3656	uint16_t base;
3657
3658	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3659	if (tmp & SIBA_TGSHIGH_DMA64)
3660		return (BWN_DMA_BIT_MASK(64));
3661	base = bwn_dma_base(0, 0);
3662	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3663	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3664	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3665		return (BWN_DMA_BIT_MASK(32));
3666
3667	return (BWN_DMA_BIT_MASK(30));
3668}
3669
3670static int
3671bwn_dma_mask2type(uint64_t dmamask)
3672{
3673
3674	if (dmamask == BWN_DMA_BIT_MASK(30))
3675		return (BWN_DMA_30BIT);
3676	if (dmamask == BWN_DMA_BIT_MASK(32))
3677		return (BWN_DMA_32BIT);
3678	if (dmamask == BWN_DMA_BIT_MASK(64))
3679		return (BWN_DMA_64BIT);
3680	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3681	return (BWN_DMA_30BIT);
3682}
3683
3684static void
3685bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3686{
3687	struct bwn_pio_txpkt *tp;
3688	unsigned int i;
3689
3690	for (i = 0; i < N(tq->tq_pkts); i++) {
3691		tp = &(tq->tq_pkts[i]);
3692		if (tp->tp_m) {
3693			m_freem(tp->tp_m);
3694			tp->tp_m = NULL;
3695		}
3696	}
3697}
3698
3699static uint16_t
3700bwn_dma_base(int type, int controller_idx)
3701{
3702	static const uint16_t map64[] = {
3703		BWN_DMA64_BASE0,
3704		BWN_DMA64_BASE1,
3705		BWN_DMA64_BASE2,
3706		BWN_DMA64_BASE3,
3707		BWN_DMA64_BASE4,
3708		BWN_DMA64_BASE5,
3709	};
3710	static const uint16_t map32[] = {
3711		BWN_DMA32_BASE0,
3712		BWN_DMA32_BASE1,
3713		BWN_DMA32_BASE2,
3714		BWN_DMA32_BASE3,
3715		BWN_DMA32_BASE4,
3716		BWN_DMA32_BASE5,
3717	};
3718
3719	if (type == BWN_DMA_64BIT) {
3720		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3721		    ("%s:%d: fail", __func__, __LINE__));
3722		return (map64[controller_idx]);
3723	}
3724	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3725	    ("%s:%d: fail", __func__, __LINE__));
3726	return (map32[controller_idx]);
3727}
3728
3729static void
3730bwn_dma_init(struct bwn_mac *mac)
3731{
3732	struct bwn_dma *dma = &mac->mac_method.dma;
3733
3734	/* setup TX DMA channels. */
3735	bwn_dma_setup(dma->wme[WME_AC_BK]);
3736	bwn_dma_setup(dma->wme[WME_AC_BE]);
3737	bwn_dma_setup(dma->wme[WME_AC_VI]);
3738	bwn_dma_setup(dma->wme[WME_AC_VO]);
3739	bwn_dma_setup(dma->mcast);
3740	/* setup RX DMA channel. */
3741	bwn_dma_setup(dma->rx);
3742}
3743
3744static struct bwn_dma_ring *
3745bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3746    int for_tx, int type)
3747{
3748	struct bwn_dma *dma = &mac->mac_method.dma;
3749	struct bwn_dma_ring *dr;
3750	struct bwn_dmadesc_generic *desc;
3751	struct bwn_dmadesc_meta *mt;
3752	struct bwn_softc *sc = mac->mac_sc;
3753	int error, i;
3754
3755	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3756	if (dr == NULL)
3757		goto out;
3758	dr->dr_numslots = BWN_RXRING_SLOTS;
3759	if (for_tx)
3760		dr->dr_numslots = BWN_TXRING_SLOTS;
3761
3762	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3763	    M_DEVBUF, M_NOWAIT | M_ZERO);
3764	if (dr->dr_meta == NULL)
3765		goto fail0;
3766
3767	dr->dr_type = type;
3768	dr->dr_mac = mac;
3769	dr->dr_base = bwn_dma_base(type, controller_index);
3770	dr->dr_index = controller_index;
3771	if (type == BWN_DMA_64BIT) {
3772		dr->getdesc = bwn_dma_64_getdesc;
3773		dr->setdesc = bwn_dma_64_setdesc;
3774		dr->start_transfer = bwn_dma_64_start_transfer;
3775		dr->suspend = bwn_dma_64_suspend;
3776		dr->resume = bwn_dma_64_resume;
3777		dr->get_curslot = bwn_dma_64_get_curslot;
3778		dr->set_curslot = bwn_dma_64_set_curslot;
3779	} else {
3780		dr->getdesc = bwn_dma_32_getdesc;
3781		dr->setdesc = bwn_dma_32_setdesc;
3782		dr->start_transfer = bwn_dma_32_start_transfer;
3783		dr->suspend = bwn_dma_32_suspend;
3784		dr->resume = bwn_dma_32_resume;
3785		dr->get_curslot = bwn_dma_32_get_curslot;
3786		dr->set_curslot = bwn_dma_32_set_curslot;
3787	}
3788	if (for_tx) {
3789		dr->dr_tx = 1;
3790		dr->dr_curslot = -1;
3791	} else {
3792		if (dr->dr_index == 0) {
3793			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3794			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3795		} else
3796			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3797	}
3798
3799	error = bwn_dma_allocringmemory(dr);
3800	if (error)
3801		goto fail2;
3802
3803	if (for_tx) {
3804		/*
3805		 * Assumption: BWN_TXRING_SLOTS can be divided by
3806		 * BWN_TX_SLOTS_PER_FRAME
3807		 */
3808		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3809		    ("%s:%d: fail", __func__, __LINE__));
3810
3811		dr->dr_txhdr_cache =
3812		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3813			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3814		KASSERT(dr->dr_txhdr_cache != NULL,
3815		    ("%s:%d: fail", __func__, __LINE__));
3816
3817		/*
3818		 * Create TX ring DMA stuffs
3819		 */
3820		error = bus_dma_tag_create(dma->parent_dtag,
3821				    BWN_ALIGN, 0,
3822				    BUS_SPACE_MAXADDR,
3823				    BUS_SPACE_MAXADDR,
3824				    NULL, NULL,
3825				    BWN_HDRSIZE(mac),
3826				    1,
3827				    BUS_SPACE_MAXSIZE_32BIT,
3828				    0,
3829				    NULL, NULL,
3830				    &dr->dr_txring_dtag);
3831		if (error) {
3832			device_printf(sc->sc_dev,
3833			    "can't create TX ring DMA tag: TODO frees\n");
3834			goto fail1;
3835		}
3836
3837		for (i = 0; i < dr->dr_numslots; i += 2) {
3838			dr->getdesc(dr, i, &desc, &mt);
3839
3840			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3841			mt->mt_m = NULL;
3842			mt->mt_ni = NULL;
3843			mt->mt_islast = 0;
3844			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3845			    &mt->mt_dmap);
3846			if (error) {
3847				device_printf(sc->sc_dev,
3848				     "can't create RX buf DMA map\n");
3849				goto fail1;
3850			}
3851
3852			dr->getdesc(dr, i + 1, &desc, &mt);
3853
3854			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3855			mt->mt_m = NULL;
3856			mt->mt_ni = NULL;
3857			mt->mt_islast = 1;
3858			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3859			    &mt->mt_dmap);
3860			if (error) {
3861				device_printf(sc->sc_dev,
3862				     "can't create RX buf DMA map\n");
3863				goto fail1;
3864			}
3865		}
3866	} else {
3867		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3868		    &dr->dr_spare_dmap);
3869		if (error) {
3870			device_printf(sc->sc_dev,
3871			    "can't create RX buf DMA map\n");
3872			goto out;		/* XXX wrong! */
3873		}
3874
3875		for (i = 0; i < dr->dr_numslots; i++) {
3876			dr->getdesc(dr, i, &desc, &mt);
3877
3878			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3879			    &mt->mt_dmap);
3880			if (error) {
3881				device_printf(sc->sc_dev,
3882				    "can't create RX buf DMA map\n");
3883				goto out;	/* XXX wrong! */
3884			}
3885			error = bwn_dma_newbuf(dr, desc, mt, 1);
3886			if (error) {
3887				device_printf(sc->sc_dev,
3888				    "failed to allocate RX buf\n");
3889				goto out;	/* XXX wrong! */
3890			}
3891		}
3892
3893		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3894		    BUS_DMASYNC_PREWRITE);
3895
3896		dr->dr_usedslot = dr->dr_numslots;
3897	}
3898
3899      out:
3900	return (dr);
3901
3902fail2:
3903	free(dr->dr_txhdr_cache, M_DEVBUF);
3904fail1:
3905	free(dr->dr_meta, M_DEVBUF);
3906fail0:
3907	free(dr, M_DEVBUF);
3908	return (NULL);
3909}
3910
3911static void
3912bwn_dma_ringfree(struct bwn_dma_ring **dr)
3913{
3914
3915	if (dr == NULL)
3916		return;
3917
3918	bwn_dma_free_descbufs(*dr);
3919	bwn_dma_free_ringmemory(*dr);
3920
3921	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3922	free((*dr)->dr_meta, M_DEVBUF);
3923	free(*dr, M_DEVBUF);
3924
3925	*dr = NULL;
3926}
3927
3928static void
3929bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3930    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3931{
3932	struct bwn_dmadesc32 *desc;
3933
3934	*meta = &(dr->dr_meta[slot]);
3935	desc = dr->dr_ring_descbase;
3936	desc = &(desc[slot]);
3937
3938	*gdesc = (struct bwn_dmadesc_generic *)desc;
3939}
3940
3941static void
3942bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3943    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3944    int start, int end, int irq)
3945{
3946	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3947	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3948	uint32_t addr, addrext, ctl;
3949	int slot;
3950
3951	slot = (int)(&(desc->dma.dma32) - descbase);
3952	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3953	    ("%s:%d: fail", __func__, __LINE__));
3954
3955	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3956	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3957	addr |= siba_dma_translation(sc->sc_dev);
3958	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3959	if (slot == dr->dr_numslots - 1)
3960		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3961	if (start)
3962		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3963	if (end)
3964		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3965	if (irq)
3966		ctl |= BWN_DMA32_DCTL_IRQ;
3967	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3968	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3969
3970	desc->dma.dma32.control = htole32(ctl);
3971	desc->dma.dma32.address = htole32(addr);
3972}
3973
3974static void
3975bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3976{
3977
3978	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3979	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3980}
3981
3982static void
3983bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3984{
3985
3986	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3987	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3988}
3989
3990static void
3991bwn_dma_32_resume(struct bwn_dma_ring *dr)
3992{
3993
3994	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3995	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3996}
3997
3998static int
3999bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4000{
4001	uint32_t val;
4002
4003	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4004	val &= BWN_DMA32_RXDPTR;
4005
4006	return (val / sizeof(struct bwn_dmadesc32));
4007}
4008
4009static void
4010bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4011{
4012
4013	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4014	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4015}
4016
4017static void
4018bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4019    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4020{
4021	struct bwn_dmadesc64 *desc;
4022
4023	*meta = &(dr->dr_meta[slot]);
4024	desc = dr->dr_ring_descbase;
4025	desc = &(desc[slot]);
4026
4027	*gdesc = (struct bwn_dmadesc_generic *)desc;
4028}
4029
4030static void
4031bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4032    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4033    int start, int end, int irq)
4034{
4035	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4036	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4037	int slot;
4038	uint32_t ctl0 = 0, ctl1 = 0;
4039	uint32_t addrlo, addrhi;
4040	uint32_t addrext;
4041
4042	slot = (int)(&(desc->dma.dma64) - descbase);
4043	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4044	    ("%s:%d: fail", __func__, __LINE__));
4045
4046	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4047	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4048	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4049	    30;
4050	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4051	if (slot == dr->dr_numslots - 1)
4052		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4053	if (start)
4054		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4055	if (end)
4056		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4057	if (irq)
4058		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4059	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4060	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4061	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4062
4063	desc->dma.dma64.control0 = htole32(ctl0);
4064	desc->dma.dma64.control1 = htole32(ctl1);
4065	desc->dma.dma64.address_low = htole32(addrlo);
4066	desc->dma.dma64.address_high = htole32(addrhi);
4067}
4068
4069static void
4070bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4071{
4072
4073	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4074	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4075}
4076
4077static void
4078bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4079{
4080
4081	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4082	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4083}
4084
4085static void
4086bwn_dma_64_resume(struct bwn_dma_ring *dr)
4087{
4088
4089	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4090	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4091}
4092
4093static int
4094bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4095{
4096	uint32_t val;
4097
4098	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4099	val &= BWN_DMA64_RXSTATDPTR;
4100
4101	return (val / sizeof(struct bwn_dmadesc64));
4102}
4103
4104static void
4105bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4106{
4107
4108	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4109	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4110}
4111
4112static int
4113bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4114{
4115	struct bwn_mac *mac = dr->dr_mac;
4116	struct bwn_dma *dma = &mac->mac_method.dma;
4117	struct bwn_softc *sc = mac->mac_sc;
4118	int error;
4119
4120	error = bus_dma_tag_create(dma->parent_dtag,
4121			    BWN_ALIGN, 0,
4122			    BUS_SPACE_MAXADDR,
4123			    BUS_SPACE_MAXADDR,
4124			    NULL, NULL,
4125			    BWN_DMA_RINGMEMSIZE,
4126			    1,
4127			    BUS_SPACE_MAXSIZE_32BIT,
4128			    0,
4129			    NULL, NULL,
4130			    &dr->dr_ring_dtag);
4131	if (error) {
4132		device_printf(sc->sc_dev,
4133		    "can't create TX ring DMA tag: TODO frees\n");
4134		return (-1);
4135	}
4136
4137	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4138	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4139	    &dr->dr_ring_dmap);
4140	if (error) {
4141		device_printf(sc->sc_dev,
4142		    "can't allocate DMA mem: TODO frees\n");
4143		return (-1);
4144	}
4145	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4146	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4147	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4148	if (error) {
4149		device_printf(sc->sc_dev,
4150		    "can't load DMA mem: TODO free\n");
4151		return (-1);
4152	}
4153
4154	return (0);
4155}
4156
4157static void
4158bwn_dma_setup(struct bwn_dma_ring *dr)
4159{
4160	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4161	uint64_t ring64;
4162	uint32_t addrext, ring32, value;
4163	uint32_t trans = siba_dma_translation(sc->sc_dev);
4164
4165	if (dr->dr_tx) {
4166		dr->dr_curslot = -1;
4167
4168		if (dr->dr_type == BWN_DMA_64BIT) {
4169			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4170			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4171			    >> 30;
4172			value = BWN_DMA64_TXENABLE;
4173			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4174			    & BWN_DMA64_TXADDREXT_MASK;
4175			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4176			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4177			    (ring64 & 0xffffffff));
4178			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4179			    ((ring64 >> 32) &
4180			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4181		} else {
4182			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4183			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4184			value = BWN_DMA32_TXENABLE;
4185			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4186			    & BWN_DMA32_TXADDREXT_MASK;
4187			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4188			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4189			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4190		}
4191		return;
4192	}
4193
4194	/*
4195	 * set for RX
4196	 */
4197	dr->dr_usedslot = dr->dr_numslots;
4198
4199	if (dr->dr_type == BWN_DMA_64BIT) {
4200		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4201		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4202		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4203		value |= BWN_DMA64_RXENABLE;
4204		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4205		    & BWN_DMA64_RXADDREXT_MASK;
4206		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4207		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4208		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4209		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4210		    | (trans << 1));
4211		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4212		    sizeof(struct bwn_dmadesc64));
4213	} else {
4214		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4215		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4216		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4217		value |= BWN_DMA32_RXENABLE;
4218		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4219		    & BWN_DMA32_RXADDREXT_MASK;
4220		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4221		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4222		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4223		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4224		    sizeof(struct bwn_dmadesc32));
4225	}
4226}
4227
4228static void
4229bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4230{
4231
4232	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4233	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4234	    dr->dr_ring_dmap);
4235}
4236
4237static void
4238bwn_dma_cleanup(struct bwn_dma_ring *dr)
4239{
4240
4241	if (dr->dr_tx) {
4242		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4243		if (dr->dr_type == BWN_DMA_64BIT) {
4244			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4245			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4246		} else
4247			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4248	} else {
4249		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4250		if (dr->dr_type == BWN_DMA_64BIT) {
4251			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4252			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4253		} else
4254			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4255	}
4256}
4257
4258static void
4259bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4260{
4261	struct bwn_dmadesc_generic *desc;
4262	struct bwn_dmadesc_meta *meta;
4263	struct bwn_mac *mac = dr->dr_mac;
4264	struct bwn_dma *dma = &mac->mac_method.dma;
4265	struct bwn_softc *sc = mac->mac_sc;
4266	int i;
4267
4268	if (!dr->dr_usedslot)
4269		return;
4270	for (i = 0; i < dr->dr_numslots; i++) {
4271		dr->getdesc(dr, i, &desc, &meta);
4272
4273		if (meta->mt_m == NULL) {
4274			if (!dr->dr_tx)
4275				device_printf(sc->sc_dev, "%s: not TX?\n",
4276				    __func__);
4277			continue;
4278		}
4279		if (dr->dr_tx) {
4280			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4281				bus_dmamap_unload(dr->dr_txring_dtag,
4282				    meta->mt_dmap);
4283			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4284				bus_dmamap_unload(dma->txbuf_dtag,
4285				    meta->mt_dmap);
4286		} else
4287			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4288		bwn_dma_free_descbuf(dr, meta);
4289	}
4290}
4291
4292static int
4293bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4294    int type)
4295{
4296	struct bwn_softc *sc = mac->mac_sc;
4297	uint32_t value;
4298	int i;
4299	uint16_t offset;
4300
4301	for (i = 0; i < 10; i++) {
4302		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4303		    BWN_DMA32_TXSTATUS;
4304		value = BWN_READ_4(mac, base + offset);
4305		if (type == BWN_DMA_64BIT) {
4306			value &= BWN_DMA64_TXSTAT;
4307			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4308			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4309			    value == BWN_DMA64_TXSTAT_STOPPED)
4310				break;
4311		} else {
4312			value &= BWN_DMA32_TXSTATE;
4313			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4314			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4315			    value == BWN_DMA32_TXSTAT_STOPPED)
4316				break;
4317		}
4318		DELAY(1000);
4319	}
4320	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4321	BWN_WRITE_4(mac, base + offset, 0);
4322	for (i = 0; i < 10; i++) {
4323		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4324						   BWN_DMA32_TXSTATUS;
4325		value = BWN_READ_4(mac, base + offset);
4326		if (type == BWN_DMA_64BIT) {
4327			value &= BWN_DMA64_TXSTAT;
4328			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4329				i = -1;
4330				break;
4331			}
4332		} else {
4333			value &= BWN_DMA32_TXSTATE;
4334			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4335				i = -1;
4336				break;
4337			}
4338		}
4339		DELAY(1000);
4340	}
4341	if (i != -1) {
4342		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4343		return (ENODEV);
4344	}
4345	DELAY(1000);
4346
4347	return (0);
4348}
4349
4350static int
4351bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4352    int type)
4353{
4354	struct bwn_softc *sc = mac->mac_sc;
4355	uint32_t value;
4356	int i;
4357	uint16_t offset;
4358
4359	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4360	BWN_WRITE_4(mac, base + offset, 0);
4361	for (i = 0; i < 10; i++) {
4362		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4363		    BWN_DMA32_RXSTATUS;
4364		value = BWN_READ_4(mac, base + offset);
4365		if (type == BWN_DMA_64BIT) {
4366			value &= BWN_DMA64_RXSTAT;
4367			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4368				i = -1;
4369				break;
4370			}
4371		} else {
4372			value &= BWN_DMA32_RXSTATE;
4373			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4374				i = -1;
4375				break;
4376			}
4377		}
4378		DELAY(1000);
4379	}
4380	if (i != -1) {
4381		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4382		return (ENODEV);
4383	}
4384
4385	return (0);
4386}
4387
4388static void
4389bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4390    struct bwn_dmadesc_meta *meta)
4391{
4392
4393	if (meta->mt_m != NULL) {
4394		m_freem(meta->mt_m);
4395		meta->mt_m = NULL;
4396	}
4397	if (meta->mt_ni != NULL) {
4398		ieee80211_free_node(meta->mt_ni);
4399		meta->mt_ni = NULL;
4400	}
4401}
4402
4403static void
4404bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4405{
4406	struct bwn_rxhdr4 *rxhdr;
4407	unsigned char *frame;
4408
4409	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4410	rxhdr->frame_len = 0;
4411
4412	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4413	    sizeof(struct bwn_plcp6) + 2,
4414	    ("%s:%d: fail", __func__, __LINE__));
4415	frame = mtod(m, char *) + dr->dr_frameoffset;
4416	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4417}
4418
4419static uint8_t
4420bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4421{
4422	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4423
4424	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4425	    == 0xff);
4426}
4427
4428static void
4429bwn_wme_init(struct bwn_mac *mac)
4430{
4431
4432	bwn_wme_load(mac);
4433
4434	/* enable WME support. */
4435	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4436	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4437	    BWN_IFSCTL_USE_EDCF);
4438}
4439
4440static void
4441bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4442{
4443	struct bwn_softc *sc = mac->mac_sc;
4444	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4445	uint16_t delay;	/* microsec */
4446
4447	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4448	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4449		delay = 500;
4450	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4451		delay = max(delay, (uint16_t)2400);
4452
4453	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4454}
4455
4456static void
4457bwn_bt_enable(struct bwn_mac *mac)
4458{
4459	struct bwn_softc *sc = mac->mac_sc;
4460	uint64_t hf;
4461
4462	if (bwn_bluetooth == 0)
4463		return;
4464	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4465		return;
4466	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4467		return;
4468
4469	hf = bwn_hf_read(mac);
4470	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4471		hf |= BWN_HF_BT_COEXISTALT;
4472	else
4473		hf |= BWN_HF_BT_COEXIST;
4474	bwn_hf_write(mac, hf);
4475}
4476
4477static void
4478bwn_set_macaddr(struct bwn_mac *mac)
4479{
4480
4481	bwn_mac_write_bssid(mac);
4482	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4483}
4484
4485static void
4486bwn_clear_keys(struct bwn_mac *mac)
4487{
4488	int i;
4489
4490	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4491		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4492		    ("%s:%d: fail", __func__, __LINE__));
4493
4494		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4495		    NULL, BWN_SEC_KEYSIZE, NULL);
4496		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4497			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4498			    NULL, BWN_SEC_KEYSIZE, NULL);
4499		}
4500		mac->mac_key[i].keyconf = NULL;
4501	}
4502}
4503
4504static void
4505bwn_crypt_init(struct bwn_mac *mac)
4506{
4507	struct bwn_softc *sc = mac->mac_sc;
4508
4509	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4510	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4511	    ("%s:%d: fail", __func__, __LINE__));
4512	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4513	mac->mac_ktp *= 2;
4514	if (siba_get_revid(sc->sc_dev) >= 5)
4515		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4516	bwn_clear_keys(mac);
4517}
4518
4519static void
4520bwn_chip_exit(struct bwn_mac *mac)
4521{
4522	struct bwn_softc *sc = mac->mac_sc;
4523
4524	bwn_phy_exit(mac);
4525	siba_gpio_set(sc->sc_dev, 0);
4526}
4527
4528static int
4529bwn_fw_fillinfo(struct bwn_mac *mac)
4530{
4531	int error;
4532
4533	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4534	if (error == 0)
4535		return (0);
4536	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4537	if (error == 0)
4538		return (0);
4539	return (error);
4540}
4541
4542static int
4543bwn_gpio_init(struct bwn_mac *mac)
4544{
4545	struct bwn_softc *sc = mac->mac_sc;
4546	uint32_t mask = 0x1f, set = 0xf, value;
4547
4548	BWN_WRITE_4(mac, BWN_MACCTL,
4549	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4550	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4551	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4552
4553	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4554		mask |= 0x0060;
4555		set |= 0x0060;
4556	}
4557	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4558		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4559		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4560		mask |= 0x0200;
4561		set |= 0x0200;
4562	}
4563	if (siba_get_revid(sc->sc_dev) >= 2)
4564		mask |= 0x0010;
4565
4566	value = siba_gpio_get(sc->sc_dev);
4567	if (value == -1)
4568		return (0);
4569	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4570
4571	return (0);
4572}
4573
4574static int
4575bwn_fw_loadinitvals(struct bwn_mac *mac)
4576{
4577#define	GETFWOFFSET(fwp, offset)				\
4578	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4579	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4580	const struct bwn_fwhdr *hdr;
4581	struct bwn_fw *fw = &mac->mac_fw;
4582	int error;
4583
4584	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4585	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4586	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4587	if (error)
4588		return (error);
4589	if (fw->initvals_band.fw) {
4590		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4591		error = bwn_fwinitvals_write(mac,
4592		    GETFWOFFSET(fw->initvals_band, hdr_len),
4593		    be32toh(hdr->size),
4594		    fw->initvals_band.fw->datasize - hdr_len);
4595	}
4596	return (error);
4597#undef GETFWOFFSET
4598}
4599
4600static int
4601bwn_phy_init(struct bwn_mac *mac)
4602{
4603	struct bwn_softc *sc = mac->mac_sc;
4604	int error;
4605
4606	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4607	mac->mac_phy.rf_onoff(mac, 1);
4608	error = mac->mac_phy.init(mac);
4609	if (error) {
4610		device_printf(sc->sc_dev, "PHY init failed\n");
4611		goto fail0;
4612	}
4613	error = bwn_switch_channel(mac,
4614	    mac->mac_phy.get_default_chan(mac));
4615	if (error) {
4616		device_printf(sc->sc_dev,
4617		    "failed to switch default channel\n");
4618		goto fail1;
4619	}
4620	return (0);
4621fail1:
4622	if (mac->mac_phy.exit)
4623		mac->mac_phy.exit(mac);
4624fail0:
4625	mac->mac_phy.rf_onoff(mac, 0);
4626
4627	return (error);
4628}
4629
4630static void
4631bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4632{
4633	uint16_t ant;
4634	uint16_t tmp;
4635
4636	ant = bwn_ant2phy(antenna);
4637
4638	/* For ACK/CTS */
4639	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4640	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4641	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4642	/* For Probe Resposes */
4643	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4644	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4645	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4646}
4647
4648static void
4649bwn_set_opmode(struct bwn_mac *mac)
4650{
4651	struct bwn_softc *sc = mac->mac_sc;
4652	struct ifnet *ifp = sc->sc_ifp;
4653	struct ieee80211com *ic = ifp->if_l2com;
4654	uint32_t ctl;
4655	uint16_t cfp_pretbtt;
4656
4657	ctl = BWN_READ_4(mac, BWN_MACCTL);
4658	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4659	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4660	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4661	ctl |= BWN_MACCTL_STA;
4662
4663	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4664	    ic->ic_opmode == IEEE80211_M_MBSS)
4665		ctl |= BWN_MACCTL_HOSTAP;
4666	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4667		ctl &= ~BWN_MACCTL_STA;
4668	ctl |= sc->sc_filters;
4669
4670	if (siba_get_revid(sc->sc_dev) <= 4)
4671		ctl |= BWN_MACCTL_PROMISC;
4672
4673	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4674
4675	cfp_pretbtt = 2;
4676	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4677		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4678		    siba_get_chiprev(sc->sc_dev) == 3)
4679			cfp_pretbtt = 100;
4680		else
4681			cfp_pretbtt = 50;
4682	}
4683	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4684}
4685
4686static int
4687bwn_dma_gettype(struct bwn_mac *mac)
4688{
4689	uint32_t tmp;
4690	uint16_t base;
4691
4692	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4693	if (tmp & SIBA_TGSHIGH_DMA64)
4694		return (BWN_DMA_64BIT);
4695	base = bwn_dma_base(0, 0);
4696	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4697	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4698	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4699		return (BWN_DMA_32BIT);
4700
4701	return (BWN_DMA_30BIT);
4702}
4703
4704static void
4705bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4706{
4707	if (!error) {
4708		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4709		*((bus_addr_t *)arg) = seg->ds_addr;
4710	}
4711}
4712
4713static void
4714bwn_phy_g_init_sub(struct bwn_mac *mac)
4715{
4716	struct bwn_phy *phy = &mac->mac_phy;
4717	struct bwn_phy_g *pg = &phy->phy_g;
4718	struct bwn_softc *sc = mac->mac_sc;
4719	uint16_t i, tmp;
4720
4721	if (phy->rev == 1)
4722		bwn_phy_init_b5(mac);
4723	else
4724		bwn_phy_init_b6(mac);
4725
4726	if (phy->rev >= 2 || phy->gmode)
4727		bwn_phy_init_a(mac);
4728
4729	if (phy->rev >= 2) {
4730		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4731		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4732	}
4733	if (phy->rev == 2) {
4734		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4735		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4736	}
4737	if (phy->rev > 5) {
4738		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4739		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4740	}
4741	if (phy->gmode || phy->rev >= 2) {
4742		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4743		tmp &= BWN_PHYVER_VERSION;
4744		if (tmp == 3 || tmp == 5) {
4745			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4746			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4747		}
4748		if (tmp == 5) {
4749			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4750			    0x1f00);
4751		}
4752	}
4753	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4754		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4755	if (phy->rf_rev == 8) {
4756		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4757		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4758	}
4759	if (BWN_HAS_LOOPBACK(phy))
4760		bwn_loopback_calcgain(mac);
4761
4762	if (phy->rf_rev != 8) {
4763		if (pg->pg_initval == 0xffff)
4764			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4765		else
4766			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4767	}
4768	bwn_lo_g_init(mac);
4769	if (BWN_HAS_TXMAG(phy)) {
4770		BWN_RF_WRITE(mac, 0x52,
4771		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4772		    | pg->pg_loctl.tx_bias |
4773		    pg->pg_loctl.tx_magn);
4774	} else {
4775		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4776	}
4777	if (phy->rev >= 6) {
4778		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4779		    (pg->pg_loctl.tx_bias << 12));
4780	}
4781	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4782		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4783	else
4784		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4785	if (phy->rev < 2)
4786		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4787	else
4788		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4789	if (phy->gmode || phy->rev >= 2) {
4790		bwn_lo_g_adjust(mac);
4791		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4792	}
4793
4794	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4795		for (i = 0; i < 64; i++) {
4796			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4797			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4798			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4799			    -32), 31));
4800		}
4801		bwn_nrssi_threshold(mac);
4802	} else if (phy->gmode || phy->rev >= 2) {
4803		if (pg->pg_nrssi[0] == -1000) {
4804			KASSERT(pg->pg_nrssi[1] == -1000,
4805			    ("%s:%d: fail", __func__, __LINE__));
4806			bwn_nrssi_slope_11g(mac);
4807		} else
4808			bwn_nrssi_threshold(mac);
4809	}
4810	if (phy->rf_rev == 8)
4811		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4812	bwn_phy_hwpctl_init(mac);
4813	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4814	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4815		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4816		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4817	}
4818}
4819
4820static uint8_t
4821bwn_has_hwpctl(struct bwn_mac *mac)
4822{
4823
4824	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4825		return (0);
4826	return (mac->mac_phy.use_hwpctl(mac));
4827}
4828
4829static void
4830bwn_phy_init_b5(struct bwn_mac *mac)
4831{
4832	struct bwn_phy *phy = &mac->mac_phy;
4833	struct bwn_phy_g *pg = &phy->phy_g;
4834	struct bwn_softc *sc = mac->mac_sc;
4835	uint16_t offset, value;
4836	uint8_t old_channel;
4837
4838	if (phy->analog == 1)
4839		BWN_RF_SET(mac, 0x007a, 0x0050);
4840	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4841	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4842		value = 0x2120;
4843		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4844			BWN_PHY_WRITE(mac, offset, value);
4845			value += 0x202;
4846		}
4847	}
4848	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4849	if (phy->rf_ver == 0x2050)
4850		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4851
4852	if (phy->gmode || phy->rev >= 2) {
4853		if (phy->rf_ver == 0x2050) {
4854			BWN_RF_SET(mac, 0x007a, 0x0020);
4855			BWN_RF_SET(mac, 0x0051, 0x0004);
4856		}
4857		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4858
4859		BWN_PHY_SET(mac, 0x0802, 0x0100);
4860		BWN_PHY_SET(mac, 0x042b, 0x2000);
4861
4862		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4863
4864		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4865		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4866		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4867	}
4868
4869	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4870		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4871
4872	if (phy->analog == 1) {
4873		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4874		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4875		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4876		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4877		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4878	} else
4879		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4880	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4881	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4882
4883	if (phy->analog == 1)
4884		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4885	else
4886		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4887
4888	if (phy->analog == 0)
4889		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4890
4891	old_channel = phy->chan;
4892	bwn_phy_g_switch_chan(mac, 7, 0);
4893
4894	if (phy->rf_ver != 0x2050) {
4895		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4896		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4897	}
4898
4899	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4900	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4901
4902	if (phy->rf_ver == 0x2050) {
4903		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4904		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4905	}
4906
4907	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4908	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4909	BWN_RF_SET(mac, 0x007a, 0x0007);
4910
4911	bwn_phy_g_switch_chan(mac, old_channel, 0);
4912	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4913	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4914	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4915
4916	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4917	    pg->pg_txctl);
4918
4919	if (phy->rf_ver == 0x2050)
4920		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4921
4922	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4923}
4924
4925static void
4926bwn_loopback_calcgain(struct bwn_mac *mac)
4927{
4928	struct bwn_phy *phy = &mac->mac_phy;
4929	struct bwn_phy_g *pg = &phy->phy_g;
4930	struct bwn_softc *sc = mac->mac_sc;
4931	uint16_t backup_phy[16] = { 0 };
4932	uint16_t backup_radio[3];
4933	uint16_t backup_bband;
4934	uint16_t i, j, loop_i_max;
4935	uint16_t trsw_rx;
4936	uint16_t loop1_outer_done, loop1_inner_done;
4937
4938	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4939	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4940	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4941	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4942	if (phy->rev != 1) {
4943		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4944		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4945	}
4946	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4947	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4948	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4949	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4950	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4951	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4952	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4953	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4954	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4955	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4956	backup_bband = pg->pg_bbatt.att;
4957	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4958	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4959	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4960
4961	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4962	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4963	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4964	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4965	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4966	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4967	if (phy->rev != 1) {
4968		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4969		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4970		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4971		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4972	}
4973	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4974	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4975	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4976	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4977
4978	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4979	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4980	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4981
4982	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4983	if (phy->rev != 1) {
4984		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4985		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4986	}
4987	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4988
4989	if (phy->rf_rev == 8)
4990		BWN_RF_WRITE(mac, 0x43, 0x000f);
4991	else {
4992		BWN_RF_WRITE(mac, 0x52, 0);
4993		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4994	}
4995	bwn_phy_g_set_bbatt(mac, 11);
4996
4997	if (phy->rev >= 3)
4998		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4999	else
5000		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5001	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5002
5003	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5004	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5005
5006	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5007	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5008
5009	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5010		if (phy->rev >= 7) {
5011			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5012			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5013		}
5014	}
5015	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5016
5017	j = 0;
5018	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5019	for (i = 0; i < loop_i_max; i++) {
5020		for (j = 0; j < 16; j++) {
5021			BWN_RF_WRITE(mac, 0x43, i);
5022			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5023			    (j << 8));
5024			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5025			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5026			DELAY(20);
5027			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5028				goto done0;
5029		}
5030	}
5031done0:
5032	loop1_outer_done = i;
5033	loop1_inner_done = j;
5034	if (j >= 8) {
5035		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5036		trsw_rx = 0x1b;
5037		for (j = j - 8; j < 16; j++) {
5038			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5039			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5040			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5041			DELAY(20);
5042			trsw_rx -= 3;
5043			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5044				goto done1;
5045		}
5046	} else
5047		trsw_rx = 0x18;
5048done1:
5049
5050	if (phy->rev != 1) {
5051		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5052		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5053	}
5054	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5055	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5056	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5061	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5062	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5063
5064	bwn_phy_g_set_bbatt(mac, backup_bband);
5065
5066	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5067	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5068	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5069
5070	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5071	DELAY(10);
5072	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5073	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5074	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5075	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5076
5077	pg->pg_max_lb_gain =
5078	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5079	pg->pg_trsw_rx_gain = trsw_rx * 2;
5080}
5081
5082static uint16_t
5083bwn_rf_init_bcm2050(struct bwn_mac *mac)
5084{
5085	struct bwn_phy *phy = &mac->mac_phy;
5086	uint32_t tmp1 = 0, tmp2 = 0;
5087	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5088	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5089	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5090	static const uint8_t rcc_table[] = {
5091		0x02, 0x03, 0x01, 0x0f,
5092		0x06, 0x07, 0x05, 0x0f,
5093		0x0a, 0x0b, 0x09, 0x0f,
5094		0x0e, 0x0f, 0x0d, 0x0f,
5095	};
5096
5097	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5098	    rfoverval = rfover = cck3 = 0;
5099	radio0 = BWN_RF_READ(mac, 0x43);
5100	radio1 = BWN_RF_READ(mac, 0x51);
5101	radio2 = BWN_RF_READ(mac, 0x52);
5102	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5103	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5104	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5105	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5106
5107	if (phy->type == BWN_PHYTYPE_B) {
5108		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5109		reg0 = BWN_READ_2(mac, 0x3ec);
5110
5111		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5112		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5113	} else if (phy->gmode || phy->rev >= 2) {
5114		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5115		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5116		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5117		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5118		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5119		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5120
5121		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5122		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5123		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5124		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5125		if (BWN_HAS_LOOPBACK(phy)) {
5126			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5127			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5128			if (phy->rev >= 3)
5129				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5130			else
5131				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5132			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5133		}
5134
5135		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5136		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5137			BWN_LPD(0, 1, 1)));
5138		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5139		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5140	}
5141	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5142
5143	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5144	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5145	reg1 = BWN_READ_2(mac, 0x3e6);
5146	reg2 = BWN_READ_2(mac, 0x3f4);
5147
5148	if (phy->analog == 0)
5149		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5150	else {
5151		if (phy->analog >= 2)
5152			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5153		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5154		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5155	}
5156
5157	reg = BWN_RF_READ(mac, 0x60);
5158	index = (reg & 0x001e) >> 1;
5159	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5160
5161	if (phy->type == BWN_PHYTYPE_B)
5162		BWN_RF_WRITE(mac, 0x78, 0x26);
5163	if (phy->gmode || phy->rev >= 2) {
5164		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5165		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5166			BWN_LPD(0, 1, 1)));
5167	}
5168	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5169	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5170	if (phy->gmode || phy->rev >= 2) {
5171		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5172		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5173			BWN_LPD(0, 0, 1)));
5174	}
5175	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5176	BWN_RF_SET(mac, 0x51, 0x0004);
5177	if (phy->rf_rev == 8)
5178		BWN_RF_WRITE(mac, 0x43, 0x1f);
5179	else {
5180		BWN_RF_WRITE(mac, 0x52, 0);
5181		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5182	}
5183	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5184
5185	for (i = 0; i < 16; i++) {
5186		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5187		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5188		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5189		if (phy->gmode || phy->rev >= 2) {
5190			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5191			    bwn_rf_2050_rfoverval(mac,
5192				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5193		}
5194		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5195		DELAY(10);
5196		if (phy->gmode || phy->rev >= 2) {
5197			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5198			    bwn_rf_2050_rfoverval(mac,
5199				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5200		}
5201		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5202		DELAY(10);
5203		if (phy->gmode || phy->rev >= 2) {
5204			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5205			    bwn_rf_2050_rfoverval(mac,
5206				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5207		}
5208		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5209		DELAY(20);
5210		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5211		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5212		if (phy->gmode || phy->rev >= 2) {
5213			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5214			    bwn_rf_2050_rfoverval(mac,
5215				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5216		}
5217		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5218	}
5219	DELAY(10);
5220
5221	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5222	tmp1++;
5223	tmp1 >>= 9;
5224
5225	for (i = 0; i < 16; i++) {
5226		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5227		BWN_RF_WRITE(mac, 0x78, radio78);
5228		DELAY(10);
5229		for (j = 0; j < 16; j++) {
5230			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5231			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5232			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5233			if (phy->gmode || phy->rev >= 2) {
5234				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5235				    bwn_rf_2050_rfoverval(mac,
5236					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5237			}
5238			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5239			DELAY(10);
5240			if (phy->gmode || phy->rev >= 2) {
5241				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5242				    bwn_rf_2050_rfoverval(mac,
5243					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5244			}
5245			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5246			DELAY(10);
5247			if (phy->gmode || phy->rev >= 2) {
5248				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5249				    bwn_rf_2050_rfoverval(mac,
5250					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5251			}
5252			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5253			DELAY(10);
5254			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5255			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5256			if (phy->gmode || phy->rev >= 2) {
5257				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5258				    bwn_rf_2050_rfoverval(mac,
5259					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5260			}
5261			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5262		}
5263		tmp2++;
5264		tmp2 >>= 8;
5265		if (tmp1 < tmp2)
5266			break;
5267	}
5268
5269	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5270	BWN_RF_WRITE(mac, 0x51, radio1);
5271	BWN_RF_WRITE(mac, 0x52, radio2);
5272	BWN_RF_WRITE(mac, 0x43, radio0);
5273	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5274	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5275	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5276	BWN_WRITE_2(mac, 0x3e6, reg1);
5277	if (phy->analog != 0)
5278		BWN_WRITE_2(mac, 0x3f4, reg2);
5279	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5280	bwn_spu_workaround(mac, phy->chan);
5281	if (phy->type == BWN_PHYTYPE_B) {
5282		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5283		BWN_WRITE_2(mac, 0x3ec, reg0);
5284	} else if (phy->gmode) {
5285		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5286			    BWN_READ_2(mac, BWN_PHY_RADIO)
5287			    & 0x7fff);
5288		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5289		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5290		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5291		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5292			      analogoverval);
5293		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5294		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5295		if (BWN_HAS_LOOPBACK(phy)) {
5296			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5297			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5298		}
5299	}
5300
5301	return ((i > 15) ? radio78 : rcc);
5302}
5303
5304static void
5305bwn_phy_init_b6(struct bwn_mac *mac)
5306{
5307	struct bwn_phy *phy = &mac->mac_phy;
5308	struct bwn_phy_g *pg = &phy->phy_g;
5309	struct bwn_softc *sc = mac->mac_sc;
5310	uint16_t offset, val;
5311	uint8_t old_channel;
5312
5313	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5314	    ("%s:%d: fail", __func__, __LINE__));
5315
5316	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5317	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5318	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5319		BWN_RF_WRITE(mac, 0x51, 0x37);
5320		BWN_RF_WRITE(mac, 0x52, 0x70);
5321		BWN_RF_WRITE(mac, 0x53, 0xb3);
5322		BWN_RF_WRITE(mac, 0x54, 0x9b);
5323		BWN_RF_WRITE(mac, 0x5a, 0x88);
5324		BWN_RF_WRITE(mac, 0x5b, 0x88);
5325		BWN_RF_WRITE(mac, 0x5d, 0x88);
5326		BWN_RF_WRITE(mac, 0x5e, 0x88);
5327		BWN_RF_WRITE(mac, 0x7d, 0x88);
5328		bwn_hf_write(mac,
5329		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5330	}
5331	if (phy->rf_rev == 8) {
5332		BWN_RF_WRITE(mac, 0x51, 0);
5333		BWN_RF_WRITE(mac, 0x52, 0x40);
5334		BWN_RF_WRITE(mac, 0x53, 0xb7);
5335		BWN_RF_WRITE(mac, 0x54, 0x98);
5336		BWN_RF_WRITE(mac, 0x5a, 0x88);
5337		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5338		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5339		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5340			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5341			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5342		} else {
5343			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5344			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5345		}
5346		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5347		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5348		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5349		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5350	}
5351	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5352		BWN_PHY_WRITE(mac, offset, val);
5353		val -= 0x0202;
5354	}
5355	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5356		BWN_PHY_WRITE(mac, offset, val);
5357		val -= 0x0202;
5358	}
5359	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5360		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5361		val += 0x0202;
5362	}
5363	if (phy->type == BWN_PHYTYPE_G) {
5364		BWN_RF_SET(mac, 0x007a, 0x0020);
5365		BWN_RF_SET(mac, 0x0051, 0x0004);
5366		BWN_PHY_SET(mac, 0x0802, 0x0100);
5367		BWN_PHY_SET(mac, 0x042b, 0x2000);
5368		BWN_PHY_WRITE(mac, 0x5b, 0);
5369		BWN_PHY_WRITE(mac, 0x5c, 0);
5370	}
5371
5372	old_channel = phy->chan;
5373	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5374
5375	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5376	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5377	DELAY(40);
5378	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5379		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5380		BWN_RF_WRITE(mac, 0x50, 0x20);
5381	}
5382	if (phy->rf_rev <= 2) {
5383		BWN_RF_WRITE(mac, 0x7c, 0x20);
5384		BWN_RF_WRITE(mac, 0x5a, 0x70);
5385		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5386		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5387	}
5388	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5389
5390	bwn_phy_g_switch_chan(mac, old_channel, 0);
5391
5392	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5393	if (phy->rf_rev >= 6)
5394		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5395	else
5396		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5397	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5398	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5399	    pg->pg_txctl);
5400	if (phy->rf_rev <= 5)
5401		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5402	if (phy->rf_rev <= 2)
5403		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5404
5405	if (phy->analog == 4) {
5406		BWN_WRITE_2(mac, 0x3e4, 9);
5407		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5408	} else
5409		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5410	if (phy->type == BWN_PHYTYPE_B)
5411		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5412	else if (phy->type == BWN_PHYTYPE_G)
5413		BWN_WRITE_2(mac, 0x03e6, 0x0);
5414}
5415
5416static void
5417bwn_phy_init_a(struct bwn_mac *mac)
5418{
5419	struct bwn_phy *phy = &mac->mac_phy;
5420	struct bwn_softc *sc = mac->mac_sc;
5421
5422	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5423	    ("%s:%d: fail", __func__, __LINE__));
5424
5425	if (phy->rev >= 6) {
5426		if (phy->type == BWN_PHYTYPE_A)
5427			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5428		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5429			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5430		else
5431			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5432	}
5433
5434	bwn_wa_init(mac);
5435
5436	if (phy->type == BWN_PHYTYPE_G &&
5437	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5438		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5439}
5440
5441static void
5442bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5443{
5444	int i;
5445
5446	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5447		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5448}
5449
5450static void
5451bwn_wa_agc(struct bwn_mac *mac)
5452{
5453	struct bwn_phy *phy = &mac->mac_phy;
5454
5455	if (phy->rev == 1) {
5456		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5457		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5463		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5464		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5465	} else {
5466		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5467		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5468		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5469		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5470	}
5471
5472	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5473	    0x5700);
5474	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5475	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5476	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5477	BWN_RF_SET(mac, 0x7a, 0x0008);
5478	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5479	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5480	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5481	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5482	if (phy->rev == 1)
5483		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5484	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5485	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5491	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5492	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5493	if (phy->rev == 1) {
5494		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5495		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5496	} else {
5497		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5498		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5499		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5500		if (phy->rev >= 6) {
5501			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5502			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5503			    (uint16_t)~0xf000, 0x3000);
5504		}
5505	}
5506	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5507	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5508	if (phy->rev == 1) {
5509		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5510		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5511		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5512		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5513		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5517	} else {
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5522	}
5523	if (phy->rev >= 6) {
5524		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5525		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5526	}
5527	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5528}
5529
5530static void
5531bwn_wa_grev1(struct bwn_mac *mac)
5532{
5533	struct bwn_phy *phy = &mac->mac_phy;
5534	int i;
5535	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5536	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5537	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5538
5539	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5540
5541	/* init CRSTHRES and ANTDWELL */
5542	if (phy->rev == 1) {
5543		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5544	} else if (phy->rev == 2) {
5545		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5546		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5547		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5548	} else {
5549		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5550		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5551		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5552		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5553	}
5554	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5555	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5556	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5557
5558	/* XXX support PHY-A??? */
5559	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5560		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5561		    bwn_tab_finefreqg[i]);
5562
5563	/* XXX support PHY-A??? */
5564	if (phy->rev == 1)
5565		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5566			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5567			    bwn_tab_noise_g1[i]);
5568	else
5569		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5570			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5571			    bwn_tab_noise_g2[i]);
5572
5573
5574	for (i = 0; i < N(bwn_tab_rotor); i++)
5575		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5576		    bwn_tab_rotor[i]);
5577
5578	/* XXX support PHY-A??? */
5579	if (phy->rev >= 6) {
5580		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5581		    BWN_PHY_ENCORE_EN)
5582			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5583		else
5584			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5585	} else
5586		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5587
5588	for (i = 0; i < N(bwn_tab_retard); i++)
5589		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5590		    bwn_tab_retard[i]);
5591
5592	if (phy->rev == 1) {
5593		for (i = 0; i < 16; i++)
5594			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5595			    i, 0x0020);
5596	} else {
5597		for (i = 0; i < 32; i++)
5598			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5599	}
5600
5601	bwn_wa_agc(mac);
5602}
5603
5604static void
5605bwn_wa_grev26789(struct bwn_mac *mac)
5606{
5607	struct bwn_phy *phy = &mac->mac_phy;
5608	int i;
5609	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5610	uint16_t ofdmrev;
5611
5612	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5613
5614	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5615
5616	/* init CRSTHRES and ANTDWELL */
5617	if (phy->rev == 1)
5618		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5619	else if (phy->rev == 2) {
5620		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5621		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5622		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5623	} else {
5624		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5625		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5626		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5627		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5628	}
5629
5630	for (i = 0; i < 64; i++)
5631		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5632
5633	/* XXX support PHY-A??? */
5634	if (phy->rev == 1)
5635		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5636			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5637			    bwn_tab_noise_g1[i]);
5638	else
5639		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5640			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5641			    bwn_tab_noise_g2[i]);
5642
5643	/* XXX support PHY-A??? */
5644	if (phy->rev >= 6) {
5645		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5646		    BWN_PHY_ENCORE_EN)
5647			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5648		else
5649			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5650	} else
5651		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5652
5653	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5654		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5655		    bwn_tab_sigmasqr2[i]);
5656
5657	if (phy->rev == 1) {
5658		for (i = 0; i < 16; i++)
5659			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5660			    0x0020);
5661	} else {
5662		for (i = 0; i < 32; i++)
5663			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5664	}
5665
5666	bwn_wa_agc(mac);
5667
5668	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5669	if (ofdmrev > 2) {
5670		if (phy->type == BWN_PHYTYPE_A)
5671			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5672		else
5673			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5674	} else {
5675		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5676		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5677		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5678	}
5679
5680	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5681	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5682}
5683
5684static void
5685bwn_wa_init(struct bwn_mac *mac)
5686{
5687	struct bwn_phy *phy = &mac->mac_phy;
5688	struct bwn_softc *sc = mac->mac_sc;
5689
5690	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5691
5692	switch (phy->rev) {
5693	case 1:
5694		bwn_wa_grev1(mac);
5695		break;
5696	case 2:
5697	case 6:
5698	case 7:
5699	case 8:
5700	case 9:
5701		bwn_wa_grev26789(mac);
5702		break;
5703	default:
5704		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5705	}
5706
5707	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5708	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5709	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5710		if (phy->rev < 2) {
5711			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5712			    0x0002);
5713			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5714			    0x0001);
5715		} else {
5716			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5717			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5718			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5719			     BWN_BFL_EXTLNA) &&
5720			    (phy->rev >= 7)) {
5721				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5722				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723				    0x0020, 0x0001);
5724				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725				    0x0021, 0x0001);
5726				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727				    0x0022, 0x0001);
5728				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729				    0x0023, 0x0000);
5730				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5731				    0x0000, 0x0000);
5732				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5733				    0x0003, 0x0002);
5734			}
5735		}
5736	}
5737	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5738		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5739		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5740	}
5741
5742	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5743	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5744}
5745
5746static void
5747bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5748    uint16_t value)
5749{
5750	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5751	uint16_t addr;
5752
5753	addr = table + offset;
5754	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5755	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5756		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5757		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5758	}
5759	pg->pg_ofdmtab_addr = addr;
5760	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5761}
5762
5763static void
5764bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5765    uint32_t value)
5766{
5767	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5768	uint16_t addr;
5769
5770	addr = table + offset;
5771	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5772	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5773		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5774		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5775	}
5776	pg->pg_ofdmtab_addr = addr;
5777
5778	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5779	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5780}
5781
5782static void
5783bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5784    uint16_t value)
5785{
5786
5787	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5788	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5789}
5790
5791static void
5792bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5793{
5794	struct bwn_phy *phy = &mac->mac_phy;
5795	struct bwn_softc *sc = mac->mac_sc;
5796	unsigned int i, max_loop;
5797	uint16_t value;
5798	uint32_t buffer[5] = {
5799		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5800	};
5801
5802	if (ofdm) {
5803		max_loop = 0x1e;
5804		buffer[0] = 0x000201cc;
5805	} else {
5806		max_loop = 0xfa;
5807		buffer[0] = 0x000b846e;
5808	}
5809
5810	BWN_ASSERT_LOCKED(mac->mac_sc);
5811
5812	for (i = 0; i < 5; i++)
5813		bwn_ram_write(mac, i * 4, buffer[i]);
5814
5815	BWN_WRITE_2(mac, 0x0568, 0x0000);
5816	BWN_WRITE_2(mac, 0x07c0,
5817	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5818	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5819	BWN_WRITE_2(mac, 0x050c, value);
5820	if (phy->type == BWN_PHYTYPE_LP)
5821		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5822	BWN_WRITE_2(mac, 0x0508, 0x0000);
5823	BWN_WRITE_2(mac, 0x050a, 0x0000);
5824	BWN_WRITE_2(mac, 0x054c, 0x0000);
5825	BWN_WRITE_2(mac, 0x056a, 0x0014);
5826	BWN_WRITE_2(mac, 0x0568, 0x0826);
5827	BWN_WRITE_2(mac, 0x0500, 0x0000);
5828	if (phy->type == BWN_PHYTYPE_LP)
5829		BWN_WRITE_2(mac, 0x0502, 0x0050);
5830	else
5831		BWN_WRITE_2(mac, 0x0502, 0x0030);
5832
5833	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5834		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5835	for (i = 0x00; i < max_loop; i++) {
5836		value = BWN_READ_2(mac, 0x050e);
5837		if (value & 0x0080)
5838			break;
5839		DELAY(10);
5840	}
5841	for (i = 0x00; i < 0x0a; i++) {
5842		value = BWN_READ_2(mac, 0x050e);
5843		if (value & 0x0400)
5844			break;
5845		DELAY(10);
5846	}
5847	for (i = 0x00; i < 0x19; i++) {
5848		value = BWN_READ_2(mac, 0x0690);
5849		if (!(value & 0x0100))
5850			break;
5851		DELAY(10);
5852	}
5853	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5854		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5855}
5856
5857static void
5858bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5859{
5860	uint32_t macctl;
5861
5862	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5863
5864	macctl = BWN_READ_4(mac, BWN_MACCTL);
5865	if (macctl & BWN_MACCTL_BIGENDIAN)
5866		printf("TODO: need swap\n");
5867
5868	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5869	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5870	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5871}
5872
5873static void
5874bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5875{
5876	uint16_t value;
5877
5878	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5879	    ("%s:%d: fail", __func__, __LINE__));
5880
5881	value = (uint8_t) (ctl->q);
5882	value |= ((uint8_t) (ctl->i)) << 8;
5883	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5884}
5885
5886static uint16_t
5887bwn_lo_calcfeed(struct bwn_mac *mac,
5888    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5889{
5890	struct bwn_phy *phy = &mac->mac_phy;
5891	struct bwn_softc *sc = mac->mac_sc;
5892	uint16_t rfover;
5893	uint16_t feedthrough;
5894
5895	if (phy->gmode) {
5896		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5897		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5898
5899		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5900		    ("%s:%d: fail", __func__, __LINE__));
5901		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5902		    ("%s:%d: fail", __func__, __LINE__));
5903
5904		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5905
5906		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5907		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5908		    phy->rev > 6)
5909			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5910
5911		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5912		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5913		DELAY(10);
5914		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5915		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5916		DELAY(10);
5917		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5918		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5919		DELAY(10);
5920		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5921	} else {
5922		pga |= BWN_PHY_PGACTL_UNKNOWN;
5923		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5924		DELAY(10);
5925		pga |= BWN_PHY_PGACTL_LOWBANDW;
5926		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5927		DELAY(10);
5928		pga |= BWN_PHY_PGACTL_LPF;
5929		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5930	}
5931	DELAY(21);
5932	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5933
5934	return (feedthrough);
5935}
5936
5937static uint16_t
5938bwn_lo_txctl_regtable(struct bwn_mac *mac,
5939    uint16_t *value, uint16_t *pad_mix_gain)
5940{
5941	struct bwn_phy *phy = &mac->mac_phy;
5942	uint16_t reg, v, padmix;
5943
5944	if (phy->type == BWN_PHYTYPE_B) {
5945		v = 0x30;
5946		if (phy->rf_rev <= 5) {
5947			reg = 0x43;
5948			padmix = 0;
5949		} else {
5950			reg = 0x52;
5951			padmix = 5;
5952		}
5953	} else {
5954		if (phy->rev >= 2 && phy->rf_rev == 8) {
5955			reg = 0x43;
5956			v = 0x10;
5957			padmix = 2;
5958		} else {
5959			reg = 0x52;
5960			v = 0x30;
5961			padmix = 5;
5962		}
5963	}
5964	if (value)
5965		*value = v;
5966	if (pad_mix_gain)
5967		*pad_mix_gain = padmix;
5968
5969	return (reg);
5970}
5971
5972static void
5973bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5974{
5975	struct bwn_phy *phy = &mac->mac_phy;
5976	struct bwn_phy_g *pg = &phy->phy_g;
5977	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5978	uint16_t reg, mask;
5979	uint16_t trsw_rx, pga;
5980	uint16_t rf_pctl_reg;
5981
5982	static const uint8_t tx_bias_values[] = {
5983		0x09, 0x08, 0x0a, 0x01, 0x00,
5984		0x02, 0x05, 0x04, 0x06,
5985	};
5986	static const uint8_t tx_magn_values[] = {
5987		0x70, 0x40,
5988	};
5989
5990	if (!BWN_HAS_LOOPBACK(phy)) {
5991		rf_pctl_reg = 6;
5992		trsw_rx = 2;
5993		pga = 0;
5994	} else {
5995		int lb_gain;
5996
5997		trsw_rx = 0;
5998		lb_gain = pg->pg_max_lb_gain / 2;
5999		if (lb_gain > 10) {
6000			rf_pctl_reg = 0;
6001			pga = abs(10 - lb_gain) / 6;
6002			pga = MIN(MAX(pga, 0), 15);
6003		} else {
6004			int cmp_val;
6005			int tmp;
6006
6007			pga = 0;
6008			cmp_val = 0x24;
6009			if ((phy->rev >= 2) &&
6010			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6011				cmp_val = 0x3c;
6012			tmp = lb_gain;
6013			if ((10 - lb_gain) < cmp_val)
6014				tmp = (10 - lb_gain);
6015			if (tmp < 0)
6016				tmp += 6;
6017			else
6018				tmp += 3;
6019			cmp_val /= 4;
6020			tmp /= 4;
6021			if (tmp >= cmp_val)
6022				rf_pctl_reg = cmp_val;
6023			else
6024				rf_pctl_reg = tmp;
6025		}
6026	}
6027	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6028	bwn_phy_g_set_bbatt(mac, 2);
6029
6030	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6031	mask = ~mask;
6032	BWN_RF_MASK(mac, reg, mask);
6033
6034	if (BWN_HAS_TXMAG(phy)) {
6035		int i, j;
6036		int feedthrough;
6037		int min_feedth = 0xffff;
6038		uint8_t tx_magn, tx_bias;
6039
6040		for (i = 0; i < N(tx_magn_values); i++) {
6041			tx_magn = tx_magn_values[i];
6042			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6043			for (j = 0; j < N(tx_bias_values); j++) {
6044				tx_bias = tx_bias_values[j];
6045				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6046				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6047				    trsw_rx);
6048				if (feedthrough < min_feedth) {
6049					lo->tx_bias = tx_bias;
6050					lo->tx_magn = tx_magn;
6051					min_feedth = feedthrough;
6052				}
6053				if (lo->tx_bias == 0)
6054					break;
6055			}
6056			BWN_RF_WRITE(mac, 0x52,
6057					  (BWN_RF_READ(mac, 0x52)
6058					   & 0xff00) | lo->tx_bias | lo->
6059					  tx_magn);
6060		}
6061	} else {
6062		lo->tx_magn = 0;
6063		lo->tx_bias = 0;
6064		BWN_RF_MASK(mac, 0x52, 0xfff0);
6065	}
6066
6067	BWN_GETTIME(lo->txctl_measured_time);
6068}
6069
6070static void
6071bwn_lo_get_powervector(struct bwn_mac *mac)
6072{
6073	struct bwn_phy *phy = &mac->mac_phy;
6074	struct bwn_phy_g *pg = &phy->phy_g;
6075	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6076	int i;
6077	uint64_t tmp;
6078	uint64_t power_vector = 0;
6079
6080	for (i = 0; i < 8; i += 2) {
6081		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6082		power_vector |= (tmp << (i * 8));
6083		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6084	}
6085	if (power_vector)
6086		lo->power_vector = power_vector;
6087
6088	BWN_GETTIME(lo->pwr_vec_read_time);
6089}
6090
6091static void
6092bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6093    int use_trsw_rx)
6094{
6095	struct bwn_phy *phy = &mac->mac_phy;
6096	struct bwn_phy_g *pg = &phy->phy_g;
6097	uint16_t tmp;
6098
6099	if (max_rx_gain < 0)
6100		max_rx_gain = 0;
6101
6102	if (BWN_HAS_LOOPBACK(phy)) {
6103		int trsw_rx = 0;
6104		int trsw_rx_gain;
6105
6106		if (use_trsw_rx) {
6107			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6108			if (max_rx_gain >= trsw_rx_gain) {
6109				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6110				trsw_rx = 0x20;
6111			}
6112		} else
6113			trsw_rx_gain = max_rx_gain;
6114		if (trsw_rx_gain < 9) {
6115			pg->pg_lna_lod_gain = 0;
6116		} else {
6117			pg->pg_lna_lod_gain = 1;
6118			trsw_rx_gain -= 8;
6119		}
6120		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6121		pg->pg_pga_gain = trsw_rx_gain / 3;
6122		if (pg->pg_pga_gain >= 5) {
6123			pg->pg_pga_gain -= 5;
6124			pg->pg_lna_gain = 2;
6125		} else
6126			pg->pg_lna_gain = 0;
6127	} else {
6128		pg->pg_lna_gain = 0;
6129		pg->pg_trsw_rx_gain = 0x20;
6130		if (max_rx_gain >= 0x14) {
6131			pg->pg_lna_lod_gain = 1;
6132			pg->pg_pga_gain = 2;
6133		} else if (max_rx_gain >= 0x12) {
6134			pg->pg_lna_lod_gain = 1;
6135			pg->pg_pga_gain = 1;
6136		} else if (max_rx_gain >= 0xf) {
6137			pg->pg_lna_lod_gain = 1;
6138			pg->pg_pga_gain = 0;
6139		} else {
6140			pg->pg_lna_lod_gain = 0;
6141			pg->pg_pga_gain = 0;
6142		}
6143	}
6144
6145	tmp = BWN_RF_READ(mac, 0x7a);
6146	if (pg->pg_lna_lod_gain == 0)
6147		tmp &= ~0x0008;
6148	else
6149		tmp |= 0x0008;
6150	BWN_RF_WRITE(mac, 0x7a, tmp);
6151}
6152
6153static void
6154bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6155{
6156	struct bwn_phy *phy = &mac->mac_phy;
6157	struct bwn_phy_g *pg = &phy->phy_g;
6158	struct bwn_softc *sc = mac->mac_sc;
6159	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6160	struct timespec ts;
6161	uint16_t tmp;
6162
6163	if (bwn_has_hwpctl(mac)) {
6164		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6165		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6166		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6167		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6168		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6169
6170		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6171		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6172		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6173		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6174	}
6175	if (phy->type == BWN_PHYTYPE_B &&
6176	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6177		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6178		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6179	}
6180	if (phy->rev >= 2) {
6181		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6182		sav->phy_analogoverval =
6183		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6184		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6185		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6186		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6187		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6188		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6189
6190		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6191		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6192		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6193		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6194		if (phy->type == BWN_PHYTYPE_G) {
6195			if ((phy->rev >= 7) &&
6196			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6197			     BWN_BFL_EXTLNA)) {
6198				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6199			} else {
6200				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6201			}
6202		} else {
6203			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6204		}
6205		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6206	}
6207	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6208	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6209	sav->rf0 = BWN_RF_READ(mac, 0x43);
6210	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6211	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6212	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6213	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6214	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6215
6216	if (!BWN_HAS_TXMAG(phy)) {
6217		sav->rf2 = BWN_RF_READ(mac, 0x52);
6218		sav->rf2 &= 0x00f0;
6219	}
6220	if (phy->type == BWN_PHYTYPE_B) {
6221		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6222		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6223		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6224		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6225	} else {
6226		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6227			    | 0x8000);
6228	}
6229	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6230		    & 0xf000);
6231
6232	tmp =
6233	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6234	BWN_PHY_WRITE(mac, tmp, 0x007f);
6235
6236	tmp = sav->phy_syncctl;
6237	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6238	tmp = sav->rf1;
6239	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6240
6241	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6242	if (phy->type == BWN_PHYTYPE_G ||
6243	    (phy->type == BWN_PHYTYPE_B &&
6244	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6245		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6246	} else
6247		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6248	if (phy->rev >= 2)
6249		bwn_dummy_transmission(mac, 0, 1);
6250	bwn_phy_g_switch_chan(mac, 6, 0);
6251	BWN_RF_READ(mac, 0x51);
6252	if (phy->type == BWN_PHYTYPE_G)
6253		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6254
6255	nanouptime(&ts);
6256	if (time_before(lo->txctl_measured_time,
6257	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6258		bwn_lo_measure_txctl_values(mac);
6259
6260	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6261		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6262	else {
6263		if (phy->type == BWN_PHYTYPE_B)
6264			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6265		else
6266			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6267	}
6268}
6269
6270static void
6271bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6272{
6273	struct bwn_phy *phy = &mac->mac_phy;
6274	struct bwn_phy_g *pg = &phy->phy_g;
6275	uint16_t tmp;
6276
6277	if (phy->rev >= 2) {
6278		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6279		tmp = (pg->pg_pga_gain << 8);
6280		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6281		DELAY(5);
6282		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6283		DELAY(2);
6284		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6285	} else {
6286		tmp = (pg->pg_pga_gain | 0xefa0);
6287		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6288	}
6289	if (phy->type == BWN_PHYTYPE_G) {
6290		if (phy->rev >= 3)
6291			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6292		else
6293			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6294		if (phy->rev >= 2)
6295			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6296		else
6297			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6298	}
6299	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6300	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6301	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6302	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6303	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6304	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6305	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6306	if (!BWN_HAS_TXMAG(phy)) {
6307		tmp = sav->rf2;
6308		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6309	}
6310	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6311	if (phy->type == BWN_PHYTYPE_B &&
6312	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6313		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6314		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6315	}
6316	if (phy->rev >= 2) {
6317		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6318		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6319			      sav->phy_analogoverval);
6320		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6321		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6322		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6323		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6324		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6325	}
6326	if (bwn_has_hwpctl(mac)) {
6327		tmp = (sav->phy_lomask & 0xbfff);
6328		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6329		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6330		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6331		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6332		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6333	}
6334	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6335}
6336
6337static int
6338bwn_lo_probe_loctl(struct bwn_mac *mac,
6339    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6340{
6341	struct bwn_phy *phy = &mac->mac_phy;
6342	struct bwn_phy_g *pg = &phy->phy_g;
6343	struct bwn_loctl orig, test;
6344	struct bwn_loctl prev = { -100, -100 };
6345	static const struct bwn_loctl modifiers[] = {
6346		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6347		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6348	};
6349	int begin, end, lower = 0, i;
6350	uint16_t feedth;
6351
6352	if (d->curstate == 0) {
6353		begin = 1;
6354		end = 8;
6355	} else if (d->curstate % 2 == 0) {
6356		begin = d->curstate - 1;
6357		end = d->curstate + 1;
6358	} else {
6359		begin = d->curstate - 2;
6360		end = d->curstate + 2;
6361	}
6362	if (begin < 1)
6363		begin += 8;
6364	if (end > 8)
6365		end -= 8;
6366
6367	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6368	i = begin;
6369	d->curstate = i;
6370	while (1) {
6371		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6372		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6373		test.i += modifiers[i - 1].i * d->multipler;
6374		test.q += modifiers[i - 1].q * d->multipler;
6375		if ((test.i != prev.i || test.q != prev.q) &&
6376		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6377			bwn_lo_write(mac, &test);
6378			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6379			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6380			if (feedth < d->feedth) {
6381				memcpy(probe, &test,
6382				    sizeof(struct bwn_loctl));
6383				lower = 1;
6384				d->feedth = feedth;
6385				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6386					break;
6387			}
6388		}
6389		memcpy(&prev, &test, sizeof(prev));
6390		if (i == end)
6391			break;
6392		if (i == 8)
6393			i = 1;
6394		else
6395			i++;
6396		d->curstate = i;
6397	}
6398
6399	return (lower);
6400}
6401
6402static void
6403bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6404{
6405	struct bwn_phy *phy = &mac->mac_phy;
6406	struct bwn_phy_g *pg = &phy->phy_g;
6407	struct bwn_lo_g_sm d;
6408	struct bwn_loctl probe;
6409	int lower, repeat, cnt = 0;
6410	uint16_t feedth;
6411
6412	d.nmeasure = 0;
6413	d.multipler = 1;
6414	if (BWN_HAS_LOOPBACK(phy))
6415		d.multipler = 3;
6416
6417	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6418	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6419
6420	do {
6421		bwn_lo_write(mac, &d.loctl);
6422		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6423		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6424		if (feedth < 0x258) {
6425			if (feedth >= 0x12c)
6426				*rxgain += 6;
6427			else
6428				*rxgain += 3;
6429			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6430			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6431		}
6432		d.feedth = feedth;
6433		d.curstate = 0;
6434		do {
6435			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6436			    ("%s:%d: fail", __func__, __LINE__));
6437			memcpy(&probe, &d.loctl,
6438			       sizeof(struct bwn_loctl));
6439			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6440			if (!lower)
6441				break;
6442			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6443				break;
6444			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6445			d.nmeasure++;
6446		} while (d.nmeasure < 24);
6447		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6448
6449		if (BWN_HAS_LOOPBACK(phy)) {
6450			if (d.feedth > 0x1194)
6451				*rxgain -= 6;
6452			else if (d.feedth < 0x5dc)
6453				*rxgain += 3;
6454			if (cnt == 0) {
6455				if (d.feedth <= 0x5dc) {
6456					d.multipler = 1;
6457					cnt++;
6458				} else
6459					d.multipler = 2;
6460			} else if (cnt == 2)
6461				d.multipler = 1;
6462		}
6463		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6464	} while (++cnt < repeat);
6465}
6466
6467static struct bwn_lo_calib *
6468bwn_lo_calibset(struct bwn_mac *mac,
6469    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6470{
6471	struct bwn_phy *phy = &mac->mac_phy;
6472	struct bwn_phy_g *pg = &phy->phy_g;
6473	struct bwn_loctl loctl = { 0, 0 };
6474	struct bwn_lo_calib *cal;
6475	struct bwn_lo_g_value sval = { 0 };
6476	int rxgain;
6477	uint16_t pad, reg, value;
6478
6479	sval.old_channel = phy->chan;
6480	bwn_mac_suspend(mac);
6481	bwn_lo_save(mac, &sval);
6482
6483	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6484	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6485	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6486
6487	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6488	if (rfatt->padmix)
6489		rxgain -= pad;
6490	if (BWN_HAS_LOOPBACK(phy))
6491		rxgain += pg->pg_max_lb_gain;
6492	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6493	bwn_phy_g_set_bbatt(mac, bbatt->att);
6494	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6495
6496	bwn_lo_restore(mac, &sval);
6497	bwn_mac_enable(mac);
6498
6499	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6500	if (!cal) {
6501		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6502		return (NULL);
6503	}
6504	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6505	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6506	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6507
6508	BWN_GETTIME(cal->calib_time);
6509
6510	return (cal);
6511}
6512
6513static struct bwn_lo_calib *
6514bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6515    const struct bwn_rfatt *rfatt)
6516{
6517	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6518	struct bwn_lo_calib *c;
6519
6520	TAILQ_FOREACH(c, &lo->calib_list, list) {
6521		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6522			continue;
6523		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6524			continue;
6525		return (c);
6526	}
6527
6528	c = bwn_lo_calibset(mac, bbatt, rfatt);
6529	if (!c)
6530		return (NULL);
6531	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6532
6533	return (c);
6534}
6535
6536static void
6537bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6538{
6539	struct bwn_phy *phy = &mac->mac_phy;
6540	struct bwn_phy_g *pg = &phy->phy_g;
6541	struct bwn_softc *sc = mac->mac_sc;
6542	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6543	const struct bwn_rfatt *rfatt;
6544	const struct bwn_bbatt *bbatt;
6545	uint64_t pvector;
6546	int i;
6547	int rf_offset, bb_offset;
6548	uint8_t changed = 0;
6549
6550	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6551	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6552	    ("%s:%d: fail", __func__, __LINE__));
6553
6554	pvector = lo->power_vector;
6555	if (!update && !pvector)
6556		return;
6557
6558	bwn_mac_suspend(mac);
6559
6560	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6561		struct bwn_lo_calib *cal;
6562		int idx;
6563		uint16_t val;
6564
6565		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6566			continue;
6567		bb_offset = i / lo->rfatt.len;
6568		rf_offset = i % lo->rfatt.len;
6569		bbatt = &(lo->bbatt.array[bb_offset]);
6570		rfatt = &(lo->rfatt.array[rf_offset]);
6571
6572		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6573		if (!cal) {
6574			device_printf(sc->sc_dev, "LO: Could not "
6575			    "calibrate DC table entry\n");
6576			continue;
6577		}
6578		val = (uint8_t)(cal->ctl.q);
6579		val |= ((uint8_t)(cal->ctl.i)) << 4;
6580		free(cal, M_DEVBUF);
6581
6582		idx = i / 2;
6583		if (i % 2)
6584			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6585			    | ((val & 0x00ff) << 8);
6586		else
6587			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6588			    | (val & 0x00ff);
6589		changed = 1;
6590	}
6591	if (changed) {
6592		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6593			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6594	}
6595	bwn_mac_enable(mac);
6596}
6597
6598static void
6599bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6600{
6601
6602	if (!rf->padmix)
6603		return;
6604	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6605		rf->att = 4;
6606}
6607
6608static void
6609bwn_lo_g_adjust(struct bwn_mac *mac)
6610{
6611	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6612	struct bwn_lo_calib *cal;
6613	struct bwn_rfatt rf;
6614
6615	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6616	bwn_lo_fixup_rfatt(&rf);
6617
6618	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6619	if (!cal)
6620		return;
6621	bwn_lo_write(mac, &cal->ctl);
6622}
6623
6624static void
6625bwn_lo_g_init(struct bwn_mac *mac)
6626{
6627
6628	if (!bwn_has_hwpctl(mac))
6629		return;
6630
6631	bwn_lo_get_powervector(mac);
6632	bwn_phy_g_dc_lookup_init(mac, 1);
6633}
6634
6635static void
6636bwn_mac_suspend(struct bwn_mac *mac)
6637{
6638	struct bwn_softc *sc = mac->mac_sc;
6639	int i;
6640	uint32_t tmp;
6641
6642	KASSERT(mac->mac_suspended >= 0,
6643	    ("%s:%d: fail", __func__, __LINE__));
6644
6645	if (mac->mac_suspended == 0) {
6646		bwn_psctl(mac, BWN_PS_AWAKE);
6647		BWN_WRITE_4(mac, BWN_MACCTL,
6648			    BWN_READ_4(mac, BWN_MACCTL)
6649			    & ~BWN_MACCTL_ON);
6650		BWN_READ_4(mac, BWN_MACCTL);
6651		for (i = 35; i; i--) {
6652			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6653			if (tmp & BWN_INTR_MAC_SUSPENDED)
6654				goto out;
6655			DELAY(10);
6656		}
6657		for (i = 40; i; i--) {
6658			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6659			if (tmp & BWN_INTR_MAC_SUSPENDED)
6660				goto out;
6661			DELAY(1000);
6662		}
6663		device_printf(sc->sc_dev, "MAC suspend failed\n");
6664	}
6665out:
6666	mac->mac_suspended++;
6667}
6668
6669static void
6670bwn_mac_enable(struct bwn_mac *mac)
6671{
6672	struct bwn_softc *sc = mac->mac_sc;
6673	uint16_t state;
6674
6675	state = bwn_shm_read_2(mac, BWN_SHARED,
6676	    BWN_SHARED_UCODESTAT);
6677	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6678	    state != BWN_SHARED_UCODESTAT_SLEEP)
6679		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6680
6681	mac->mac_suspended--;
6682	KASSERT(mac->mac_suspended >= 0,
6683	    ("%s:%d: fail", __func__, __LINE__));
6684	if (mac->mac_suspended == 0) {
6685		BWN_WRITE_4(mac, BWN_MACCTL,
6686		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6687		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6688		BWN_READ_4(mac, BWN_MACCTL);
6689		BWN_READ_4(mac, BWN_INTR_REASON);
6690		bwn_psctl(mac, 0);
6691	}
6692}
6693
6694static void
6695bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6696{
6697	struct bwn_softc *sc = mac->mac_sc;
6698	int i;
6699	uint16_t ucstat;
6700
6701	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6702	    ("%s:%d: fail", __func__, __LINE__));
6703	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6704	    ("%s:%d: fail", __func__, __LINE__));
6705
6706	/* XXX forcibly awake and hwps-off */
6707
6708	BWN_WRITE_4(mac, BWN_MACCTL,
6709	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6710	    ~BWN_MACCTL_HWPS);
6711	BWN_READ_4(mac, BWN_MACCTL);
6712	if (siba_get_revid(sc->sc_dev) >= 5) {
6713		for (i = 0; i < 100; i++) {
6714			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6715			    BWN_SHARED_UCODESTAT);
6716			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6717				break;
6718			DELAY(10);
6719		}
6720	}
6721}
6722
6723static int16_t
6724bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6725{
6726
6727	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6728	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6729}
6730
6731static void
6732bwn_nrssi_threshold(struct bwn_mac *mac)
6733{
6734	struct bwn_phy *phy = &mac->mac_phy;
6735	struct bwn_phy_g *pg = &phy->phy_g;
6736	struct bwn_softc *sc = mac->mac_sc;
6737	int32_t a, b;
6738	int16_t tmp16;
6739	uint16_t tmpu16;
6740
6741	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6742
6743	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6744		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6745			a = 0x13;
6746			b = 0x12;
6747		} else {
6748			a = 0xe;
6749			b = 0x11;
6750		}
6751
6752		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6753		a += (pg->pg_nrssi[0] << 6);
6754		a += (a < 32) ? 31 : 32;
6755		a = a >> 6;
6756		a = MIN(MAX(a, -31), 31);
6757
6758		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6759		b += (pg->pg_nrssi[0] << 6);
6760		if (b < 32)
6761			b += 31;
6762		else
6763			b += 32;
6764		b = b >> 6;
6765		b = MIN(MAX(b, -31), 31);
6766
6767		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6768		tmpu16 |= ((uint32_t)b & 0x0000003f);
6769		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6770		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6771		return;
6772	}
6773
6774	tmp16 = bwn_nrssi_read(mac, 0x20);
6775	if (tmp16 >= 0x20)
6776		tmp16 -= 0x40;
6777	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6778}
6779
6780static void
6781bwn_nrssi_slope_11g(struct bwn_mac *mac)
6782{
6783#define	SAVE_RF_MAX		3
6784#define	SAVE_PHY_COMM_MAX	4
6785#define	SAVE_PHY3_MAX		8
6786	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6787		{ 0x7a, 0x52, 0x43 };
6788	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6789		{ 0x15, 0x5a, 0x59, 0x58 };
6790	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6791		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6792		0x0801, 0x0060, 0x0014, 0x0478
6793	};
6794	struct bwn_phy *phy = &mac->mac_phy;
6795	struct bwn_phy_g *pg = &phy->phy_g;
6796	int32_t i, tmp32, phy3_idx = 0;
6797	uint16_t delta, tmp;
6798	uint16_t save_rf[SAVE_RF_MAX];
6799	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6800	uint16_t save_phy3[SAVE_PHY3_MAX];
6801	uint16_t ant_div, phy0, chan_ex;
6802	int16_t nrssi0, nrssi1;
6803
6804	KASSERT(phy->type == BWN_PHYTYPE_G,
6805	    ("%s:%d: fail", __func__, __LINE__));
6806
6807	if (phy->rf_rev >= 9)
6808		return;
6809	if (phy->rf_rev == 8)
6810		bwn_nrssi_offset(mac);
6811
6812	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6813	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6814
6815	/*
6816	 * Save RF/PHY registers for later restoration
6817	 */
6818	ant_div = BWN_READ_2(mac, 0x03e2);
6819	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6820	for (i = 0; i < SAVE_RF_MAX; ++i)
6821		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6822	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6823		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6824
6825	phy0 = BWN_READ_2(mac, BWN_PHY0);
6826	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6827	if (phy->rev >= 3) {
6828		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6829			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6830		BWN_PHY_WRITE(mac, 0x002e, 0);
6831		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6832		switch (phy->rev) {
6833		case 4:
6834		case 6:
6835		case 7:
6836			BWN_PHY_SET(mac, 0x0478, 0x0100);
6837			BWN_PHY_SET(mac, 0x0801, 0x0040);
6838			break;
6839		case 3:
6840		case 5:
6841			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6842			break;
6843		}
6844		BWN_PHY_SET(mac, 0x0060, 0x0040);
6845		BWN_PHY_SET(mac, 0x0014, 0x0200);
6846	}
6847	/*
6848	 * Calculate nrssi0
6849	 */
6850	BWN_RF_SET(mac, 0x007a, 0x0070);
6851	bwn_set_all_gains(mac, 0, 8, 0);
6852	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6853	if (phy->rev >= 2) {
6854		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6855		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6856	}
6857	BWN_RF_SET(mac, 0x007a, 0x0080);
6858	DELAY(20);
6859
6860	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6861	if (nrssi0 >= 0x0020)
6862		nrssi0 -= 0x0040;
6863
6864	/*
6865	 * Calculate nrssi1
6866	 */
6867	BWN_RF_MASK(mac, 0x007a, 0x007f);
6868	if (phy->rev >= 2)
6869		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6870
6871	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6872	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6873	BWN_RF_SET(mac, 0x007a, 0x000f);
6874	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6875	if (phy->rev >= 2) {
6876		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6877		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6878	}
6879
6880	bwn_set_all_gains(mac, 3, 0, 1);
6881	if (phy->rf_rev == 8) {
6882		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6883	} else {
6884		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6885		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6886		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6887		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6888	}
6889	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6890	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6891	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6892	DELAY(20);
6893	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6894
6895	/*
6896	 * Install calculated narrow RSSI values
6897	 */
6898	if (nrssi1 >= 0x0020)
6899		nrssi1 -= 0x0040;
6900	if (nrssi0 == nrssi1)
6901		pg->pg_nrssi_slope = 0x00010000;
6902	else
6903		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6904	if (nrssi0 >= -4) {
6905		pg->pg_nrssi[0] = nrssi1;
6906		pg->pg_nrssi[1] = nrssi0;
6907	}
6908
6909	/*
6910	 * Restore saved RF/PHY registers
6911	 */
6912	if (phy->rev >= 3) {
6913		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6914			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6915			    save_phy3[phy3_idx]);
6916		}
6917	}
6918	if (phy->rev >= 2) {
6919		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6920		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6921	}
6922
6923	for (i = 0; i < SAVE_RF_MAX; ++i)
6924		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6925
6926	BWN_WRITE_2(mac, 0x03e2, ant_div);
6927	BWN_WRITE_2(mac, 0x03e6, phy0);
6928	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6929
6930	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6931		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6932
6933	bwn_spu_workaround(mac, phy->chan);
6934	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6935	bwn_set_original_gains(mac);
6936	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6937	if (phy->rev >= 3) {
6938		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6939			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6940			    save_phy3[phy3_idx]);
6941		}
6942	}
6943
6944	delta = 0x1f - pg->pg_nrssi[0];
6945	for (i = 0; i < 64; i++) {
6946		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6947		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6948		pg->pg_nrssi_lt[i] = tmp32;
6949	}
6950
6951	bwn_nrssi_threshold(mac);
6952#undef SAVE_RF_MAX
6953#undef SAVE_PHY_COMM_MAX
6954#undef SAVE_PHY3_MAX
6955}
6956
6957static void
6958bwn_nrssi_offset(struct bwn_mac *mac)
6959{
6960#define	SAVE_RF_MAX		2
6961#define	SAVE_PHY_COMM_MAX	10
6962#define	SAVE_PHY6_MAX		8
6963	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6964		{ 0x7a, 0x43 };
6965	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6966		0x0001, 0x0811, 0x0812, 0x0814,
6967		0x0815, 0x005a, 0x0059, 0x0058,
6968		0x000a, 0x0003
6969	};
6970	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6971		0x002e, 0x002f, 0x080f, 0x0810,
6972		0x0801, 0x0060, 0x0014, 0x0478
6973	};
6974	struct bwn_phy *phy = &mac->mac_phy;
6975	int i, phy6_idx = 0;
6976	uint16_t save_rf[SAVE_RF_MAX];
6977	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6978	uint16_t save_phy6[SAVE_PHY6_MAX];
6979	int16_t nrssi;
6980	uint16_t saved = 0xffff;
6981
6982	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6983		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6984	for (i = 0; i < SAVE_RF_MAX; ++i)
6985		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6986
6987	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6988	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6989	BWN_PHY_SET(mac, 0x0811, 0x000c);
6990	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6991	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6992	if (phy->rev >= 6) {
6993		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6994			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6995
6996		BWN_PHY_WRITE(mac, 0x002e, 0);
6997		BWN_PHY_WRITE(mac, 0x002f, 0);
6998		BWN_PHY_WRITE(mac, 0x080f, 0);
6999		BWN_PHY_WRITE(mac, 0x0810, 0);
7000		BWN_PHY_SET(mac, 0x0478, 0x0100);
7001		BWN_PHY_SET(mac, 0x0801, 0x0040);
7002		BWN_PHY_SET(mac, 0x0060, 0x0040);
7003		BWN_PHY_SET(mac, 0x0014, 0x0200);
7004	}
7005	BWN_RF_SET(mac, 0x007a, 0x0070);
7006	BWN_RF_SET(mac, 0x007a, 0x0080);
7007	DELAY(30);
7008
7009	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7010	if (nrssi >= 0x20)
7011		nrssi -= 0x40;
7012	if (nrssi == 31) {
7013		for (i = 7; i >= 4; i--) {
7014			BWN_RF_WRITE(mac, 0x007b, i);
7015			DELAY(20);
7016			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7017			    0x003f);
7018			if (nrssi >= 0x20)
7019				nrssi -= 0x40;
7020			if (nrssi < 31 && saved == 0xffff)
7021				saved = i;
7022		}
7023		if (saved == 0xffff)
7024			saved = 4;
7025	} else {
7026		BWN_RF_MASK(mac, 0x007a, 0x007f);
7027		if (phy->rev != 1) {
7028			BWN_PHY_SET(mac, 0x0814, 0x0001);
7029			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7030		}
7031		BWN_PHY_SET(mac, 0x0811, 0x000c);
7032		BWN_PHY_SET(mac, 0x0812, 0x000c);
7033		BWN_PHY_SET(mac, 0x0811, 0x0030);
7034		BWN_PHY_SET(mac, 0x0812, 0x0030);
7035		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7036		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7037		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7038		if (phy->rev == 0)
7039			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7040		else
7041			BWN_PHY_SET(mac, 0x000a, 0x2000);
7042		if (phy->rev != 1) {
7043			BWN_PHY_SET(mac, 0x0814, 0x0004);
7044			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7045		}
7046		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7047		BWN_RF_SET(mac, 0x007a, 0x000f);
7048		bwn_set_all_gains(mac, 3, 0, 1);
7049		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7050		DELAY(30);
7051		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7052		if (nrssi >= 0x20)
7053			nrssi -= 0x40;
7054		if (nrssi == -32) {
7055			for (i = 0; i < 4; i++) {
7056				BWN_RF_WRITE(mac, 0x007b, i);
7057				DELAY(20);
7058				nrssi = (int16_t)((BWN_PHY_READ(mac,
7059				    0x047f) >> 8) & 0x003f);
7060				if (nrssi >= 0x20)
7061					nrssi -= 0x40;
7062				if (nrssi > -31 && saved == 0xffff)
7063					saved = i;
7064			}
7065			if (saved == 0xffff)
7066				saved = 3;
7067		} else
7068			saved = 0;
7069	}
7070	BWN_RF_WRITE(mac, 0x007b, saved);
7071
7072	/*
7073	 * Restore saved RF/PHY registers
7074	 */
7075	if (phy->rev >= 6) {
7076		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7077			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7078			    save_phy6[phy6_idx]);
7079		}
7080	}
7081	if (phy->rev != 1) {
7082		for (i = 3; i < 5; i++)
7083			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7084			    save_phy_comm[i]);
7085	}
7086	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7087		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7088
7089	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7090		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7091
7092	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7093	BWN_PHY_SET(mac, 0x0429, 0x8000);
7094	bwn_set_original_gains(mac);
7095	if (phy->rev >= 6) {
7096		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7097			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7098			    save_phy6[phy6_idx]);
7099		}
7100	}
7101
7102	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7103	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7104	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7105}
7106
7107static void
7108bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7109    int16_t third)
7110{
7111	struct bwn_phy *phy = &mac->mac_phy;
7112	uint16_t i;
7113	uint16_t start = 0x08, end = 0x18;
7114	uint16_t tmp;
7115	uint16_t table;
7116
7117	if (phy->rev <= 1) {
7118		start = 0x10;
7119		end = 0x20;
7120	}
7121
7122	table = BWN_OFDMTAB_GAINX;
7123	if (phy->rev <= 1)
7124		table = BWN_OFDMTAB_GAINX_R1;
7125	for (i = 0; i < 4; i++)
7126		bwn_ofdmtab_write_2(mac, table, i, first);
7127
7128	for (i = start; i < end; i++)
7129		bwn_ofdmtab_write_2(mac, table, i, second);
7130
7131	if (third != -1) {
7132		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7133		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7134		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7135		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7136	}
7137	bwn_dummy_transmission(mac, 0, 1);
7138}
7139
7140static void
7141bwn_set_original_gains(struct bwn_mac *mac)
7142{
7143	struct bwn_phy *phy = &mac->mac_phy;
7144	uint16_t i, tmp;
7145	uint16_t table;
7146	uint16_t start = 0x0008, end = 0x0018;
7147
7148	if (phy->rev <= 1) {
7149		start = 0x0010;
7150		end = 0x0020;
7151	}
7152
7153	table = BWN_OFDMTAB_GAINX;
7154	if (phy->rev <= 1)
7155		table = BWN_OFDMTAB_GAINX_R1;
7156	for (i = 0; i < 4; i++) {
7157		tmp = (i & 0xfffc);
7158		tmp |= (i & 0x0001) << 1;
7159		tmp |= (i & 0x0002) >> 1;
7160
7161		bwn_ofdmtab_write_2(mac, table, i, tmp);
7162	}
7163
7164	for (i = start; i < end; i++)
7165		bwn_ofdmtab_write_2(mac, table, i, i - start);
7166
7167	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7168	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7169	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7170	bwn_dummy_transmission(mac, 0, 1);
7171}
7172
7173static void
7174bwn_phy_hwpctl_init(struct bwn_mac *mac)
7175{
7176	struct bwn_phy *phy = &mac->mac_phy;
7177	struct bwn_phy_g *pg = &phy->phy_g;
7178	struct bwn_rfatt old_rfatt, rfatt;
7179	struct bwn_bbatt old_bbatt, bbatt;
7180	struct bwn_softc *sc = mac->mac_sc;
7181	uint8_t old_txctl = 0;
7182
7183	KASSERT(phy->type == BWN_PHYTYPE_G,
7184	    ("%s:%d: fail", __func__, __LINE__));
7185
7186	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7187	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7188		return;
7189
7190	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7191
7192	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7193
7194	if (!phy->gmode)
7195		return;
7196	bwn_hwpctl_early_init(mac);
7197	if (pg->pg_curtssi == 0) {
7198		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7199			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7200		} else {
7201			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7202			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7203			old_txctl = pg->pg_txctl;
7204
7205			bbatt.att = 11;
7206			if (phy->rf_rev == 8) {
7207				rfatt.att = 15;
7208				rfatt.padmix = 1;
7209			} else {
7210				rfatt.att = 9;
7211				rfatt.padmix = 0;
7212			}
7213			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7214		}
7215		bwn_dummy_transmission(mac, 0, 1);
7216		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7217		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7218			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7219		else
7220			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7221			    &old_rfatt, old_txctl);
7222	}
7223	bwn_hwpctl_init_gphy(mac);
7224
7225	/* clear TSSI */
7226	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7227	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7228	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7229	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7230}
7231
7232static void
7233bwn_hwpctl_early_init(struct bwn_mac *mac)
7234{
7235	struct bwn_phy *phy = &mac->mac_phy;
7236
7237	if (!bwn_has_hwpctl(mac)) {
7238		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7239		return;
7240	}
7241
7242	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7243	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7244	BWN_PHY_SET(mac, 0x047c, 0x0002);
7245	BWN_PHY_SET(mac, 0x047a, 0xf000);
7246	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7247		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7248		BWN_PHY_SET(mac, 0x005d, 0x8000);
7249		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7250		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7251		BWN_PHY_SET(mac, 0x0036, 0x0400);
7252	} else {
7253		BWN_PHY_SET(mac, 0x0036, 0x0200);
7254		BWN_PHY_SET(mac, 0x0036, 0x0400);
7255		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7256		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7257		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7258		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7259		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7260	}
7261}
7262
7263static void
7264bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7265{
7266	struct bwn_phy *phy = &mac->mac_phy;
7267	struct bwn_phy_g *pg = &phy->phy_g;
7268	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7269	int i;
7270	uint16_t nr_written = 0, tmp, value;
7271	uint8_t rf, bb;
7272
7273	if (!bwn_has_hwpctl(mac)) {
7274		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7275		return;
7276	}
7277
7278	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7279	    (pg->pg_idletssi - pg->pg_curtssi));
7280	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7281	    (pg->pg_idletssi - pg->pg_curtssi));
7282
7283	for (i = 0; i < 32; i++)
7284		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7285	for (i = 32; i < 64; i++)
7286		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7287	for (i = 0; i < 64; i += 2) {
7288		value = (uint16_t) pg->pg_tssi2dbm[i];
7289		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7290		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7291	}
7292
7293	for (rf = 0; rf < lo->rfatt.len; rf++) {
7294		for (bb = 0; bb < lo->bbatt.len; bb++) {
7295			if (nr_written >= 0x40)
7296				return;
7297			tmp = lo->bbatt.array[bb].att;
7298			tmp <<= 8;
7299			if (phy->rf_rev == 8)
7300				tmp |= 0x50;
7301			else
7302				tmp |= 0x40;
7303			tmp |= lo->rfatt.array[rf].att;
7304			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7305			nr_written++;
7306		}
7307	}
7308
7309	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7310	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7311
7312	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7313	BWN_PHY_SET(mac, 0x0478, 0x0800);
7314	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7315	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7316
7317	bwn_phy_g_dc_lookup_init(mac, 1);
7318	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7319}
7320
7321static void
7322bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7323{
7324	struct bwn_softc *sc = mac->mac_sc;
7325
7326	if (spu != 0)
7327		bwn_spu_workaround(mac, channel);
7328
7329	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7330
7331	if (channel == 14) {
7332		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7333			bwn_hf_write(mac,
7334			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7335		else
7336			bwn_hf_write(mac,
7337			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7338		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7339		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7340		return;
7341	}
7342
7343	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7344	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7345}
7346
7347static uint16_t
7348bwn_phy_g_chan2freq(uint8_t channel)
7349{
7350	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7351
7352	KASSERT(channel >= 1 && channel <= 14,
7353	    ("%s:%d: fail", __func__, __LINE__));
7354
7355	return (bwn_phy_g_rf_channels[channel - 1]);
7356}
7357
7358static void
7359bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7360    const struct bwn_rfatt *rfatt, uint8_t txctl)
7361{
7362	struct bwn_phy *phy = &mac->mac_phy;
7363	struct bwn_phy_g *pg = &phy->phy_g;
7364	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7365	uint16_t bb, rf;
7366	uint16_t tx_bias, tx_magn;
7367
7368	bb = bbatt->att;
7369	rf = rfatt->att;
7370	tx_bias = lo->tx_bias;
7371	tx_magn = lo->tx_magn;
7372	if (tx_bias == 0xff)
7373		tx_bias = 0;
7374
7375	pg->pg_txctl = txctl;
7376	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7377	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7378	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7379	bwn_phy_g_set_bbatt(mac, bb);
7380	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7381	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7382		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7383	else {
7384		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7385		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7386	}
7387	if (BWN_HAS_TXMAG(phy))
7388		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7389	else
7390		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7391	bwn_lo_g_adjust(mac);
7392}
7393
7394static void
7395bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7396    uint16_t bbatt)
7397{
7398	struct bwn_phy *phy = &mac->mac_phy;
7399
7400	if (phy->analog == 0) {
7401		BWN_WRITE_2(mac, BWN_PHY0,
7402		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7403		return;
7404	}
7405	if (phy->analog > 1) {
7406		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7407		return;
7408	}
7409	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7410}
7411
7412static uint16_t
7413bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7414{
7415	struct bwn_phy *phy = &mac->mac_phy;
7416	struct bwn_phy_g *pg = &phy->phy_g;
7417	struct bwn_softc *sc = mac->mac_sc;
7418	int max_lb_gain;
7419	uint16_t extlna;
7420	uint16_t i;
7421
7422	if (phy->gmode == 0)
7423		return (0);
7424
7425	if (BWN_HAS_LOOPBACK(phy)) {
7426		max_lb_gain = pg->pg_max_lb_gain;
7427		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7428		if (max_lb_gain >= 0x46) {
7429			extlna = 0x3000;
7430			max_lb_gain -= 0x46;
7431		} else if (max_lb_gain >= 0x3a) {
7432			extlna = 0x1000;
7433			max_lb_gain -= 0x3a;
7434		} else if (max_lb_gain >= 0x2e) {
7435			extlna = 0x2000;
7436			max_lb_gain -= 0x2e;
7437		} else {
7438			extlna = 0;
7439			max_lb_gain -= 0x10;
7440		}
7441
7442		for (i = 0; i < 16; i++) {
7443			max_lb_gain -= (i * 6);
7444			if (max_lb_gain < 6)
7445				break;
7446		}
7447
7448		if ((phy->rev < 7) ||
7449		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7450			if (reg == BWN_PHY_RFOVER) {
7451				return (0x1b3);
7452			} else if (reg == BWN_PHY_RFOVERVAL) {
7453				extlna |= (i << 8);
7454				switch (lpd) {
7455				case BWN_LPD(0, 1, 1):
7456					return (0x0f92);
7457				case BWN_LPD(0, 0, 1):
7458				case BWN_LPD(1, 0, 1):
7459					return (0x0092 | extlna);
7460				case BWN_LPD(1, 0, 0):
7461					return (0x0093 | extlna);
7462				}
7463				KASSERT(0 == 1,
7464				    ("%s:%d: fail", __func__, __LINE__));
7465			}
7466			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7467		} else {
7468			if (reg == BWN_PHY_RFOVER)
7469				return (0x9b3);
7470			if (reg == BWN_PHY_RFOVERVAL) {
7471				if (extlna)
7472					extlna |= 0x8000;
7473				extlna |= (i << 8);
7474				switch (lpd) {
7475				case BWN_LPD(0, 1, 1):
7476					return (0x8f92);
7477				case BWN_LPD(0, 0, 1):
7478					return (0x8092 | extlna);
7479				case BWN_LPD(1, 0, 1):
7480					return (0x2092 | extlna);
7481				case BWN_LPD(1, 0, 0):
7482					return (0x2093 | extlna);
7483				}
7484				KASSERT(0 == 1,
7485				    ("%s:%d: fail", __func__, __LINE__));
7486			}
7487			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7488		}
7489		return (0);
7490	}
7491
7492	if ((phy->rev < 7) ||
7493	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7494		if (reg == BWN_PHY_RFOVER) {
7495			return (0x1b3);
7496		} else if (reg == BWN_PHY_RFOVERVAL) {
7497			switch (lpd) {
7498			case BWN_LPD(0, 1, 1):
7499				return (0x0fb2);
7500			case BWN_LPD(0, 0, 1):
7501				return (0x00b2);
7502			case BWN_LPD(1, 0, 1):
7503				return (0x30b2);
7504			case BWN_LPD(1, 0, 0):
7505				return (0x30b3);
7506			}
7507			KASSERT(0 == 1,
7508			    ("%s:%d: fail", __func__, __LINE__));
7509		}
7510		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7511	} else {
7512		if (reg == BWN_PHY_RFOVER) {
7513			return (0x9b3);
7514		} else if (reg == BWN_PHY_RFOVERVAL) {
7515			switch (lpd) {
7516			case BWN_LPD(0, 1, 1):
7517				return (0x8fb2);
7518			case BWN_LPD(0, 0, 1):
7519				return (0x80b2);
7520			case BWN_LPD(1, 0, 1):
7521				return (0x20b2);
7522			case BWN_LPD(1, 0, 0):
7523				return (0x20b3);
7524			}
7525			KASSERT(0 == 1,
7526			    ("%s:%d: fail", __func__, __LINE__));
7527		}
7528		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7529	}
7530	return (0);
7531}
7532
7533static void
7534bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7535{
7536
7537	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7538		return;
7539	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7540	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7541	DELAY(1000);
7542	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7543}
7544
7545static int
7546bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7547{
7548	struct bwn_softc *sc = mac->mac_sc;
7549	struct bwn_fw *fw = &mac->mac_fw;
7550	const uint8_t rev = siba_get_revid(sc->sc_dev);
7551	const char *filename;
7552	uint32_t high;
7553	int error;
7554
7555	/* microcode */
7556	if (rev >= 5 && rev <= 10)
7557		filename = "ucode5";
7558	else if (rev >= 11 && rev <= 12)
7559		filename = "ucode11";
7560	else if (rev == 13)
7561		filename = "ucode13";
7562	else if (rev == 14)
7563		filename = "ucode14";
7564	else if (rev >= 15)
7565		filename = "ucode15";
7566	else {
7567		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7568		bwn_release_firmware(mac);
7569		return (EOPNOTSUPP);
7570	}
7571	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7572	if (error) {
7573		bwn_release_firmware(mac);
7574		return (error);
7575	}
7576
7577	/* PCM */
7578	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7579	if (rev >= 5 && rev <= 10) {
7580		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7581		if (error == ENOENT)
7582			fw->no_pcmfile = 1;
7583		else if (error) {
7584			bwn_release_firmware(mac);
7585			return (error);
7586		}
7587	} else if (rev < 11) {
7588		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7589		return (EOPNOTSUPP);
7590	}
7591
7592	/* initvals */
7593	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7594	switch (mac->mac_phy.type) {
7595	case BWN_PHYTYPE_A:
7596		if (rev < 5 || rev > 10)
7597			goto fail1;
7598		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7599			filename = "a0g1initvals5";
7600		else
7601			filename = "a0g0initvals5";
7602		break;
7603	case BWN_PHYTYPE_G:
7604		if (rev >= 5 && rev <= 10)
7605			filename = "b0g0initvals5";
7606		else if (rev >= 13)
7607			filename = "b0g0initvals13";
7608		else
7609			goto fail1;
7610		break;
7611	case BWN_PHYTYPE_LP:
7612		if (rev == 13)
7613			filename = "lp0initvals13";
7614		else if (rev == 14)
7615			filename = "lp0initvals14";
7616		else if (rev >= 15)
7617			filename = "lp0initvals15";
7618		else
7619			goto fail1;
7620		break;
7621	case BWN_PHYTYPE_N:
7622		if (rev >= 11 && rev <= 12)
7623			filename = "n0initvals11";
7624		else
7625			goto fail1;
7626		break;
7627	default:
7628		goto fail1;
7629	}
7630	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7631	if (error) {
7632		bwn_release_firmware(mac);
7633		return (error);
7634	}
7635
7636	/* bandswitch initvals */
7637	switch (mac->mac_phy.type) {
7638	case BWN_PHYTYPE_A:
7639		if (rev >= 5 && rev <= 10) {
7640			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7641				filename = "a0g1bsinitvals5";
7642			else
7643				filename = "a0g0bsinitvals5";
7644		} else if (rev >= 11)
7645			filename = NULL;
7646		else
7647			goto fail1;
7648		break;
7649	case BWN_PHYTYPE_G:
7650		if (rev >= 5 && rev <= 10)
7651			filename = "b0g0bsinitvals5";
7652		else if (rev >= 11)
7653			filename = NULL;
7654		else
7655			goto fail1;
7656		break;
7657	case BWN_PHYTYPE_LP:
7658		if (rev == 13)
7659			filename = "lp0bsinitvals13";
7660		else if (rev == 14)
7661			filename = "lp0bsinitvals14";
7662		else if (rev >= 15)
7663			filename = "lp0bsinitvals15";
7664		else
7665			goto fail1;
7666		break;
7667	case BWN_PHYTYPE_N:
7668		if (rev >= 11 && rev <= 12)
7669			filename = "n0bsinitvals11";
7670		else
7671			goto fail1;
7672		break;
7673	default:
7674		goto fail1;
7675	}
7676	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7677	if (error) {
7678		bwn_release_firmware(mac);
7679		return (error);
7680	}
7681	return (0);
7682fail1:
7683	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7684	bwn_release_firmware(mac);
7685	return (EOPNOTSUPP);
7686}
7687
7688static int
7689bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7690    const char *name, struct bwn_fwfile *bfw)
7691{
7692	const struct bwn_fwhdr *hdr;
7693	struct bwn_softc *sc = mac->mac_sc;
7694	const struct firmware *fw;
7695	char namebuf[64];
7696
7697	if (name == NULL) {
7698		bwn_do_release_fw(bfw);
7699		return (0);
7700	}
7701	if (bfw->filename != NULL) {
7702		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7703			return (0);
7704		bwn_do_release_fw(bfw);
7705	}
7706
7707	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7708	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7709	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7710	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7711	fw = firmware_get(namebuf);
7712	if (fw == NULL) {
7713		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7714		    namebuf);
7715		return (ENOENT);
7716	}
7717	if (fw->datasize < sizeof(struct bwn_fwhdr))
7718		goto fail;
7719	hdr = (const struct bwn_fwhdr *)(fw->data);
7720	switch (hdr->type) {
7721	case BWN_FWTYPE_UCODE:
7722	case BWN_FWTYPE_PCM:
7723		if (be32toh(hdr->size) !=
7724		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7725			goto fail;
7726		/* FALLTHROUGH */
7727	case BWN_FWTYPE_IV:
7728		if (hdr->ver != 1)
7729			goto fail;
7730		break;
7731	default:
7732		goto fail;
7733	}
7734	bfw->filename = name;
7735	bfw->fw = fw;
7736	bfw->type = type;
7737	return (0);
7738fail:
7739	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7740	if (fw != NULL)
7741		firmware_put(fw, FIRMWARE_UNLOAD);
7742	return (EPROTO);
7743}
7744
7745static void
7746bwn_release_firmware(struct bwn_mac *mac)
7747{
7748
7749	bwn_do_release_fw(&mac->mac_fw.ucode);
7750	bwn_do_release_fw(&mac->mac_fw.pcm);
7751	bwn_do_release_fw(&mac->mac_fw.initvals);
7752	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7753}
7754
7755static void
7756bwn_do_release_fw(struct bwn_fwfile *bfw)
7757{
7758
7759	if (bfw->fw != NULL)
7760		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7761	bfw->fw = NULL;
7762	bfw->filename = NULL;
7763}
7764
7765static int
7766bwn_fw_loaducode(struct bwn_mac *mac)
7767{
7768#define	GETFWOFFSET(fwp, offset)	\
7769	((const uint32_t *)((const char *)fwp.fw->data + offset))
7770#define	GETFWSIZE(fwp, offset)	\
7771	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7772	struct bwn_softc *sc = mac->mac_sc;
7773	const uint32_t *data;
7774	unsigned int i;
7775	uint32_t ctl;
7776	uint16_t date, fwcaps, time;
7777	int error = 0;
7778
7779	ctl = BWN_READ_4(mac, BWN_MACCTL);
7780	ctl |= BWN_MACCTL_MCODE_JMP0;
7781	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7782	    __LINE__));
7783	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7784	for (i = 0; i < 64; i++)
7785		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7786	for (i = 0; i < 4096; i += 2)
7787		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7788
7789	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7790	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7791	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7792	     i++) {
7793		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7794		DELAY(10);
7795	}
7796
7797	if (mac->mac_fw.pcm.fw) {
7798		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7799		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7800		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7801		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7802		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7803		    sizeof(struct bwn_fwhdr)); i++) {
7804			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7805			DELAY(10);
7806		}
7807	}
7808
7809	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7810	BWN_WRITE_4(mac, BWN_MACCTL,
7811	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7812	    BWN_MACCTL_MCODE_RUN);
7813
7814	for (i = 0; i < 21; i++) {
7815		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7816			break;
7817		if (i >= 20) {
7818			device_printf(sc->sc_dev, "ucode timeout\n");
7819			error = ENXIO;
7820			goto error;
7821		}
7822		DELAY(50000);
7823	}
7824	BWN_READ_4(mac, BWN_INTR_REASON);
7825
7826	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7827	if (mac->mac_fw.rev <= 0x128) {
7828		device_printf(sc->sc_dev, "the firmware is too old\n");
7829		error = EOPNOTSUPP;
7830		goto error;
7831	}
7832	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7833	    BWN_SHARED_UCODE_PATCH);
7834	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7835	mac->mac_fw.opensource = (date == 0xffff);
7836	if (bwn_wme != 0)
7837		mac->mac_flags |= BWN_MAC_FLAG_WME;
7838	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7839
7840	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7841	if (mac->mac_fw.opensource == 0) {
7842		device_printf(sc->sc_dev,
7843		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7844		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7845		if (mac->mac_fw.no_pcmfile)
7846			device_printf(sc->sc_dev,
7847			    "no HW crypto acceleration due to pcm5\n");
7848	} else {
7849		mac->mac_fw.patch = time;
7850		fwcaps = bwn_fwcaps_read(mac);
7851		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7852			device_printf(sc->sc_dev,
7853			    "disabling HW crypto acceleration\n");
7854			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7855		}
7856		if (!(fwcaps & BWN_FWCAPS_WME)) {
7857			device_printf(sc->sc_dev, "disabling WME support\n");
7858			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7859		}
7860	}
7861
7862	if (BWN_ISOLDFMT(mac))
7863		device_printf(sc->sc_dev, "using old firmware image\n");
7864
7865	return (0);
7866
7867error:
7868	BWN_WRITE_4(mac, BWN_MACCTL,
7869	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7870	    BWN_MACCTL_MCODE_JMP0);
7871
7872	return (error);
7873#undef GETFWSIZE
7874#undef GETFWOFFSET
7875}
7876
7877/* OpenFirmware only */
7878static uint16_t
7879bwn_fwcaps_read(struct bwn_mac *mac)
7880{
7881
7882	KASSERT(mac->mac_fw.opensource == 1,
7883	    ("%s:%d: fail", __func__, __LINE__));
7884	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7885}
7886
7887static int
7888bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7889    size_t count, size_t array_size)
7890{
7891#define	GET_NEXTIV16(iv)						\
7892	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7893	    sizeof(uint16_t) + sizeof(uint16_t)))
7894#define	GET_NEXTIV32(iv)						\
7895	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7896	    sizeof(uint16_t) + sizeof(uint32_t)))
7897	struct bwn_softc *sc = mac->mac_sc;
7898	const struct bwn_fwinitvals *iv;
7899	uint16_t offset;
7900	size_t i;
7901	uint8_t bit32;
7902
7903	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7904	    ("%s:%d: fail", __func__, __LINE__));
7905	iv = ivals;
7906	for (i = 0; i < count; i++) {
7907		if (array_size < sizeof(iv->offset_size))
7908			goto fail;
7909		array_size -= sizeof(iv->offset_size);
7910		offset = be16toh(iv->offset_size);
7911		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7912		offset &= BWN_FWINITVALS_OFFSET_MASK;
7913		if (offset >= 0x1000)
7914			goto fail;
7915		if (bit32) {
7916			if (array_size < sizeof(iv->data.d32))
7917				goto fail;
7918			array_size -= sizeof(iv->data.d32);
7919			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7920			iv = GET_NEXTIV32(iv);
7921		} else {
7922
7923			if (array_size < sizeof(iv->data.d16))
7924				goto fail;
7925			array_size -= sizeof(iv->data.d16);
7926			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7927
7928			iv = GET_NEXTIV16(iv);
7929		}
7930	}
7931	if (array_size != 0)
7932		goto fail;
7933	return (0);
7934fail:
7935	device_printf(sc->sc_dev, "initvals: invalid format\n");
7936	return (EPROTO);
7937#undef GET_NEXTIV16
7938#undef GET_NEXTIV32
7939}
7940
7941static int
7942bwn_switch_channel(struct bwn_mac *mac, int chan)
7943{
7944	struct bwn_phy *phy = &(mac->mac_phy);
7945	struct bwn_softc *sc = mac->mac_sc;
7946	struct ifnet *ifp = sc->sc_ifp;
7947	struct ieee80211com *ic = ifp->if_l2com;
7948	uint16_t channelcookie, savedcookie;
7949	int error;
7950
7951	if (chan == 0xffff)
7952		chan = phy->get_default_chan(mac);
7953
7954	channelcookie = chan;
7955	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7956		channelcookie |= 0x100;
7957	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7958	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7959	error = phy->switch_channel(mac, chan);
7960	if (error)
7961		goto fail;
7962
7963	mac->mac_phy.chan = chan;
7964	DELAY(8000);
7965	return (0);
7966fail:
7967	device_printf(sc->sc_dev, "failed to switch channel\n");
7968	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7969	return (error);
7970}
7971
7972static uint16_t
7973bwn_ant2phy(int antenna)
7974{
7975
7976	switch (antenna) {
7977	case BWN_ANT0:
7978		return (BWN_TX_PHY_ANT0);
7979	case BWN_ANT1:
7980		return (BWN_TX_PHY_ANT1);
7981	case BWN_ANT2:
7982		return (BWN_TX_PHY_ANT2);
7983	case BWN_ANT3:
7984		return (BWN_TX_PHY_ANT3);
7985	case BWN_ANTAUTO:
7986		return (BWN_TX_PHY_ANT01AUTO);
7987	}
7988	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7989	return (0);
7990}
7991
7992static void
7993bwn_wme_load(struct bwn_mac *mac)
7994{
7995	struct bwn_softc *sc = mac->mac_sc;
7996	int i;
7997
7998	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7999	    ("%s:%d: fail", __func__, __LINE__));
8000
8001	bwn_mac_suspend(mac);
8002	for (i = 0; i < N(sc->sc_wmeParams); i++)
8003		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8004		    bwn_wme_shm_offsets[i]);
8005	bwn_mac_enable(mac);
8006}
8007
8008static void
8009bwn_wme_loadparams(struct bwn_mac *mac,
8010    const struct wmeParams *p, uint16_t shm_offset)
8011{
8012#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8013	struct bwn_softc *sc = mac->mac_sc;
8014	uint16_t params[BWN_NR_WMEPARAMS];
8015	int slot, tmp;
8016	unsigned int i;
8017
8018	slot = BWN_READ_2(mac, BWN_RNG) &
8019	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8020
8021	memset(&params, 0, sizeof(params));
8022
8023	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8024	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8025	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8026
8027	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8028	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8029	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8030	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8031	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8032	params[BWN_WMEPARAM_BSLOTS] = slot;
8033	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8034
8035	for (i = 0; i < N(params); i++) {
8036		if (i == BWN_WMEPARAM_STATUS) {
8037			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8038			    shm_offset + (i * 2));
8039			tmp |= 0x100;
8040			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8041			    tmp);
8042		} else {
8043			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8044			    params[i]);
8045		}
8046	}
8047}
8048
8049static void
8050bwn_mac_write_bssid(struct bwn_mac *mac)
8051{
8052	struct bwn_softc *sc = mac->mac_sc;
8053	uint32_t tmp;
8054	int i;
8055	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8056
8057	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8058	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8059	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8060	    IEEE80211_ADDR_LEN);
8061
8062	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8063		tmp = (uint32_t) (mac_bssid[i + 0]);
8064		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8065		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8066		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8067		bwn_ram_write(mac, 0x20 + i, tmp);
8068	}
8069}
8070
8071static void
8072bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8073    const uint8_t *macaddr)
8074{
8075	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8076	uint16_t data;
8077
8078	if (!mac)
8079		macaddr = zero;
8080
8081	offset |= 0x0020;
8082	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8083
8084	data = macaddr[0];
8085	data |= macaddr[1] << 8;
8086	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8087	data = macaddr[2];
8088	data |= macaddr[3] << 8;
8089	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8090	data = macaddr[4];
8091	data |= macaddr[5] << 8;
8092	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8093}
8094
8095static void
8096bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8097    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8098{
8099	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8100	uint8_t per_sta_keys_start = 8;
8101
8102	if (BWN_SEC_NEWAPI(mac))
8103		per_sta_keys_start = 4;
8104
8105	KASSERT(index < mac->mac_max_nr_keys,
8106	    ("%s:%d: fail", __func__, __LINE__));
8107	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8108	    ("%s:%d: fail", __func__, __LINE__));
8109
8110	if (index >= per_sta_keys_start)
8111		bwn_key_macwrite(mac, index, NULL);
8112	if (key)
8113		memcpy(buf, key, key_len);
8114	bwn_key_write(mac, index, algorithm, buf);
8115	if (index >= per_sta_keys_start)
8116		bwn_key_macwrite(mac, index, mac_addr);
8117
8118	mac->mac_key[index].algorithm = algorithm;
8119}
8120
8121static void
8122bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8123{
8124	struct bwn_softc *sc = mac->mac_sc;
8125	uint32_t addrtmp[2] = { 0, 0 };
8126	uint8_t start = 8;
8127
8128	if (BWN_SEC_NEWAPI(mac))
8129		start = 4;
8130
8131	KASSERT(index >= start,
8132	    ("%s:%d: fail", __func__, __LINE__));
8133	index -= start;
8134
8135	if (addr) {
8136		addrtmp[0] = addr[0];
8137		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8138		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8139		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8140		addrtmp[1] = addr[4];
8141		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8142	}
8143
8144	if (siba_get_revid(sc->sc_dev) >= 5) {
8145		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8146		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8147	} else {
8148		if (index >= 8) {
8149			bwn_shm_write_4(mac, BWN_SHARED,
8150			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8151			bwn_shm_write_2(mac, BWN_SHARED,
8152			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8153		}
8154	}
8155}
8156
8157static void
8158bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8159    const uint8_t *key)
8160{
8161	unsigned int i;
8162	uint32_t offset;
8163	uint16_t kidx, value;
8164
8165	kidx = BWN_SEC_KEY2FW(mac, index);
8166	bwn_shm_write_2(mac, BWN_SHARED,
8167	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8168
8169	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8170	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8171		value = key[i];
8172		value |= (uint16_t)(key[i + 1]) << 8;
8173		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8174	}
8175}
8176
8177static void
8178bwn_phy_exit(struct bwn_mac *mac)
8179{
8180
8181	mac->mac_phy.rf_onoff(mac, 0);
8182	if (mac->mac_phy.exit != NULL)
8183		mac->mac_phy.exit(mac);
8184}
8185
8186static void
8187bwn_dma_free(struct bwn_mac *mac)
8188{
8189	struct bwn_dma *dma;
8190
8191	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8192		return;
8193	dma = &mac->mac_method.dma;
8194
8195	bwn_dma_ringfree(&dma->rx);
8196	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8197	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8198	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8199	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8200	bwn_dma_ringfree(&dma->mcast);
8201}
8202
8203static void
8204bwn_core_stop(struct bwn_mac *mac)
8205{
8206	struct bwn_softc *sc = mac->mac_sc;
8207
8208	BWN_ASSERT_LOCKED(sc);
8209
8210	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8211		return;
8212
8213	callout_stop(&sc->sc_rfswitch_ch);
8214	callout_stop(&sc->sc_task_ch);
8215	callout_stop(&sc->sc_watchdog_ch);
8216	sc->sc_watchdog_timer = 0;
8217	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8218	BWN_READ_4(mac, BWN_INTR_MASK);
8219	bwn_mac_suspend(mac);
8220
8221	mac->mac_status = BWN_MAC_STATUS_INITED;
8222}
8223
8224static int
8225bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8226{
8227	struct bwn_mac *up_dev = NULL;
8228	struct bwn_mac *down_dev;
8229	struct bwn_mac *mac;
8230	int err, status;
8231	uint8_t gmode;
8232
8233	BWN_ASSERT_LOCKED(sc);
8234
8235	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8236		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8237		    mac->mac_phy.supports_2ghz) {
8238			up_dev = mac;
8239			gmode = 1;
8240		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8241		    mac->mac_phy.supports_5ghz) {
8242			up_dev = mac;
8243			gmode = 0;
8244		} else {
8245			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8246			return (EINVAL);
8247		}
8248		if (up_dev != NULL)
8249			break;
8250	}
8251	if (up_dev == NULL) {
8252		device_printf(sc->sc_dev, "Could not find a device\n");
8253		return (ENODEV);
8254	}
8255	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8256		return (0);
8257
8258	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8259	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8260
8261	down_dev = sc->sc_curmac;
8262	status = down_dev->mac_status;
8263	if (status >= BWN_MAC_STATUS_STARTED)
8264		bwn_core_stop(down_dev);
8265	if (status >= BWN_MAC_STATUS_INITED)
8266		bwn_core_exit(down_dev);
8267
8268	if (down_dev != up_dev)
8269		bwn_phy_reset(down_dev);
8270
8271	up_dev->mac_phy.gmode = gmode;
8272	if (status >= BWN_MAC_STATUS_INITED) {
8273		err = bwn_core_init(up_dev);
8274		if (err) {
8275			device_printf(sc->sc_dev,
8276			    "fatal: failed to initialize for %s-GHz\n",
8277			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8278			goto fail;
8279		}
8280	}
8281	if (status >= BWN_MAC_STATUS_STARTED)
8282		bwn_core_start(up_dev);
8283	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8284	sc->sc_curmac = up_dev;
8285
8286	return (0);
8287fail:
8288	sc->sc_curmac = NULL;
8289	return (err);
8290}
8291
8292static void
8293bwn_rf_turnon(struct bwn_mac *mac)
8294{
8295
8296	bwn_mac_suspend(mac);
8297	mac->mac_phy.rf_onoff(mac, 1);
8298	mac->mac_phy.rf_on = 1;
8299	bwn_mac_enable(mac);
8300}
8301
8302static void
8303bwn_rf_turnoff(struct bwn_mac *mac)
8304{
8305
8306	bwn_mac_suspend(mac);
8307	mac->mac_phy.rf_onoff(mac, 0);
8308	mac->mac_phy.rf_on = 0;
8309	bwn_mac_enable(mac);
8310}
8311
8312static void
8313bwn_phy_reset(struct bwn_mac *mac)
8314{
8315	struct bwn_softc *sc = mac->mac_sc;
8316
8317	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8318	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8319	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8320	DELAY(1000);
8321	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8322	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8323	    BWN_TGSLOW_PHYRESET);
8324	DELAY(1000);
8325}
8326
8327static int
8328bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8329{
8330	struct bwn_vap *bvp = BWN_VAP(vap);
8331	struct ieee80211com *ic= vap->iv_ic;
8332	struct ifnet *ifp = ic->ic_ifp;
8333	enum ieee80211_state ostate = vap->iv_state;
8334	struct bwn_softc *sc = ifp->if_softc;
8335	struct bwn_mac *mac = sc->sc_curmac;
8336	int error;
8337
8338	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8339	    ieee80211_state_name[vap->iv_state],
8340	    ieee80211_state_name[nstate]);
8341
8342	error = bvp->bv_newstate(vap, nstate, arg);
8343	if (error != 0)
8344		return (error);
8345
8346	BWN_LOCK(sc);
8347
8348	bwn_led_newstate(mac, nstate);
8349
8350	/*
8351	 * Clear the BSSID when we stop a STA
8352	 */
8353	if (vap->iv_opmode == IEEE80211_M_STA) {
8354		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8355			/*
8356			 * Clear out the BSSID.  If we reassociate to
8357			 * the same AP, this will reinialize things
8358			 * correctly...
8359			 */
8360			if (ic->ic_opmode == IEEE80211_M_STA &&
8361			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8362				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8363				bwn_set_macaddr(mac);
8364			}
8365		}
8366	}
8367
8368	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8369	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8370		/* XXX nothing to do? */
8371	} else if (nstate == IEEE80211_S_RUN) {
8372		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8373		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8374		bwn_set_opmode(mac);
8375		bwn_set_pretbtt(mac);
8376		bwn_spu_setdelay(mac, 0);
8377		bwn_set_macaddr(mac);
8378	}
8379
8380	BWN_UNLOCK(sc);
8381
8382	return (error);
8383}
8384
8385static void
8386bwn_set_pretbtt(struct bwn_mac *mac)
8387{
8388	struct bwn_softc *sc = mac->mac_sc;
8389	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8390	uint16_t pretbtt;
8391
8392	if (ic->ic_opmode == IEEE80211_M_IBSS)
8393		pretbtt = 2;
8394	else
8395		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8396	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8397	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8398}
8399
8400static int
8401bwn_intr(void *arg)
8402{
8403	struct bwn_mac *mac = arg;
8404	struct bwn_softc *sc = mac->mac_sc;
8405	uint32_t reason;
8406
8407	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8408	    (sc->sc_flags & BWN_FLAG_INVALID))
8409		return (FILTER_STRAY);
8410
8411	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8412	if (reason == 0xffffffff)	/* shared IRQ */
8413		return (FILTER_STRAY);
8414	reason &= mac->mac_intr_mask;
8415	if (reason == 0)
8416		return (FILTER_HANDLED);
8417
8418	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8419	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8420	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8421	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8422	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8423	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8424	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8425	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8426	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8427	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8428	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8429
8430	/* Disable interrupts. */
8431	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8432
8433	mac->mac_reason_intr = reason;
8434
8435	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8436	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8437
8438	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8439	return (FILTER_HANDLED);
8440}
8441
8442static void
8443bwn_intrtask(void *arg, int npending)
8444{
8445	struct bwn_mac *mac = arg;
8446	struct bwn_softc *sc = mac->mac_sc;
8447	struct ifnet *ifp = sc->sc_ifp;
8448	uint32_t merged = 0;
8449	int i, tx = 0, rx = 0;
8450
8451	BWN_LOCK(sc);
8452	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8453	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8454		BWN_UNLOCK(sc);
8455		return;
8456	}
8457
8458	for (i = 0; i < N(mac->mac_reason); i++)
8459		merged |= mac->mac_reason[i];
8460
8461	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8462		device_printf(sc->sc_dev, "MAC trans error\n");
8463
8464	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8465		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8466		mac->mac_phy.txerrors--;
8467		if (mac->mac_phy.txerrors == 0) {
8468			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8469			bwn_restart(mac, "PHY TX errors");
8470		}
8471	}
8472
8473	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8474		if (merged & BWN_DMAINTR_FATALMASK) {
8475			device_printf(sc->sc_dev,
8476			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8477			    mac->mac_reason[0], mac->mac_reason[1],
8478			    mac->mac_reason[2], mac->mac_reason[3],
8479			    mac->mac_reason[4], mac->mac_reason[5]);
8480			bwn_restart(mac, "DMA error");
8481			BWN_UNLOCK(sc);
8482			return;
8483		}
8484		if (merged & BWN_DMAINTR_NONFATALMASK) {
8485			device_printf(sc->sc_dev,
8486			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8487			    mac->mac_reason[0], mac->mac_reason[1],
8488			    mac->mac_reason[2], mac->mac_reason[3],
8489			    mac->mac_reason[4], mac->mac_reason[5]);
8490		}
8491	}
8492
8493	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8494		bwn_intr_ucode_debug(mac);
8495	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8496		bwn_intr_tbtt_indication(mac);
8497	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8498		bwn_intr_atim_end(mac);
8499	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8500		bwn_intr_beacon(mac);
8501	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8502		bwn_intr_pmq(mac);
8503	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8504		bwn_intr_noise(mac);
8505
8506	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8507		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8508			bwn_dma_rx(mac->mac_method.dma.rx);
8509			rx = 1;
8510		}
8511	} else
8512		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8513
8514	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8519
8520	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8521		bwn_intr_txeof(mac);
8522		tx = 1;
8523	}
8524
8525	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8526
8527	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8528		int evt = BWN_LED_EVENT_NONE;
8529
8530		if (tx && rx) {
8531			if (sc->sc_rx_rate > sc->sc_tx_rate)
8532				evt = BWN_LED_EVENT_RX;
8533			else
8534				evt = BWN_LED_EVENT_TX;
8535		} else if (tx) {
8536			evt = BWN_LED_EVENT_TX;
8537		} else if (rx) {
8538			evt = BWN_LED_EVENT_RX;
8539		} else if (rx == 0) {
8540			evt = BWN_LED_EVENT_POLL;
8541		}
8542
8543		if (evt != BWN_LED_EVENT_NONE)
8544			bwn_led_event(mac, evt);
8545       }
8546
8547	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8548		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8549			bwn_start_locked(ifp);
8550	}
8551
8552	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8553	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8554
8555	BWN_UNLOCK(sc);
8556}
8557
8558static void
8559bwn_restart(struct bwn_mac *mac, const char *msg)
8560{
8561	struct bwn_softc *sc = mac->mac_sc;
8562	struct ifnet *ifp = sc->sc_ifp;
8563	struct ieee80211com *ic = ifp->if_l2com;
8564
8565	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8566		return;
8567
8568	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8569	ieee80211_runtask(ic, &mac->mac_hwreset);
8570}
8571
8572static void
8573bwn_intr_ucode_debug(struct bwn_mac *mac)
8574{
8575	struct bwn_softc *sc = mac->mac_sc;
8576	uint16_t reason;
8577
8578	if (mac->mac_fw.opensource == 0)
8579		return;
8580
8581	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8582	switch (reason) {
8583	case BWN_DEBUGINTR_PANIC:
8584		bwn_handle_fwpanic(mac);
8585		break;
8586	case BWN_DEBUGINTR_DUMP_SHM:
8587		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8588		break;
8589	case BWN_DEBUGINTR_DUMP_REGS:
8590		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8591		break;
8592	case BWN_DEBUGINTR_MARKER:
8593		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8594		break;
8595	default:
8596		device_printf(sc->sc_dev,
8597		    "ucode debug unknown reason: %#x\n", reason);
8598	}
8599
8600	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8601	    BWN_DEBUGINTR_ACK);
8602}
8603
8604static void
8605bwn_intr_tbtt_indication(struct bwn_mac *mac)
8606{
8607	struct bwn_softc *sc = mac->mac_sc;
8608	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8609
8610	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8611		bwn_psctl(mac, 0);
8612	if (ic->ic_opmode == IEEE80211_M_IBSS)
8613		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8614}
8615
8616static void
8617bwn_intr_atim_end(struct bwn_mac *mac)
8618{
8619
8620	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8621		BWN_WRITE_4(mac, BWN_MACCMD,
8622		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8623		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8624	}
8625}
8626
8627static void
8628bwn_intr_beacon(struct bwn_mac *mac)
8629{
8630	struct bwn_softc *sc = mac->mac_sc;
8631	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8632	uint32_t cmd, beacon0, beacon1;
8633
8634	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8635	    ic->ic_opmode == IEEE80211_M_MBSS)
8636		return;
8637
8638	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8639
8640	cmd = BWN_READ_4(mac, BWN_MACCMD);
8641	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8642	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8643
8644	if (beacon0 && beacon1) {
8645		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8646		mac->mac_intr_mask |= BWN_INTR_BEACON;
8647		return;
8648	}
8649
8650	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8651		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8652		bwn_load_beacon0(mac);
8653		bwn_load_beacon1(mac);
8654		cmd = BWN_READ_4(mac, BWN_MACCMD);
8655		cmd |= BWN_MACCMD_BEACON0_VALID;
8656		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8657	} else {
8658		if (!beacon0) {
8659			bwn_load_beacon0(mac);
8660			cmd = BWN_READ_4(mac, BWN_MACCMD);
8661			cmd |= BWN_MACCMD_BEACON0_VALID;
8662			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8663		} else if (!beacon1) {
8664			bwn_load_beacon1(mac);
8665			cmd = BWN_READ_4(mac, BWN_MACCMD);
8666			cmd |= BWN_MACCMD_BEACON1_VALID;
8667			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8668		}
8669	}
8670}
8671
8672static void
8673bwn_intr_pmq(struct bwn_mac *mac)
8674{
8675	uint32_t tmp;
8676
8677	while (1) {
8678		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8679		if (!(tmp & 0x00000008))
8680			break;
8681	}
8682	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8683}
8684
8685static void
8686bwn_intr_noise(struct bwn_mac *mac)
8687{
8688	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8689	uint16_t tmp;
8690	uint8_t noise[4];
8691	uint8_t i, j;
8692	int32_t average;
8693
8694	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8695		return;
8696
8697	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8698	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8699	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8700	    noise[3] == 0x7f)
8701		goto new;
8702
8703	KASSERT(mac->mac_noise.noi_nsamples < 8,
8704	    ("%s:%d: fail", __func__, __LINE__));
8705	i = mac->mac_noise.noi_nsamples;
8706	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8707	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8708	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8709	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8710	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8711	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8712	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8713	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8714	mac->mac_noise.noi_nsamples++;
8715	if (mac->mac_noise.noi_nsamples == 8) {
8716		average = 0;
8717		for (i = 0; i < 8; i++) {
8718			for (j = 0; j < 4; j++)
8719				average += mac->mac_noise.noi_samples[i][j];
8720		}
8721		average = (((average / 32) * 125) + 64) / 128;
8722		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8723		if (tmp >= 8)
8724			average += 2;
8725		else
8726			average -= 25;
8727		average -= (tmp == 8) ? 72 : 48;
8728
8729		mac->mac_stats.link_noise = average;
8730		mac->mac_noise.noi_running = 0;
8731		return;
8732	}
8733new:
8734	bwn_noise_gensample(mac);
8735}
8736
8737static int
8738bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8739{
8740	struct bwn_mac *mac = prq->prq_mac;
8741	struct bwn_softc *sc = mac->mac_sc;
8742	unsigned int i;
8743
8744	BWN_ASSERT_LOCKED(sc);
8745
8746	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8747		return (0);
8748
8749	for (i = 0; i < 5000; i++) {
8750		if (bwn_pio_rxeof(prq) == 0)
8751			break;
8752	}
8753	if (i >= 5000)
8754		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8755	return ((i > 0) ? 1 : 0);
8756}
8757
8758static void
8759bwn_dma_rx(struct bwn_dma_ring *dr)
8760{
8761	int slot, curslot;
8762
8763	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8764	curslot = dr->get_curslot(dr);
8765	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8766	    ("%s:%d: fail", __func__, __LINE__));
8767
8768	slot = dr->dr_curslot;
8769	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8770		bwn_dma_rxeof(dr, &slot);
8771
8772	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8773	    BUS_DMASYNC_PREWRITE);
8774
8775	dr->set_curslot(dr, slot);
8776	dr->dr_curslot = slot;
8777}
8778
8779static void
8780bwn_intr_txeof(struct bwn_mac *mac)
8781{
8782	struct bwn_txstatus stat;
8783	uint32_t stat0, stat1;
8784	uint16_t tmp;
8785
8786	BWN_ASSERT_LOCKED(mac->mac_sc);
8787
8788	while (1) {
8789		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8790		if (!(stat0 & 0x00000001))
8791			break;
8792		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8793
8794		stat.cookie = (stat0 >> 16);
8795		stat.seq = (stat1 & 0x0000ffff);
8796		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8797		tmp = (stat0 & 0x0000ffff);
8798		stat.framecnt = ((tmp & 0xf000) >> 12);
8799		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8800		stat.sreason = ((tmp & 0x001c) >> 2);
8801		stat.pm = (tmp & 0x0080) ? 1 : 0;
8802		stat.im = (tmp & 0x0040) ? 1 : 0;
8803		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8804		stat.ack = (tmp & 0x0002) ? 1 : 0;
8805
8806		bwn_handle_txeof(mac, &stat);
8807	}
8808}
8809
8810static void
8811bwn_hwreset(void *arg, int npending)
8812{
8813	struct bwn_mac *mac = arg;
8814	struct bwn_softc *sc = mac->mac_sc;
8815	int error = 0;
8816	int prev_status;
8817
8818	BWN_LOCK(sc);
8819
8820	prev_status = mac->mac_status;
8821	if (prev_status >= BWN_MAC_STATUS_STARTED)
8822		bwn_core_stop(mac);
8823	if (prev_status >= BWN_MAC_STATUS_INITED)
8824		bwn_core_exit(mac);
8825
8826	if (prev_status >= BWN_MAC_STATUS_INITED) {
8827		error = bwn_core_init(mac);
8828		if (error)
8829			goto out;
8830	}
8831	if (prev_status >= BWN_MAC_STATUS_STARTED)
8832		bwn_core_start(mac);
8833out:
8834	if (error) {
8835		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8836		sc->sc_curmac = NULL;
8837	}
8838	BWN_UNLOCK(sc);
8839}
8840
8841static void
8842bwn_handle_fwpanic(struct bwn_mac *mac)
8843{
8844	struct bwn_softc *sc = mac->mac_sc;
8845	uint16_t reason;
8846
8847	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8848	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8849
8850	if (reason == BWN_FWPANIC_RESTART)
8851		bwn_restart(mac, "ucode panic");
8852}
8853
8854static void
8855bwn_load_beacon0(struct bwn_mac *mac)
8856{
8857
8858	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8859}
8860
8861static void
8862bwn_load_beacon1(struct bwn_mac *mac)
8863{
8864
8865	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8866}
8867
8868static uint32_t
8869bwn_jssi_read(struct bwn_mac *mac)
8870{
8871	uint32_t val = 0;
8872
8873	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8874	val <<= 16;
8875	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8876
8877	return (val);
8878}
8879
8880static void
8881bwn_noise_gensample(struct bwn_mac *mac)
8882{
8883	uint32_t jssi = 0x7f7f7f7f;
8884
8885	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8886	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8887	BWN_WRITE_4(mac, BWN_MACCMD,
8888	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8889}
8890
8891static int
8892bwn_dma_freeslot(struct bwn_dma_ring *dr)
8893{
8894	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8895
8896	return (dr->dr_numslots - dr->dr_usedslot);
8897}
8898
8899static int
8900bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8901{
8902	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8903
8904	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8905	    ("%s:%d: fail", __func__, __LINE__));
8906	if (slot == dr->dr_numslots - 1)
8907		return (0);
8908	return (slot + 1);
8909}
8910
8911static void
8912bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8913{
8914	struct bwn_mac *mac = dr->dr_mac;
8915	struct bwn_softc *sc = mac->mac_sc;
8916	struct bwn_dma *dma = &mac->mac_method.dma;
8917	struct bwn_dmadesc_generic *desc;
8918	struct bwn_dmadesc_meta *meta;
8919	struct bwn_rxhdr4 *rxhdr;
8920	struct ifnet *ifp = sc->sc_ifp;
8921	struct mbuf *m;
8922	uint32_t macstat;
8923	int32_t tmp;
8924	int cnt = 0;
8925	uint16_t len;
8926
8927	dr->getdesc(dr, *slot, &desc, &meta);
8928
8929	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8930	m = meta->mt_m;
8931
8932	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8933		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8934		return;
8935	}
8936
8937	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8938	len = le16toh(rxhdr->frame_len);
8939	if (len <= 0) {
8940		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8941		return;
8942	}
8943	if (bwn_dma_check_redzone(dr, m)) {
8944		device_printf(sc->sc_dev, "redzone error.\n");
8945		bwn_dma_set_redzone(dr, m);
8946		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8947		    BUS_DMASYNC_PREWRITE);
8948		return;
8949	}
8950	if (len > dr->dr_rx_bufsize) {
8951		tmp = len;
8952		while (1) {
8953			dr->getdesc(dr, *slot, &desc, &meta);
8954			bwn_dma_set_redzone(dr, meta->mt_m);
8955			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8956			    BUS_DMASYNC_PREWRITE);
8957			*slot = bwn_dma_nextslot(dr, *slot);
8958			cnt++;
8959			tmp -= dr->dr_rx_bufsize;
8960			if (tmp <= 0)
8961				break;
8962		}
8963		device_printf(sc->sc_dev, "too small buffer "
8964		       "(len %u buffer %u dropped %d)\n",
8965		       len, dr->dr_rx_bufsize, cnt);
8966		return;
8967	}
8968	macstat = le32toh(rxhdr->mac_status);
8969	if (macstat & BWN_RX_MAC_FCSERR) {
8970		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8971			device_printf(sc->sc_dev, "RX drop\n");
8972			return;
8973		}
8974	}
8975
8976	m->m_pkthdr.rcvif = ifp;
8977	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8978	m_adj(m, dr->dr_frameoffset);
8979
8980	bwn_rxeof(dr->dr_mac, m, rxhdr);
8981}
8982
8983static void
8984bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8985{
8986	struct bwn_dma_ring *dr;
8987	struct bwn_dmadesc_generic *desc;
8988	struct bwn_dmadesc_meta *meta;
8989	struct bwn_pio_txqueue *tq;
8990	struct bwn_pio_txpkt *tp = NULL;
8991	struct bwn_softc *sc = mac->mac_sc;
8992	struct bwn_stats *stats = &mac->mac_stats;
8993	struct ieee80211_node *ni;
8994	struct ieee80211vap *vap;
8995	int retrycnt = 0, slot;
8996
8997	BWN_ASSERT_LOCKED(mac->mac_sc);
8998
8999	if (status->im)
9000		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9001	if (status->ampdu)
9002		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9003	if (status->rtscnt) {
9004		if (status->rtscnt == 0xf)
9005			stats->rtsfail++;
9006		else
9007			stats->rts++;
9008	}
9009
9010	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9011		if (status->ack) {
9012			dr = bwn_dma_parse_cookie(mac, status,
9013			    status->cookie, &slot);
9014			if (dr == NULL) {
9015				device_printf(sc->sc_dev,
9016				    "failed to parse cookie\n");
9017				return;
9018			}
9019			while (1) {
9020				dr->getdesc(dr, slot, &desc, &meta);
9021				if (meta->mt_islast) {
9022					ni = meta->mt_ni;
9023					vap = ni->ni_vap;
9024					ieee80211_ratectl_tx_complete(vap, ni,
9025					    status->ack ?
9026					      IEEE80211_RATECTL_TX_SUCCESS :
9027					      IEEE80211_RATECTL_TX_FAILURE,
9028					    &retrycnt, 0);
9029					break;
9030				}
9031				slot = bwn_dma_nextslot(dr, slot);
9032			}
9033		}
9034		bwn_dma_handle_txeof(mac, status);
9035	} else {
9036		if (status->ack) {
9037			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9038			if (tq == NULL) {
9039				device_printf(sc->sc_dev,
9040				    "failed to parse cookie\n");
9041				return;
9042			}
9043			ni = tp->tp_ni;
9044			vap = ni->ni_vap;
9045			ieee80211_ratectl_tx_complete(vap, ni,
9046			    status->ack ?
9047			      IEEE80211_RATECTL_TX_SUCCESS :
9048			      IEEE80211_RATECTL_TX_FAILURE,
9049			    &retrycnt, 0);
9050		}
9051		bwn_pio_handle_txeof(mac, status);
9052	}
9053
9054	bwn_phy_txpower_check(mac, 0);
9055}
9056
9057static uint8_t
9058bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9059{
9060	struct bwn_mac *mac = prq->prq_mac;
9061	struct bwn_softc *sc = mac->mac_sc;
9062	struct bwn_rxhdr4 rxhdr;
9063	struct ifnet *ifp = sc->sc_ifp;
9064	struct mbuf *m;
9065	uint32_t ctl32, macstat, v32;
9066	unsigned int i, padding;
9067	uint16_t ctl16, len, totlen, v16;
9068	unsigned char *mp;
9069	char *data;
9070
9071	memset(&rxhdr, 0, sizeof(rxhdr));
9072
9073	if (prq->prq_rev >= 8) {
9074		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9075		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9076			return (0);
9077		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9078		    BWN_PIO8_RXCTL_FRAMEREADY);
9079		for (i = 0; i < 10; i++) {
9080			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9081			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9082				goto ready;
9083			DELAY(10);
9084		}
9085	} else {
9086		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9087		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9088			return (0);
9089		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9090		    BWN_PIO_RXCTL_FRAMEREADY);
9091		for (i = 0; i < 10; i++) {
9092			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9093			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9094				goto ready;
9095			DELAY(10);
9096		}
9097	}
9098	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9099	return (1);
9100ready:
9101	if (prq->prq_rev >= 8)
9102		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9103		    prq->prq_base + BWN_PIO8_RXDATA);
9104	else
9105		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9106		    prq->prq_base + BWN_PIO_RXDATA);
9107	len = le16toh(rxhdr.frame_len);
9108	if (len > 0x700) {
9109		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9110		goto error;
9111	}
9112	if (len == 0) {
9113		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9114		goto error;
9115	}
9116
9117	macstat = le32toh(rxhdr.mac_status);
9118	if (macstat & BWN_RX_MAC_FCSERR) {
9119		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9120			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9121			goto error;
9122		}
9123	}
9124
9125	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9126	totlen = len + padding;
9127	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9128	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9129	if (m == NULL) {
9130		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9131		goto error;
9132	}
9133	mp = mtod(m, unsigned char *);
9134	if (prq->prq_rev >= 8) {
9135		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9136		    prq->prq_base + BWN_PIO8_RXDATA);
9137		if (totlen & 3) {
9138			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9139			data = &(mp[totlen - 1]);
9140			switch (totlen & 3) {
9141			case 3:
9142				*data = (v32 >> 16);
9143				data--;
9144			case 2:
9145				*data = (v32 >> 8);
9146				data--;
9147			case 1:
9148				*data = v32;
9149			}
9150		}
9151	} else {
9152		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9153		    prq->prq_base + BWN_PIO_RXDATA);
9154		if (totlen & 1) {
9155			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9156			mp[totlen - 1] = v16;
9157		}
9158	}
9159
9160	m->m_pkthdr.rcvif = ifp;
9161	m->m_len = m->m_pkthdr.len = totlen;
9162
9163	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9164
9165	return (1);
9166error:
9167	if (prq->prq_rev >= 8)
9168		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9169		    BWN_PIO8_RXCTL_DATAREADY);
9170	else
9171		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9172	return (1);
9173}
9174
9175static int
9176bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9177    struct bwn_dmadesc_meta *meta, int init)
9178{
9179	struct bwn_mac *mac = dr->dr_mac;
9180	struct bwn_dma *dma = &mac->mac_method.dma;
9181	struct bwn_rxhdr4 *hdr;
9182	bus_dmamap_t map;
9183	bus_addr_t paddr;
9184	struct mbuf *m;
9185	int error;
9186
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, meta->mt_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	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
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			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
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	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
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_PROTECTED)
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_PROTECTED)
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			       BUS_SPACE_MAXSIZE,	/* 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.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