if_bwn.c revision 204922
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 204922 2010-03-09 19:58:00Z weongyo $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_amrr.h>
71#include <net80211/ieee80211_phy.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
76SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77
78/*
79 * Tunable & sysctl variables.
80 */
81
82#ifdef BWN_DEBUG
83static	int bwn_debug = 0;
84SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85    "Broadcom debugging printfs");
86TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87enum {
88	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106	BWN_DEBUG_ANY		= 0xffffffff
107};
108#define	DPRINTF(sc, m, fmt, ...) do {			\
109	if (sc->sc_debug & (m))				\
110		printf(fmt, __VA_ARGS__);		\
111} while (0)
112#else
113#define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114#endif
115
116static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118    "uses Bad Frames Preemption");
119static int	bwn_bluetooth = 1;
120SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121    "turns on Bluetooth Coexistence");
122static int	bwn_hwpctl = 0;
123SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124    "uses H/W power control");
125static int	bwn_msi_disable = 0;		/* MSI disabled  */
126TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127static int	bwn_usedma = 1;
128SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129    "uses DMA");
130TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131static int	bwn_wme = 1;
132SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133    "uses WME support");
134
135static int	bwn_attach_pre(struct bwn_softc *);
136static int	bwn_attach_post(struct bwn_softc *);
137static void	bwn_sprom_bugfixes(device_t);
138static void	bwn_init(void *);
139static int	bwn_init_locked(struct bwn_softc *);
140static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141static void	bwn_start(struct ifnet *);
142static int	bwn_attach_core(struct bwn_mac *);
143static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144static int	bwn_phy_getinfo(struct bwn_mac *, int);
145static int	bwn_chiptest(struct bwn_mac *);
146static int	bwn_setup_channels(struct bwn_mac *, int, int);
147static int	bwn_phy_g_attach(struct bwn_mac *);
148static void	bwn_phy_g_detach(struct bwn_mac *);
149static void	bwn_phy_g_init_pre(struct bwn_mac *);
150static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151static int	bwn_phy_g_init(struct bwn_mac *);
152static void	bwn_phy_g_exit(struct bwn_mac *);
153static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155		    uint16_t);
156static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158		    uint16_t);
159static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164static int	bwn_phy_g_im(struct bwn_mac *, int);
165static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167static void	bwn_phy_g_task_15s(struct bwn_mac *);
168static void	bwn_phy_g_task_60s(struct bwn_mac *);
169static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173		    uint16_t);
174static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176		    uint32_t);
177static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178		    uint16_t);
179static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180		    const struct bwn_channelinfo *, int);
181static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182		    const struct ieee80211_bpf_params *);
183static void	bwn_newassoc(struct ieee80211_node *, int);
184static void	bwn_updateslot(struct ifnet *);
185static void	bwn_update_promisc(struct ifnet *);
186static void	bwn_wme_init(struct bwn_mac *);
187static int	bwn_wme_update(struct ieee80211com *);
188static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189		    const uint8_t [IEEE80211_ADDR_LEN]);
190static void	bwn_wme_clear(struct bwn_softc *);
191static void	bwn_wme_load(struct bwn_mac *);
192static void	bwn_wme_loadparams(struct bwn_mac *,
193		    const struct wmeParams *, uint16_t);
194static void	bwn_node_cleanup(struct ieee80211_node *);
195static void	bwn_scan_start(struct ieee80211com *);
196static void	bwn_scan_end(struct ieee80211com *);
197static void	bwn_set_channel(struct ieee80211com *);
198static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199		    const char [IFNAMSIZ], int, int,
200		    int, const uint8_t [IEEE80211_ADDR_LEN],
201		    const uint8_t [IEEE80211_ADDR_LEN]);
202static void	bwn_vap_delete(struct ieee80211vap *);
203static void	bwn_stop(struct bwn_softc *, int);
204static void	bwn_stop_locked(struct bwn_softc *, int);
205static int	bwn_core_init(struct bwn_mac *);
206static void	bwn_core_start(struct bwn_mac *);
207static void	bwn_core_exit(struct bwn_mac *);
208static void	bwn_bt_disable(struct bwn_mac *);
209static int	bwn_chip_init(struct bwn_mac *);
210static uint64_t	bwn_hf_read(struct bwn_mac *);
211static void	bwn_hf_write(struct bwn_mac *, uint64_t);
212static void	bwn_set_txretry(struct bwn_mac *, int, int);
213static void	bwn_rate_init(struct bwn_mac *);
214static void	bwn_set_phytxctl(struct bwn_mac *);
215static void	bwn_spu_setdelay(struct bwn_mac *, int);
216static void	bwn_bt_enable(struct bwn_mac *);
217static void	bwn_set_macaddr(struct bwn_mac *);
218static void	bwn_crypt_init(struct bwn_mac *);
219static void	bwn_chip_exit(struct bwn_mac *);
220static int	bwn_fw_fillinfo(struct bwn_mac *);
221static int	bwn_fw_loaducode(struct bwn_mac *);
222static int	bwn_gpio_init(struct bwn_mac *);
223static int	bwn_fw_loadinitvals(struct bwn_mac *);
224static int	bwn_phy_init(struct bwn_mac *);
225static void	bwn_set_txantenna(struct bwn_mac *, int);
226static void	bwn_set_opmode(struct bwn_mac *);
227static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
228static uint8_t	bwn_plcp_getcck(const uint8_t);
229static uint8_t	bwn_plcp_getofdm(const uint8_t);
230static void	bwn_pio_init(struct bwn_mac *);
231static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
232static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
233		    int);
234static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
235		    struct bwn_pio_rxqueue *, int);
236static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
237static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
238		    uint16_t);
239static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
240static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
241static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
242static void	bwn_pio_handle_txeof(struct bwn_mac *,
243		    const struct bwn_txstatus *);
244static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
245static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
246static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
247		    uint16_t);
248static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
249		    uint32_t);
250static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
251		    struct mbuf *);
252static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
253static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
254		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
255static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
256		    uint16_t, uint32_t);
257static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
258		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
259static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
260		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
261static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
262		    uint16_t, struct bwn_pio_txpkt **);
263static void	bwn_dma_init(struct bwn_mac *);
264static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
265static int	bwn_dma_mask2type(uint64_t);
266static uint64_t	bwn_dma_mask(struct bwn_mac *);
267static uint16_t	bwn_dma_base(int, int);
268static void	bwn_dma_ringfree(struct bwn_dma_ring **);
269static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
270		    int, struct bwn_dmadesc_generic **,
271		    struct bwn_dmadesc_meta **);
272static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
273		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
274		    int, int);
275static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
276static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
277static void	bwn_dma_32_resume(struct bwn_dma_ring *);
278static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
279static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
280static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
281		    int, struct bwn_dmadesc_generic **,
282		    struct bwn_dmadesc_meta **);
283static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
284		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
285		    int, int);
286static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
287static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
288static void	bwn_dma_64_resume(struct bwn_dma_ring *);
289static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
290static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
291static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
292static void	bwn_dma_setup(struct bwn_dma_ring *);
293static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
294static void	bwn_dma_cleanup(struct bwn_dma_ring *);
295static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
296static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
297static void	bwn_dma_rx(struct bwn_dma_ring *);
298static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
300		    struct bwn_dmadesc_meta *);
301static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302static int	bwn_dma_gettype(struct bwn_mac *);
303static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304static int	bwn_dma_freeslot(struct bwn_dma_ring *);
305static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
306static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307static int	bwn_dma_newbuf(struct bwn_dma_ring *,
308		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309		    int);
310static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311		    bus_size_t, int);
312static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313static void	bwn_dma_handle_txeof(struct bwn_mac *,
314		    const struct bwn_txstatus *);
315static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316		    struct mbuf *);
317static int	bwn_dma_getslot(struct bwn_dma_ring *);
318static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319		    uint8_t);
320static int	bwn_dma_attach(struct bwn_mac *);
321static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322		    int, int, int);
323static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324		    const struct bwn_txstatus *, uint16_t, int *);
325static void	bwn_dma_free(struct bwn_mac *);
326static void	bwn_phy_g_init_sub(struct bwn_mac *);
327static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
328static void	bwn_phy_init_b5(struct bwn_mac *);
329static void	bwn_phy_init_b6(struct bwn_mac *);
330static void	bwn_phy_init_a(struct bwn_mac *);
331static void	bwn_loopback_calcgain(struct bwn_mac *);
332static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
333static void	bwn_lo_g_init(struct bwn_mac *);
334static void	bwn_lo_g_adjust(struct bwn_mac *);
335static void	bwn_lo_get_powervector(struct bwn_mac *);
336static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337		    const struct bwn_bbatt *, const struct bwn_rfatt *);
338static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339static void	bwn_phy_hwpctl_init(struct bwn_mac *);
340static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342		    const struct bwn_bbatt *, const struct bwn_rfatt *,
343		    uint8_t);
344static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
347static void	bwn_wa_init(struct bwn_mac *);
348static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349		    uint16_t);
350static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
351static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352		    uint32_t);
353static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354		    uint16_t);
355static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356static void	bwn_mac_suspend(struct bwn_mac *);
357static void	bwn_mac_enable(struct bwn_mac *);
358static void	bwn_psctl(struct bwn_mac *, uint32_t);
359static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
360static void	bwn_nrssi_offset(struct bwn_mac *);
361static void	bwn_nrssi_threshold(struct bwn_mac *);
362static void	bwn_nrssi_slope_11g(struct bwn_mac *);
363static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364		    int16_t);
365static void	bwn_set_original_gains(struct bwn_mac *);
366static void	bwn_hwpctl_early_init(struct bwn_mac *);
367static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
368static uint16_t	bwn_phy_g_chan2freq(uint8_t);
369static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371		    const char *, struct bwn_fwfile *);
372static void	bwn_release_firmware(struct bwn_mac *);
373static void	bwn_do_release_fw(struct bwn_fwfile *);
374static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
375static int	bwn_fwinitvals_write(struct bwn_mac *,
376		    const struct bwn_fwinitvals *, size_t, size_t);
377static int	bwn_switch_channel(struct bwn_mac *, int);
378static uint16_t	bwn_ant2phy(int);
379static void	bwn_mac_write_bssid(struct bwn_mac *);
380static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381		    const uint8_t *);
382static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383		    const uint8_t *, size_t, const uint8_t *);
384static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
385		    const uint8_t *);
386static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387		    const uint8_t *);
388static void	bwn_phy_exit(struct bwn_mac *);
389static void	bwn_core_stop(struct bwn_mac *);
390static int	bwn_switch_band(struct bwn_softc *,
391		    struct ieee80211_channel *);
392static void	bwn_phy_reset(struct bwn_mac *);
393static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394static void	bwn_set_pretbtt(struct bwn_mac *);
395static int	bwn_intr(void *);
396static void	bwn_intrtask(void *, int);
397static void	bwn_restart(struct bwn_mac *, const char *);
398static void	bwn_intr_ucode_debug(struct bwn_mac *);
399static void	bwn_intr_tbtt_indication(struct bwn_mac *);
400static void	bwn_intr_atim_end(struct bwn_mac *);
401static void	bwn_intr_beacon(struct bwn_mac *);
402static void	bwn_intr_pmq(struct bwn_mac *);
403static void	bwn_intr_noise(struct bwn_mac *);
404static void	bwn_intr_txeof(struct bwn_mac *);
405static void	bwn_hwreset(void *, int);
406static void	bwn_handle_fwpanic(struct bwn_mac *);
407static void	bwn_load_beacon0(struct bwn_mac *);
408static void	bwn_load_beacon1(struct bwn_mac *);
409static uint32_t	bwn_jssi_read(struct bwn_mac *);
410static void	bwn_noise_gensample(struct bwn_mac *);
411static void	bwn_handle_txeof(struct bwn_mac *,
412		    const struct bwn_txstatus *);
413static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415static void	bwn_start_locked(struct ifnet *);
416static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417		    struct mbuf *);
418static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419static int	bwn_set_txhdr(struct bwn_mac *,
420		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421		    uint16_t);
422static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423		    const uint8_t);
424static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425static uint8_t	bwn_get_fbrate(uint8_t);
426static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428static void	bwn_phy_lock(struct bwn_mac *);
429static void	bwn_phy_unlock(struct bwn_mac *);
430static void	bwn_rf_lock(struct bwn_mac *);
431static void	bwn_rf_unlock(struct bwn_mac *);
432static void	bwn_txpwr(void *, int);
433static void	bwn_tasks(void *);
434static void	bwn_task_15s(struct bwn_mac *);
435static void	bwn_task_30s(struct bwn_mac *);
436static void	bwn_task_60s(struct bwn_mac *);
437static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438		    uint8_t);
439static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442		    int, int);
443static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
444static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
446static void	bwn_watchdog(void *);
447static void	bwn_dma_stop(struct bwn_mac *);
448static void	bwn_pio_stop(struct bwn_mac *);
449static void	bwn_dma_ringstop(struct bwn_dma_ring **);
450static void	bwn_led_attach(struct bwn_mac *);
451static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452static void	bwn_led_event(struct bwn_mac *, int);
453static void	bwn_led_blink_start(struct bwn_mac *, int, int);
454static void	bwn_led_blink_next(void *);
455static void	bwn_led_blink_end(void *);
456static void	bwn_rfswitch(void *);
457static void	bwn_rf_turnon(struct bwn_mac *);
458static void	bwn_rf_turnoff(struct bwn_mac *);
459static void	bwn_phy_lp_init_pre(struct bwn_mac *);
460static int	bwn_phy_lp_init(struct bwn_mac *);
461static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464		    uint16_t);
465static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
470static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471static void	bwn_phy_lp_task_60s(struct bwn_mac *);
472static void	bwn_phy_lp_readsprom(struct bwn_mac *);
473static void	bwn_phy_lp_bbinit(struct bwn_mac *);
474static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
475static void	bwn_phy_lp_calib(struct bwn_mac *);
476static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
482static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484static void	bwn_phy_lp_bugfix(struct bwn_mac *);
485static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
486static void	bwn_phy_lp_tblinit(struct bwn_mac *);
487static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
490static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
491static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
493static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
494static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498		    const void *);
499static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500static struct bwn_txgain
501		bwn_phy_lp_get_txgain(struct bwn_mac *);
502static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
503static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516static int	bwn_phy_lp_loopback(struct bwn_mac *);
517static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519		    int);
520static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521		    struct bwn_phy_lp_iq_est *);
522static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
524static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528static uint8_t	bwn_nbits(int32_t);
529static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530		    struct bwn_txgain_entry *);
531static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532		    struct bwn_txgain_entry);
533static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534		    struct bwn_txgain_entry);
535static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536		    struct bwn_txgain_entry);
537static void	bwn_sysctl_node(struct bwn_softc *);
538
539static struct resource_spec bwn_res_spec_legacy[] = {
540	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
541	{ -1,			0,		0 }
542};
543
544static struct resource_spec bwn_res_spec_msi[] = {
545	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
546	{ -1,			0,		0 }
547};
548
549static const struct bwn_channelinfo bwn_chantable_bg = {
550	.channels = {
551		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
552		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
553		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
554		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
555		{ 2472, 13, 30 }, { 2484, 14, 30 } },
556	.nchannels = 14
557};
558
559static const struct bwn_channelinfo bwn_chantable_a = {
560	.channels = {
561		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
562		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
563		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
564		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
565		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
566		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
567		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
568		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
569		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
570		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
571		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
572		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
573		{ 6080, 216, 30 } },
574	.nchannels = 37
575};
576
577static const struct bwn_channelinfo bwn_chantable_n = {
578	.channels = {
579		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
580		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
581		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
582		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
583		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
584		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
585		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
586		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
587		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
588		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
589		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
590		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
591		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
592		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
593		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
594		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
595		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
596		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
597		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
598		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
599		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
600		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
601		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
602		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
603		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
604		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
605		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
606		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
607		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
608		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
609		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
610		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
611		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
612		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
613		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
614		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
615		{ 6130, 226, 30 }, { 6140, 228, 30 } },
616	.nchannels = 110
617};
618
619static const uint8_t bwn_b2063_chantable_data[33][12] = {
620	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
626	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
627	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
629	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
630	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
631	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
632	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
633	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
634	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
635	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
636	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
637	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
638	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
639	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
640	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
641	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
642	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
643	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
645	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
646	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
647	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
648	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
649	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
651	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
652	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
653};
654
655static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
656	{ 1, 2412, bwn_b2063_chantable_data[0] },
657	{ 2, 2417, bwn_b2063_chantable_data[0] },
658	{ 3, 2422, bwn_b2063_chantable_data[0] },
659	{ 4, 2427, bwn_b2063_chantable_data[1] },
660	{ 5, 2432, bwn_b2063_chantable_data[1] },
661	{ 6, 2437, bwn_b2063_chantable_data[1] },
662	{ 7, 2442, bwn_b2063_chantable_data[1] },
663	{ 8, 2447, bwn_b2063_chantable_data[1] },
664	{ 9, 2452, bwn_b2063_chantable_data[2] },
665	{ 10, 2457, bwn_b2063_chantable_data[2] },
666	{ 11, 2462, bwn_b2063_chantable_data[3] },
667	{ 12, 2467, bwn_b2063_chantable_data[3] },
668	{ 13, 2472, bwn_b2063_chantable_data[3] },
669	{ 14, 2484, bwn_b2063_chantable_data[4] },
670	{ 34, 5170, bwn_b2063_chantable_data[5] },
671	{ 36, 5180, bwn_b2063_chantable_data[6] },
672	{ 38, 5190, bwn_b2063_chantable_data[7] },
673	{ 40, 5200, bwn_b2063_chantable_data[8] },
674	{ 42, 5210, bwn_b2063_chantable_data[9] },
675	{ 44, 5220, bwn_b2063_chantable_data[10] },
676	{ 46, 5230, bwn_b2063_chantable_data[11] },
677	{ 48, 5240, bwn_b2063_chantable_data[12] },
678	{ 52, 5260, bwn_b2063_chantable_data[13] },
679	{ 56, 5280, bwn_b2063_chantable_data[14] },
680	{ 60, 5300, bwn_b2063_chantable_data[14] },
681	{ 64, 5320, bwn_b2063_chantable_data[15] },
682	{ 100, 5500, bwn_b2063_chantable_data[16] },
683	{ 104, 5520, bwn_b2063_chantable_data[17] },
684	{ 108, 5540, bwn_b2063_chantable_data[18] },
685	{ 112, 5560, bwn_b2063_chantable_data[19] },
686	{ 116, 5580, bwn_b2063_chantable_data[20] },
687	{ 120, 5600, bwn_b2063_chantable_data[21] },
688	{ 124, 5620, bwn_b2063_chantable_data[21] },
689	{ 128, 5640, bwn_b2063_chantable_data[22] },
690	{ 132, 5660, bwn_b2063_chantable_data[22] },
691	{ 136, 5680, bwn_b2063_chantable_data[22] },
692	{ 140, 5700, bwn_b2063_chantable_data[23] },
693	{ 149, 5745, bwn_b2063_chantable_data[23] },
694	{ 153, 5765, bwn_b2063_chantable_data[23] },
695	{ 157, 5785, bwn_b2063_chantable_data[23] },
696	{ 161, 5805, bwn_b2063_chantable_data[23] },
697	{ 165, 5825, bwn_b2063_chantable_data[23] },
698	{ 184, 4920, bwn_b2063_chantable_data[24] },
699	{ 188, 4940, bwn_b2063_chantable_data[25] },
700	{ 192, 4960, bwn_b2063_chantable_data[26] },
701	{ 196, 4980, bwn_b2063_chantable_data[27] },
702	{ 200, 5000, bwn_b2063_chantable_data[28] },
703	{ 204, 5020, bwn_b2063_chantable_data[29] },
704	{ 208, 5040, bwn_b2063_chantable_data[30] },
705	{ 212, 5060, bwn_b2063_chantable_data[31] },
706	{ 216, 5080, bwn_b2063_chantable_data[32] }
707};
708
709static const uint8_t bwn_b2062_chantable_data[22][12] = {
710	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
711	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
721	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
731	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
732};
733
734static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
735	{ 1, 2412, bwn_b2062_chantable_data[0] },
736	{ 2, 2417, bwn_b2062_chantable_data[0] },
737	{ 3, 2422, bwn_b2062_chantable_data[0] },
738	{ 4, 2427, bwn_b2062_chantable_data[0] },
739	{ 5, 2432, bwn_b2062_chantable_data[0] },
740	{ 6, 2437, bwn_b2062_chantable_data[0] },
741	{ 7, 2442, bwn_b2062_chantable_data[0] },
742	{ 8, 2447, bwn_b2062_chantable_data[0] },
743	{ 9, 2452, bwn_b2062_chantable_data[0] },
744	{ 10, 2457, bwn_b2062_chantable_data[0] },
745	{ 11, 2462, bwn_b2062_chantable_data[0] },
746	{ 12, 2467, bwn_b2062_chantable_data[0] },
747	{ 13, 2472, bwn_b2062_chantable_data[0] },
748	{ 14, 2484, bwn_b2062_chantable_data[0] },
749	{ 34, 5170, bwn_b2062_chantable_data[1] },
750	{ 38, 5190, bwn_b2062_chantable_data[2] },
751	{ 42, 5210, bwn_b2062_chantable_data[2] },
752	{ 46, 5230, bwn_b2062_chantable_data[3] },
753	{ 36, 5180, bwn_b2062_chantable_data[4] },
754	{ 40, 5200, bwn_b2062_chantable_data[5] },
755	{ 44, 5220, bwn_b2062_chantable_data[6] },
756	{ 48, 5240, bwn_b2062_chantable_data[3] },
757	{ 52, 5260, bwn_b2062_chantable_data[3] },
758	{ 56, 5280, bwn_b2062_chantable_data[3] },
759	{ 60, 5300, bwn_b2062_chantable_data[7] },
760	{ 64, 5320, bwn_b2062_chantable_data[8] },
761	{ 100, 5500, bwn_b2062_chantable_data[9] },
762	{ 104, 5520, bwn_b2062_chantable_data[10] },
763	{ 108, 5540, bwn_b2062_chantable_data[10] },
764	{ 112, 5560, bwn_b2062_chantable_data[10] },
765	{ 116, 5580, bwn_b2062_chantable_data[11] },
766	{ 120, 5600, bwn_b2062_chantable_data[12] },
767	{ 124, 5620, bwn_b2062_chantable_data[12] },
768	{ 128, 5640, bwn_b2062_chantable_data[12] },
769	{ 132, 5660, bwn_b2062_chantable_data[12] },
770	{ 136, 5680, bwn_b2062_chantable_data[12] },
771	{ 140, 5700, bwn_b2062_chantable_data[12] },
772	{ 149, 5745, bwn_b2062_chantable_data[12] },
773	{ 153, 5765, bwn_b2062_chantable_data[12] },
774	{ 157, 5785, bwn_b2062_chantable_data[12] },
775	{ 161, 5805, bwn_b2062_chantable_data[12] },
776	{ 165, 5825, bwn_b2062_chantable_data[12] },
777	{ 184, 4920, bwn_b2062_chantable_data[13] },
778	{ 188, 4940, bwn_b2062_chantable_data[14] },
779	{ 192, 4960, bwn_b2062_chantable_data[15] },
780	{ 196, 4980, bwn_b2062_chantable_data[16] },
781	{ 200, 5000, bwn_b2062_chantable_data[17] },
782	{ 204, 5020, bwn_b2062_chantable_data[18] },
783	{ 208, 5040, bwn_b2062_chantable_data[19] },
784	{ 212, 5060, bwn_b2062_chantable_data[20] },
785	{ 216, 5080, bwn_b2062_chantable_data[21] }
786};
787
788/* for LP PHY */
789static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
790	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
791	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
792	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
793	{ 13, -66, 13 }, { 14, -66, 13 },
794};
795
796/* for LP PHY */
797static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
798	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
799	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
800	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
801	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
802	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
803	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
804	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
805	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
806	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
807	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
808	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
809	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
810	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
811};
812
813static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
814
815static const uint8_t bwn_tab_sigsq_tbl[] = {
816	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
817	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
818	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
819	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
821	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
822};
823
824static const uint8_t bwn_tab_pllfrac_tbl[] = {
825	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
826	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
827};
828
829static const uint16_t bwn_tabl_iqlocal_tbl[] = {
830	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
831	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
832	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
834	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
835	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
840	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
842};
843
844static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
845static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
846static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
847static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
848static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
849const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
850
851#define	VENDOR_LED_ACT(vendor)				\
852{							\
853	.vid = PCI_VENDOR_##vendor,			\
854	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
855}
856
857static const struct {
858	uint16_t	vid;
859	uint8_t		led_act[BWN_LED_MAX];
860} bwn_vendor_led_act[] = {
861	VENDOR_LED_ACT(COMPAQ),
862	VENDOR_LED_ACT(ASUSTEK)
863};
864
865static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
866	{ BWN_VENDOR_LED_ACT_DEFAULT };
867
868#undef VENDOR_LED_ACT
869
870static const struct {
871	int		on_dur;
872	int		off_dur;
873} bwn_led_duration[109] = {
874	[0]	= { 400, 100 },
875	[2]	= { 150, 75 },
876	[4]	= { 90, 45 },
877	[11]	= { 66, 34 },
878	[12]	= { 53, 26 },
879	[18]	= { 42, 21 },
880	[22]	= { 35, 17 },
881	[24]	= { 32, 16 },
882	[36]	= { 21, 10 },
883	[48]	= { 16, 8 },
884	[72]	= { 11, 5 },
885	[96]	= { 9, 4 },
886	[108]	= { 7, 3 }
887};
888
889static const uint16_t bwn_wme_shm_offsets[] = {
890	[0] = BWN_WME_BESTEFFORT,
891	[1] = BWN_WME_BACKGROUND,
892	[2] = BWN_WME_VOICE,
893	[3] = BWN_WME_VIDEO,
894};
895
896static const struct siba_devid bwn_devs[] = {
897	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
898	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
899	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
900	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
901	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
902	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
903	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
904	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
905	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
906};
907
908static int
909bwn_probe(device_t dev)
910{
911	int i;
912
913	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
914		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
915		    siba_get_device(dev) == bwn_devs[i].sd_device &&
916		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
917			return (BUS_PROBE_DEFAULT);
918	}
919
920	return (ENXIO);
921}
922
923static int
924bwn_attach(device_t dev)
925{
926	struct bwn_mac *mac;
927	struct bwn_softc *sc = device_get_softc(dev);
928	int error, i, msic, reg;
929
930	sc->sc_dev = dev;
931#ifdef BWN_DEBUG
932	sc->sc_debug = bwn_debug;
933#endif
934
935	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
936		error = bwn_attach_pre(sc);
937		if (error != 0)
938			return (error);
939		bwn_sprom_bugfixes(dev);
940		sc->sc_flags |= BWN_FLAG_ATTACHED;
941	}
942
943	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
944		if (siba_get_pci_device(dev) != 0x4313 &&
945		    siba_get_pci_device(dev) != 0x431a &&
946		    siba_get_pci_device(dev) != 0x4321) {
947			device_printf(sc->sc_dev,
948			    "skip 802.11 cores\n");
949			return (ENODEV);
950		}
951	}
952
953	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
954	    M_NOWAIT | M_ZERO);
955	if (mac == NULL)
956		return (ENOMEM);
957	mac->mac_sc = sc;
958	mac->mac_status = BWN_MAC_STATUS_UNINIT;
959	if (bwn_bfp != 0)
960		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
961
962	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
963	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
964	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
965
966	error = bwn_attach_core(mac);
967	if (error)
968		goto fail0;
969	bwn_led_attach(mac);
970
971	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
972	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
973	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
974	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
975	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
976	    mac->mac_phy.rf_rev);
977	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
978		device_printf(sc->sc_dev, "DMA (%d bits)\n",
979		    mac->mac_method.dma.dmatype);
980	else
981		device_printf(sc->sc_dev, "PIO\n");
982
983	/*
984	 * setup PCI resources and interrupt.
985	 */
986	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
987		msic = pci_msi_count(dev);
988		if (bootverbose)
989			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
990	} else
991		msic = 0;
992
993	mac->mac_intr_spec = bwn_res_spec_legacy;
994	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
995		if (pci_alloc_msi(dev, &msic) == 0) {
996			device_printf(sc->sc_dev,
997			    "Using %d MSI messages\n", msic);
998			mac->mac_intr_spec = bwn_res_spec_msi;
999			mac->mac_msi = 1;
1000		}
1001	}
1002
1003	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1004	    mac->mac_res_irq);
1005	if (error) {
1006		device_printf(sc->sc_dev,
1007		    "couldn't allocate IRQ resources (%d)\n", error);
1008		goto fail1;
1009	}
1010
1011	if (mac->mac_msi == 0)
1012		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1013		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1014		    &mac->mac_intrhand[0]);
1015	else {
1016		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1017			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1018			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1019			    &mac->mac_intrhand[i]);
1020			if (error != 0) {
1021				device_printf(sc->sc_dev,
1022				    "couldn't setup interrupt (%d)\n", error);
1023				break;
1024			}
1025		}
1026	}
1027
1028	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1029
1030	/*
1031	 * calls attach-post routine
1032	 */
1033	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1034		bwn_attach_post(sc);
1035
1036	return (0);
1037fail1:
1038	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1039		pci_release_msi(dev);
1040fail0:
1041	free(mac, M_DEVBUF);
1042	return (error);
1043}
1044
1045static int
1046bwn_is_valid_ether_addr(uint8_t *addr)
1047{
1048	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1049
1050	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1051		return (FALSE);
1052
1053	return (TRUE);
1054}
1055
1056static int
1057bwn_attach_post(struct bwn_softc *sc)
1058{
1059	struct ieee80211com *ic;
1060	struct ifnet *ifp = sc->sc_ifp;
1061
1062	ic = ifp->if_l2com;
1063	ic->ic_ifp = ifp;
1064	/* XXX not right but it's not used anywhere important */
1065	ic->ic_phytype = IEEE80211_T_OFDM;
1066	ic->ic_opmode = IEEE80211_M_STA;
1067	ic->ic_caps =
1068		  IEEE80211_C_STA		/* station mode supported */
1069		| IEEE80211_C_MONITOR		/* monitor mode */
1070		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1071		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1072		| IEEE80211_C_SHSLOT		/* short slot time supported */
1073		| IEEE80211_C_WME		/* WME/WMM supported */
1074		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1075		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1076		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1077		;
1078
1079	/* call MI attach routine. */
1080	ieee80211_ifattach(ic,
1081	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1082	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1083	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1084
1085	ic->ic_headroom = sizeof(struct bwn_txhdr);
1086
1087	/* override default methods */
1088	ic->ic_raw_xmit = bwn_raw_xmit;
1089	ic->ic_newassoc = bwn_newassoc;
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_node_alloc = bwn_node_alloc;
1095	sc->sc_node_cleanup = ic->ic_node_cleanup;
1096	ic->ic_node_cleanup = bwn_node_cleanup;
1097
1098	ic->ic_scan_start = bwn_scan_start;
1099	ic->ic_scan_end = bwn_scan_end;
1100	ic->ic_set_channel = bwn_set_channel;
1101
1102	ic->ic_vap_create = bwn_vap_create;
1103	ic->ic_vap_delete = bwn_vap_delete;
1104
1105	ieee80211_radiotap_attach(ic,
1106	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1107	    BWN_TX_RADIOTAP_PRESENT,
1108	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1109	    BWN_RX_RADIOTAP_PRESENT);
1110
1111	bwn_sysctl_node(sc);
1112
1113	if (bootverbose)
1114		ieee80211_announce(ic);
1115	return (0);
1116}
1117
1118static void
1119bwn_phy_detach(struct bwn_mac *mac)
1120{
1121
1122	if (mac->mac_phy.detach != NULL)
1123		mac->mac_phy.detach(mac);
1124}
1125
1126static int
1127bwn_detach(device_t dev)
1128{
1129	struct bwn_softc *sc = device_get_softc(dev);
1130	struct bwn_mac *mac = sc->sc_curmac;
1131	struct ifnet *ifp = sc->sc_ifp;
1132	struct ieee80211com *ic = ifp->if_l2com;
1133	int i;
1134
1135	sc->sc_flags |= BWN_FLAG_INVALID;
1136
1137	if (device_is_attached(sc->sc_dev)) {
1138		bwn_stop(sc, 1);
1139		bwn_dma_free(mac);
1140		callout_drain(&sc->sc_led_blink_ch);
1141		callout_drain(&sc->sc_rfswitch_ch);
1142		callout_drain(&sc->sc_task_ch);
1143		callout_drain(&sc->sc_watchdog_ch);
1144		bwn_phy_detach(mac);
1145		if (ifp != NULL) {
1146			ieee80211_draintask(ic, &mac->mac_hwreset);
1147			ieee80211_draintask(ic, &mac->mac_txpower);
1148			ieee80211_ifdetach(ic);
1149			if_free(ifp);
1150		}
1151	}
1152	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1153	taskqueue_free(sc->sc_tq);
1154
1155	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1156		if (mac->mac_intrhand[i] != NULL) {
1157			bus_teardown_intr(dev, mac->mac_res_irq[i],
1158			    mac->mac_intrhand[i]);
1159			mac->mac_intrhand[i] = NULL;
1160		}
1161	}
1162	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1163	if (mac->mac_msi != 0)
1164		pci_release_msi(dev);
1165
1166	BWN_LOCK_DESTROY(sc);
1167	return (0);
1168}
1169
1170static int
1171bwn_attach_pre(struct bwn_softc *sc)
1172{
1173	struct ifnet *ifp;
1174	int error = 0;
1175
1176	BWN_LOCK_INIT(sc);
1177	TAILQ_INIT(&sc->sc_maclist);
1178	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1179	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1180	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1181
1182	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1183		taskqueue_thread_enqueue, &sc->sc_tq);
1184	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1185		"%s taskq", device_get_nameunit(sc->sc_dev));
1186
1187	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1188	if (ifp == NULL) {
1189		device_printf(sc->sc_dev, "can not if_alloc()\n");
1190		error = ENOSPC;
1191		goto fail;
1192	}
1193
1194	/* set these up early for if_printf use */
1195	if_initname(ifp, device_get_name(sc->sc_dev),
1196	    device_get_unit(sc->sc_dev));
1197
1198	ifp->if_softc = sc;
1199	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1200	ifp->if_init = bwn_init;
1201	ifp->if_ioctl = bwn_ioctl;
1202	ifp->if_start = bwn_start;
1203	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1204	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1205	IFQ_SET_READY(&ifp->if_snd);
1206
1207	return (0);
1208
1209fail:	BWN_LOCK_DESTROY(sc);
1210	return (error);
1211}
1212
1213static void
1214bwn_sprom_bugfixes(device_t dev)
1215{
1216#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1217	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1218	 (siba_get_pci_device(dev) == _device) &&			\
1219	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1220	 (siba_get_pci_subdevice(dev) == _subdevice))
1221
1222	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1223	    siba_get_pci_subdevice(dev) == 0x4e &&
1224	    siba_get_pci_revid(dev) > 0x40)
1225		siba_sprom_set_bf_lo(dev,
1226		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1227	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1228	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1229		siba_sprom_set_bf_lo(dev,
1230		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1231	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1232		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1233		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1234		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1235		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1236		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1237		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1238		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1239			siba_sprom_set_bf_lo(dev,
1240			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1241	}
1242#undef	BWN_ISDEV
1243}
1244
1245static int
1246bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1247{
1248#define	IS_RUNNING(ifp) \
1249	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1250	struct bwn_softc *sc = ifp->if_softc;
1251	struct ieee80211com *ic = ifp->if_l2com;
1252	struct ifreq *ifr = (struct ifreq *)data;
1253	int error = 0, startall;
1254
1255	switch (cmd) {
1256	case SIOCSIFFLAGS:
1257		startall = 0;
1258		if (IS_RUNNING(ifp)) {
1259			bwn_update_promisc(ifp);
1260		} else if (ifp->if_flags & IFF_UP) {
1261			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1262				bwn_init(sc);
1263				startall = 1;
1264			}
1265		} else
1266			bwn_stop(sc, 1);
1267		if (startall)
1268			ieee80211_start_all(ic);
1269		break;
1270	case SIOCGIFMEDIA:
1271		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1272		break;
1273	case SIOCGIFADDR:
1274		error = ether_ioctl(ifp, cmd, data);
1275		break;
1276	default:
1277		error = EINVAL;
1278		break;
1279	}
1280	return (error);
1281}
1282
1283static void
1284bwn_start(struct ifnet *ifp)
1285{
1286	struct bwn_softc *sc = ifp->if_softc;
1287
1288	BWN_LOCK(sc);
1289	bwn_start_locked(ifp);
1290	BWN_UNLOCK(sc);
1291}
1292
1293static void
1294bwn_start_locked(struct ifnet *ifp)
1295{
1296	struct bwn_softc *sc = ifp->if_softc;
1297	struct bwn_mac *mac = sc->sc_curmac;
1298	struct ieee80211_frame *wh;
1299	struct ieee80211_node *ni;
1300	struct ieee80211_key *k;
1301	struct mbuf *m;
1302
1303	BWN_ASSERT_LOCKED(sc);
1304
1305	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1306	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1307		return;
1308
1309	for (;;) {
1310		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1311		if (m == NULL)
1312			break;
1313
1314		if (bwn_tx_isfull(sc, m))
1315			break;
1316		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1317		if (ni == NULL) {
1318			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1319			m_freem(m);
1320			ifp->if_oerrors++;
1321			continue;
1322		}
1323		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1324		wh = mtod(m, struct ieee80211_frame *);
1325		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1326			k = ieee80211_crypto_encap(ni, m);
1327			if (k == NULL) {
1328				ieee80211_free_node(ni);
1329				m_freem(m);
1330				ifp->if_oerrors++;
1331				continue;
1332			}
1333		}
1334		wh = NULL;	/* Catch any invalid use */
1335
1336		if (bwn_tx_start(sc, ni, m) != 0) {
1337			if (ni != NULL)
1338				ieee80211_free_node(ni);
1339			ifp->if_oerrors++;
1340			continue;
1341		}
1342
1343		sc->sc_watchdog_timer = 5;
1344	}
1345}
1346
1347static int
1348bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1349{
1350	struct bwn_dma_ring *dr;
1351	struct bwn_mac *mac = sc->sc_curmac;
1352	struct bwn_pio_txqueue *tq;
1353	struct ifnet *ifp = sc->sc_ifp;
1354	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1355
1356	BWN_ASSERT_LOCKED(sc);
1357
1358	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1359		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1360		if (dr->dr_stop == 1 ||
1361		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1362			dr->dr_stop = 1;
1363			goto full;
1364		}
1365	} else {
1366		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1367		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1368		    pktlen > (tq->tq_size - tq->tq_used)) {
1369			tq->tq_stop = 1;
1370			goto full;
1371		}
1372	}
1373	return (0);
1374full:
1375	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1376	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1377	return (1);
1378}
1379
1380static int
1381bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1382{
1383	struct bwn_mac *mac = sc->sc_curmac;
1384	int error;
1385
1386	BWN_ASSERT_LOCKED(sc);
1387
1388	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1389		m_freem(m);
1390		return (ENXIO);
1391	}
1392
1393	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1394	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1395	if (error) {
1396		m_freem(m);
1397		return (error);
1398	}
1399	return (0);
1400}
1401
1402static int
1403bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1404{
1405	struct bwn_pio_txpkt *tp;
1406	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1407	struct bwn_softc *sc = mac->mac_sc;
1408	struct bwn_txhdr txhdr;
1409	struct mbuf *m_new;
1410	uint32_t ctl32;
1411	int error;
1412	uint16_t ctl16;
1413
1414	BWN_ASSERT_LOCKED(sc);
1415
1416	/* XXX TODO send packets after DTIM */
1417
1418	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1419	tp = TAILQ_FIRST(&tq->tq_pktlist);
1420	tp->tp_ni = ni;
1421	tp->tp_m = m;
1422
1423	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1424	if (error) {
1425		device_printf(sc->sc_dev, "tx fail\n");
1426		return (error);
1427	}
1428
1429	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1430	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1431	tq->tq_free--;
1432
1433	if (siba_get_revid(sc->sc_dev) >= 8) {
1434		/*
1435		 * XXX please removes m_defrag(9)
1436		 */
1437		m_new = m_defrag(m, M_DONTWAIT);
1438		if (m_new == NULL) {
1439			device_printf(sc->sc_dev,
1440			    "%s: can't defrag TX buffer\n",
1441			    __func__);
1442			return (ENOBUFS);
1443		}
1444		if (m_new->m_next != NULL)
1445			device_printf(sc->sc_dev,
1446			    "TODO: fragmented packets for PIO\n");
1447		tp->tp_m = m_new;
1448
1449		/* send HEADER */
1450		ctl32 = bwn_pio_write_multi_4(mac, tq,
1451		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1452			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1453		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1454		/* send BODY */
1455		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1456		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1457		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1458		    ctl32 | BWN_PIO8_TXCTL_EOF);
1459	} else {
1460		ctl16 = bwn_pio_write_multi_2(mac, tq,
1461		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1462			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1463		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1464		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1465		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1466		    ctl16 | BWN_PIO_TXCTL_EOF);
1467	}
1468
1469	return (0);
1470}
1471
1472static struct bwn_pio_txqueue *
1473bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1474{
1475
1476	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1477		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478
1479	switch (prio) {
1480	case 0:
1481		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482	case 1:
1483		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1484	case 2:
1485		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1486	case 3:
1487		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1488	}
1489	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1490	return (NULL);
1491}
1492
1493static int
1494bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1495{
1496#define	BWN_GET_TXHDRCACHE(slot)					\
1497	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1498	struct bwn_dma *dma = &mac->mac_method.dma;
1499	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1500	struct bwn_dmadesc_generic *desc;
1501	struct bwn_dmadesc_meta *mt;
1502	struct bwn_softc *sc = mac->mac_sc;
1503	struct ifnet *ifp = sc->sc_ifp;
1504	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1505	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1506
1507	BWN_ASSERT_LOCKED(sc);
1508	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1509
1510	/* XXX send after DTIM */
1511
1512	slot = bwn_dma_getslot(dr);
1513	dr->getdesc(dr, slot, &desc, &mt);
1514	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1515	    ("%s:%d: fail", __func__, __LINE__));
1516
1517	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1518	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1519	    BWN_DMA_COOKIE(dr, slot));
1520	if (error)
1521		goto fail;
1522	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1523	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1524	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1525	if (error) {
1526		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1527		    __func__, error);
1528		goto fail;
1529	}
1530	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1531	    BUS_DMASYNC_PREWRITE);
1532	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1533	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1534	    BUS_DMASYNC_PREWRITE);
1535
1536	slot = bwn_dma_getslot(dr);
1537	dr->getdesc(dr, slot, &desc, &mt);
1538	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1539	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1540	mt->mt_m = m;
1541	mt->mt_ni = ni;
1542
1543	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1544	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1545	if (error && error != EFBIG) {
1546		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1547		    __func__, error);
1548		goto fail;
1549	}
1550	if (error) {    /* error == EFBIG */
1551		struct mbuf *m_new;
1552
1553		m_new = m_defrag(m, M_DONTWAIT);
1554		if (m_new == NULL) {
1555			if_printf(ifp, "%s: can't defrag TX buffer\n",
1556			    __func__);
1557			error = ENOBUFS;
1558			goto fail;
1559		} else {
1560			m = m_new;
1561		}
1562
1563		mt->mt_m = m;
1564		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1565		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1566		if (error) {
1567			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1568			    __func__, error);
1569			goto fail;
1570		}
1571	}
1572	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1573	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1574	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1575	    BUS_DMASYNC_PREWRITE);
1576
1577	/* XXX send after DTIM */
1578
1579	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1580	return (0);
1581fail:
1582	dr->dr_curslot = backup[0];
1583	dr->dr_usedslot = backup[1];
1584	return (error);
1585#undef BWN_GET_TXHDRCACHE
1586}
1587
1588static void
1589bwn_watchdog(void *arg)
1590{
1591	struct bwn_softc *sc = arg;
1592	struct ifnet *ifp = sc->sc_ifp;
1593
1594	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1595		if_printf(ifp, "device timeout\n");
1596		ifp->if_oerrors++;
1597	}
1598	callout_schedule(&sc->sc_watchdog_ch, hz);
1599}
1600
1601static int
1602bwn_attach_core(struct bwn_mac *mac)
1603{
1604	struct bwn_softc *sc = mac->mac_sc;
1605	int error, have_bg = 0, have_a = 0;
1606	uint32_t high;
1607
1608	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1609	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1610
1611	siba_powerup(sc->sc_dev, 0);
1612
1613	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1614	bwn_reset_core(mac,
1615	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1616	error = bwn_phy_getinfo(mac, high);
1617	if (error)
1618		goto fail;
1619
1620	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1621	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1622	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1623	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1624	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1625		have_a = have_bg = 0;
1626		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1627			have_a = 1;
1628		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1629		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1630		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1631			have_bg = 1;
1632		else
1633			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1634			    mac->mac_phy.type));
1635	}
1636	/* XXX turns off PHY A because it's not supported */
1637	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1638	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1639		have_a = 0;
1640		have_bg = 1;
1641	}
1642
1643	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1644		mac->mac_phy.attach = bwn_phy_g_attach;
1645		mac->mac_phy.detach = bwn_phy_g_detach;
1646		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1647		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1648		mac->mac_phy.init = bwn_phy_g_init;
1649		mac->mac_phy.exit = bwn_phy_g_exit;
1650		mac->mac_phy.phy_read = bwn_phy_g_read;
1651		mac->mac_phy.phy_write = bwn_phy_g_write;
1652		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1653		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1654		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1655		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1656		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1657		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1658		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1659		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1660		mac->mac_phy.set_im = bwn_phy_g_im;
1661		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1662		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1663		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1664		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1665	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1666		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1667		mac->mac_phy.init = bwn_phy_lp_init;
1668		mac->mac_phy.phy_read = bwn_phy_lp_read;
1669		mac->mac_phy.phy_write = bwn_phy_lp_write;
1670		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1671		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1672		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1673		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1674		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1675		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1676		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1677		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1678		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1679	} else {
1680		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1681		    mac->mac_phy.type);
1682		error = ENXIO;
1683		goto fail;
1684	}
1685
1686	mac->mac_phy.gmode = have_bg;
1687	if (mac->mac_phy.attach != NULL) {
1688		error = mac->mac_phy.attach(mac);
1689		if (error) {
1690			device_printf(sc->sc_dev, "failed\n");
1691			goto fail;
1692		}
1693	}
1694
1695	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1696
1697	error = bwn_chiptest(mac);
1698	if (error)
1699		goto fail;
1700	error = bwn_setup_channels(mac, have_bg, have_a);
1701	if (error) {
1702		device_printf(sc->sc_dev, "failed to setup channels\n");
1703		goto fail;
1704	}
1705
1706	if (sc->sc_curmac == NULL)
1707		sc->sc_curmac = mac;
1708
1709	error = bwn_dma_attach(mac);
1710	if (error != 0) {
1711		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1712		goto fail;
1713	}
1714
1715	mac->mac_phy.switch_analog(mac, 0);
1716
1717	siba_dev_down(sc->sc_dev, 0);
1718fail:
1719	siba_powerdown(sc->sc_dev);
1720	return (error);
1721}
1722
1723static void
1724bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1725{
1726	struct bwn_softc *sc = mac->mac_sc;
1727	uint32_t low, ctl;
1728
1729	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1730
1731	siba_dev_up(sc->sc_dev, flags);
1732	DELAY(2000);
1733
1734	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1735	    ~BWN_TGSLOW_PHYRESET;
1736	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1737	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1738	DELAY(1000);
1739	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1740	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1741	DELAY(1000);
1742
1743	if (mac->mac_phy.switch_analog != NULL)
1744		mac->mac_phy.switch_analog(mac, 1);
1745
1746	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1747	if (flags & BWN_TGSLOW_SUPPORT_G)
1748		ctl |= BWN_MACCTL_GMODE;
1749	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1750}
1751
1752static int
1753bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1754{
1755	struct bwn_phy *phy = &mac->mac_phy;
1756	struct bwn_softc *sc = mac->mac_sc;
1757	uint32_t tmp;
1758
1759	/* PHY */
1760	tmp = BWN_READ_2(mac, BWN_PHYVER);
1761	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1762	phy->rf_on = 1;
1763	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1764	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1765	phy->rev = (tmp & BWN_PHYVER_VERSION);
1766	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1767	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1768		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1769	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1770	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1771	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1772		goto unsupphy;
1773
1774	/* RADIO */
1775	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1776		if (siba_get_chiprev(sc->sc_dev) == 0)
1777			tmp = 0x3205017f;
1778		else if (siba_get_chiprev(sc->sc_dev) == 1)
1779			tmp = 0x4205017f;
1780		else
1781			tmp = 0x5205017f;
1782	} else {
1783		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1784		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1785		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1786		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1787	}
1788	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1789	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1790	phy->rf_manuf = (tmp & 0x00000fff);
1791	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1792		goto unsupradio;
1793	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1794	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1795	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1796	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1797	    (phy->type == BWN_PHYTYPE_N &&
1798	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1799	    (phy->type == BWN_PHYTYPE_LP &&
1800	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1801		goto unsupradio;
1802
1803	return (0);
1804unsupphy:
1805	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1806	    "analog %#x)\n",
1807	    phy->type, phy->rev, phy->analog);
1808	return (ENXIO);
1809unsupradio:
1810	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1811	    "rev %#x)\n",
1812	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1813	return (ENXIO);
1814}
1815
1816static int
1817bwn_chiptest(struct bwn_mac *mac)
1818{
1819#define	TESTVAL0	0x55aaaa55
1820#define	TESTVAL1	0xaa5555aa
1821	struct bwn_softc *sc = mac->mac_sc;
1822	uint32_t v, backup;
1823
1824	BWN_LOCK(sc);
1825
1826	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1827
1828	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1829	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1830		goto error;
1831	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1832	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1833		goto error;
1834
1835	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1836
1837	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1838	    (siba_get_revid(sc->sc_dev) <= 10)) {
1839		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1840		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1841		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1842			goto error;
1843		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1844			goto error;
1845	}
1846	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1847
1848	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1849	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1850		goto error;
1851
1852	BWN_UNLOCK(sc);
1853	return (0);
1854error:
1855	BWN_UNLOCK(sc);
1856	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1857	return (ENODEV);
1858}
1859
1860#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1861#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1862
1863static int
1864bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1865{
1866	struct bwn_softc *sc = mac->mac_sc;
1867	struct ifnet *ifp = sc->sc_ifp;
1868	struct ieee80211com *ic = ifp->if_l2com;
1869
1870	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1871	ic->ic_nchans = 0;
1872
1873	if (have_bg)
1874		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1876	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1877		if (have_a)
1878			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1879			    &ic->ic_nchans, &bwn_chantable_n,
1880			    IEEE80211_CHAN_HTA);
1881	} else {
1882		if (have_a)
1883			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1884			    &ic->ic_nchans, &bwn_chantable_a,
1885			    IEEE80211_CHAN_A);
1886	}
1887
1888	mac->mac_phy.supports_2ghz = have_bg;
1889	mac->mac_phy.supports_5ghz = have_a;
1890
1891	return (ic->ic_nchans == 0 ? ENXIO : 0);
1892}
1893
1894static uint32_t
1895bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1896{
1897	uint32_t ret;
1898
1899	BWN_ASSERT_LOCKED(mac->mac_sc);
1900
1901	if (way == BWN_SHARED) {
1902		KASSERT((offset & 0x0001) == 0,
1903		    ("%s:%d warn", __func__, __LINE__));
1904		if (offset & 0x0003) {
1905			bwn_shm_ctlword(mac, way, offset >> 2);
1906			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1907			ret <<= 16;
1908			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1909			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1910			goto out;
1911		}
1912		offset >>= 2;
1913	}
1914	bwn_shm_ctlword(mac, way, offset);
1915	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1916out:
1917	return (ret);
1918}
1919
1920static uint16_t
1921bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1922{
1923	uint16_t ret;
1924
1925	BWN_ASSERT_LOCKED(mac->mac_sc);
1926
1927	if (way == BWN_SHARED) {
1928		KASSERT((offset & 0x0001) == 0,
1929		    ("%s:%d warn", __func__, __LINE__));
1930		if (offset & 0x0003) {
1931			bwn_shm_ctlword(mac, way, offset >> 2);
1932			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1933			goto out;
1934		}
1935		offset >>= 2;
1936	}
1937	bwn_shm_ctlword(mac, way, offset);
1938	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1939out:
1940
1941	return (ret);
1942}
1943
1944static void
1945bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1946    uint16_t offset)
1947{
1948	uint32_t control;
1949
1950	control = way;
1951	control <<= 16;
1952	control |= offset;
1953	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1954}
1955
1956static void
1957bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1958    uint32_t value)
1959{
1960	BWN_ASSERT_LOCKED(mac->mac_sc);
1961
1962	if (way == BWN_SHARED) {
1963		KASSERT((offset & 0x0001) == 0,
1964		    ("%s:%d warn", __func__, __LINE__));
1965		if (offset & 0x0003) {
1966			bwn_shm_ctlword(mac, way, offset >> 2);
1967			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1968				    (value >> 16) & 0xffff);
1969			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1970			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1971			return;
1972		}
1973		offset >>= 2;
1974	}
1975	bwn_shm_ctlword(mac, way, offset);
1976	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1977}
1978
1979static void
1980bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1981    uint16_t value)
1982{
1983	BWN_ASSERT_LOCKED(mac->mac_sc);
1984
1985	if (way == BWN_SHARED) {
1986		KASSERT((offset & 0x0001) == 0,
1987		    ("%s:%d warn", __func__, __LINE__));
1988		if (offset & 0x0003) {
1989			bwn_shm_ctlword(mac, way, offset >> 2);
1990			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1991			return;
1992		}
1993		offset >>= 2;
1994	}
1995	bwn_shm_ctlword(mac, way, offset);
1996	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1997}
1998
1999static void
2000bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2001    int txpow)
2002{
2003
2004	c->ic_freq = freq;
2005	c->ic_flags = flags;
2006	c->ic_ieee = ieee;
2007	c->ic_minpower = 0;
2008	c->ic_maxpower = 2 * txpow;
2009	c->ic_maxregpower = txpow;
2010}
2011
2012static void
2013bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2014    const struct bwn_channelinfo *ci, int flags)
2015{
2016	struct ieee80211_channel *c;
2017	int i;
2018
2019	c = &chans[*nchans];
2020
2021	for (i = 0; i < ci->nchannels; i++) {
2022		const struct bwn_channel *hc;
2023
2024		hc = &ci->channels[i];
2025		if (*nchans >= maxchans)
2026			break;
2027		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2028		c++, (*nchans)++;
2029		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2030			/* g channel have a separate b-only entry */
2031			if (*nchans >= maxchans)
2032				break;
2033			c[0] = c[-1];
2034			c[-1].ic_flags = IEEE80211_CHAN_B;
2035			c++, (*nchans)++;
2036		}
2037		if (flags == IEEE80211_CHAN_HTG) {
2038			/* HT g channel have a separate g-only entry */
2039			if (*nchans >= maxchans)
2040				break;
2041			c[-1].ic_flags = IEEE80211_CHAN_G;
2042			c[0] = c[-1];
2043			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2044			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2045			c++, (*nchans)++;
2046		}
2047		if (flags == IEEE80211_CHAN_HTA) {
2048			/* HT a channel have a separate a-only entry */
2049			if (*nchans >= maxchans)
2050				break;
2051			c[-1].ic_flags = IEEE80211_CHAN_A;
2052			c[0] = c[-1];
2053			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2054			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2055			c++, (*nchans)++;
2056		}
2057	}
2058}
2059
2060static int
2061bwn_phy_g_attach(struct bwn_mac *mac)
2062{
2063	struct bwn_softc *sc = mac->mac_sc;
2064	struct bwn_phy *phy = &mac->mac_phy;
2065	struct bwn_phy_g *pg = &phy->phy_g;
2066	unsigned int i;
2067	int16_t pab0, pab1, pab2;
2068	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2069	int8_t bg;
2070
2071	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2072	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2073	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2074	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2075
2076	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2077		device_printf(sc->sc_dev, "not supported anymore\n");
2078
2079	pg->pg_flags = 0;
2080	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2081	    pab2 == -1) {
2082		pg->pg_idletssi = 52;
2083		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2084		return (0);
2085	}
2086
2087	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2088	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2089	if (pg->pg_tssi2dbm == NULL) {
2090		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2091		return (ENOMEM);
2092	}
2093	for (i = 0; i < 64; i++) {
2094		int32_t m1, m2, f, q, delta;
2095		int8_t j = 0;
2096
2097		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2098		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2099		f = 256;
2100
2101		do {
2102			if (j > 15) {
2103				device_printf(sc->sc_dev,
2104				    "failed to generate tssi2dBm\n");
2105				free(pg->pg_tssi2dbm, M_DEVBUF);
2106				return (ENOMEM);
2107			}
2108			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2109			    f, 2048);
2110			delta = abs(q - f);
2111			f = q;
2112			j++;
2113		} while (delta >= 2);
2114
2115		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2116		    128);
2117	}
2118
2119	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2120	return (0);
2121}
2122
2123static void
2124bwn_phy_g_detach(struct bwn_mac *mac)
2125{
2126	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2127
2128	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2129		free(pg->pg_tssi2dbm, M_DEVBUF);
2130		pg->pg_tssi2dbm = NULL;
2131	}
2132	pg->pg_flags = 0;
2133}
2134
2135static void
2136bwn_phy_g_init_pre(struct bwn_mac *mac)
2137{
2138	struct bwn_phy *phy = &mac->mac_phy;
2139	struct bwn_phy_g *pg = &phy->phy_g;
2140	void *tssi2dbm;
2141	int idletssi;
2142	unsigned int i;
2143
2144	tssi2dbm = pg->pg_tssi2dbm;
2145	idletssi = pg->pg_idletssi;
2146
2147	memset(pg, 0, sizeof(*pg));
2148
2149	pg->pg_tssi2dbm = tssi2dbm;
2150	pg->pg_idletssi = idletssi;
2151
2152	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2153
2154	for (i = 0; i < N(pg->pg_nrssi); i++)
2155		pg->pg_nrssi[i] = -1000;
2156	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2157		pg->pg_nrssi_lt[i] = i;
2158	pg->pg_lofcal = 0xffff;
2159	pg->pg_initval = 0xffff;
2160	pg->pg_immode = BWN_IMMODE_NONE;
2161	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2162	pg->pg_avgtssi = 0xff;
2163
2164	pg->pg_loctl.tx_bias = 0xff;
2165	TAILQ_INIT(&pg->pg_loctl.calib_list);
2166}
2167
2168static int
2169bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2170{
2171	struct bwn_phy *phy = &mac->mac_phy;
2172	struct bwn_phy_g *pg = &phy->phy_g;
2173	struct bwn_softc *sc = mac->mac_sc;
2174	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2175	static const struct bwn_rfatt rfatt0[] = {
2176		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2177		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2178		{ 3, 1 }, { 4, 1 }
2179	};
2180	static const struct bwn_rfatt rfatt1[] = {
2181		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2182		{ 14, 1 }
2183	};
2184	static const struct bwn_rfatt rfatt2[] = {
2185		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2186		{ 9, 1 }
2187	};
2188	static const struct bwn_bbatt bbatt_0[] = {
2189		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2190	};
2191
2192	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2193
2194	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2195		pg->pg_bbatt.att = 0;
2196	else
2197		pg->pg_bbatt.att = 2;
2198
2199	/* prepare Radio Attenuation */
2200	pg->pg_rfatt.padmix = 0;
2201
2202	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2203	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2204		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2205			pg->pg_rfatt.att = 2;
2206			goto done;
2207		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2208			pg->pg_rfatt.att = 3;
2209			goto done;
2210		}
2211	}
2212
2213	if (phy->type == BWN_PHYTYPE_A) {
2214		pg->pg_rfatt.att = 0x60;
2215		goto done;
2216	}
2217
2218	switch (phy->rf_ver) {
2219	case 0x2050:
2220		switch (phy->rf_rev) {
2221		case 0:
2222			pg->pg_rfatt.att = 5;
2223			goto done;
2224		case 1:
2225			if (phy->type == BWN_PHYTYPE_G) {
2226				if (siba_get_pci_subvendor(sc->sc_dev) ==
2227				    SIBA_BOARDVENDOR_BCM &&
2228				    siba_get_pci_subdevice(sc->sc_dev) ==
2229				    SIBA_BOARD_BCM4309G &&
2230				    siba_get_pci_revid(sc->sc_dev) >= 30)
2231					pg->pg_rfatt.att = 3;
2232				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2233				    SIBA_BOARDVENDOR_BCM &&
2234				    siba_get_pci_subdevice(sc->sc_dev) ==
2235				    SIBA_BOARD_BU4306)
2236					pg->pg_rfatt.att = 3;
2237				else
2238					pg->pg_rfatt.att = 1;
2239			} else {
2240				if (siba_get_pci_subvendor(sc->sc_dev) ==
2241				    SIBA_BOARDVENDOR_BCM &&
2242				    siba_get_pci_subdevice(sc->sc_dev) ==
2243				    SIBA_BOARD_BCM4309G &&
2244				    siba_get_pci_revid(sc->sc_dev) >= 30)
2245					pg->pg_rfatt.att = 7;
2246				else
2247					pg->pg_rfatt.att = 6;
2248			}
2249			goto done;
2250		case 2:
2251			if (phy->type == BWN_PHYTYPE_G) {
2252				if (siba_get_pci_subvendor(sc->sc_dev) ==
2253				    SIBA_BOARDVENDOR_BCM &&
2254				    siba_get_pci_subdevice(sc->sc_dev) ==
2255				    SIBA_BOARD_BCM4309G &&
2256				    siba_get_pci_revid(sc->sc_dev) >= 30)
2257					pg->pg_rfatt.att = 3;
2258				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2259				    SIBA_BOARDVENDOR_BCM &&
2260				    siba_get_pci_subdevice(sc->sc_dev) ==
2261				    SIBA_BOARD_BU4306)
2262					pg->pg_rfatt.att = 5;
2263				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2264					pg->pg_rfatt.att = 4;
2265				else
2266					pg->pg_rfatt.att = 3;
2267			} else
2268				pg->pg_rfatt.att = 6;
2269			goto done;
2270		case 3:
2271			pg->pg_rfatt.att = 5;
2272			goto done;
2273		case 4:
2274		case 5:
2275			pg->pg_rfatt.att = 1;
2276			goto done;
2277		case 6:
2278		case 7:
2279			pg->pg_rfatt.att = 5;
2280			goto done;
2281		case 8:
2282			pg->pg_rfatt.att = 0xa;
2283			pg->pg_rfatt.padmix = 1;
2284			goto done;
2285		case 9:
2286		default:
2287			pg->pg_rfatt.att = 5;
2288			goto done;
2289		}
2290		break;
2291	case 0x2053:
2292		switch (phy->rf_rev) {
2293		case 1:
2294			pg->pg_rfatt.att = 6;
2295			goto done;
2296		}
2297		break;
2298	}
2299	pg->pg_rfatt.att = 5;
2300done:
2301	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2302
2303	if (!bwn_has_hwpctl(mac)) {
2304		lo->rfatt.array = rfatt0;
2305		lo->rfatt.len = N(rfatt0);
2306		lo->rfatt.min = 0;
2307		lo->rfatt.max = 9;
2308		goto genbbatt;
2309	}
2310	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2311		lo->rfatt.array = rfatt1;
2312		lo->rfatt.len = N(rfatt1);
2313		lo->rfatt.min = 0;
2314		lo->rfatt.max = 14;
2315		goto genbbatt;
2316	}
2317	lo->rfatt.array = rfatt2;
2318	lo->rfatt.len = N(rfatt2);
2319	lo->rfatt.min = 0;
2320	lo->rfatt.max = 9;
2321genbbatt:
2322	lo->bbatt.array = bbatt_0;
2323	lo->bbatt.len = N(bbatt_0);
2324	lo->bbatt.min = 0;
2325	lo->bbatt.max = 8;
2326
2327	BWN_READ_4(mac, BWN_MACCTL);
2328	if (phy->rev == 1) {
2329		phy->gmode = 0;
2330		bwn_reset_core(mac, 0);
2331		bwn_phy_g_init_sub(mac);
2332		phy->gmode = 1;
2333		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2334	}
2335	return (0);
2336}
2337
2338static uint16_t
2339bwn_phy_g_txctl(struct bwn_mac *mac)
2340{
2341	struct bwn_phy *phy = &mac->mac_phy;
2342
2343	if (phy->rf_ver != 0x2050)
2344		return (0);
2345	if (phy->rf_rev == 1)
2346		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2347	if (phy->rf_rev < 6)
2348		return (BWN_TXCTL_PA2DB);
2349	if (phy->rf_rev == 8)
2350		return (BWN_TXCTL_TXMIX);
2351	return (0);
2352}
2353
2354static int
2355bwn_phy_g_init(struct bwn_mac *mac)
2356{
2357
2358	bwn_phy_g_init_sub(mac);
2359	return (0);
2360}
2361
2362static void
2363bwn_phy_g_exit(struct bwn_mac *mac)
2364{
2365	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2366	struct bwn_lo_calib *cal, *tmp;
2367
2368	if (lo == NULL)
2369		return;
2370	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2371		TAILQ_REMOVE(&lo->calib_list, cal, list);
2372		free(cal, M_DEVBUF);
2373	}
2374}
2375
2376static uint16_t
2377bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2378{
2379
2380	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2381	return (BWN_READ_2(mac, BWN_PHYDATA));
2382}
2383
2384static void
2385bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2386{
2387
2388	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2389	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2390}
2391
2392static uint16_t
2393bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2394{
2395
2396	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2397	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2398	return (BWN_READ_2(mac, BWN_RFDATALO));
2399}
2400
2401static void
2402bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2403{
2404
2405	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2406	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2407	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2408}
2409
2410static int
2411bwn_phy_g_hwpctl(struct bwn_mac *mac)
2412{
2413
2414	return (mac->mac_phy.rev >= 6);
2415}
2416
2417static void
2418bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2419{
2420	struct bwn_phy *phy = &mac->mac_phy;
2421	struct bwn_phy_g *pg = &phy->phy_g;
2422	unsigned int channel;
2423	uint16_t rfover, rfoverval;
2424
2425	if (on) {
2426		if (phy->rf_on)
2427			return;
2428
2429		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2430		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2431		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2432		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2433			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2434			    pg->pg_radioctx_over);
2435			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2436			    pg->pg_radioctx_overval);
2437			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2438		}
2439		channel = phy->chan;
2440		bwn_phy_g_switch_chan(mac, 6, 1);
2441		bwn_phy_g_switch_chan(mac, channel, 0);
2442		return;
2443	}
2444
2445	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2446	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2447	pg->pg_radioctx_over = rfover;
2448	pg->pg_radioctx_overval = rfoverval;
2449	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2450	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2451	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2452}
2453
2454static int
2455bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2456{
2457
2458	if ((newchan < 1) || (newchan > 14))
2459		return (EINVAL);
2460	bwn_phy_g_switch_chan(mac, newchan, 0);
2461
2462	return (0);
2463}
2464
2465static uint32_t
2466bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2467{
2468
2469	return (1);
2470}
2471
2472static void
2473bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2474{
2475	struct bwn_phy *phy = &mac->mac_phy;
2476	uint64_t hf;
2477	int autodiv = 0;
2478	uint16_t tmp;
2479
2480	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2481		autodiv = 1;
2482
2483	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2484	bwn_hf_write(mac, hf);
2485
2486	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2487	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2488	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2489		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2490
2491	if (autodiv) {
2492		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2493		if (antenna == BWN_ANTAUTO1)
2494			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2495		else
2496			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2497		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2498	}
2499	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2500	if (autodiv)
2501		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2502	else
2503		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2504	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2505	if (phy->rev >= 2) {
2506		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2507		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2508		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2509		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2510		    0x15);
2511		if (phy->rev == 2)
2512			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2513		else
2514			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2515			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2516			    8);
2517	}
2518	if (phy->rev >= 6)
2519		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2520
2521	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2522	bwn_hf_write(mac, hf);
2523}
2524
2525static int
2526bwn_phy_g_im(struct bwn_mac *mac, int mode)
2527{
2528	struct bwn_phy *phy = &mac->mac_phy;
2529	struct bwn_phy_g *pg = &phy->phy_g;
2530
2531	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2532	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2533
2534	if (phy->rev == 0 || !phy->gmode)
2535		return (ENODEV);
2536
2537	pg->pg_aci_wlan_automatic = 0;
2538	return (0);
2539}
2540
2541static int
2542bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2543{
2544	struct bwn_phy *phy = &mac->mac_phy;
2545	struct bwn_phy_g *pg = &phy->phy_g;
2546	struct bwn_softc *sc = mac->mac_sc;
2547	unsigned int tssi;
2548	int cck, ofdm;
2549	int power;
2550	int rfatt, bbatt;
2551	unsigned int max;
2552
2553	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2554
2555	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2556	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2557	if (cck < 0 && ofdm < 0) {
2558		if (ignore_tssi == 0)
2559			return (BWN_TXPWR_RES_DONE);
2560		cck = 0;
2561		ofdm = 0;
2562	}
2563	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2564	if (pg->pg_avgtssi != 0xff)
2565		tssi = (tssi + pg->pg_avgtssi) / 2;
2566	pg->pg_avgtssi = tssi;
2567	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2568
2569	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2570	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2571		max -= 3;
2572	if (max >= 120) {
2573		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2574		max = 80;
2575		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2576	}
2577
2578	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2579	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2580	     tssi, 0x00), 0x3f)]);
2581	if (power == 0)
2582		return (BWN_TXPWR_RES_DONE);
2583
2584	rfatt = -((power + 7) / 8);
2585	bbatt = (-(power / 2)) - (4 * rfatt);
2586	if ((rfatt == 0) && (bbatt == 0))
2587		return (BWN_TXPWR_RES_DONE);
2588	pg->pg_bbatt_delta = bbatt;
2589	pg->pg_rfatt_delta = rfatt;
2590	return (BWN_TXPWR_RES_NEED_ADJUST);
2591}
2592
2593static void
2594bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2595{
2596	struct bwn_phy *phy = &mac->mac_phy;
2597	struct bwn_phy_g *pg = &phy->phy_g;
2598	struct bwn_softc *sc = mac->mac_sc;
2599	int rfatt, bbatt;
2600	uint8_t txctl;
2601
2602	bwn_mac_suspend(mac);
2603
2604	BWN_ASSERT_LOCKED(sc);
2605
2606	bbatt = pg->pg_bbatt.att;
2607	bbatt += pg->pg_bbatt_delta;
2608	rfatt = pg->pg_rfatt.att;
2609	rfatt += pg->pg_rfatt_delta;
2610
2611	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2612	txctl = pg->pg_txctl;
2613	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2614		if (rfatt <= 1) {
2615			if (txctl == 0) {
2616				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2617				rfatt += 2;
2618				bbatt += 2;
2619			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2620			    BWN_BFL_PACTRL) {
2621				bbatt += 4 * (rfatt - 2);
2622				rfatt = 2;
2623			}
2624		} else if (rfatt > 4 && txctl) {
2625			txctl = 0;
2626			if (bbatt < 3) {
2627				rfatt -= 3;
2628				bbatt += 2;
2629			} else {
2630				rfatt -= 2;
2631				bbatt -= 2;
2632			}
2633		}
2634	}
2635	pg->pg_txctl = txctl;
2636	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2637	pg->pg_rfatt.att = rfatt;
2638	pg->pg_bbatt.att = bbatt;
2639
2640	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2641
2642	bwn_phy_lock(mac);
2643	bwn_rf_lock(mac);
2644	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2645	    pg->pg_txctl);
2646	bwn_rf_unlock(mac);
2647	bwn_phy_unlock(mac);
2648
2649	bwn_mac_enable(mac);
2650}
2651
2652static void
2653bwn_phy_g_task_15s(struct bwn_mac *mac)
2654{
2655	struct bwn_phy *phy = &mac->mac_phy;
2656	struct bwn_phy_g *pg = &phy->phy_g;
2657	struct bwn_softc *sc = mac->mac_sc;
2658	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2659	unsigned long expire, now;
2660	struct bwn_lo_calib *cal, *tmp;
2661	uint8_t expired = 0;
2662
2663	bwn_mac_suspend(mac);
2664
2665	if (lo == NULL)
2666		goto fail;
2667
2668	BWN_GETTIME(now);
2669	if (bwn_has_hwpctl(mac)) {
2670		expire = now - BWN_LO_PWRVEC_EXPIRE;
2671		if (time_before(lo->pwr_vec_read_time, expire)) {
2672			bwn_lo_get_powervector(mac);
2673			bwn_phy_g_dc_lookup_init(mac, 0);
2674		}
2675		goto fail;
2676	}
2677
2678	expire = now - BWN_LO_CALIB_EXPIRE;
2679	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2680		if (!time_before(cal->calib_time, expire))
2681			continue;
2682		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2683		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2684			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2685			expired = 1;
2686		}
2687
2688		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2689		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2690		    cal->ctl.i, cal->ctl.q);
2691
2692		TAILQ_REMOVE(&lo->calib_list, cal, list);
2693		free(cal, M_DEVBUF);
2694	}
2695	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2696		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2697		    &pg->pg_rfatt);
2698		if (cal == NULL) {
2699			device_printf(sc->sc_dev,
2700			    "failed to recalibrate LO\n");
2701			goto fail;
2702		}
2703		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2704		bwn_lo_write(mac, &cal->ctl);
2705	}
2706
2707fail:
2708	bwn_mac_enable(mac);
2709}
2710
2711static void
2712bwn_phy_g_task_60s(struct bwn_mac *mac)
2713{
2714	struct bwn_phy *phy = &mac->mac_phy;
2715	struct bwn_softc *sc = mac->mac_sc;
2716	uint8_t old = phy->chan;
2717
2718	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2719		return;
2720
2721	bwn_mac_suspend(mac);
2722	bwn_nrssi_slope_11g(mac);
2723	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2724		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2725		bwn_switch_channel(mac, old);
2726	}
2727	bwn_mac_enable(mac);
2728}
2729
2730static void
2731bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2732{
2733
2734	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2735}
2736
2737static int
2738bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2739	const struct ieee80211_bpf_params *params)
2740{
2741	struct ieee80211com *ic = ni->ni_ic;
2742	struct ifnet *ifp = ic->ic_ifp;
2743	struct bwn_softc *sc = ifp->if_softc;
2744	struct bwn_mac *mac = sc->sc_curmac;
2745
2746	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2747	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2748		ieee80211_free_node(ni);
2749		m_freem(m);
2750		return (ENETDOWN);
2751	}
2752
2753	BWN_LOCK(sc);
2754	if (bwn_tx_isfull(sc, m)) {
2755		ieee80211_free_node(ni);
2756		m_freem(m);
2757		ifp->if_oerrors++;
2758		BWN_UNLOCK(sc);
2759		return (ENOBUFS);
2760	}
2761
2762	if (bwn_tx_start(sc, ni, m) != 0) {
2763		if (ni != NULL)
2764			ieee80211_free_node(ni);
2765		ifp->if_oerrors++;
2766	}
2767	sc->sc_watchdog_timer = 5;
2768	BWN_UNLOCK(sc);
2769	return (0);
2770}
2771
2772/*
2773 * Setup driver-specific state for a newly associated node.
2774 * Note that we're called also on a re-associate, the isnew
2775 * param tells us if this is the first time or not.
2776 */
2777static void
2778bwn_newassoc(struct ieee80211_node *ni, int isnew)
2779{
2780	struct ieee80211vap *vap = ni->ni_vap;
2781
2782	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2783	    &BWN_NODE(ni)->bn_amn, ni);
2784}
2785
2786/*
2787 * Callback from the 802.11 layer to update the slot time
2788 * based on the current setting.  We use it to notify the
2789 * firmware of ERP changes and the f/w takes care of things
2790 * like slot time and preamble.
2791 */
2792static void
2793bwn_updateslot(struct ifnet *ifp)
2794{
2795	struct bwn_softc *sc = ifp->if_softc;
2796	struct ieee80211com *ic = ifp->if_l2com;
2797	struct bwn_mac *mac;
2798
2799	BWN_LOCK(sc);
2800	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2801		mac = (struct bwn_mac *)sc->sc_curmac;
2802		bwn_set_slot_time(mac,
2803		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2804	}
2805	BWN_UNLOCK(sc);
2806}
2807
2808/*
2809 * Callback from the 802.11 layer after a promiscuous mode change.
2810 * Note this interface does not check the operating mode as this
2811 * is an internal callback and we are expected to honor the current
2812 * state (e.g. this is used for setting the interface in promiscuous
2813 * mode when operating in hostap mode to do ACS).
2814 */
2815static void
2816bwn_update_promisc(struct ifnet *ifp)
2817{
2818	struct bwn_softc *sc = ifp->if_softc;
2819	struct bwn_mac *mac = sc->sc_curmac;
2820
2821	BWN_LOCK(sc);
2822	mac = sc->sc_curmac;
2823	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2824		if (ifp->if_flags & IFF_PROMISC)
2825			sc->sc_filters |= BWN_MACCTL_PROMISC;
2826		else
2827			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2828		bwn_set_opmode(mac);
2829	}
2830	BWN_UNLOCK(sc);
2831}
2832
2833/*
2834 * Callback from the 802.11 layer to update WME parameters.
2835 */
2836static int
2837bwn_wme_update(struct ieee80211com *ic)
2838{
2839	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2840	struct bwn_mac *mac = sc->sc_curmac;
2841	struct wmeParams *wmep;
2842	int i;
2843
2844	BWN_LOCK(sc);
2845	mac = sc->sc_curmac;
2846	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847		bwn_mac_suspend(mac);
2848		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2849			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2850			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2851		}
2852		bwn_mac_enable(mac);
2853	}
2854	BWN_UNLOCK(sc);
2855	return (0);
2856}
2857
2858static struct ieee80211_node *
2859bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2860{
2861	struct ieee80211com *ic = vap->iv_ic;
2862	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2863	const size_t space = sizeof(struct bwn_node);
2864	struct bwn_node *bn;
2865
2866	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2867	if (bn == NULL) {
2868		/* XXX stat+msg */
2869		return (NULL);
2870	}
2871	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2872	return (&bn->bn_node);
2873}
2874
2875static void
2876bwn_node_cleanup(struct ieee80211_node *ni)
2877{
2878	struct ieee80211com *ic = ni->ni_ic;
2879	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2880
2881	sc->sc_node_cleanup(ni);
2882}
2883
2884static void
2885bwn_scan_start(struct ieee80211com *ic)
2886{
2887	struct ifnet *ifp = ic->ic_ifp;
2888	struct bwn_softc *sc = ifp->if_softc;
2889	struct bwn_mac *mac;
2890
2891	BWN_LOCK(sc);
2892	mac = sc->sc_curmac;
2893	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2894		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2895		bwn_set_opmode(mac);
2896		/* disable CFP update during scan */
2897		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2898	}
2899	BWN_UNLOCK(sc);
2900}
2901
2902static void
2903bwn_scan_end(struct ieee80211com *ic)
2904{
2905	struct ifnet *ifp = ic->ic_ifp;
2906	struct bwn_softc *sc = ifp->if_softc;
2907	struct bwn_mac *mac;
2908
2909	BWN_LOCK(sc);
2910	mac = sc->sc_curmac;
2911	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2912		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2913		bwn_set_opmode(mac);
2914		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2915	}
2916	BWN_UNLOCK(sc);
2917}
2918
2919static void
2920bwn_set_channel(struct ieee80211com *ic)
2921{
2922	struct ifnet *ifp = ic->ic_ifp;
2923	struct bwn_softc *sc = ifp->if_softc;
2924	struct bwn_mac *mac = sc->sc_curmac;
2925	struct bwn_phy *phy = &mac->mac_phy;
2926	int chan, error;
2927
2928	BWN_LOCK(sc);
2929
2930	error = bwn_switch_band(sc, ic->ic_curchan);
2931	if (error)
2932		goto fail;;
2933	bwn_mac_suspend(mac);
2934	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2935	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2936	if (chan != phy->chan)
2937		bwn_switch_channel(mac, chan);
2938
2939	/* TX power level */
2940	if (ic->ic_curchan->ic_maxpower != 0 &&
2941	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2942		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2943		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2944		    BWN_TXPWR_IGNORE_TSSI);
2945	}
2946
2947	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2948	if (phy->set_antenna)
2949		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2950
2951	if (sc->sc_rf_enabled != phy->rf_on) {
2952		if (sc->sc_rf_enabled) {
2953			bwn_rf_turnon(mac);
2954			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2955				device_printf(sc->sc_dev,
2956				    "please turns on the RF switch\n");
2957		} else
2958			bwn_rf_turnoff(mac);
2959	}
2960
2961	bwn_mac_enable(mac);
2962
2963fail:
2964	/*
2965	 * Setup radio tap channel freq and flags
2966	 */
2967	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2968		htole16(ic->ic_curchan->ic_freq);
2969	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2970		htole16(ic->ic_curchan->ic_flags & 0xffff);
2971
2972	BWN_UNLOCK(sc);
2973}
2974
2975static struct ieee80211vap *
2976bwn_vap_create(struct ieee80211com *ic,
2977	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2978	const uint8_t bssid[IEEE80211_ADDR_LEN],
2979	const uint8_t mac0[IEEE80211_ADDR_LEN])
2980{
2981	struct ifnet *ifp = ic->ic_ifp;
2982	struct bwn_softc *sc = ifp->if_softc;
2983	struct ieee80211vap *vap;
2984	struct bwn_vap *bvp;
2985	uint8_t mac[IEEE80211_ADDR_LEN];
2986
2987	IEEE80211_ADDR_COPY(mac, mac0);
2988	switch (opmode) {
2989	case IEEE80211_M_HOSTAP:
2990	case IEEE80211_M_MBSS:
2991	case IEEE80211_M_STA:
2992	case IEEE80211_M_WDS:
2993	case IEEE80211_M_MONITOR:
2994	case IEEE80211_M_IBSS:
2995	case IEEE80211_M_AHDEMO:
2996		break;
2997	default:
2998		return (NULL);
2999	}
3000
3001	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3002
3003	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3004	    M_80211_VAP, M_NOWAIT | M_ZERO);
3005	if (bvp == NULL) {
3006		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3007		return (NULL);
3008	}
3009	vap = &bvp->bv_vap;
3010	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3011	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3012	/* override with driver methods */
3013	bvp->bv_newstate = vap->iv_newstate;
3014	vap->iv_newstate = bwn_newstate;
3015
3016	/* override max aid so sta's cannot assoc when we're out of sta id's */
3017	vap->iv_max_aid = BWN_STAID_MAX;
3018
3019	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3020	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3021	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3022	    500 /*ms*/);
3023
3024	/* complete setup */
3025	ieee80211_vap_attach(vap, ieee80211_media_change,
3026	    ieee80211_media_status);
3027	return (vap);
3028}
3029
3030static void
3031bwn_vap_delete(struct ieee80211vap *vap)
3032{
3033	struct bwn_vap *bvp = BWN_VAP(vap);
3034
3035	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3036	ieee80211_vap_detach(vap);
3037	free(bvp, M_80211_VAP);
3038}
3039
3040static void
3041bwn_init(void *arg)
3042{
3043	struct bwn_softc *sc = arg;
3044	struct ifnet *ifp = sc->sc_ifp;
3045	struct ieee80211com *ic = ifp->if_l2com;
3046	int error = 0;
3047
3048	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3049		__func__, ifp->if_flags);
3050
3051	BWN_LOCK(sc);
3052	error = bwn_init_locked(sc);
3053	BWN_UNLOCK(sc);
3054
3055	if (error == 0)
3056		ieee80211_start_all(ic);	/* start all vap's */
3057}
3058
3059static int
3060bwn_init_locked(struct bwn_softc *sc)
3061{
3062	struct bwn_mac *mac;
3063	struct ifnet *ifp = sc->sc_ifp;
3064	int error;
3065
3066	BWN_ASSERT_LOCKED(sc);
3067
3068	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3069	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3070	sc->sc_filters = 0;
3071	bwn_wme_clear(sc);
3072	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3073	sc->sc_rf_enabled = 1;
3074
3075	mac = sc->sc_curmac;
3076	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3077		error = bwn_core_init(mac);
3078		if (error != 0)
3079			return (error);
3080	}
3081	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3082		bwn_core_start(mac);
3083
3084	bwn_set_opmode(mac);
3085	bwn_set_pretbtt(mac);
3086	bwn_spu_setdelay(mac, 0);
3087	bwn_set_macaddr(mac);
3088
3089	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3090	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3091	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3092
3093	return (0);
3094}
3095
3096static void
3097bwn_stop(struct bwn_softc *sc, int statechg)
3098{
3099
3100	BWN_LOCK(sc);
3101	bwn_stop_locked(sc, statechg);
3102	BWN_UNLOCK(sc);
3103}
3104
3105static void
3106bwn_stop_locked(struct bwn_softc *sc, int statechg)
3107{
3108	struct bwn_mac *mac = sc->sc_curmac;
3109	struct ifnet *ifp = sc->sc_ifp;
3110
3111	BWN_ASSERT_LOCKED(sc);
3112
3113	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3114		/* XXX FIXME opmode not based on VAP */
3115		bwn_set_opmode(mac);
3116		bwn_set_macaddr(mac);
3117	}
3118
3119	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3120		bwn_core_stop(mac);
3121
3122	callout_stop(&sc->sc_led_blink_ch);
3123	sc->sc_led_blinking = 0;
3124
3125	bwn_core_exit(mac);
3126	sc->sc_rf_enabled = 0;
3127
3128	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3129}
3130
3131static void
3132bwn_wme_clear(struct bwn_softc *sc)
3133{
3134#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3135	struct wmeParams *p;
3136	unsigned int i;
3137
3138	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3139	    ("%s:%d: fail", __func__, __LINE__));
3140
3141	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3142		p = &(sc->sc_wmeParams[i]);
3143
3144		switch (bwn_wme_shm_offsets[i]) {
3145		case BWN_WME_VOICE:
3146			p->wmep_txopLimit = 0;
3147			p->wmep_aifsn = 2;
3148			/* XXX FIXME: log2(cwmin) */
3149			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3150			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3151			break;
3152		case BWN_WME_VIDEO:
3153			p->wmep_txopLimit = 0;
3154			p->wmep_aifsn = 2;
3155			/* XXX FIXME: log2(cwmin) */
3156			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3157			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3158			break;
3159		case BWN_WME_BESTEFFORT:
3160			p->wmep_txopLimit = 0;
3161			p->wmep_aifsn = 3;
3162			/* XXX FIXME: log2(cwmin) */
3163			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3164			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3165			break;
3166		case BWN_WME_BACKGROUND:
3167			p->wmep_txopLimit = 0;
3168			p->wmep_aifsn = 7;
3169			/* XXX FIXME: log2(cwmin) */
3170			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3171			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3172			break;
3173		default:
3174			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3175		}
3176	}
3177}
3178
3179static int
3180bwn_core_init(struct bwn_mac *mac)
3181{
3182	struct bwn_softc *sc = mac->mac_sc;
3183	uint64_t hf;
3184	int error;
3185
3186	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3187	    ("%s:%d: fail", __func__, __LINE__));
3188
3189	siba_powerup(sc->sc_dev, 0);
3190	if (!siba_dev_isup(sc->sc_dev))
3191		bwn_reset_core(mac,
3192		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3193
3194	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3195	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3196	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3197	BWN_GETTIME(mac->mac_phy.nexttime);
3198	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3199	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3200	mac->mac_stats.link_noise = -95;
3201	mac->mac_reason_intr = 0;
3202	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3203	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3204#ifdef BWN_DEBUG
3205	if (sc->sc_debug & BWN_DEBUG_XMIT)
3206		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3207#endif
3208	mac->mac_suspended = 1;
3209	mac->mac_task_state = 0;
3210	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3211
3212	mac->mac_phy.init_pre(mac);
3213
3214	siba_pcicore_intr(sc->sc_dev);
3215
3216	siba_fix_imcfglobug(sc->sc_dev);
3217	bwn_bt_disable(mac);
3218	if (mac->mac_phy.prepare_hw) {
3219		error = mac->mac_phy.prepare_hw(mac);
3220		if (error)
3221			goto fail0;
3222	}
3223	error = bwn_chip_init(mac);
3224	if (error)
3225		goto fail0;
3226	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3227	    siba_get_revid(sc->sc_dev));
3228	hf = bwn_hf_read(mac);
3229	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3230		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3231		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3232			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3233		if (mac->mac_phy.rev == 1)
3234			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3235	}
3236	if (mac->mac_phy.rf_ver == 0x2050) {
3237		if (mac->mac_phy.rf_rev < 6)
3238			hf |= BWN_HF_FORCE_VCO_RECALC;
3239		if (mac->mac_phy.rf_rev == 6)
3240			hf |= BWN_HF_4318_TSSI;
3241	}
3242	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3243		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3244	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3245	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3246		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3247	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3248	bwn_hf_write(mac, hf);
3249
3250	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3251	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3252	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3253	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3254
3255	bwn_rate_init(mac);
3256	bwn_set_phytxctl(mac);
3257
3258	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3259	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3260	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3261
3262	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3263		bwn_pio_init(mac);
3264	else
3265		bwn_dma_init(mac);
3266	if (error)
3267		goto fail1;
3268	bwn_wme_init(mac);
3269	bwn_spu_setdelay(mac, 1);
3270	bwn_bt_enable(mac);
3271
3272	siba_powerup(sc->sc_dev,
3273	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3274	bwn_set_macaddr(mac);
3275	bwn_crypt_init(mac);
3276
3277	/* XXX LED initializatin */
3278
3279	mac->mac_status = BWN_MAC_STATUS_INITED;
3280
3281	return (error);
3282
3283fail1:
3284	bwn_chip_exit(mac);
3285fail0:
3286	siba_powerdown(sc->sc_dev);
3287	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3288	    ("%s:%d: fail", __func__, __LINE__));
3289	return (error);
3290}
3291
3292static void
3293bwn_core_start(struct bwn_mac *mac)
3294{
3295	struct bwn_softc *sc = mac->mac_sc;
3296	uint32_t tmp;
3297
3298	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3299	    ("%s:%d: fail", __func__, __LINE__));
3300
3301	if (siba_get_revid(sc->sc_dev) < 5)
3302		return;
3303
3304	while (1) {
3305		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3306		if (!(tmp & 0x00000001))
3307			break;
3308		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3309	}
3310
3311	bwn_mac_enable(mac);
3312	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3313	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3314
3315	mac->mac_status = BWN_MAC_STATUS_STARTED;
3316}
3317
3318static void
3319bwn_core_exit(struct bwn_mac *mac)
3320{
3321	struct bwn_softc *sc = mac->mac_sc;
3322	uint32_t macctl;
3323
3324	BWN_ASSERT_LOCKED(mac->mac_sc);
3325
3326	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3327	    ("%s:%d: fail", __func__, __LINE__));
3328
3329	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3330		return;
3331	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3332
3333	macctl = BWN_READ_4(mac, BWN_MACCTL);
3334	macctl &= ~BWN_MACCTL_MCODE_RUN;
3335	macctl |= BWN_MACCTL_MCODE_JMP0;
3336	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3337
3338	bwn_dma_stop(mac);
3339	bwn_pio_stop(mac);
3340	bwn_chip_exit(mac);
3341	mac->mac_phy.switch_analog(mac, 0);
3342	siba_dev_down(sc->sc_dev, 0);
3343	siba_powerdown(sc->sc_dev);
3344}
3345
3346static void
3347bwn_bt_disable(struct bwn_mac *mac)
3348{
3349	struct bwn_softc *sc = mac->mac_sc;
3350
3351	(void)sc;
3352	/* XXX do nothing yet */
3353}
3354
3355static int
3356bwn_chip_init(struct bwn_mac *mac)
3357{
3358	struct bwn_softc *sc = mac->mac_sc;
3359	struct bwn_phy *phy = &mac->mac_phy;
3360	uint32_t macctl;
3361	int error;
3362
3363	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3364	if (phy->gmode)
3365		macctl |= BWN_MACCTL_GMODE;
3366	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3367
3368	error = bwn_fw_fillinfo(mac);
3369	if (error)
3370		return (error);
3371	error = bwn_fw_loaducode(mac);
3372	if (error)
3373		return (error);
3374
3375	error = bwn_gpio_init(mac);
3376	if (error)
3377		return (error);
3378
3379	error = bwn_fw_loadinitvals(mac);
3380	if (error) {
3381		siba_gpio_set(sc->sc_dev, 0);
3382		return (error);
3383	}
3384	phy->switch_analog(mac, 1);
3385	error = bwn_phy_init(mac);
3386	if (error) {
3387		siba_gpio_set(sc->sc_dev, 0);
3388		return (error);
3389	}
3390	if (phy->set_im)
3391		phy->set_im(mac, BWN_IMMODE_NONE);
3392	if (phy->set_antenna)
3393		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3394	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3395
3396	if (phy->type == BWN_PHYTYPE_B)
3397		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3398	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3399	if (siba_get_revid(sc->sc_dev) < 5)
3400		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3401
3402	BWN_WRITE_4(mac, BWN_MACCTL,
3403	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3404	BWN_WRITE_4(mac, BWN_MACCTL,
3405	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3406	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3407
3408	bwn_set_opmode(mac);
3409	if (siba_get_revid(sc->sc_dev) < 3) {
3410		BWN_WRITE_2(mac, 0x060e, 0x0000);
3411		BWN_WRITE_2(mac, 0x0610, 0x8000);
3412		BWN_WRITE_2(mac, 0x0604, 0x0000);
3413		BWN_WRITE_2(mac, 0x0606, 0x0200);
3414	} else {
3415		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3416		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3417	}
3418	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3419	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3420	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3421	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3422	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3423	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3424	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3425	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3426	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3427	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3428	return (error);
3429}
3430
3431/* read hostflags */
3432static uint64_t
3433bwn_hf_read(struct bwn_mac *mac)
3434{
3435	uint64_t ret;
3436
3437	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3438	ret <<= 16;
3439	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3440	ret <<= 16;
3441	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3442	return (ret);
3443}
3444
3445static void
3446bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3447{
3448
3449	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3450	    (value & 0x00000000ffffull));
3451	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3452	    (value & 0x0000ffff0000ull) >> 16);
3453	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3454	    (value & 0xffff00000000ULL) >> 32);
3455}
3456
3457static void
3458bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3459{
3460
3461	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3462	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3463}
3464
3465static void
3466bwn_rate_init(struct bwn_mac *mac)
3467{
3468
3469	switch (mac->mac_phy.type) {
3470	case BWN_PHYTYPE_A:
3471	case BWN_PHYTYPE_G:
3472	case BWN_PHYTYPE_LP:
3473	case BWN_PHYTYPE_N:
3474		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3475		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3476		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3477		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3478		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3479		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3480		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3481		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3482			break;
3483		/* FALLTHROUGH */
3484	case BWN_PHYTYPE_B:
3485		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3486		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3487		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3488		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3489		break;
3490	default:
3491		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3492	}
3493}
3494
3495static void
3496bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3497{
3498	uint16_t offset;
3499
3500	if (ofdm) {
3501		offset = 0x480;
3502		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3503	} else {
3504		offset = 0x4c0;
3505		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3506	}
3507	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3508	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3509}
3510
3511static uint8_t
3512bwn_plcp_getcck(const uint8_t bitrate)
3513{
3514
3515	switch (bitrate) {
3516	case BWN_CCK_RATE_1MB:
3517		return (0x0a);
3518	case BWN_CCK_RATE_2MB:
3519		return (0x14);
3520	case BWN_CCK_RATE_5MB:
3521		return (0x37);
3522	case BWN_CCK_RATE_11MB:
3523		return (0x6e);
3524	}
3525	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3526	return (0);
3527}
3528
3529static uint8_t
3530bwn_plcp_getofdm(const uint8_t bitrate)
3531{
3532
3533	switch (bitrate) {
3534	case BWN_OFDM_RATE_6MB:
3535		return (0xb);
3536	case BWN_OFDM_RATE_9MB:
3537		return (0xf);
3538	case BWN_OFDM_RATE_12MB:
3539		return (0xa);
3540	case BWN_OFDM_RATE_18MB:
3541		return (0xe);
3542	case BWN_OFDM_RATE_24MB:
3543		return (0x9);
3544	case BWN_OFDM_RATE_36MB:
3545		return (0xd);
3546	case BWN_OFDM_RATE_48MB:
3547		return (0x8);
3548	case BWN_OFDM_RATE_54MB:
3549		return (0xc);
3550	}
3551	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3552	return (0);
3553}
3554
3555static void
3556bwn_set_phytxctl(struct bwn_mac *mac)
3557{
3558	uint16_t ctl;
3559
3560	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3561	    BWN_TX_PHY_TXPWR);
3562	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3563	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3564	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3565}
3566
3567static void
3568bwn_pio_init(struct bwn_mac *mac)
3569{
3570	struct bwn_pio *pio = &mac->mac_method.pio;
3571
3572	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3573	    & ~BWN_MACCTL_BIGENDIAN);
3574	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3575
3576	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3577	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3578	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3579	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3580	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3581	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3582}
3583
3584static void
3585bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3586    int index)
3587{
3588	struct bwn_pio_txpkt *tp;
3589	struct bwn_softc *sc = mac->mac_sc;
3590	unsigned int i;
3591
3592	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3593	tq->tq_index = index;
3594
3595	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3596	if (siba_get_revid(sc->sc_dev) >= 8)
3597		tq->tq_size = 1920;
3598	else {
3599		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3600		tq->tq_size -= 80;
3601	}
3602
3603	TAILQ_INIT(&tq->tq_pktlist);
3604	for (i = 0; i < N(tq->tq_pkts); i++) {
3605		tp = &(tq->tq_pkts[i]);
3606		tp->tp_index = i;
3607		tp->tp_queue = tq;
3608		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3609	}
3610}
3611
3612static uint16_t
3613bwn_pio_idx2base(struct bwn_mac *mac, int index)
3614{
3615	struct bwn_softc *sc = mac->mac_sc;
3616	static const uint16_t bases[] = {
3617		BWN_PIO_BASE0,
3618		BWN_PIO_BASE1,
3619		BWN_PIO_BASE2,
3620		BWN_PIO_BASE3,
3621		BWN_PIO_BASE4,
3622		BWN_PIO_BASE5,
3623		BWN_PIO_BASE6,
3624		BWN_PIO_BASE7,
3625	};
3626	static const uint16_t bases_rev11[] = {
3627		BWN_PIO11_BASE0,
3628		BWN_PIO11_BASE1,
3629		BWN_PIO11_BASE2,
3630		BWN_PIO11_BASE3,
3631		BWN_PIO11_BASE4,
3632		BWN_PIO11_BASE5,
3633	};
3634
3635	if (siba_get_revid(sc->sc_dev) >= 11) {
3636		if (index >= N(bases_rev11))
3637			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3638		return (bases_rev11[index]);
3639	}
3640	if (index >= N(bases))
3641		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3642	return (bases[index]);
3643}
3644
3645static void
3646bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3647    int index)
3648{
3649	struct bwn_softc *sc = mac->mac_sc;
3650
3651	prq->prq_mac = mac;
3652	prq->prq_rev = siba_get_revid(sc->sc_dev);
3653	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3654	bwn_dma_rxdirectfifo(mac, index, 1);
3655}
3656
3657static void
3658bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3659{
3660	if (tq == NULL)
3661		return;
3662	bwn_pio_cancel_tx_packets(tq);
3663}
3664
3665static void
3666bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3667{
3668
3669	bwn_destroy_pioqueue_tx(pio);
3670}
3671
3672static uint16_t
3673bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3674    uint16_t offset)
3675{
3676
3677	return (BWN_READ_2(mac, tq->tq_base + offset));
3678}
3679
3680static void
3681bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3682{
3683	uint32_t ctl;
3684	int type;
3685	uint16_t base;
3686
3687	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3688	base = bwn_dma_base(type, idx);
3689	if (type == BWN_DMA_64BIT) {
3690		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3691		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3692		if (enable)
3693			ctl |= BWN_DMA64_RXDIRECTFIFO;
3694		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3695	} else {
3696		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3697		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3698		if (enable)
3699			ctl |= BWN_DMA32_RXDIRECTFIFO;
3700		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3701	}
3702}
3703
3704static uint64_t
3705bwn_dma_mask(struct bwn_mac *mac)
3706{
3707	uint32_t tmp;
3708	uint16_t base;
3709
3710	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3711	if (tmp & SIBA_TGSHIGH_DMA64)
3712		return (BWN_DMA_BIT_MASK(64));
3713	base = bwn_dma_base(0, 0);
3714	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3715	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3716	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3717		return (BWN_DMA_BIT_MASK(32));
3718
3719	return (BWN_DMA_BIT_MASK(30));
3720}
3721
3722static int
3723bwn_dma_mask2type(uint64_t dmamask)
3724{
3725
3726	if (dmamask == BWN_DMA_BIT_MASK(30))
3727		return (BWN_DMA_30BIT);
3728	if (dmamask == BWN_DMA_BIT_MASK(32))
3729		return (BWN_DMA_32BIT);
3730	if (dmamask == BWN_DMA_BIT_MASK(64))
3731		return (BWN_DMA_64BIT);
3732	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3733	return (BWN_DMA_30BIT);
3734}
3735
3736static void
3737bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3738{
3739	struct bwn_pio_txpkt *tp;
3740	unsigned int i;
3741
3742	for (i = 0; i < N(tq->tq_pkts); i++) {
3743		tp = &(tq->tq_pkts[i]);
3744		if (tp->tp_m) {
3745			m_freem(tp->tp_m);
3746			tp->tp_m = NULL;
3747		}
3748	}
3749}
3750
3751static uint16_t
3752bwn_dma_base(int type, int controller_idx)
3753{
3754	static const uint16_t map64[] = {
3755		BWN_DMA64_BASE0,
3756		BWN_DMA64_BASE1,
3757		BWN_DMA64_BASE2,
3758		BWN_DMA64_BASE3,
3759		BWN_DMA64_BASE4,
3760		BWN_DMA64_BASE5,
3761	};
3762	static const uint16_t map32[] = {
3763		BWN_DMA32_BASE0,
3764		BWN_DMA32_BASE1,
3765		BWN_DMA32_BASE2,
3766		BWN_DMA32_BASE3,
3767		BWN_DMA32_BASE4,
3768		BWN_DMA32_BASE5,
3769	};
3770
3771	if (type == BWN_DMA_64BIT) {
3772		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3773		    ("%s:%d: fail", __func__, __LINE__));
3774		return (map64[controller_idx]);
3775	}
3776	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3777	    ("%s:%d: fail", __func__, __LINE__));
3778	return (map32[controller_idx]);
3779}
3780
3781static void
3782bwn_dma_init(struct bwn_mac *mac)
3783{
3784	struct bwn_dma *dma = &mac->mac_method.dma;
3785
3786	/* setup TX DMA channels. */
3787	bwn_dma_setup(dma->wme[WME_AC_BK]);
3788	bwn_dma_setup(dma->wme[WME_AC_BE]);
3789	bwn_dma_setup(dma->wme[WME_AC_VI]);
3790	bwn_dma_setup(dma->wme[WME_AC_VO]);
3791	bwn_dma_setup(dma->mcast);
3792	/* setup RX DMA channel. */
3793	bwn_dma_setup(dma->rx);
3794}
3795
3796static struct bwn_dma_ring *
3797bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3798    int for_tx, int type)
3799{
3800	struct bwn_dma *dma = &mac->mac_method.dma;
3801	struct bwn_dma_ring *dr;
3802	struct bwn_dmadesc_generic *desc;
3803	struct bwn_dmadesc_meta *mt;
3804	struct bwn_softc *sc = mac->mac_sc;
3805	int error, i;
3806
3807	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3808	if (dr == NULL)
3809		goto out;
3810	dr->dr_numslots = BWN_RXRING_SLOTS;
3811	if (for_tx)
3812		dr->dr_numslots = BWN_TXRING_SLOTS;
3813
3814	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3815	    M_DEVBUF, M_NOWAIT | M_ZERO);
3816	if (dr->dr_meta == NULL)
3817		goto fail0;
3818
3819	dr->dr_type = type;
3820	dr->dr_mac = mac;
3821	dr->dr_base = bwn_dma_base(type, controller_index);
3822	dr->dr_index = controller_index;
3823	if (type == BWN_DMA_64BIT) {
3824		dr->getdesc = bwn_dma_64_getdesc;
3825		dr->setdesc = bwn_dma_64_setdesc;
3826		dr->start_transfer = bwn_dma_64_start_transfer;
3827		dr->suspend = bwn_dma_64_suspend;
3828		dr->resume = bwn_dma_64_resume;
3829		dr->get_curslot = bwn_dma_64_get_curslot;
3830		dr->set_curslot = bwn_dma_64_set_curslot;
3831	} else {
3832		dr->getdesc = bwn_dma_32_getdesc;
3833		dr->setdesc = bwn_dma_32_setdesc;
3834		dr->start_transfer = bwn_dma_32_start_transfer;
3835		dr->suspend = bwn_dma_32_suspend;
3836		dr->resume = bwn_dma_32_resume;
3837		dr->get_curslot = bwn_dma_32_get_curslot;
3838		dr->set_curslot = bwn_dma_32_set_curslot;
3839	}
3840	if (for_tx) {
3841		dr->dr_tx = 1;
3842		dr->dr_curslot = -1;
3843	} else {
3844		if (dr->dr_index == 0) {
3845			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3846			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3847		} else
3848			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3849	}
3850
3851	error = bwn_dma_allocringmemory(dr);
3852	if (error)
3853		goto fail2;
3854
3855	if (for_tx) {
3856		/*
3857		 * Assumption: BWN_TXRING_SLOTS can be divided by
3858		 * BWN_TX_SLOTS_PER_FRAME
3859		 */
3860		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3861		    ("%s:%d: fail", __func__, __LINE__));
3862
3863		dr->dr_txhdr_cache =
3864		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3865			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3866		KASSERT(dr->dr_txhdr_cache != NULL,
3867		    ("%s:%d: fail", __func__, __LINE__));
3868
3869		/*
3870		 * Create TX ring DMA stuffs
3871		 */
3872		error = bus_dma_tag_create(dma->parent_dtag,
3873				    BWN_ALIGN, 0,
3874				    BUS_SPACE_MAXADDR,
3875				    BUS_SPACE_MAXADDR,
3876				    NULL, NULL,
3877				    BWN_HDRSIZE(mac),
3878				    1,
3879				    BUS_SPACE_MAXSIZE_32BIT,
3880				    0,
3881				    NULL, NULL,
3882				    &dr->dr_txring_dtag);
3883		if (error) {
3884			device_printf(sc->sc_dev,
3885			    "can't create TX ring DMA tag: TODO frees\n");
3886			goto fail1;
3887		}
3888
3889		for (i = 0; i < dr->dr_numslots; i += 2) {
3890			dr->getdesc(dr, i, &desc, &mt);
3891
3892			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3893			mt->mt_m = NULL;
3894			mt->mt_ni = NULL;
3895			mt->mt_islast = 0;
3896			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3897			    &mt->mt_dmap);
3898			if (error) {
3899				device_printf(sc->sc_dev,
3900				     "can't create RX buf DMA map\n");
3901				goto fail1;
3902			}
3903
3904			dr->getdesc(dr, i + 1, &desc, &mt);
3905
3906			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3907			mt->mt_m = NULL;
3908			mt->mt_ni = NULL;
3909			mt->mt_islast = 1;
3910			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3911			    &mt->mt_dmap);
3912			if (error) {
3913				device_printf(sc->sc_dev,
3914				     "can't create RX buf DMA map\n");
3915				goto fail1;
3916			}
3917		}
3918	} else {
3919		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3920		    &dr->dr_spare_dmap);
3921		if (error) {
3922			device_printf(sc->sc_dev,
3923			    "can't create RX buf DMA map\n");
3924			goto out;		/* XXX wrong! */
3925		}
3926
3927		for (i = 0; i < dr->dr_numslots; i++) {
3928			dr->getdesc(dr, i, &desc, &mt);
3929
3930			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3931			    &mt->mt_dmap);
3932			if (error) {
3933				device_printf(sc->sc_dev,
3934				    "can't create RX buf DMA map\n");
3935				goto out;	/* XXX wrong! */
3936			}
3937			error = bwn_dma_newbuf(dr, desc, mt, 1);
3938			if (error) {
3939				device_printf(sc->sc_dev,
3940				    "failed to allocate RX buf\n");
3941				goto out;	/* XXX wrong! */
3942			}
3943		}
3944
3945		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3946		    BUS_DMASYNC_PREWRITE);
3947
3948		dr->dr_usedslot = dr->dr_numslots;
3949	}
3950
3951      out:
3952	return (dr);
3953
3954fail2:
3955	free(dr->dr_txhdr_cache, M_DEVBUF);
3956fail1:
3957	free(dr->dr_meta, M_DEVBUF);
3958fail0:
3959	free(dr, M_DEVBUF);
3960	return (NULL);
3961}
3962
3963static void
3964bwn_dma_ringfree(struct bwn_dma_ring **dr)
3965{
3966
3967	if (dr == NULL)
3968		return;
3969
3970	bwn_dma_free_descbufs(*dr);
3971	bwn_dma_free_ringmemory(*dr);
3972
3973	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3974	free((*dr)->dr_meta, M_DEVBUF);
3975	free(*dr, M_DEVBUF);
3976
3977	*dr = NULL;
3978}
3979
3980static void
3981bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3982    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3983{
3984	struct bwn_dmadesc32 *desc;
3985
3986	*meta = &(dr->dr_meta[slot]);
3987	desc = dr->dr_ring_descbase;
3988	desc = &(desc[slot]);
3989
3990	*gdesc = (struct bwn_dmadesc_generic *)desc;
3991}
3992
3993static void
3994bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3995    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3996    int start, int end, int irq)
3997{
3998	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3999	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4000	uint32_t addr, addrext, ctl;
4001	int slot;
4002
4003	slot = (int)(&(desc->dma.dma32) - descbase);
4004	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4005	    ("%s:%d: fail", __func__, __LINE__));
4006
4007	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4008	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4009	addr |= siba_dma_translation(sc->sc_dev);
4010	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4011	if (slot == dr->dr_numslots - 1)
4012		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4013	if (start)
4014		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4015	if (end)
4016		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4017	if (irq)
4018		ctl |= BWN_DMA32_DCTL_IRQ;
4019	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4020	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4021
4022	desc->dma.dma32.control = htole32(ctl);
4023	desc->dma.dma32.address = htole32(addr);
4024}
4025
4026static void
4027bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4028{
4029
4030	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4031	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4032}
4033
4034static void
4035bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4036{
4037
4038	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4039	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4040}
4041
4042static void
4043bwn_dma_32_resume(struct bwn_dma_ring *dr)
4044{
4045
4046	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4047	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4048}
4049
4050static int
4051bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4052{
4053	uint32_t val;
4054
4055	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4056	val &= BWN_DMA32_RXDPTR;
4057
4058	return (val / sizeof(struct bwn_dmadesc32));
4059}
4060
4061static void
4062bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4063{
4064
4065	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4066	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4067}
4068
4069static void
4070bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4071    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4072{
4073	struct bwn_dmadesc64 *desc;
4074
4075	*meta = &(dr->dr_meta[slot]);
4076	desc = dr->dr_ring_descbase;
4077	desc = &(desc[slot]);
4078
4079	*gdesc = (struct bwn_dmadesc_generic *)desc;
4080}
4081
4082static void
4083bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4084    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4085    int start, int end, int irq)
4086{
4087	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4088	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4089	int slot;
4090	uint32_t ctl0 = 0, ctl1 = 0;
4091	uint32_t addrlo, addrhi;
4092	uint32_t addrext;
4093
4094	slot = (int)(&(desc->dma.dma64) - descbase);
4095	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4096	    ("%s:%d: fail", __func__, __LINE__));
4097
4098	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4099	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4100	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4101	    30;
4102	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4103	if (slot == dr->dr_numslots - 1)
4104		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4105	if (start)
4106		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4107	if (end)
4108		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4109	if (irq)
4110		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4111	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4112	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4113	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4114
4115	desc->dma.dma64.control0 = htole32(ctl0);
4116	desc->dma.dma64.control1 = htole32(ctl1);
4117	desc->dma.dma64.address_low = htole32(addrlo);
4118	desc->dma.dma64.address_high = htole32(addrhi);
4119}
4120
4121static void
4122bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4123{
4124
4125	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4126	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4127}
4128
4129static void
4130bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4131{
4132
4133	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4134	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4135}
4136
4137static void
4138bwn_dma_64_resume(struct bwn_dma_ring *dr)
4139{
4140
4141	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4142	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4143}
4144
4145static int
4146bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4147{
4148	uint32_t val;
4149
4150	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4151	val &= BWN_DMA64_RXSTATDPTR;
4152
4153	return (val / sizeof(struct bwn_dmadesc64));
4154}
4155
4156static void
4157bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4158{
4159
4160	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4161	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4162}
4163
4164static int
4165bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4166{
4167	struct bwn_mac *mac = dr->dr_mac;
4168	struct bwn_dma *dma = &mac->mac_method.dma;
4169	struct bwn_softc *sc = mac->mac_sc;
4170	int error;
4171
4172	error = bus_dma_tag_create(dma->parent_dtag,
4173			    BWN_ALIGN, 0,
4174			    BUS_SPACE_MAXADDR,
4175			    BUS_SPACE_MAXADDR,
4176			    NULL, NULL,
4177			    BWN_DMA_RINGMEMSIZE,
4178			    1,
4179			    BUS_SPACE_MAXSIZE_32BIT,
4180			    0,
4181			    NULL, NULL,
4182			    &dr->dr_ring_dtag);
4183	if (error) {
4184		device_printf(sc->sc_dev,
4185		    "can't create TX ring DMA tag: TODO frees\n");
4186		return (-1);
4187	}
4188
4189	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4190	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4191	    &dr->dr_ring_dmap);
4192	if (error) {
4193		device_printf(sc->sc_dev,
4194		    "can't allocate DMA mem: TODO frees\n");
4195		return (-1);
4196	}
4197	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4198	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4199	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4200	if (error) {
4201		device_printf(sc->sc_dev,
4202		    "can't load DMA mem: TODO free\n");
4203		return (-1);
4204	}
4205
4206	return (0);
4207}
4208
4209static void
4210bwn_dma_setup(struct bwn_dma_ring *dr)
4211{
4212	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4213	uint64_t ring64;
4214	uint32_t addrext, ring32, value;
4215	uint32_t trans = siba_dma_translation(sc->sc_dev);
4216
4217	if (dr->dr_tx) {
4218		dr->dr_curslot = -1;
4219
4220		if (dr->dr_type == BWN_DMA_64BIT) {
4221			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4222			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4223			    >> 30;
4224			value = BWN_DMA64_TXENABLE;
4225			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4226			    & BWN_DMA64_TXADDREXT_MASK;
4227			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4228			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4229			    (ring64 & 0xffffffff));
4230			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4231			    ((ring64 >> 32) &
4232			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4233		} else {
4234			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4235			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4236			value = BWN_DMA32_TXENABLE;
4237			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4238			    & BWN_DMA32_TXADDREXT_MASK;
4239			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4240			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4241			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4242		}
4243		return;
4244	}
4245
4246	/*
4247	 * set for RX
4248	 */
4249	dr->dr_usedslot = dr->dr_numslots;
4250
4251	if (dr->dr_type == BWN_DMA_64BIT) {
4252		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4253		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4254		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4255		value |= BWN_DMA64_RXENABLE;
4256		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4257		    & BWN_DMA64_RXADDREXT_MASK;
4258		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4259		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4260		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4261		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4262		    | (trans << 1));
4263		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4264		    sizeof(struct bwn_dmadesc64));
4265	} else {
4266		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4267		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4268		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4269		value |= BWN_DMA32_RXENABLE;
4270		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4271		    & BWN_DMA32_RXADDREXT_MASK;
4272		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4273		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4274		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4275		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4276		    sizeof(struct bwn_dmadesc32));
4277	}
4278}
4279
4280static void
4281bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4282{
4283
4284	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4285	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4286	    dr->dr_ring_dmap);
4287}
4288
4289static void
4290bwn_dma_cleanup(struct bwn_dma_ring *dr)
4291{
4292
4293	if (dr->dr_tx) {
4294		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4295		if (dr->dr_type == BWN_DMA_64BIT) {
4296			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4297			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4298		} else
4299			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4300	} else {
4301		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4302		if (dr->dr_type == BWN_DMA_64BIT) {
4303			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4304			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4305		} else
4306			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4307	}
4308}
4309
4310static void
4311bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4312{
4313	struct bwn_dmadesc_generic *desc;
4314	struct bwn_dmadesc_meta *meta;
4315	struct bwn_mac *mac = dr->dr_mac;
4316	struct bwn_dma *dma = &mac->mac_method.dma;
4317	struct bwn_softc *sc = mac->mac_sc;
4318	int i;
4319
4320	if (!dr->dr_usedslot)
4321		return;
4322	for (i = 0; i < dr->dr_numslots; i++) {
4323		dr->getdesc(dr, i, &desc, &meta);
4324
4325		if (meta->mt_m == NULL) {
4326			if (!dr->dr_tx)
4327				device_printf(sc->sc_dev, "%s: not TX?\n",
4328				    __func__);
4329			continue;
4330		}
4331		if (dr->dr_tx) {
4332			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4333				bus_dmamap_unload(dr->dr_txring_dtag,
4334				    meta->mt_dmap);
4335			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4336				bus_dmamap_unload(dma->txbuf_dtag,
4337				    meta->mt_dmap);
4338		} else
4339			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4340		bwn_dma_free_descbuf(dr, meta);
4341	}
4342}
4343
4344static int
4345bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4346    int type)
4347{
4348	struct bwn_softc *sc = mac->mac_sc;
4349	uint32_t value;
4350	int i;
4351	uint16_t offset;
4352
4353	for (i = 0; i < 10; i++) {
4354		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4355		    BWN_DMA32_TXSTATUS;
4356		value = BWN_READ_4(mac, base + offset);
4357		if (type == BWN_DMA_64BIT) {
4358			value &= BWN_DMA64_TXSTAT;
4359			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4360			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4361			    value == BWN_DMA64_TXSTAT_STOPPED)
4362				break;
4363		} else {
4364			value &= BWN_DMA32_TXSTATE;
4365			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4366			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4367			    value == BWN_DMA32_TXSTAT_STOPPED)
4368				break;
4369		}
4370		DELAY(1000);
4371	}
4372	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4373	BWN_WRITE_4(mac, base + offset, 0);
4374	for (i = 0; i < 10; i++) {
4375		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4376						   BWN_DMA32_TXSTATUS;
4377		value = BWN_READ_4(mac, base + offset);
4378		if (type == BWN_DMA_64BIT) {
4379			value &= BWN_DMA64_TXSTAT;
4380			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4381				i = -1;
4382				break;
4383			}
4384		} else {
4385			value &= BWN_DMA32_TXSTATE;
4386			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4387				i = -1;
4388				break;
4389			}
4390		}
4391		DELAY(1000);
4392	}
4393	if (i != -1) {
4394		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4395		return (ENODEV);
4396	}
4397	DELAY(1000);
4398
4399	return (0);
4400}
4401
4402static int
4403bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4404    int type)
4405{
4406	struct bwn_softc *sc = mac->mac_sc;
4407	uint32_t value;
4408	int i;
4409	uint16_t offset;
4410
4411	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4412	BWN_WRITE_4(mac, base + offset, 0);
4413	for (i = 0; i < 10; i++) {
4414		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4415		    BWN_DMA32_RXSTATUS;
4416		value = BWN_READ_4(mac, base + offset);
4417		if (type == BWN_DMA_64BIT) {
4418			value &= BWN_DMA64_RXSTAT;
4419			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4420				i = -1;
4421				break;
4422			}
4423		} else {
4424			value &= BWN_DMA32_RXSTATE;
4425			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4426				i = -1;
4427				break;
4428			}
4429		}
4430		DELAY(1000);
4431	}
4432	if (i != -1) {
4433		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4434		return (ENODEV);
4435	}
4436
4437	return (0);
4438}
4439
4440static void
4441bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4442    struct bwn_dmadesc_meta *meta)
4443{
4444
4445	if (meta->mt_m != NULL) {
4446		m_freem(meta->mt_m);
4447		meta->mt_m = NULL;
4448	}
4449	if (meta->mt_ni != NULL) {
4450		ieee80211_free_node(meta->mt_ni);
4451		meta->mt_ni = NULL;
4452	}
4453}
4454
4455static void
4456bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4457{
4458	struct bwn_rxhdr4 *rxhdr;
4459	unsigned char *frame;
4460
4461	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4462	rxhdr->frame_len = 0;
4463
4464	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4465	    sizeof(struct bwn_plcp6) + 2,
4466	    ("%s:%d: fail", __func__, __LINE__));
4467	frame = mtod(m, char *) + dr->dr_frameoffset;
4468	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4469}
4470
4471static uint8_t
4472bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4473{
4474	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4475
4476	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4477	    == 0xff);
4478}
4479
4480static void
4481bwn_wme_init(struct bwn_mac *mac)
4482{
4483
4484	bwn_wme_load(mac);
4485
4486	/* enable WME support. */
4487	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4488	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4489	    BWN_IFSCTL_USE_EDCF);
4490}
4491
4492static void
4493bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4494{
4495	struct bwn_softc *sc = mac->mac_sc;
4496	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4497	uint16_t delay;	/* microsec */
4498
4499	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4500	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4501		delay = 500;
4502	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4503		delay = max(delay, (uint16_t)2400);
4504
4505	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4506}
4507
4508static void
4509bwn_bt_enable(struct bwn_mac *mac)
4510{
4511	struct bwn_softc *sc = mac->mac_sc;
4512	uint64_t hf;
4513
4514	if (bwn_bluetooth == 0)
4515		return;
4516	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4517		return;
4518	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4519		return;
4520
4521	hf = bwn_hf_read(mac);
4522	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4523		hf |= BWN_HF_BT_COEXISTALT;
4524	else
4525		hf |= BWN_HF_BT_COEXIST;
4526	bwn_hf_write(mac, hf);
4527}
4528
4529static void
4530bwn_set_macaddr(struct bwn_mac *mac)
4531{
4532
4533	bwn_mac_write_bssid(mac);
4534	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4535}
4536
4537static void
4538bwn_clear_keys(struct bwn_mac *mac)
4539{
4540	int i;
4541
4542	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4543		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4544		    ("%s:%d: fail", __func__, __LINE__));
4545
4546		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4547		    NULL, BWN_SEC_KEYSIZE, NULL);
4548		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4549			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4550			    NULL, BWN_SEC_KEYSIZE, NULL);
4551		}
4552		mac->mac_key[i].keyconf = NULL;
4553	}
4554}
4555
4556static void
4557bwn_crypt_init(struct bwn_mac *mac)
4558{
4559	struct bwn_softc *sc = mac->mac_sc;
4560
4561	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4562	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4563	    ("%s:%d: fail", __func__, __LINE__));
4564	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4565	mac->mac_ktp *= 2;
4566	if (siba_get_revid(sc->sc_dev) >= 5)
4567		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4568	bwn_clear_keys(mac);
4569}
4570
4571static void
4572bwn_chip_exit(struct bwn_mac *mac)
4573{
4574	struct bwn_softc *sc = mac->mac_sc;
4575
4576	bwn_phy_exit(mac);
4577	siba_gpio_set(sc->sc_dev, 0);
4578}
4579
4580static int
4581bwn_fw_fillinfo(struct bwn_mac *mac)
4582{
4583	int error;
4584
4585	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4586	if (error == 0)
4587		return (0);
4588	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4589	if (error == 0)
4590		return (0);
4591	return (error);
4592}
4593
4594static int
4595bwn_gpio_init(struct bwn_mac *mac)
4596{
4597	struct bwn_softc *sc = mac->mac_sc;
4598	uint32_t mask = 0x1f, set = 0xf, value;
4599
4600	BWN_WRITE_4(mac, BWN_MACCTL,
4601	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4602	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4603	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4604
4605	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4606		mask |= 0x0060;
4607		set |= 0x0060;
4608	}
4609	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4610		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4611		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4612		mask |= 0x0200;
4613		set |= 0x0200;
4614	}
4615	if (siba_get_revid(sc->sc_dev) >= 2)
4616		mask |= 0x0010;
4617
4618	value = siba_gpio_get(sc->sc_dev);
4619	if (value == -1)
4620		return (0);
4621	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4622
4623	return (0);
4624}
4625
4626static int
4627bwn_fw_loadinitvals(struct bwn_mac *mac)
4628{
4629#define	GETFWOFFSET(fwp, offset)				\
4630	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4631	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4632	const struct bwn_fwhdr *hdr;
4633	struct bwn_fw *fw = &mac->mac_fw;
4634	int error;
4635
4636	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4637	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4638	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4639	if (error)
4640		return (error);
4641	if (fw->initvals_band.fw) {
4642		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4643		error = bwn_fwinitvals_write(mac,
4644		    GETFWOFFSET(fw->initvals_band, hdr_len),
4645		    be32toh(hdr->size),
4646		    fw->initvals_band.fw->datasize - hdr_len);
4647	}
4648	return (error);
4649#undef GETFWOFFSET
4650}
4651
4652static int
4653bwn_phy_init(struct bwn_mac *mac)
4654{
4655	struct bwn_softc *sc = mac->mac_sc;
4656	int error;
4657
4658	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4659	mac->mac_phy.rf_onoff(mac, 1);
4660	error = mac->mac_phy.init(mac);
4661	if (error) {
4662		device_printf(sc->sc_dev, "PHY init failed\n");
4663		goto fail0;
4664	}
4665	error = bwn_switch_channel(mac,
4666	    mac->mac_phy.get_default_chan(mac));
4667	if (error) {
4668		device_printf(sc->sc_dev,
4669		    "failed to switch default channel\n");
4670		goto fail1;
4671	}
4672	return (0);
4673fail1:
4674	if (mac->mac_phy.exit)
4675		mac->mac_phy.exit(mac);
4676fail0:
4677	mac->mac_phy.rf_onoff(mac, 0);
4678
4679	return (error);
4680}
4681
4682static void
4683bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4684{
4685	uint16_t ant;
4686	uint16_t tmp;
4687
4688	ant = bwn_ant2phy(antenna);
4689
4690	/* For ACK/CTS */
4691	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4692	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4693	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4694	/* For Probe Resposes */
4695	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4696	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4697	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4698}
4699
4700static void
4701bwn_set_opmode(struct bwn_mac *mac)
4702{
4703	struct bwn_softc *sc = mac->mac_sc;
4704	struct ifnet *ifp = sc->sc_ifp;
4705	struct ieee80211com *ic = ifp->if_l2com;
4706	uint32_t ctl;
4707	uint16_t cfp_pretbtt;
4708
4709	ctl = BWN_READ_4(mac, BWN_MACCTL);
4710	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4711	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4712	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4713	ctl |= BWN_MACCTL_STA;
4714
4715	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4716	    ic->ic_opmode == IEEE80211_M_MBSS)
4717		ctl |= BWN_MACCTL_HOSTAP;
4718	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4719		ctl &= ~BWN_MACCTL_STA;
4720	ctl |= sc->sc_filters;
4721
4722	if (siba_get_revid(sc->sc_dev) <= 4)
4723		ctl |= BWN_MACCTL_PROMISC;
4724
4725	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4726
4727	cfp_pretbtt = 2;
4728	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4729		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4730		    siba_get_chiprev(sc->sc_dev) == 3)
4731			cfp_pretbtt = 100;
4732		else
4733			cfp_pretbtt = 50;
4734	}
4735	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4736}
4737
4738static int
4739bwn_dma_gettype(struct bwn_mac *mac)
4740{
4741	uint32_t tmp;
4742	uint16_t base;
4743
4744	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4745	if (tmp & SIBA_TGSHIGH_DMA64)
4746		return (BWN_DMA_64BIT);
4747	base = bwn_dma_base(0, 0);
4748	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4749	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4750	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4751		return (BWN_DMA_32BIT);
4752
4753	return (BWN_DMA_30BIT);
4754}
4755
4756static void
4757bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4758{
4759	if (!error) {
4760		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4761		*((bus_addr_t *)arg) = seg->ds_addr;
4762	}
4763}
4764
4765static void
4766bwn_phy_g_init_sub(struct bwn_mac *mac)
4767{
4768	struct bwn_phy *phy = &mac->mac_phy;
4769	struct bwn_phy_g *pg = &phy->phy_g;
4770	struct bwn_softc *sc = mac->mac_sc;
4771	uint16_t i, tmp;
4772
4773	if (phy->rev == 1)
4774		bwn_phy_init_b5(mac);
4775	else
4776		bwn_phy_init_b6(mac);
4777
4778	if (phy->rev >= 2 || phy->gmode)
4779		bwn_phy_init_a(mac);
4780
4781	if (phy->rev >= 2) {
4782		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4783		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4784	}
4785	if (phy->rev == 2) {
4786		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4787		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4788	}
4789	if (phy->rev > 5) {
4790		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4791		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4792	}
4793	if (phy->gmode || phy->rev >= 2) {
4794		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4795		tmp &= BWN_PHYVER_VERSION;
4796		if (tmp == 3 || tmp == 5) {
4797			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4798			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4799		}
4800		if (tmp == 5) {
4801			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4802			    0x1f00);
4803		}
4804	}
4805	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4806		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4807	if (phy->rf_rev == 8) {
4808		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4809		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4810	}
4811	if (BWN_HAS_LOOPBACK(phy))
4812		bwn_loopback_calcgain(mac);
4813
4814	if (phy->rf_rev != 8) {
4815		if (pg->pg_initval == 0xffff)
4816			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4817		else
4818			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4819	}
4820	bwn_lo_g_init(mac);
4821	if (BWN_HAS_TXMAG(phy)) {
4822		BWN_RF_WRITE(mac, 0x52,
4823		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4824		    | pg->pg_loctl.tx_bias |
4825		    pg->pg_loctl.tx_magn);
4826	} else {
4827		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4828	}
4829	if (phy->rev >= 6) {
4830		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4831		    (pg->pg_loctl.tx_bias << 12));
4832	}
4833	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4834		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4835	else
4836		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4837	if (phy->rev < 2)
4838		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4839	else
4840		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4841	if (phy->gmode || phy->rev >= 2) {
4842		bwn_lo_g_adjust(mac);
4843		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4844	}
4845
4846	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4847		for (i = 0; i < 64; i++) {
4848			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4849			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4850			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4851			    -32), 31));
4852		}
4853		bwn_nrssi_threshold(mac);
4854	} else if (phy->gmode || phy->rev >= 2) {
4855		if (pg->pg_nrssi[0] == -1000) {
4856			KASSERT(pg->pg_nrssi[1] == -1000,
4857			    ("%s:%d: fail", __func__, __LINE__));
4858			bwn_nrssi_slope_11g(mac);
4859		} else
4860			bwn_nrssi_threshold(mac);
4861	}
4862	if (phy->rf_rev == 8)
4863		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4864	bwn_phy_hwpctl_init(mac);
4865	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4866	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4867		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4868		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4869	}
4870}
4871
4872static uint8_t
4873bwn_has_hwpctl(struct bwn_mac *mac)
4874{
4875
4876	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4877		return (0);
4878	return (mac->mac_phy.use_hwpctl(mac));
4879}
4880
4881static void
4882bwn_phy_init_b5(struct bwn_mac *mac)
4883{
4884	struct bwn_phy *phy = &mac->mac_phy;
4885	struct bwn_phy_g *pg = &phy->phy_g;
4886	struct bwn_softc *sc = mac->mac_sc;
4887	uint16_t offset, value;
4888	uint8_t old_channel;
4889
4890	if (phy->analog == 1)
4891		BWN_RF_SET(mac, 0x007a, 0x0050);
4892	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4893	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4894		value = 0x2120;
4895		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4896			BWN_PHY_WRITE(mac, offset, value);
4897			value += 0x202;
4898		}
4899	}
4900	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4901	if (phy->rf_ver == 0x2050)
4902		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4903
4904	if (phy->gmode || phy->rev >= 2) {
4905		if (phy->rf_ver == 0x2050) {
4906			BWN_RF_SET(mac, 0x007a, 0x0020);
4907			BWN_RF_SET(mac, 0x0051, 0x0004);
4908		}
4909		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4910
4911		BWN_PHY_SET(mac, 0x0802, 0x0100);
4912		BWN_PHY_SET(mac, 0x042b, 0x2000);
4913
4914		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4915
4916		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4917		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4918		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4919	}
4920
4921	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4922		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4923
4924	if (phy->analog == 1) {
4925		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4926		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4927		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4928		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4929		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4930	} else
4931		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4932	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4933	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4934
4935	if (phy->analog == 1)
4936		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4937	else
4938		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4939
4940	if (phy->analog == 0)
4941		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4942
4943	old_channel = phy->chan;
4944	bwn_phy_g_switch_chan(mac, 7, 0);
4945
4946	if (phy->rf_ver != 0x2050) {
4947		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4948		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4949	}
4950
4951	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4952	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4953
4954	if (phy->rf_ver == 0x2050) {
4955		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4956		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4957	}
4958
4959	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4960	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4961	BWN_RF_SET(mac, 0x007a, 0x0007);
4962
4963	bwn_phy_g_switch_chan(mac, old_channel, 0);
4964	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4965	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4966	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4967
4968	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4969	    pg->pg_txctl);
4970
4971	if (phy->rf_ver == 0x2050)
4972		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4973
4974	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4975}
4976
4977static void
4978bwn_loopback_calcgain(struct bwn_mac *mac)
4979{
4980	struct bwn_phy *phy = &mac->mac_phy;
4981	struct bwn_phy_g *pg = &phy->phy_g;
4982	struct bwn_softc *sc = mac->mac_sc;
4983	uint16_t backup_phy[16] = { 0 };
4984	uint16_t backup_radio[3];
4985	uint16_t backup_bband;
4986	uint16_t i, j, loop_i_max;
4987	uint16_t trsw_rx;
4988	uint16_t loop1_outer_done, loop1_inner_done;
4989
4990	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4991	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4992	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4993	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4994	if (phy->rev != 1) {
4995		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4996		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4997	}
4998	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4999	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5000	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5001	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5002	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5003	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5004	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5005	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5006	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5007	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5008	backup_bband = pg->pg_bbatt.att;
5009	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5010	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5011	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5012
5013	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5014	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5015	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5016	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5017	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5018	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5019	if (phy->rev != 1) {
5020		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5021		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5022		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5023		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5024	}
5025	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5026	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5027	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5028	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5029
5030	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5031	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5032	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5033
5034	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5035	if (phy->rev != 1) {
5036		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5037		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5038	}
5039	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5040
5041	if (phy->rf_rev == 8)
5042		BWN_RF_WRITE(mac, 0x43, 0x000f);
5043	else {
5044		BWN_RF_WRITE(mac, 0x52, 0);
5045		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5046	}
5047	bwn_phy_g_set_bbatt(mac, 11);
5048
5049	if (phy->rev >= 3)
5050		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5051	else
5052		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5053	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5054
5055	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5056	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5057
5058	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5059	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5060
5061	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5062		if (phy->rev >= 7) {
5063			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5064			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5065		}
5066	}
5067	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5068
5069	j = 0;
5070	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5071	for (i = 0; i < loop_i_max; i++) {
5072		for (j = 0; j < 16; j++) {
5073			BWN_RF_WRITE(mac, 0x43, i);
5074			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5075			    (j << 8));
5076			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5077			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5078			DELAY(20);
5079			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5080				goto done0;
5081		}
5082	}
5083done0:
5084	loop1_outer_done = i;
5085	loop1_inner_done = j;
5086	if (j >= 8) {
5087		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5088		trsw_rx = 0x1b;
5089		for (j = j - 8; j < 16; j++) {
5090			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5091			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5092			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5093			DELAY(20);
5094			trsw_rx -= 3;
5095			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5096				goto done1;
5097		}
5098	} else
5099		trsw_rx = 0x18;
5100done1:
5101
5102	if (phy->rev != 1) {
5103		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5104		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5105	}
5106	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5107	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5108	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5109	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5110	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5111	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5112	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5113	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5114	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5115
5116	bwn_phy_g_set_bbatt(mac, backup_bband);
5117
5118	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5119	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5120	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5121
5122	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5123	DELAY(10);
5124	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5125	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5126	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5127	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5128
5129	pg->pg_max_lb_gain =
5130	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5131	pg->pg_trsw_rx_gain = trsw_rx * 2;
5132}
5133
5134static uint16_t
5135bwn_rf_init_bcm2050(struct bwn_mac *mac)
5136{
5137	struct bwn_phy *phy = &mac->mac_phy;
5138	uint32_t tmp1 = 0, tmp2 = 0;
5139	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5140	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5141	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5142	static const uint8_t rcc_table[] = {
5143		0x02, 0x03, 0x01, 0x0f,
5144		0x06, 0x07, 0x05, 0x0f,
5145		0x0a, 0x0b, 0x09, 0x0f,
5146		0x0e, 0x0f, 0x0d, 0x0f,
5147	};
5148
5149	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5150	    rfoverval = rfover = cck3 = 0;
5151	radio0 = BWN_RF_READ(mac, 0x43);
5152	radio1 = BWN_RF_READ(mac, 0x51);
5153	radio2 = BWN_RF_READ(mac, 0x52);
5154	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5155	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5156	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5157	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5158
5159	if (phy->type == BWN_PHYTYPE_B) {
5160		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5161		reg0 = BWN_READ_2(mac, 0x3ec);
5162
5163		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5164		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5165	} else if (phy->gmode || phy->rev >= 2) {
5166		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5167		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5168		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5169		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5170		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5171		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5172
5173		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5174		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5175		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5176		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5177		if (BWN_HAS_LOOPBACK(phy)) {
5178			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5179			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5180			if (phy->rev >= 3)
5181				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5182			else
5183				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5184			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5185		}
5186
5187		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5188		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5189			BWN_LPD(0, 1, 1)));
5190		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5191		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5192	}
5193	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5194
5195	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5196	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5197	reg1 = BWN_READ_2(mac, 0x3e6);
5198	reg2 = BWN_READ_2(mac, 0x3f4);
5199
5200	if (phy->analog == 0)
5201		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5202	else {
5203		if (phy->analog >= 2)
5204			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5205		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5206		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5207	}
5208
5209	reg = BWN_RF_READ(mac, 0x60);
5210	index = (reg & 0x001e) >> 1;
5211	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5212
5213	if (phy->type == BWN_PHYTYPE_B)
5214		BWN_RF_WRITE(mac, 0x78, 0x26);
5215	if (phy->gmode || phy->rev >= 2) {
5216		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5217		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5218			BWN_LPD(0, 1, 1)));
5219	}
5220	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5221	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5222	if (phy->gmode || phy->rev >= 2) {
5223		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5224		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5225			BWN_LPD(0, 0, 1)));
5226	}
5227	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5228	BWN_RF_SET(mac, 0x51, 0x0004);
5229	if (phy->rf_rev == 8)
5230		BWN_RF_WRITE(mac, 0x43, 0x1f);
5231	else {
5232		BWN_RF_WRITE(mac, 0x52, 0);
5233		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5234	}
5235	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5236
5237	for (i = 0; i < 16; i++) {
5238		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5239		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5240		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5241		if (phy->gmode || phy->rev >= 2) {
5242			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5243			    bwn_rf_2050_rfoverval(mac,
5244				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5245		}
5246		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5247		DELAY(10);
5248		if (phy->gmode || phy->rev >= 2) {
5249			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5250			    bwn_rf_2050_rfoverval(mac,
5251				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5252		}
5253		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5254		DELAY(10);
5255		if (phy->gmode || phy->rev >= 2) {
5256			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257			    bwn_rf_2050_rfoverval(mac,
5258				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5259		}
5260		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5261		DELAY(20);
5262		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5263		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5264		if (phy->gmode || phy->rev >= 2) {
5265			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5266			    bwn_rf_2050_rfoverval(mac,
5267				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5268		}
5269		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5270	}
5271	DELAY(10);
5272
5273	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5274	tmp1++;
5275	tmp1 >>= 9;
5276
5277	for (i = 0; i < 16; i++) {
5278		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5279		BWN_RF_WRITE(mac, 0x78, radio78);
5280		DELAY(10);
5281		for (j = 0; j < 16; j++) {
5282			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5283			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5284			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5285			if (phy->gmode || phy->rev >= 2) {
5286				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5287				    bwn_rf_2050_rfoverval(mac,
5288					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5289			}
5290			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5291			DELAY(10);
5292			if (phy->gmode || phy->rev >= 2) {
5293				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5294				    bwn_rf_2050_rfoverval(mac,
5295					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5296			}
5297			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5298			DELAY(10);
5299			if (phy->gmode || phy->rev >= 2) {
5300				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5301				    bwn_rf_2050_rfoverval(mac,
5302					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5303			}
5304			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5305			DELAY(10);
5306			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5307			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5308			if (phy->gmode || phy->rev >= 2) {
5309				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5310				    bwn_rf_2050_rfoverval(mac,
5311					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5312			}
5313			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5314		}
5315		tmp2++;
5316		tmp2 >>= 8;
5317		if (tmp1 < tmp2)
5318			break;
5319	}
5320
5321	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5322	BWN_RF_WRITE(mac, 0x51, radio1);
5323	BWN_RF_WRITE(mac, 0x52, radio2);
5324	BWN_RF_WRITE(mac, 0x43, radio0);
5325	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5326	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5327	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5328	BWN_WRITE_2(mac, 0x3e6, reg1);
5329	if (phy->analog != 0)
5330		BWN_WRITE_2(mac, 0x3f4, reg2);
5331	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5332	bwn_spu_workaround(mac, phy->chan);
5333	if (phy->type == BWN_PHYTYPE_B) {
5334		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5335		BWN_WRITE_2(mac, 0x3ec, reg0);
5336	} else if (phy->gmode) {
5337		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5338			    BWN_READ_2(mac, BWN_PHY_RADIO)
5339			    & 0x7fff);
5340		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5341		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5342		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5343		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5344			      analogoverval);
5345		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5346		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5347		if (BWN_HAS_LOOPBACK(phy)) {
5348			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5349			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5350		}
5351	}
5352
5353	return ((i > 15) ? radio78 : rcc);
5354}
5355
5356static void
5357bwn_phy_init_b6(struct bwn_mac *mac)
5358{
5359	struct bwn_phy *phy = &mac->mac_phy;
5360	struct bwn_phy_g *pg = &phy->phy_g;
5361	struct bwn_softc *sc = mac->mac_sc;
5362	uint16_t offset, val;
5363	uint8_t old_channel;
5364
5365	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5366	    ("%s:%d: fail", __func__, __LINE__));
5367
5368	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5369	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5370	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5371		BWN_RF_WRITE(mac, 0x51, 0x37);
5372		BWN_RF_WRITE(mac, 0x52, 0x70);
5373		BWN_RF_WRITE(mac, 0x53, 0xb3);
5374		BWN_RF_WRITE(mac, 0x54, 0x9b);
5375		BWN_RF_WRITE(mac, 0x5a, 0x88);
5376		BWN_RF_WRITE(mac, 0x5b, 0x88);
5377		BWN_RF_WRITE(mac, 0x5d, 0x88);
5378		BWN_RF_WRITE(mac, 0x5e, 0x88);
5379		BWN_RF_WRITE(mac, 0x7d, 0x88);
5380		bwn_hf_write(mac,
5381		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5382	}
5383	if (phy->rf_rev == 8) {
5384		BWN_RF_WRITE(mac, 0x51, 0);
5385		BWN_RF_WRITE(mac, 0x52, 0x40);
5386		BWN_RF_WRITE(mac, 0x53, 0xb7);
5387		BWN_RF_WRITE(mac, 0x54, 0x98);
5388		BWN_RF_WRITE(mac, 0x5a, 0x88);
5389		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5390		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5391		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5392			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5393			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5394		} else {
5395			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5396			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5397		}
5398		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5399		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5400		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5401		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5402	}
5403	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5404		BWN_PHY_WRITE(mac, offset, val);
5405		val -= 0x0202;
5406	}
5407	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5408		BWN_PHY_WRITE(mac, offset, val);
5409		val -= 0x0202;
5410	}
5411	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5412		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5413		val += 0x0202;
5414	}
5415	if (phy->type == BWN_PHYTYPE_G) {
5416		BWN_RF_SET(mac, 0x007a, 0x0020);
5417		BWN_RF_SET(mac, 0x0051, 0x0004);
5418		BWN_PHY_SET(mac, 0x0802, 0x0100);
5419		BWN_PHY_SET(mac, 0x042b, 0x2000);
5420		BWN_PHY_WRITE(mac, 0x5b, 0);
5421		BWN_PHY_WRITE(mac, 0x5c, 0);
5422	}
5423
5424	old_channel = phy->chan;
5425	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5426
5427	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5428	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5429	DELAY(40);
5430	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5431		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5432		BWN_RF_WRITE(mac, 0x50, 0x20);
5433	}
5434	if (phy->rf_rev <= 2) {
5435		BWN_RF_WRITE(mac, 0x7c, 0x20);
5436		BWN_RF_WRITE(mac, 0x5a, 0x70);
5437		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5438		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5439	}
5440	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5441
5442	bwn_phy_g_switch_chan(mac, old_channel, 0);
5443
5444	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5445	if (phy->rf_rev >= 6)
5446		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5447	else
5448		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5449	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5450	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5451	    pg->pg_txctl);
5452	if (phy->rf_rev <= 5)
5453		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5454	if (phy->rf_rev <= 2)
5455		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5456
5457	if (phy->analog == 4) {
5458		BWN_WRITE_2(mac, 0x3e4, 9);
5459		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5460	} else
5461		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5462	if (phy->type == BWN_PHYTYPE_B)
5463		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5464	else if (phy->type == BWN_PHYTYPE_G)
5465		BWN_WRITE_2(mac, 0x03e6, 0x0);
5466}
5467
5468static void
5469bwn_phy_init_a(struct bwn_mac *mac)
5470{
5471	struct bwn_phy *phy = &mac->mac_phy;
5472	struct bwn_softc *sc = mac->mac_sc;
5473
5474	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5475	    ("%s:%d: fail", __func__, __LINE__));
5476
5477	if (phy->rev >= 6) {
5478		if (phy->type == BWN_PHYTYPE_A)
5479			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5480		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5481			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5482		else
5483			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5484	}
5485
5486	bwn_wa_init(mac);
5487
5488	if (phy->type == BWN_PHYTYPE_G &&
5489	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5490		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5491}
5492
5493static void
5494bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5495{
5496	int i;
5497
5498	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5499		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5500}
5501
5502static void
5503bwn_wa_agc(struct bwn_mac *mac)
5504{
5505	struct bwn_phy *phy = &mac->mac_phy;
5506
5507	if (phy->rev == 1) {
5508		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5509		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5510		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5511		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5512		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5513		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5514		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5516		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5517	} else {
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5519		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5522	}
5523
5524	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5525	    0x5700);
5526	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5527	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5528	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5529	BWN_RF_SET(mac, 0x7a, 0x0008);
5530	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5531	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5532	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5533	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5534	if (phy->rev == 1)
5535		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5536	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5537	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5538	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5539	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5540	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5541	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5542	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5543	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5544	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5545	if (phy->rev == 1) {
5546		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5547		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5548	} else {
5549		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5550		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5551		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5552		if (phy->rev >= 6) {
5553			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5554			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5555			    (uint16_t)~0xf000, 0x3000);
5556		}
5557	}
5558	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5559	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5560	if (phy->rev == 1) {
5561		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5562		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5563		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5564		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5565		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5566		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5567		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5568		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5569	} else {
5570		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5571		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5572		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5573		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5574	}
5575	if (phy->rev >= 6) {
5576		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5577		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5578	}
5579	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5580}
5581
5582static void
5583bwn_wa_grev1(struct bwn_mac *mac)
5584{
5585	struct bwn_phy *phy = &mac->mac_phy;
5586	int i;
5587	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5588	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5589	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5590
5591	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5592
5593	/* init CRSTHRES and ANTDWELL */
5594	if (phy->rev == 1) {
5595		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5596	} else if (phy->rev == 2) {
5597		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5598		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5599		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5600	} else {
5601		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5602		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5603		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5604		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5605	}
5606	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5607	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5608	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5609
5610	/* XXX support PHY-A??? */
5611	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5612		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5613		    bwn_tab_finefreqg[i]);
5614
5615	/* XXX support PHY-A??? */
5616	if (phy->rev == 1)
5617		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5618			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5619			    bwn_tab_noise_g1[i]);
5620	else
5621		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5622			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5623			    bwn_tab_noise_g2[i]);
5624
5625
5626	for (i = 0; i < N(bwn_tab_rotor); i++)
5627		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5628		    bwn_tab_rotor[i]);
5629
5630	/* XXX support PHY-A??? */
5631	if (phy->rev >= 6) {
5632		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5633		    BWN_PHY_ENCORE_EN)
5634			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5635		else
5636			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5637	} else
5638		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5639
5640	for (i = 0; i < N(bwn_tab_retard); i++)
5641		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5642		    bwn_tab_retard[i]);
5643
5644	if (phy->rev == 1) {
5645		for (i = 0; i < 16; i++)
5646			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5647			    i, 0x0020);
5648	} else {
5649		for (i = 0; i < 32; i++)
5650			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5651	}
5652
5653	bwn_wa_agc(mac);
5654}
5655
5656static void
5657bwn_wa_grev26789(struct bwn_mac *mac)
5658{
5659	struct bwn_phy *phy = &mac->mac_phy;
5660	int i;
5661	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5662	uint16_t ofdmrev;
5663
5664	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5665
5666	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5667
5668	/* init CRSTHRES and ANTDWELL */
5669	if (phy->rev == 1)
5670		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5671	else if (phy->rev == 2) {
5672		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5673		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5674		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5675	} else {
5676		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5677		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5678		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5679		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5680	}
5681
5682	for (i = 0; i < 64; i++)
5683		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5684
5685	/* XXX support PHY-A??? */
5686	if (phy->rev == 1)
5687		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5688			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5689			    bwn_tab_noise_g1[i]);
5690	else
5691		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5692			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5693			    bwn_tab_noise_g2[i]);
5694
5695	/* XXX support PHY-A??? */
5696	if (phy->rev >= 6) {
5697		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5698		    BWN_PHY_ENCORE_EN)
5699			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5700		else
5701			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5702	} else
5703		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5704
5705	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5706		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5707		    bwn_tab_sigmasqr2[i]);
5708
5709	if (phy->rev == 1) {
5710		for (i = 0; i < 16; i++)
5711			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5712			    0x0020);
5713	} else {
5714		for (i = 0; i < 32; i++)
5715			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5716	}
5717
5718	bwn_wa_agc(mac);
5719
5720	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5721	if (ofdmrev > 2) {
5722		if (phy->type == BWN_PHYTYPE_A)
5723			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5724		else
5725			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5726	} else {
5727		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5728		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5729		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5730	}
5731
5732	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5733	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5734}
5735
5736static void
5737bwn_wa_init(struct bwn_mac *mac)
5738{
5739	struct bwn_phy *phy = &mac->mac_phy;
5740	struct bwn_softc *sc = mac->mac_sc;
5741
5742	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5743
5744	switch (phy->rev) {
5745	case 1:
5746		bwn_wa_grev1(mac);
5747		break;
5748	case 2:
5749	case 6:
5750	case 7:
5751	case 8:
5752	case 9:
5753		bwn_wa_grev26789(mac);
5754		break;
5755	default:
5756		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5757	}
5758
5759	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5760	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5761	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5762		if (phy->rev < 2) {
5763			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5764			    0x0002);
5765			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5766			    0x0001);
5767		} else {
5768			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5769			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5770			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5771			     BWN_BFL_EXTLNA) &&
5772			    (phy->rev >= 7)) {
5773				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5774				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5775				    0x0020, 0x0001);
5776				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5777				    0x0021, 0x0001);
5778				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5779				    0x0022, 0x0001);
5780				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5781				    0x0023, 0x0000);
5782				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5783				    0x0000, 0x0000);
5784				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5785				    0x0003, 0x0002);
5786			}
5787		}
5788	}
5789	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5790		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5791		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5792	}
5793
5794	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5795	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5796}
5797
5798static void
5799bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5800    uint16_t value)
5801{
5802	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5803	uint16_t addr;
5804
5805	addr = table + offset;
5806	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5807	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5808		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5809		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5810	}
5811	pg->pg_ofdmtab_addr = addr;
5812	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5813}
5814
5815static void
5816bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5817    uint32_t value)
5818{
5819	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5820	uint16_t addr;
5821
5822	addr = table + offset;
5823	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5824	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5825		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5826		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5827	}
5828	pg->pg_ofdmtab_addr = addr;
5829
5830	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5831	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5832}
5833
5834static void
5835bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5836    uint16_t value)
5837{
5838
5839	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5840	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5841}
5842
5843static void
5844bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5845{
5846	struct bwn_phy *phy = &mac->mac_phy;
5847	struct bwn_softc *sc = mac->mac_sc;
5848	unsigned int i, max_loop;
5849	uint16_t value;
5850	uint32_t buffer[5] = {
5851		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5852	};
5853
5854	if (ofdm) {
5855		max_loop = 0x1e;
5856		buffer[0] = 0x000201cc;
5857	} else {
5858		max_loop = 0xfa;
5859		buffer[0] = 0x000b846e;
5860	}
5861
5862	BWN_ASSERT_LOCKED(mac->mac_sc);
5863
5864	for (i = 0; i < 5; i++)
5865		bwn_ram_write(mac, i * 4, buffer[i]);
5866
5867	BWN_WRITE_2(mac, 0x0568, 0x0000);
5868	BWN_WRITE_2(mac, 0x07c0,
5869	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5870	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5871	BWN_WRITE_2(mac, 0x050c, value);
5872	if (phy->type == BWN_PHYTYPE_LP)
5873		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5874	BWN_WRITE_2(mac, 0x0508, 0x0000);
5875	BWN_WRITE_2(mac, 0x050a, 0x0000);
5876	BWN_WRITE_2(mac, 0x054c, 0x0000);
5877	BWN_WRITE_2(mac, 0x056a, 0x0014);
5878	BWN_WRITE_2(mac, 0x0568, 0x0826);
5879	BWN_WRITE_2(mac, 0x0500, 0x0000);
5880	if (phy->type == BWN_PHYTYPE_LP)
5881		BWN_WRITE_2(mac, 0x0502, 0x0050);
5882	else
5883		BWN_WRITE_2(mac, 0x0502, 0x0030);
5884
5885	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5886		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5887	for (i = 0x00; i < max_loop; i++) {
5888		value = BWN_READ_2(mac, 0x050e);
5889		if (value & 0x0080)
5890			break;
5891		DELAY(10);
5892	}
5893	for (i = 0x00; i < 0x0a; i++) {
5894		value = BWN_READ_2(mac, 0x050e);
5895		if (value & 0x0400)
5896			break;
5897		DELAY(10);
5898	}
5899	for (i = 0x00; i < 0x19; i++) {
5900		value = BWN_READ_2(mac, 0x0690);
5901		if (!(value & 0x0100))
5902			break;
5903		DELAY(10);
5904	}
5905	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5906		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5907}
5908
5909static void
5910bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5911{
5912	uint32_t macctl;
5913
5914	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5915
5916	macctl = BWN_READ_4(mac, BWN_MACCTL);
5917	if (macctl & BWN_MACCTL_BIGENDIAN)
5918		printf("TODO: need swap\n");
5919
5920	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5921	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5922	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5923}
5924
5925static void
5926bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5927{
5928	uint16_t value;
5929
5930	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5931	    ("%s:%d: fail", __func__, __LINE__));
5932
5933	value = (uint8_t) (ctl->q);
5934	value |= ((uint8_t) (ctl->i)) << 8;
5935	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5936}
5937
5938static uint16_t
5939bwn_lo_calcfeed(struct bwn_mac *mac,
5940    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5941{
5942	struct bwn_phy *phy = &mac->mac_phy;
5943	struct bwn_softc *sc = mac->mac_sc;
5944	uint16_t rfover;
5945	uint16_t feedthrough;
5946
5947	if (phy->gmode) {
5948		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5949		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5950
5951		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5952		    ("%s:%d: fail", __func__, __LINE__));
5953		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5954		    ("%s:%d: fail", __func__, __LINE__));
5955
5956		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5957
5958		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5959		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5960		    phy->rev > 6)
5961			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5962
5963		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5964		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5965		DELAY(10);
5966		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5967		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5968		DELAY(10);
5969		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5970		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5971		DELAY(10);
5972		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5973	} else {
5974		pga |= BWN_PHY_PGACTL_UNKNOWN;
5975		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5976		DELAY(10);
5977		pga |= BWN_PHY_PGACTL_LOWBANDW;
5978		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5979		DELAY(10);
5980		pga |= BWN_PHY_PGACTL_LPF;
5981		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5982	}
5983	DELAY(21);
5984	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5985
5986	return (feedthrough);
5987}
5988
5989static uint16_t
5990bwn_lo_txctl_regtable(struct bwn_mac *mac,
5991    uint16_t *value, uint16_t *pad_mix_gain)
5992{
5993	struct bwn_phy *phy = &mac->mac_phy;
5994	uint16_t reg, v, padmix;
5995
5996	if (phy->type == BWN_PHYTYPE_B) {
5997		v = 0x30;
5998		if (phy->rf_rev <= 5) {
5999			reg = 0x43;
6000			padmix = 0;
6001		} else {
6002			reg = 0x52;
6003			padmix = 5;
6004		}
6005	} else {
6006		if (phy->rev >= 2 && phy->rf_rev == 8) {
6007			reg = 0x43;
6008			v = 0x10;
6009			padmix = 2;
6010		} else {
6011			reg = 0x52;
6012			v = 0x30;
6013			padmix = 5;
6014		}
6015	}
6016	if (value)
6017		*value = v;
6018	if (pad_mix_gain)
6019		*pad_mix_gain = padmix;
6020
6021	return (reg);
6022}
6023
6024static void
6025bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6026{
6027	struct bwn_phy *phy = &mac->mac_phy;
6028	struct bwn_phy_g *pg = &phy->phy_g;
6029	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6030	uint16_t reg, mask;
6031	uint16_t trsw_rx, pga;
6032	uint16_t rf_pctl_reg;
6033
6034	static const uint8_t tx_bias_values[] = {
6035		0x09, 0x08, 0x0a, 0x01, 0x00,
6036		0x02, 0x05, 0x04, 0x06,
6037	};
6038	static const uint8_t tx_magn_values[] = {
6039		0x70, 0x40,
6040	};
6041
6042	if (!BWN_HAS_LOOPBACK(phy)) {
6043		rf_pctl_reg = 6;
6044		trsw_rx = 2;
6045		pga = 0;
6046	} else {
6047		int lb_gain;
6048
6049		trsw_rx = 0;
6050		lb_gain = pg->pg_max_lb_gain / 2;
6051		if (lb_gain > 10) {
6052			rf_pctl_reg = 0;
6053			pga = abs(10 - lb_gain) / 6;
6054			pga = MIN(MAX(pga, 0), 15);
6055		} else {
6056			int cmp_val;
6057			int tmp;
6058
6059			pga = 0;
6060			cmp_val = 0x24;
6061			if ((phy->rev >= 2) &&
6062			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6063				cmp_val = 0x3c;
6064			tmp = lb_gain;
6065			if ((10 - lb_gain) < cmp_val)
6066				tmp = (10 - lb_gain);
6067			if (tmp < 0)
6068				tmp += 6;
6069			else
6070				tmp += 3;
6071			cmp_val /= 4;
6072			tmp /= 4;
6073			if (tmp >= cmp_val)
6074				rf_pctl_reg = cmp_val;
6075			else
6076				rf_pctl_reg = tmp;
6077		}
6078	}
6079	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6080	bwn_phy_g_set_bbatt(mac, 2);
6081
6082	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6083	mask = ~mask;
6084	BWN_RF_MASK(mac, reg, mask);
6085
6086	if (BWN_HAS_TXMAG(phy)) {
6087		int i, j;
6088		int feedthrough;
6089		int min_feedth = 0xffff;
6090		uint8_t tx_magn, tx_bias;
6091
6092		for (i = 0; i < N(tx_magn_values); i++) {
6093			tx_magn = tx_magn_values[i];
6094			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6095			for (j = 0; j < N(tx_bias_values); j++) {
6096				tx_bias = tx_bias_values[j];
6097				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6098				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6099				    trsw_rx);
6100				if (feedthrough < min_feedth) {
6101					lo->tx_bias = tx_bias;
6102					lo->tx_magn = tx_magn;
6103					min_feedth = feedthrough;
6104				}
6105				if (lo->tx_bias == 0)
6106					break;
6107			}
6108			BWN_RF_WRITE(mac, 0x52,
6109					  (BWN_RF_READ(mac, 0x52)
6110					   & 0xff00) | lo->tx_bias | lo->
6111					  tx_magn);
6112		}
6113	} else {
6114		lo->tx_magn = 0;
6115		lo->tx_bias = 0;
6116		BWN_RF_MASK(mac, 0x52, 0xfff0);
6117	}
6118
6119	BWN_GETTIME(lo->txctl_measured_time);
6120}
6121
6122static void
6123bwn_lo_get_powervector(struct bwn_mac *mac)
6124{
6125	struct bwn_phy *phy = &mac->mac_phy;
6126	struct bwn_phy_g *pg = &phy->phy_g;
6127	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6128	int i;
6129	uint64_t tmp;
6130	uint64_t power_vector = 0;
6131
6132	for (i = 0; i < 8; i += 2) {
6133		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6134		power_vector |= (tmp << (i * 8));
6135		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6136	}
6137	if (power_vector)
6138		lo->power_vector = power_vector;
6139
6140	BWN_GETTIME(lo->pwr_vec_read_time);
6141}
6142
6143static void
6144bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6145    int use_trsw_rx)
6146{
6147	struct bwn_phy *phy = &mac->mac_phy;
6148	struct bwn_phy_g *pg = &phy->phy_g;
6149	uint16_t tmp;
6150
6151	if (max_rx_gain < 0)
6152		max_rx_gain = 0;
6153
6154	if (BWN_HAS_LOOPBACK(phy)) {
6155		int trsw_rx = 0;
6156		int trsw_rx_gain;
6157
6158		if (use_trsw_rx) {
6159			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6160			if (max_rx_gain >= trsw_rx_gain) {
6161				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6162				trsw_rx = 0x20;
6163			}
6164		} else
6165			trsw_rx_gain = max_rx_gain;
6166		if (trsw_rx_gain < 9) {
6167			pg->pg_lna_lod_gain = 0;
6168		} else {
6169			pg->pg_lna_lod_gain = 1;
6170			trsw_rx_gain -= 8;
6171		}
6172		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6173		pg->pg_pga_gain = trsw_rx_gain / 3;
6174		if (pg->pg_pga_gain >= 5) {
6175			pg->pg_pga_gain -= 5;
6176			pg->pg_lna_gain = 2;
6177		} else
6178			pg->pg_lna_gain = 0;
6179	} else {
6180		pg->pg_lna_gain = 0;
6181		pg->pg_trsw_rx_gain = 0x20;
6182		if (max_rx_gain >= 0x14) {
6183			pg->pg_lna_lod_gain = 1;
6184			pg->pg_pga_gain = 2;
6185		} else if (max_rx_gain >= 0x12) {
6186			pg->pg_lna_lod_gain = 1;
6187			pg->pg_pga_gain = 1;
6188		} else if (max_rx_gain >= 0xf) {
6189			pg->pg_lna_lod_gain = 1;
6190			pg->pg_pga_gain = 0;
6191		} else {
6192			pg->pg_lna_lod_gain = 0;
6193			pg->pg_pga_gain = 0;
6194		}
6195	}
6196
6197	tmp = BWN_RF_READ(mac, 0x7a);
6198	if (pg->pg_lna_lod_gain == 0)
6199		tmp &= ~0x0008;
6200	else
6201		tmp |= 0x0008;
6202	BWN_RF_WRITE(mac, 0x7a, tmp);
6203}
6204
6205static void
6206bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6207{
6208	struct bwn_phy *phy = &mac->mac_phy;
6209	struct bwn_phy_g *pg = &phy->phy_g;
6210	struct bwn_softc *sc = mac->mac_sc;
6211	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6212	struct timespec ts;
6213	uint16_t tmp;
6214
6215	if (bwn_has_hwpctl(mac)) {
6216		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6217		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6218		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6219		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6220		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6221
6222		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6223		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6224		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6225		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6226	}
6227	if (phy->type == BWN_PHYTYPE_B &&
6228	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6229		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6230		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6231	}
6232	if (phy->rev >= 2) {
6233		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6234		sav->phy_analogoverval =
6235		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6236		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6237		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6238		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6239		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6240		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6241
6242		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6243		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6244		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6245		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6246		if (phy->type == BWN_PHYTYPE_G) {
6247			if ((phy->rev >= 7) &&
6248			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6249			     BWN_BFL_EXTLNA)) {
6250				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6251			} else {
6252				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6253			}
6254		} else {
6255			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6256		}
6257		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6258	}
6259	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6260	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6261	sav->rf0 = BWN_RF_READ(mac, 0x43);
6262	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6263	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6264	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6265	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6266	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6267
6268	if (!BWN_HAS_TXMAG(phy)) {
6269		sav->rf2 = BWN_RF_READ(mac, 0x52);
6270		sav->rf2 &= 0x00f0;
6271	}
6272	if (phy->type == BWN_PHYTYPE_B) {
6273		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6274		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6275		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6276		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6277	} else {
6278		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6279			    | 0x8000);
6280	}
6281	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6282		    & 0xf000);
6283
6284	tmp =
6285	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6286	BWN_PHY_WRITE(mac, tmp, 0x007f);
6287
6288	tmp = sav->phy_syncctl;
6289	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6290	tmp = sav->rf1;
6291	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6292
6293	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6294	if (phy->type == BWN_PHYTYPE_G ||
6295	    (phy->type == BWN_PHYTYPE_B &&
6296	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6297		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6298	} else
6299		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6300	if (phy->rev >= 2)
6301		bwn_dummy_transmission(mac, 0, 1);
6302	bwn_phy_g_switch_chan(mac, 6, 0);
6303	BWN_RF_READ(mac, 0x51);
6304	if (phy->type == BWN_PHYTYPE_G)
6305		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6306
6307	nanouptime(&ts);
6308	if (time_before(lo->txctl_measured_time,
6309	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6310		bwn_lo_measure_txctl_values(mac);
6311
6312	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6313		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6314	else {
6315		if (phy->type == BWN_PHYTYPE_B)
6316			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6317		else
6318			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6319	}
6320}
6321
6322static void
6323bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6324{
6325	struct bwn_phy *phy = &mac->mac_phy;
6326	struct bwn_phy_g *pg = &phy->phy_g;
6327	uint16_t tmp;
6328
6329	if (phy->rev >= 2) {
6330		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6331		tmp = (pg->pg_pga_gain << 8);
6332		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6333		DELAY(5);
6334		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6335		DELAY(2);
6336		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6337	} else {
6338		tmp = (pg->pg_pga_gain | 0xefa0);
6339		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6340	}
6341	if (phy->type == BWN_PHYTYPE_G) {
6342		if (phy->rev >= 3)
6343			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6344		else
6345			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6346		if (phy->rev >= 2)
6347			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6348		else
6349			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6350	}
6351	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6352	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6353	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6354	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6355	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6356	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6357	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6358	if (!BWN_HAS_TXMAG(phy)) {
6359		tmp = sav->rf2;
6360		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6361	}
6362	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6363	if (phy->type == BWN_PHYTYPE_B &&
6364	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6365		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6366		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6367	}
6368	if (phy->rev >= 2) {
6369		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6370		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6371			      sav->phy_analogoverval);
6372		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6373		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6374		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6375		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6376		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6377	}
6378	if (bwn_has_hwpctl(mac)) {
6379		tmp = (sav->phy_lomask & 0xbfff);
6380		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6381		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6382		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6383		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6384		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6385	}
6386	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6387}
6388
6389static int
6390bwn_lo_probe_loctl(struct bwn_mac *mac,
6391    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6392{
6393	struct bwn_phy *phy = &mac->mac_phy;
6394	struct bwn_phy_g *pg = &phy->phy_g;
6395	struct bwn_loctl orig, test;
6396	struct bwn_loctl prev = { -100, -100 };
6397	static const struct bwn_loctl modifiers[] = {
6398		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6399		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6400	};
6401	int begin, end, lower = 0, i;
6402	uint16_t feedth;
6403
6404	if (d->curstate == 0) {
6405		begin = 1;
6406		end = 8;
6407	} else if (d->curstate % 2 == 0) {
6408		begin = d->curstate - 1;
6409		end = d->curstate + 1;
6410	} else {
6411		begin = d->curstate - 2;
6412		end = d->curstate + 2;
6413	}
6414	if (begin < 1)
6415		begin += 8;
6416	if (end > 8)
6417		end -= 8;
6418
6419	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6420	i = begin;
6421	d->curstate = i;
6422	while (1) {
6423		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6424		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6425		test.i += modifiers[i - 1].i * d->multipler;
6426		test.q += modifiers[i - 1].q * d->multipler;
6427		if ((test.i != prev.i || test.q != prev.q) &&
6428		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6429			bwn_lo_write(mac, &test);
6430			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6431			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6432			if (feedth < d->feedth) {
6433				memcpy(probe, &test,
6434				    sizeof(struct bwn_loctl));
6435				lower = 1;
6436				d->feedth = feedth;
6437				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6438					break;
6439			}
6440		}
6441		memcpy(&prev, &test, sizeof(prev));
6442		if (i == end)
6443			break;
6444		if (i == 8)
6445			i = 1;
6446		else
6447			i++;
6448		d->curstate = i;
6449	}
6450
6451	return (lower);
6452}
6453
6454static void
6455bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6456{
6457	struct bwn_phy *phy = &mac->mac_phy;
6458	struct bwn_phy_g *pg = &phy->phy_g;
6459	struct bwn_lo_g_sm d;
6460	struct bwn_loctl probe;
6461	int lower, repeat, cnt = 0;
6462	uint16_t feedth;
6463
6464	d.nmeasure = 0;
6465	d.multipler = 1;
6466	if (BWN_HAS_LOOPBACK(phy))
6467		d.multipler = 3;
6468
6469	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6470	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6471
6472	do {
6473		bwn_lo_write(mac, &d.loctl);
6474		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6475		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6476		if (feedth < 0x258) {
6477			if (feedth >= 0x12c)
6478				*rxgain += 6;
6479			else
6480				*rxgain += 3;
6481			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6482			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6483		}
6484		d.feedth = feedth;
6485		d.curstate = 0;
6486		do {
6487			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6488			    ("%s:%d: fail", __func__, __LINE__));
6489			memcpy(&probe, &d.loctl,
6490			       sizeof(struct bwn_loctl));
6491			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6492			if (!lower)
6493				break;
6494			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6495				break;
6496			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6497			d.nmeasure++;
6498		} while (d.nmeasure < 24);
6499		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6500
6501		if (BWN_HAS_LOOPBACK(phy)) {
6502			if (d.feedth > 0x1194)
6503				*rxgain -= 6;
6504			else if (d.feedth < 0x5dc)
6505				*rxgain += 3;
6506			if (cnt == 0) {
6507				if (d.feedth <= 0x5dc) {
6508					d.multipler = 1;
6509					cnt++;
6510				} else
6511					d.multipler = 2;
6512			} else if (cnt == 2)
6513				d.multipler = 1;
6514		}
6515		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6516	} while (++cnt < repeat);
6517}
6518
6519static struct bwn_lo_calib *
6520bwn_lo_calibset(struct bwn_mac *mac,
6521    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6522{
6523	struct bwn_phy *phy = &mac->mac_phy;
6524	struct bwn_phy_g *pg = &phy->phy_g;
6525	struct bwn_loctl loctl = { 0, 0 };
6526	struct bwn_lo_calib *cal;
6527	struct bwn_lo_g_value sval = { 0 };
6528	int rxgain;
6529	uint16_t pad, reg, value;
6530
6531	sval.old_channel = phy->chan;
6532	bwn_mac_suspend(mac);
6533	bwn_lo_save(mac, &sval);
6534
6535	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6536	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6537	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6538
6539	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6540	if (rfatt->padmix)
6541		rxgain -= pad;
6542	if (BWN_HAS_LOOPBACK(phy))
6543		rxgain += pg->pg_max_lb_gain;
6544	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6545	bwn_phy_g_set_bbatt(mac, bbatt->att);
6546	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6547
6548	bwn_lo_restore(mac, &sval);
6549	bwn_mac_enable(mac);
6550
6551	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6552	if (!cal) {
6553		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6554		return (NULL);
6555	}
6556	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6557	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6558	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6559
6560	BWN_GETTIME(cal->calib_time);
6561
6562	return (cal);
6563}
6564
6565static struct bwn_lo_calib *
6566bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6567    const struct bwn_rfatt *rfatt)
6568{
6569	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6570	struct bwn_lo_calib *c;
6571
6572	TAILQ_FOREACH(c, &lo->calib_list, list) {
6573		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6574			continue;
6575		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6576			continue;
6577		return (c);
6578	}
6579
6580	c = bwn_lo_calibset(mac, bbatt, rfatt);
6581	if (!c)
6582		return (NULL);
6583	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6584
6585	return (c);
6586}
6587
6588static void
6589bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6590{
6591	struct bwn_phy *phy = &mac->mac_phy;
6592	struct bwn_phy_g *pg = &phy->phy_g;
6593	struct bwn_softc *sc = mac->mac_sc;
6594	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6595	const struct bwn_rfatt *rfatt;
6596	const struct bwn_bbatt *bbatt;
6597	uint64_t pvector;
6598	int i;
6599	int rf_offset, bb_offset;
6600	uint8_t changed = 0;
6601
6602	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6603	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6604	    ("%s:%d: fail", __func__, __LINE__));
6605
6606	pvector = lo->power_vector;
6607	if (!update && !pvector)
6608		return;
6609
6610	bwn_mac_suspend(mac);
6611
6612	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6613		struct bwn_lo_calib *cal;
6614		int idx;
6615		uint16_t val;
6616
6617		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6618			continue;
6619		bb_offset = i / lo->rfatt.len;
6620		rf_offset = i % lo->rfatt.len;
6621		bbatt = &(lo->bbatt.array[bb_offset]);
6622		rfatt = &(lo->rfatt.array[rf_offset]);
6623
6624		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6625		if (!cal) {
6626			device_printf(sc->sc_dev, "LO: Could not "
6627			    "calibrate DC table entry\n");
6628			continue;
6629		}
6630		val = (uint8_t)(cal->ctl.q);
6631		val |= ((uint8_t)(cal->ctl.i)) << 4;
6632		free(cal, M_DEVBUF);
6633
6634		idx = i / 2;
6635		if (i % 2)
6636			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6637			    | ((val & 0x00ff) << 8);
6638		else
6639			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6640			    | (val & 0x00ff);
6641		changed = 1;
6642	}
6643	if (changed) {
6644		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6645			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6646	}
6647	bwn_mac_enable(mac);
6648}
6649
6650static void
6651bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6652{
6653
6654	if (!rf->padmix)
6655		return;
6656	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6657		rf->att = 4;
6658}
6659
6660static void
6661bwn_lo_g_adjust(struct bwn_mac *mac)
6662{
6663	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6664	struct bwn_lo_calib *cal;
6665	struct bwn_rfatt rf;
6666
6667	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6668	bwn_lo_fixup_rfatt(&rf);
6669
6670	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6671	if (!cal)
6672		return;
6673	bwn_lo_write(mac, &cal->ctl);
6674}
6675
6676static void
6677bwn_lo_g_init(struct bwn_mac *mac)
6678{
6679
6680	if (!bwn_has_hwpctl(mac))
6681		return;
6682
6683	bwn_lo_get_powervector(mac);
6684	bwn_phy_g_dc_lookup_init(mac, 1);
6685}
6686
6687static void
6688bwn_mac_suspend(struct bwn_mac *mac)
6689{
6690	struct bwn_softc *sc = mac->mac_sc;
6691	int i;
6692	uint32_t tmp;
6693
6694	KASSERT(mac->mac_suspended >= 0,
6695	    ("%s:%d: fail", __func__, __LINE__));
6696
6697	if (mac->mac_suspended == 0) {
6698		bwn_psctl(mac, BWN_PS_AWAKE);
6699		BWN_WRITE_4(mac, BWN_MACCTL,
6700			    BWN_READ_4(mac, BWN_MACCTL)
6701			    & ~BWN_MACCTL_ON);
6702		BWN_READ_4(mac, BWN_MACCTL);
6703		for (i = 35; i; i--) {
6704			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6705			if (tmp & BWN_INTR_MAC_SUSPENDED)
6706				goto out;
6707			DELAY(10);
6708		}
6709		for (i = 40; i; i--) {
6710			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6711			if (tmp & BWN_INTR_MAC_SUSPENDED)
6712				goto out;
6713			DELAY(1000);
6714		}
6715		device_printf(sc->sc_dev, "MAC suspend failed\n");
6716	}
6717out:
6718	mac->mac_suspended++;
6719}
6720
6721static void
6722bwn_mac_enable(struct bwn_mac *mac)
6723{
6724	struct bwn_softc *sc = mac->mac_sc;
6725	uint16_t state;
6726
6727	state = bwn_shm_read_2(mac, BWN_SHARED,
6728	    BWN_SHARED_UCODESTAT);
6729	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6730	    state != BWN_SHARED_UCODESTAT_SLEEP)
6731		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6732
6733	mac->mac_suspended--;
6734	KASSERT(mac->mac_suspended >= 0,
6735	    ("%s:%d: fail", __func__, __LINE__));
6736	if (mac->mac_suspended == 0) {
6737		BWN_WRITE_4(mac, BWN_MACCTL,
6738		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6739		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6740		BWN_READ_4(mac, BWN_MACCTL);
6741		BWN_READ_4(mac, BWN_INTR_REASON);
6742		bwn_psctl(mac, 0);
6743	}
6744}
6745
6746static void
6747bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6748{
6749	struct bwn_softc *sc = mac->mac_sc;
6750	int i;
6751	uint16_t ucstat;
6752
6753	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6754	    ("%s:%d: fail", __func__, __LINE__));
6755	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6756	    ("%s:%d: fail", __func__, __LINE__));
6757
6758	/* XXX forcibly awake and hwps-off */
6759
6760	BWN_WRITE_4(mac, BWN_MACCTL,
6761	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6762	    ~BWN_MACCTL_HWPS);
6763	BWN_READ_4(mac, BWN_MACCTL);
6764	if (siba_get_revid(sc->sc_dev) >= 5) {
6765		for (i = 0; i < 100; i++) {
6766			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6767			    BWN_SHARED_UCODESTAT);
6768			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6769				break;
6770			DELAY(10);
6771		}
6772	}
6773}
6774
6775static int16_t
6776bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6777{
6778
6779	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6780	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6781}
6782
6783static void
6784bwn_nrssi_threshold(struct bwn_mac *mac)
6785{
6786	struct bwn_phy *phy = &mac->mac_phy;
6787	struct bwn_phy_g *pg = &phy->phy_g;
6788	struct bwn_softc *sc = mac->mac_sc;
6789	int32_t a, b;
6790	int16_t tmp16;
6791	uint16_t tmpu16;
6792
6793	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6794
6795	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6796		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6797			a = 0x13;
6798			b = 0x12;
6799		} else {
6800			a = 0xe;
6801			b = 0x11;
6802		}
6803
6804		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6805		a += (pg->pg_nrssi[0] << 6);
6806		a += (a < 32) ? 31 : 32;
6807		a = a >> 6;
6808		a = MIN(MAX(a, -31), 31);
6809
6810		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6811		b += (pg->pg_nrssi[0] << 6);
6812		if (b < 32)
6813			b += 31;
6814		else
6815			b += 32;
6816		b = b >> 6;
6817		b = MIN(MAX(b, -31), 31);
6818
6819		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6820		tmpu16 |= ((uint32_t)b & 0x0000003f);
6821		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6822		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6823		return;
6824	}
6825
6826	tmp16 = bwn_nrssi_read(mac, 0x20);
6827	if (tmp16 >= 0x20)
6828		tmp16 -= 0x40;
6829	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6830}
6831
6832static void
6833bwn_nrssi_slope_11g(struct bwn_mac *mac)
6834{
6835#define	SAVE_RF_MAX		3
6836#define	SAVE_PHY_COMM_MAX	4
6837#define	SAVE_PHY3_MAX		8
6838	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6839		{ 0x7a, 0x52, 0x43 };
6840	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6841		{ 0x15, 0x5a, 0x59, 0x58 };
6842	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6843		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6844		0x0801, 0x0060, 0x0014, 0x0478
6845	};
6846	struct bwn_phy *phy = &mac->mac_phy;
6847	struct bwn_phy_g *pg = &phy->phy_g;
6848	int32_t i, tmp32, phy3_idx = 0;
6849	uint16_t delta, tmp;
6850	uint16_t save_rf[SAVE_RF_MAX];
6851	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6852	uint16_t save_phy3[SAVE_PHY3_MAX];
6853	uint16_t ant_div, phy0, chan_ex;
6854	int16_t nrssi0, nrssi1;
6855
6856	KASSERT(phy->type == BWN_PHYTYPE_G,
6857	    ("%s:%d: fail", __func__, __LINE__));
6858
6859	if (phy->rf_rev >= 9)
6860		return;
6861	if (phy->rf_rev == 8)
6862		bwn_nrssi_offset(mac);
6863
6864	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6865	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6866
6867	/*
6868	 * Save RF/PHY registers for later restoration
6869	 */
6870	ant_div = BWN_READ_2(mac, 0x03e2);
6871	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6872	for (i = 0; i < SAVE_RF_MAX; ++i)
6873		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6874	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6875		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6876
6877	phy0 = BWN_READ_2(mac, BWN_PHY0);
6878	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6879	if (phy->rev >= 3) {
6880		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6881			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6882		BWN_PHY_WRITE(mac, 0x002e, 0);
6883		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6884		switch (phy->rev) {
6885		case 4:
6886		case 6:
6887		case 7:
6888			BWN_PHY_SET(mac, 0x0478, 0x0100);
6889			BWN_PHY_SET(mac, 0x0801, 0x0040);
6890			break;
6891		case 3:
6892		case 5:
6893			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6894			break;
6895		}
6896		BWN_PHY_SET(mac, 0x0060, 0x0040);
6897		BWN_PHY_SET(mac, 0x0014, 0x0200);
6898	}
6899	/*
6900	 * Calculate nrssi0
6901	 */
6902	BWN_RF_SET(mac, 0x007a, 0x0070);
6903	bwn_set_all_gains(mac, 0, 8, 0);
6904	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6905	if (phy->rev >= 2) {
6906		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6907		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6908	}
6909	BWN_RF_SET(mac, 0x007a, 0x0080);
6910	DELAY(20);
6911
6912	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6913	if (nrssi0 >= 0x0020)
6914		nrssi0 -= 0x0040;
6915
6916	/*
6917	 * Calculate nrssi1
6918	 */
6919	BWN_RF_MASK(mac, 0x007a, 0x007f);
6920	if (phy->rev >= 2)
6921		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6922
6923	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6924	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6925	BWN_RF_SET(mac, 0x007a, 0x000f);
6926	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6927	if (phy->rev >= 2) {
6928		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6929		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6930	}
6931
6932	bwn_set_all_gains(mac, 3, 0, 1);
6933	if (phy->rf_rev == 8) {
6934		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6935	} else {
6936		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6937		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6938		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6939		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6940	}
6941	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6942	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6943	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6944	DELAY(20);
6945	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6946
6947	/*
6948	 * Install calculated narrow RSSI values
6949	 */
6950	if (nrssi1 >= 0x0020)
6951		nrssi1 -= 0x0040;
6952	if (nrssi0 == nrssi1)
6953		pg->pg_nrssi_slope = 0x00010000;
6954	else
6955		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6956	if (nrssi0 >= -4) {
6957		pg->pg_nrssi[0] = nrssi1;
6958		pg->pg_nrssi[1] = nrssi0;
6959	}
6960
6961	/*
6962	 * Restore saved RF/PHY registers
6963	 */
6964	if (phy->rev >= 3) {
6965		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6966			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6967			    save_phy3[phy3_idx]);
6968		}
6969	}
6970	if (phy->rev >= 2) {
6971		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6972		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6973	}
6974
6975	for (i = 0; i < SAVE_RF_MAX; ++i)
6976		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6977
6978	BWN_WRITE_2(mac, 0x03e2, ant_div);
6979	BWN_WRITE_2(mac, 0x03e6, phy0);
6980	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6981
6982	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6983		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6984
6985	bwn_spu_workaround(mac, phy->chan);
6986	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6987	bwn_set_original_gains(mac);
6988	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6989	if (phy->rev >= 3) {
6990		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6991			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6992			    save_phy3[phy3_idx]);
6993		}
6994	}
6995
6996	delta = 0x1f - pg->pg_nrssi[0];
6997	for (i = 0; i < 64; i++) {
6998		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6999		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7000		pg->pg_nrssi_lt[i] = tmp32;
7001	}
7002
7003	bwn_nrssi_threshold(mac);
7004#undef SAVE_RF_MAX
7005#undef SAVE_PHY_COMM_MAX
7006#undef SAVE_PHY3_MAX
7007}
7008
7009static void
7010bwn_nrssi_offset(struct bwn_mac *mac)
7011{
7012#define	SAVE_RF_MAX		2
7013#define	SAVE_PHY_COMM_MAX	10
7014#define	SAVE_PHY6_MAX		8
7015	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7016		{ 0x7a, 0x43 };
7017	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7018		0x0001, 0x0811, 0x0812, 0x0814,
7019		0x0815, 0x005a, 0x0059, 0x0058,
7020		0x000a, 0x0003
7021	};
7022	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7023		0x002e, 0x002f, 0x080f, 0x0810,
7024		0x0801, 0x0060, 0x0014, 0x0478
7025	};
7026	struct bwn_phy *phy = &mac->mac_phy;
7027	int i, phy6_idx = 0;
7028	uint16_t save_rf[SAVE_RF_MAX];
7029	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7030	uint16_t save_phy6[SAVE_PHY6_MAX];
7031	int16_t nrssi;
7032	uint16_t saved = 0xffff;
7033
7034	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7035		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7036	for (i = 0; i < SAVE_RF_MAX; ++i)
7037		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7038
7039	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7040	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7041	BWN_PHY_SET(mac, 0x0811, 0x000c);
7042	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7043	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7044	if (phy->rev >= 6) {
7045		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7046			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7047
7048		BWN_PHY_WRITE(mac, 0x002e, 0);
7049		BWN_PHY_WRITE(mac, 0x002f, 0);
7050		BWN_PHY_WRITE(mac, 0x080f, 0);
7051		BWN_PHY_WRITE(mac, 0x0810, 0);
7052		BWN_PHY_SET(mac, 0x0478, 0x0100);
7053		BWN_PHY_SET(mac, 0x0801, 0x0040);
7054		BWN_PHY_SET(mac, 0x0060, 0x0040);
7055		BWN_PHY_SET(mac, 0x0014, 0x0200);
7056	}
7057	BWN_RF_SET(mac, 0x007a, 0x0070);
7058	BWN_RF_SET(mac, 0x007a, 0x0080);
7059	DELAY(30);
7060
7061	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7062	if (nrssi >= 0x20)
7063		nrssi -= 0x40;
7064	if (nrssi == 31) {
7065		for (i = 7; i >= 4; i--) {
7066			BWN_RF_WRITE(mac, 0x007b, i);
7067			DELAY(20);
7068			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7069			    0x003f);
7070			if (nrssi >= 0x20)
7071				nrssi -= 0x40;
7072			if (nrssi < 31 && saved == 0xffff)
7073				saved = i;
7074		}
7075		if (saved == 0xffff)
7076			saved = 4;
7077	} else {
7078		BWN_RF_MASK(mac, 0x007a, 0x007f);
7079		if (phy->rev != 1) {
7080			BWN_PHY_SET(mac, 0x0814, 0x0001);
7081			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7082		}
7083		BWN_PHY_SET(mac, 0x0811, 0x000c);
7084		BWN_PHY_SET(mac, 0x0812, 0x000c);
7085		BWN_PHY_SET(mac, 0x0811, 0x0030);
7086		BWN_PHY_SET(mac, 0x0812, 0x0030);
7087		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7088		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7089		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7090		if (phy->rev == 0)
7091			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7092		else
7093			BWN_PHY_SET(mac, 0x000a, 0x2000);
7094		if (phy->rev != 1) {
7095			BWN_PHY_SET(mac, 0x0814, 0x0004);
7096			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7097		}
7098		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7099		BWN_RF_SET(mac, 0x007a, 0x000f);
7100		bwn_set_all_gains(mac, 3, 0, 1);
7101		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7102		DELAY(30);
7103		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7104		if (nrssi >= 0x20)
7105			nrssi -= 0x40;
7106		if (nrssi == -32) {
7107			for (i = 0; i < 4; i++) {
7108				BWN_RF_WRITE(mac, 0x007b, i);
7109				DELAY(20);
7110				nrssi = (int16_t)((BWN_PHY_READ(mac,
7111				    0x047f) >> 8) & 0x003f);
7112				if (nrssi >= 0x20)
7113					nrssi -= 0x40;
7114				if (nrssi > -31 && saved == 0xffff)
7115					saved = i;
7116			}
7117			if (saved == 0xffff)
7118				saved = 3;
7119		} else
7120			saved = 0;
7121	}
7122	BWN_RF_WRITE(mac, 0x007b, saved);
7123
7124	/*
7125	 * Restore saved RF/PHY registers
7126	 */
7127	if (phy->rev >= 6) {
7128		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7129			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7130			    save_phy6[phy6_idx]);
7131		}
7132	}
7133	if (phy->rev != 1) {
7134		for (i = 3; i < 5; i++)
7135			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7136			    save_phy_comm[i]);
7137	}
7138	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7139		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7140
7141	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7142		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7143
7144	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7145	BWN_PHY_SET(mac, 0x0429, 0x8000);
7146	bwn_set_original_gains(mac);
7147	if (phy->rev >= 6) {
7148		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7149			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7150			    save_phy6[phy6_idx]);
7151		}
7152	}
7153
7154	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7155	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7156	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7157}
7158
7159static void
7160bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7161    int16_t third)
7162{
7163	struct bwn_phy *phy = &mac->mac_phy;
7164	uint16_t i;
7165	uint16_t start = 0x08, end = 0x18;
7166	uint16_t tmp;
7167	uint16_t table;
7168
7169	if (phy->rev <= 1) {
7170		start = 0x10;
7171		end = 0x20;
7172	}
7173
7174	table = BWN_OFDMTAB_GAINX;
7175	if (phy->rev <= 1)
7176		table = BWN_OFDMTAB_GAINX_R1;
7177	for (i = 0; i < 4; i++)
7178		bwn_ofdmtab_write_2(mac, table, i, first);
7179
7180	for (i = start; i < end; i++)
7181		bwn_ofdmtab_write_2(mac, table, i, second);
7182
7183	if (third != -1) {
7184		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7185		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7186		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7187		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7188	}
7189	bwn_dummy_transmission(mac, 0, 1);
7190}
7191
7192static void
7193bwn_set_original_gains(struct bwn_mac *mac)
7194{
7195	struct bwn_phy *phy = &mac->mac_phy;
7196	uint16_t i, tmp;
7197	uint16_t table;
7198	uint16_t start = 0x0008, end = 0x0018;
7199
7200	if (phy->rev <= 1) {
7201		start = 0x0010;
7202		end = 0x0020;
7203	}
7204
7205	table = BWN_OFDMTAB_GAINX;
7206	if (phy->rev <= 1)
7207		table = BWN_OFDMTAB_GAINX_R1;
7208	for (i = 0; i < 4; i++) {
7209		tmp = (i & 0xfffc);
7210		tmp |= (i & 0x0001) << 1;
7211		tmp |= (i & 0x0002) >> 1;
7212
7213		bwn_ofdmtab_write_2(mac, table, i, tmp);
7214	}
7215
7216	for (i = start; i < end; i++)
7217		bwn_ofdmtab_write_2(mac, table, i, i - start);
7218
7219	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7220	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7221	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7222	bwn_dummy_transmission(mac, 0, 1);
7223}
7224
7225static void
7226bwn_phy_hwpctl_init(struct bwn_mac *mac)
7227{
7228	struct bwn_phy *phy = &mac->mac_phy;
7229	struct bwn_phy_g *pg = &phy->phy_g;
7230	struct bwn_rfatt old_rfatt, rfatt;
7231	struct bwn_bbatt old_bbatt, bbatt;
7232	struct bwn_softc *sc = mac->mac_sc;
7233	uint8_t old_txctl = 0;
7234
7235	KASSERT(phy->type == BWN_PHYTYPE_G,
7236	    ("%s:%d: fail", __func__, __LINE__));
7237
7238	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7239	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7240		return;
7241
7242	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7243
7244	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7245
7246	if (!phy->gmode)
7247		return;
7248	bwn_hwpctl_early_init(mac);
7249	if (pg->pg_curtssi == 0) {
7250		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7251			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7252		} else {
7253			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7254			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7255			old_txctl = pg->pg_txctl;
7256
7257			bbatt.att = 11;
7258			if (phy->rf_rev == 8) {
7259				rfatt.att = 15;
7260				rfatt.padmix = 1;
7261			} else {
7262				rfatt.att = 9;
7263				rfatt.padmix = 0;
7264			}
7265			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7266		}
7267		bwn_dummy_transmission(mac, 0, 1);
7268		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7269		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7270			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7271		else
7272			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7273			    &old_rfatt, old_txctl);
7274	}
7275	bwn_hwpctl_init_gphy(mac);
7276
7277	/* clear TSSI */
7278	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7279	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7280	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7281	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7282}
7283
7284static void
7285bwn_hwpctl_early_init(struct bwn_mac *mac)
7286{
7287	struct bwn_phy *phy = &mac->mac_phy;
7288
7289	if (!bwn_has_hwpctl(mac)) {
7290		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7291		return;
7292	}
7293
7294	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7295	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7296	BWN_PHY_SET(mac, 0x047c, 0x0002);
7297	BWN_PHY_SET(mac, 0x047a, 0xf000);
7298	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7299		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7300		BWN_PHY_SET(mac, 0x005d, 0x8000);
7301		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7302		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7303		BWN_PHY_SET(mac, 0x0036, 0x0400);
7304	} else {
7305		BWN_PHY_SET(mac, 0x0036, 0x0200);
7306		BWN_PHY_SET(mac, 0x0036, 0x0400);
7307		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7308		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7309		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7310		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7311		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7312	}
7313}
7314
7315static void
7316bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7317{
7318	struct bwn_phy *phy = &mac->mac_phy;
7319	struct bwn_phy_g *pg = &phy->phy_g;
7320	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7321	int i;
7322	uint16_t nr_written = 0, tmp, value;
7323	uint8_t rf, bb;
7324
7325	if (!bwn_has_hwpctl(mac)) {
7326		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7327		return;
7328	}
7329
7330	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7331	    (pg->pg_idletssi - pg->pg_curtssi));
7332	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7333	    (pg->pg_idletssi - pg->pg_curtssi));
7334
7335	for (i = 0; i < 32; i++)
7336		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7337	for (i = 32; i < 64; i++)
7338		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7339	for (i = 0; i < 64; i += 2) {
7340		value = (uint16_t) pg->pg_tssi2dbm[i];
7341		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7342		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7343	}
7344
7345	for (rf = 0; rf < lo->rfatt.len; rf++) {
7346		for (bb = 0; bb < lo->bbatt.len; bb++) {
7347			if (nr_written >= 0x40)
7348				return;
7349			tmp = lo->bbatt.array[bb].att;
7350			tmp <<= 8;
7351			if (phy->rf_rev == 8)
7352				tmp |= 0x50;
7353			else
7354				tmp |= 0x40;
7355			tmp |= lo->rfatt.array[rf].att;
7356			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7357			nr_written++;
7358		}
7359	}
7360
7361	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7362	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7363
7364	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7365	BWN_PHY_SET(mac, 0x0478, 0x0800);
7366	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7367	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7368
7369	bwn_phy_g_dc_lookup_init(mac, 1);
7370	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7371}
7372
7373static void
7374bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7375{
7376	struct bwn_softc *sc = mac->mac_sc;
7377
7378	if (spu != 0)
7379		bwn_spu_workaround(mac, channel);
7380
7381	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7382
7383	if (channel == 14) {
7384		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7385			bwn_hf_write(mac,
7386			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7387		else
7388			bwn_hf_write(mac,
7389			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7390		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7391		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7392		return;
7393	}
7394
7395	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7396	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7397}
7398
7399static uint16_t
7400bwn_phy_g_chan2freq(uint8_t channel)
7401{
7402	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7403
7404	KASSERT(channel >= 1 && channel <= 14,
7405	    ("%s:%d: fail", __func__, __LINE__));
7406
7407	return (bwn_phy_g_rf_channels[channel - 1]);
7408}
7409
7410static void
7411bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7412    const struct bwn_rfatt *rfatt, uint8_t txctl)
7413{
7414	struct bwn_phy *phy = &mac->mac_phy;
7415	struct bwn_phy_g *pg = &phy->phy_g;
7416	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7417	uint16_t bb, rf;
7418	uint16_t tx_bias, tx_magn;
7419
7420	bb = bbatt->att;
7421	rf = rfatt->att;
7422	tx_bias = lo->tx_bias;
7423	tx_magn = lo->tx_magn;
7424	if (tx_bias == 0xff)
7425		tx_bias = 0;
7426
7427	pg->pg_txctl = txctl;
7428	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7429	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7430	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7431	bwn_phy_g_set_bbatt(mac, bb);
7432	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7433	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7434		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7435	else {
7436		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7437		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7438	}
7439	if (BWN_HAS_TXMAG(phy))
7440		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7441	else
7442		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7443	bwn_lo_g_adjust(mac);
7444}
7445
7446static void
7447bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7448    uint16_t bbatt)
7449{
7450	struct bwn_phy *phy = &mac->mac_phy;
7451
7452	if (phy->analog == 0) {
7453		BWN_WRITE_2(mac, BWN_PHY0,
7454		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7455		return;
7456	}
7457	if (phy->analog > 1) {
7458		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7459		return;
7460	}
7461	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7462}
7463
7464static uint16_t
7465bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7466{
7467	struct bwn_phy *phy = &mac->mac_phy;
7468	struct bwn_phy_g *pg = &phy->phy_g;
7469	struct bwn_softc *sc = mac->mac_sc;
7470	int max_lb_gain;
7471	uint16_t extlna;
7472	uint16_t i;
7473
7474	if (phy->gmode == 0)
7475		return (0);
7476
7477	if (BWN_HAS_LOOPBACK(phy)) {
7478		max_lb_gain = pg->pg_max_lb_gain;
7479		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7480		if (max_lb_gain >= 0x46) {
7481			extlna = 0x3000;
7482			max_lb_gain -= 0x46;
7483		} else if (max_lb_gain >= 0x3a) {
7484			extlna = 0x1000;
7485			max_lb_gain -= 0x3a;
7486		} else if (max_lb_gain >= 0x2e) {
7487			extlna = 0x2000;
7488			max_lb_gain -= 0x2e;
7489		} else {
7490			extlna = 0;
7491			max_lb_gain -= 0x10;
7492		}
7493
7494		for (i = 0; i < 16; i++) {
7495			max_lb_gain -= (i * 6);
7496			if (max_lb_gain < 6)
7497				break;
7498		}
7499
7500		if ((phy->rev < 7) ||
7501		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7502			if (reg == BWN_PHY_RFOVER) {
7503				return (0x1b3);
7504			} else if (reg == BWN_PHY_RFOVERVAL) {
7505				extlna |= (i << 8);
7506				switch (lpd) {
7507				case BWN_LPD(0, 1, 1):
7508					return (0x0f92);
7509				case BWN_LPD(0, 0, 1):
7510				case BWN_LPD(1, 0, 1):
7511					return (0x0092 | extlna);
7512				case BWN_LPD(1, 0, 0):
7513					return (0x0093 | extlna);
7514				}
7515				KASSERT(0 == 1,
7516				    ("%s:%d: fail", __func__, __LINE__));
7517			}
7518			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7519		} else {
7520			if (reg == BWN_PHY_RFOVER)
7521				return (0x9b3);
7522			if (reg == BWN_PHY_RFOVERVAL) {
7523				if (extlna)
7524					extlna |= 0x8000;
7525				extlna |= (i << 8);
7526				switch (lpd) {
7527				case BWN_LPD(0, 1, 1):
7528					return (0x8f92);
7529				case BWN_LPD(0, 0, 1):
7530					return (0x8092 | extlna);
7531				case BWN_LPD(1, 0, 1):
7532					return (0x2092 | extlna);
7533				case BWN_LPD(1, 0, 0):
7534					return (0x2093 | extlna);
7535				}
7536				KASSERT(0 == 1,
7537				    ("%s:%d: fail", __func__, __LINE__));
7538			}
7539			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7540		}
7541		return (0);
7542	}
7543
7544	if ((phy->rev < 7) ||
7545	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7546		if (reg == BWN_PHY_RFOVER) {
7547			return (0x1b3);
7548		} else if (reg == BWN_PHY_RFOVERVAL) {
7549			switch (lpd) {
7550			case BWN_LPD(0, 1, 1):
7551				return (0x0fb2);
7552			case BWN_LPD(0, 0, 1):
7553				return (0x00b2);
7554			case BWN_LPD(1, 0, 1):
7555				return (0x30b2);
7556			case BWN_LPD(1, 0, 0):
7557				return (0x30b3);
7558			}
7559			KASSERT(0 == 1,
7560			    ("%s:%d: fail", __func__, __LINE__));
7561		}
7562		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7563	} else {
7564		if (reg == BWN_PHY_RFOVER) {
7565			return (0x9b3);
7566		} else if (reg == BWN_PHY_RFOVERVAL) {
7567			switch (lpd) {
7568			case BWN_LPD(0, 1, 1):
7569				return (0x8fb2);
7570			case BWN_LPD(0, 0, 1):
7571				return (0x80b2);
7572			case BWN_LPD(1, 0, 1):
7573				return (0x20b2);
7574			case BWN_LPD(1, 0, 0):
7575				return (0x20b3);
7576			}
7577			KASSERT(0 == 1,
7578			    ("%s:%d: fail", __func__, __LINE__));
7579		}
7580		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7581	}
7582	return (0);
7583}
7584
7585static void
7586bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7587{
7588
7589	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7590		return;
7591	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7592	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7593	DELAY(1000);
7594	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7595}
7596
7597static int
7598bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7599{
7600	struct bwn_softc *sc = mac->mac_sc;
7601	struct bwn_fw *fw = &mac->mac_fw;
7602	const uint8_t rev = siba_get_revid(sc->sc_dev);
7603	const char *filename;
7604	uint32_t high;
7605	int error;
7606
7607	/* microcode */
7608	if (rev >= 5 && rev <= 10)
7609		filename = "ucode5";
7610	else if (rev >= 11 && rev <= 12)
7611		filename = "ucode11";
7612	else if (rev == 13)
7613		filename = "ucode13";
7614	else if (rev == 14)
7615		filename = "ucode14";
7616	else if (rev >= 15)
7617		filename = "ucode15";
7618	else {
7619		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7620		bwn_release_firmware(mac);
7621		return (EOPNOTSUPP);
7622	}
7623	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7624	if (error) {
7625		bwn_release_firmware(mac);
7626		return (error);
7627	}
7628
7629	/* PCM */
7630	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7631	if (rev >= 5 && rev <= 10) {
7632		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7633		if (error == ENOENT)
7634			fw->no_pcmfile = 1;
7635		else if (error) {
7636			bwn_release_firmware(mac);
7637			return (error);
7638		}
7639	} else if (rev < 11) {
7640		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7641		return (EOPNOTSUPP);
7642	}
7643
7644	/* initvals */
7645	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7646	switch (mac->mac_phy.type) {
7647	case BWN_PHYTYPE_A:
7648		if (rev < 5 || rev > 10)
7649			goto fail1;
7650		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7651			filename = "a0g1initvals5";
7652		else
7653			filename = "a0g0initvals5";
7654		break;
7655	case BWN_PHYTYPE_G:
7656		if (rev >= 5 && rev <= 10)
7657			filename = "b0g0initvals5";
7658		else if (rev >= 13)
7659			filename = "b0g0initvals13";
7660		else
7661			goto fail1;
7662		break;
7663	case BWN_PHYTYPE_LP:
7664		if (rev == 13)
7665			filename = "lp0initvals13";
7666		else if (rev == 14)
7667			filename = "lp0initvals14";
7668		else if (rev >= 15)
7669			filename = "lp0initvals15";
7670		else
7671			goto fail1;
7672		break;
7673	case BWN_PHYTYPE_N:
7674		if (rev >= 11 && rev <= 12)
7675			filename = "n0initvals11";
7676		else
7677			goto fail1;
7678		break;
7679	default:
7680		goto fail1;
7681	}
7682	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7683	if (error) {
7684		bwn_release_firmware(mac);
7685		return (error);
7686	}
7687
7688	/* bandswitch initvals */
7689	switch (mac->mac_phy.type) {
7690	case BWN_PHYTYPE_A:
7691		if (rev >= 5 && rev <= 10) {
7692			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7693				filename = "a0g1bsinitvals5";
7694			else
7695				filename = "a0g0bsinitvals5";
7696		} else if (rev >= 11)
7697			filename = NULL;
7698		else
7699			goto fail1;
7700		break;
7701	case BWN_PHYTYPE_G:
7702		if (rev >= 5 && rev <= 10)
7703			filename = "b0g0bsinitvals5";
7704		else if (rev >= 11)
7705			filename = NULL;
7706		else
7707			goto fail1;
7708		break;
7709	case BWN_PHYTYPE_LP:
7710		if (rev == 13)
7711			filename = "lp0bsinitvals13";
7712		else if (rev == 14)
7713			filename = "lp0bsinitvals14";
7714		else if (rev >= 15)
7715			filename = "lp0bsinitvals15";
7716		else
7717			goto fail1;
7718		break;
7719	case BWN_PHYTYPE_N:
7720		if (rev >= 11 && rev <= 12)
7721			filename = "n0bsinitvals11";
7722		else
7723			goto fail1;
7724		break;
7725	default:
7726		goto fail1;
7727	}
7728	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7729	if (error) {
7730		bwn_release_firmware(mac);
7731		return (error);
7732	}
7733	return (0);
7734fail1:
7735	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7736	bwn_release_firmware(mac);
7737	return (EOPNOTSUPP);
7738}
7739
7740static int
7741bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7742    const char *name, struct bwn_fwfile *bfw)
7743{
7744	const struct bwn_fwhdr *hdr;
7745	struct bwn_softc *sc = mac->mac_sc;
7746	const struct firmware *fw;
7747	char namebuf[64];
7748
7749	if (name == NULL) {
7750		bwn_do_release_fw(bfw);
7751		return (0);
7752	}
7753	if (bfw->filename != NULL) {
7754		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7755			return (0);
7756		bwn_do_release_fw(bfw);
7757	}
7758
7759	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7760	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7761	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7762	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7763	fw = firmware_get(namebuf);
7764	if (fw == NULL) {
7765		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7766		    namebuf);
7767		return (ENOENT);
7768	}
7769	if (fw->datasize < sizeof(struct bwn_fwhdr))
7770		goto fail;
7771	hdr = (const struct bwn_fwhdr *)(fw->data);
7772	switch (hdr->type) {
7773	case BWN_FWTYPE_UCODE:
7774	case BWN_FWTYPE_PCM:
7775		if (be32toh(hdr->size) !=
7776		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7777			goto fail;
7778		/* FALLTHROUGH */
7779	case BWN_FWTYPE_IV:
7780		if (hdr->ver != 1)
7781			goto fail;
7782		break;
7783	default:
7784		goto fail;
7785	}
7786	bfw->filename = name;
7787	bfw->fw = fw;
7788	bfw->type = type;
7789	return (0);
7790fail:
7791	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7792	if (fw != NULL)
7793		firmware_put(fw, FIRMWARE_UNLOAD);
7794	return (EPROTO);
7795}
7796
7797static void
7798bwn_release_firmware(struct bwn_mac *mac)
7799{
7800
7801	bwn_do_release_fw(&mac->mac_fw.ucode);
7802	bwn_do_release_fw(&mac->mac_fw.pcm);
7803	bwn_do_release_fw(&mac->mac_fw.initvals);
7804	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7805}
7806
7807static void
7808bwn_do_release_fw(struct bwn_fwfile *bfw)
7809{
7810
7811	if (bfw->fw != NULL)
7812		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7813	bfw->fw = NULL;
7814	bfw->filename = NULL;
7815}
7816
7817static int
7818bwn_fw_loaducode(struct bwn_mac *mac)
7819{
7820#define	GETFWOFFSET(fwp, offset)	\
7821	((const uint32_t *)((const char *)fwp.fw->data + offset))
7822#define	GETFWSIZE(fwp, offset)	\
7823	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7824	struct bwn_softc *sc = mac->mac_sc;
7825	const uint32_t *data;
7826	unsigned int i;
7827	uint32_t ctl;
7828	uint16_t date, fwcaps, time;
7829	int error = 0;
7830
7831	ctl = BWN_READ_4(mac, BWN_MACCTL);
7832	ctl |= BWN_MACCTL_MCODE_JMP0;
7833	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7834	    __LINE__));
7835	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7836	for (i = 0; i < 64; i++)
7837		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7838	for (i = 0; i < 4096; i += 2)
7839		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7840
7841	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7842	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7843	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7844	     i++) {
7845		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7846		DELAY(10);
7847	}
7848
7849	if (mac->mac_fw.pcm.fw) {
7850		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7851		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7852		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7853		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7854		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7855		    sizeof(struct bwn_fwhdr)); i++) {
7856			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7857			DELAY(10);
7858		}
7859	}
7860
7861	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7862	BWN_WRITE_4(mac, BWN_MACCTL,
7863	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7864	    BWN_MACCTL_MCODE_RUN);
7865
7866	for (i = 0; i < 21; i++) {
7867		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7868			break;
7869		if (i >= 20) {
7870			device_printf(sc->sc_dev, "ucode timeout\n");
7871			error = ENXIO;
7872			goto error;
7873		}
7874		DELAY(50000);
7875	}
7876	BWN_READ_4(mac, BWN_INTR_REASON);
7877
7878	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7879	if (mac->mac_fw.rev <= 0x128) {
7880		device_printf(sc->sc_dev, "the firmware is too old\n");
7881		error = EOPNOTSUPP;
7882		goto error;
7883	}
7884	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7885	    BWN_SHARED_UCODE_PATCH);
7886	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7887	mac->mac_fw.opensource = (date == 0xffff);
7888	if (bwn_wme != 0)
7889		mac->mac_flags |= BWN_MAC_FLAG_WME;
7890	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7891
7892	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7893	if (mac->mac_fw.opensource == 0) {
7894		device_printf(sc->sc_dev,
7895		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7896		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7897		if (mac->mac_fw.no_pcmfile)
7898			device_printf(sc->sc_dev,
7899			    "no HW crypto acceleration due to pcm5\n");
7900	} else {
7901		mac->mac_fw.patch = time;
7902		fwcaps = bwn_fwcaps_read(mac);
7903		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7904			device_printf(sc->sc_dev,
7905			    "disabling HW crypto acceleration\n");
7906			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7907		}
7908		if (!(fwcaps & BWN_FWCAPS_WME)) {
7909			device_printf(sc->sc_dev, "disabling WME support\n");
7910			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7911		}
7912	}
7913
7914	if (BWN_ISOLDFMT(mac))
7915		device_printf(sc->sc_dev, "using old firmware image\n");
7916
7917	return (0);
7918
7919error:
7920	BWN_WRITE_4(mac, BWN_MACCTL,
7921	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7922	    BWN_MACCTL_MCODE_JMP0);
7923
7924	return (error);
7925#undef GETFWSIZE
7926#undef GETFWOFFSET
7927}
7928
7929/* OpenFirmware only */
7930static uint16_t
7931bwn_fwcaps_read(struct bwn_mac *mac)
7932{
7933
7934	KASSERT(mac->mac_fw.opensource == 1,
7935	    ("%s:%d: fail", __func__, __LINE__));
7936	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7937}
7938
7939static int
7940bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7941    size_t count, size_t array_size)
7942{
7943#define	GET_NEXTIV16(iv)						\
7944	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7945	    sizeof(uint16_t) + sizeof(uint16_t)))
7946#define	GET_NEXTIV32(iv)						\
7947	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7948	    sizeof(uint16_t) + sizeof(uint32_t)))
7949	struct bwn_softc *sc = mac->mac_sc;
7950	const struct bwn_fwinitvals *iv;
7951	uint16_t offset;
7952	size_t i;
7953	uint8_t bit32;
7954
7955	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7956	    ("%s:%d: fail", __func__, __LINE__));
7957	iv = ivals;
7958	for (i = 0; i < count; i++) {
7959		if (array_size < sizeof(iv->offset_size))
7960			goto fail;
7961		array_size -= sizeof(iv->offset_size);
7962		offset = be16toh(iv->offset_size);
7963		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7964		offset &= BWN_FWINITVALS_OFFSET_MASK;
7965		if (offset >= 0x1000)
7966			goto fail;
7967		if (bit32) {
7968			if (array_size < sizeof(iv->data.d32))
7969				goto fail;
7970			array_size -= sizeof(iv->data.d32);
7971			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7972			iv = GET_NEXTIV32(iv);
7973		} else {
7974
7975			if (array_size < sizeof(iv->data.d16))
7976				goto fail;
7977			array_size -= sizeof(iv->data.d16);
7978			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7979
7980			iv = GET_NEXTIV16(iv);
7981		}
7982	}
7983	if (array_size != 0)
7984		goto fail;
7985	return (0);
7986fail:
7987	device_printf(sc->sc_dev, "initvals: invalid format\n");
7988	return (EPROTO);
7989#undef GET_NEXTIV16
7990#undef GET_NEXTIV32
7991}
7992
7993static int
7994bwn_switch_channel(struct bwn_mac *mac, int chan)
7995{
7996	struct bwn_phy *phy = &(mac->mac_phy);
7997	struct bwn_softc *sc = mac->mac_sc;
7998	struct ifnet *ifp = sc->sc_ifp;
7999	struct ieee80211com *ic = ifp->if_l2com;
8000	uint16_t channelcookie, savedcookie;
8001	int error;
8002
8003	if (chan == 0xffff)
8004		chan = phy->get_default_chan(mac);
8005
8006	channelcookie = chan;
8007	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8008		channelcookie |= 0x100;
8009	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8010	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8011	error = phy->switch_channel(mac, chan);
8012	if (error)
8013		goto fail;
8014
8015	mac->mac_phy.chan = chan;
8016	DELAY(8000);
8017	return (0);
8018fail:
8019	device_printf(sc->sc_dev, "failed to switch channel\n");
8020	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8021	return (error);
8022}
8023
8024static uint16_t
8025bwn_ant2phy(int antenna)
8026{
8027
8028	switch (antenna) {
8029	case BWN_ANT0:
8030		return (BWN_TX_PHY_ANT0);
8031	case BWN_ANT1:
8032		return (BWN_TX_PHY_ANT1);
8033	case BWN_ANT2:
8034		return (BWN_TX_PHY_ANT2);
8035	case BWN_ANT3:
8036		return (BWN_TX_PHY_ANT3);
8037	case BWN_ANTAUTO:
8038		return (BWN_TX_PHY_ANT01AUTO);
8039	}
8040	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8041	return (0);
8042}
8043
8044static void
8045bwn_wme_load(struct bwn_mac *mac)
8046{
8047	struct bwn_softc *sc = mac->mac_sc;
8048	int i;
8049
8050	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8051	    ("%s:%d: fail", __func__, __LINE__));
8052
8053	bwn_mac_suspend(mac);
8054	for (i = 0; i < N(sc->sc_wmeParams); i++)
8055		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8056		    bwn_wme_shm_offsets[i]);
8057	bwn_mac_enable(mac);
8058}
8059
8060static void
8061bwn_wme_loadparams(struct bwn_mac *mac,
8062    const struct wmeParams *p, uint16_t shm_offset)
8063{
8064#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8065	struct bwn_softc *sc = mac->mac_sc;
8066	uint16_t params[BWN_NR_WMEPARAMS];
8067	int slot, tmp;
8068	unsigned int i;
8069
8070	slot = BWN_READ_2(mac, BWN_RNG) &
8071	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8072
8073	memset(&params, 0, sizeof(params));
8074
8075	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8076	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8077	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8078
8079	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8080	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8081	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8082	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8083	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8084	params[BWN_WMEPARAM_BSLOTS] = slot;
8085	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8086
8087	for (i = 0; i < N(params); i++) {
8088		if (i == BWN_WMEPARAM_STATUS) {
8089			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8090			    shm_offset + (i * 2));
8091			tmp |= 0x100;
8092			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8093			    tmp);
8094		} else {
8095			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8096			    params[i]);
8097		}
8098	}
8099}
8100
8101static void
8102bwn_mac_write_bssid(struct bwn_mac *mac)
8103{
8104	struct bwn_softc *sc = mac->mac_sc;
8105	uint32_t tmp;
8106	int i;
8107	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8108
8109	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8110	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8111	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8112	    IEEE80211_ADDR_LEN);
8113
8114	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8115		tmp = (uint32_t) (mac_bssid[i + 0]);
8116		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8117		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8118		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8119		bwn_ram_write(mac, 0x20 + i, tmp);
8120	}
8121}
8122
8123static void
8124bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8125    const uint8_t *macaddr)
8126{
8127	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8128	uint16_t data;
8129
8130	if (!mac)
8131		macaddr = zero;
8132
8133	offset |= 0x0020;
8134	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8135
8136	data = macaddr[0];
8137	data |= macaddr[1] << 8;
8138	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8139	data = macaddr[2];
8140	data |= macaddr[3] << 8;
8141	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8142	data = macaddr[4];
8143	data |= macaddr[5] << 8;
8144	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8145}
8146
8147static void
8148bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8149    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8150{
8151	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8152	uint8_t per_sta_keys_start = 8;
8153
8154	if (BWN_SEC_NEWAPI(mac))
8155		per_sta_keys_start = 4;
8156
8157	KASSERT(index < mac->mac_max_nr_keys,
8158	    ("%s:%d: fail", __func__, __LINE__));
8159	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8160	    ("%s:%d: fail", __func__, __LINE__));
8161
8162	if (index >= per_sta_keys_start)
8163		bwn_key_macwrite(mac, index, NULL);
8164	if (key)
8165		memcpy(buf, key, key_len);
8166	bwn_key_write(mac, index, algorithm, buf);
8167	if (index >= per_sta_keys_start)
8168		bwn_key_macwrite(mac, index, mac_addr);
8169
8170	mac->mac_key[index].algorithm = algorithm;
8171}
8172
8173static void
8174bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8175{
8176	struct bwn_softc *sc = mac->mac_sc;
8177	uint32_t addrtmp[2] = { 0, 0 };
8178	uint8_t start = 8;
8179
8180	if (BWN_SEC_NEWAPI(mac))
8181		start = 4;
8182
8183	KASSERT(index >= start,
8184	    ("%s:%d: fail", __func__, __LINE__));
8185	index -= start;
8186
8187	if (addr) {
8188		addrtmp[0] = addr[0];
8189		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8190		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8191		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8192		addrtmp[1] = addr[4];
8193		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8194	}
8195
8196	if (siba_get_revid(sc->sc_dev) >= 5) {
8197		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8198		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8199	} else {
8200		if (index >= 8) {
8201			bwn_shm_write_4(mac, BWN_SHARED,
8202			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8203			bwn_shm_write_2(mac, BWN_SHARED,
8204			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8205		}
8206	}
8207}
8208
8209static void
8210bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8211    const uint8_t *key)
8212{
8213	unsigned int i;
8214	uint32_t offset;
8215	uint16_t kidx, value;
8216
8217	kidx = BWN_SEC_KEY2FW(mac, index);
8218	bwn_shm_write_2(mac, BWN_SHARED,
8219	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8220
8221	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8222	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8223		value = key[i];
8224		value |= (uint16_t)(key[i + 1]) << 8;
8225		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8226	}
8227}
8228
8229static void
8230bwn_phy_exit(struct bwn_mac *mac)
8231{
8232
8233	mac->mac_phy.rf_onoff(mac, 0);
8234	if (mac->mac_phy.exit != NULL)
8235		mac->mac_phy.exit(mac);
8236}
8237
8238static void
8239bwn_dma_free(struct bwn_mac *mac)
8240{
8241	struct bwn_dma *dma;
8242
8243	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8244		return;
8245	dma = &mac->mac_method.dma;
8246
8247	bwn_dma_ringfree(&dma->rx);
8248	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8249	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8250	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8251	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8252	bwn_dma_ringfree(&dma->mcast);
8253}
8254
8255static void
8256bwn_core_stop(struct bwn_mac *mac)
8257{
8258	struct bwn_softc *sc = mac->mac_sc;
8259
8260	BWN_ASSERT_LOCKED(sc);
8261
8262	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8263		return;
8264
8265	callout_stop(&sc->sc_rfswitch_ch);
8266	callout_stop(&sc->sc_task_ch);
8267	callout_stop(&sc->sc_watchdog_ch);
8268	sc->sc_watchdog_timer = 0;
8269	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8270	BWN_READ_4(mac, BWN_INTR_MASK);
8271	bwn_mac_suspend(mac);
8272
8273	mac->mac_status = BWN_MAC_STATUS_INITED;
8274}
8275
8276static int
8277bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8278{
8279	struct bwn_mac *up_dev = NULL;
8280	struct bwn_mac *down_dev;
8281	struct bwn_mac *mac;
8282	int err, status;
8283	uint8_t gmode;
8284
8285	BWN_ASSERT_LOCKED(sc);
8286
8287	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8288		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8289		    mac->mac_phy.supports_2ghz) {
8290			up_dev = mac;
8291			gmode = 1;
8292		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8293		    mac->mac_phy.supports_5ghz) {
8294			up_dev = mac;
8295			gmode = 0;
8296		} else {
8297			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8298			return (EINVAL);
8299		}
8300		if (up_dev != NULL)
8301			break;
8302	}
8303	if (up_dev == NULL) {
8304		device_printf(sc->sc_dev, "Could not find a device\n");
8305		return (ENODEV);
8306	}
8307	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8308		return (0);
8309
8310	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8311	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8312
8313	down_dev = sc->sc_curmac;;
8314	status = down_dev->mac_status;
8315	if (status >= BWN_MAC_STATUS_STARTED)
8316		bwn_core_stop(down_dev);
8317	if (status >= BWN_MAC_STATUS_INITED)
8318		bwn_core_exit(down_dev);
8319
8320	if (down_dev != up_dev)
8321		bwn_phy_reset(down_dev);
8322
8323	up_dev->mac_phy.gmode = gmode;
8324	if (status >= BWN_MAC_STATUS_INITED) {
8325		err = bwn_core_init(up_dev);
8326		if (err) {
8327			device_printf(sc->sc_dev,
8328			    "fatal: failed to initialize for %s-GHz\n",
8329			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8330			goto fail;
8331		}
8332	}
8333	if (status >= BWN_MAC_STATUS_STARTED)
8334		bwn_core_start(up_dev);
8335	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8336	sc->sc_curmac = up_dev;
8337
8338	return (0);
8339fail:
8340	sc->sc_curmac = NULL;
8341	return (err);
8342}
8343
8344static void
8345bwn_rf_turnon(struct bwn_mac *mac)
8346{
8347
8348	bwn_mac_suspend(mac);
8349	mac->mac_phy.rf_onoff(mac, 1);
8350	mac->mac_phy.rf_on = 1;
8351	bwn_mac_enable(mac);
8352}
8353
8354static void
8355bwn_rf_turnoff(struct bwn_mac *mac)
8356{
8357
8358	bwn_mac_suspend(mac);
8359	mac->mac_phy.rf_onoff(mac, 0);
8360	mac->mac_phy.rf_on = 0;
8361	bwn_mac_enable(mac);
8362}
8363
8364static void
8365bwn_phy_reset(struct bwn_mac *mac)
8366{
8367	struct bwn_softc *sc = mac->mac_sc;
8368
8369	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8370	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8371	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8372	DELAY(1000);
8373	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8374	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8375	    BWN_TGSLOW_PHYRESET);
8376	DELAY(1000);
8377}
8378
8379static int
8380bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8381{
8382	struct bwn_vap *bvp = BWN_VAP(vap);
8383	struct ieee80211com *ic= vap->iv_ic;
8384	struct ifnet *ifp = ic->ic_ifp;
8385	enum ieee80211_state ostate = vap->iv_state;
8386	struct bwn_softc *sc = ifp->if_softc;
8387	struct bwn_mac *mac = sc->sc_curmac;
8388	int error;
8389
8390	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8391	    ieee80211_state_name[vap->iv_state],
8392	    ieee80211_state_name[nstate]);
8393
8394	error = bvp->bv_newstate(vap, nstate, arg);
8395	if (error != 0)
8396		return (error);
8397
8398	BWN_LOCK(sc);
8399
8400	bwn_led_newstate(mac, nstate);
8401
8402	/*
8403	 * Clear the BSSID when we stop a STA
8404	 */
8405	if (vap->iv_opmode == IEEE80211_M_STA) {
8406		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8407			/*
8408			 * Clear out the BSSID.  If we reassociate to
8409			 * the same AP, this will reinialize things
8410			 * correctly...
8411			 */
8412			if (ic->ic_opmode == IEEE80211_M_STA &&
8413			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8414				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8415				bwn_set_macaddr(mac);
8416			}
8417		}
8418	}
8419
8420	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8421	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8422		/* XXX nothing to do? */
8423	} else if (nstate == IEEE80211_S_RUN) {
8424		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8425		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8426		bwn_set_opmode(mac);
8427		bwn_set_pretbtt(mac);
8428		bwn_spu_setdelay(mac, 0);
8429		bwn_set_macaddr(mac);
8430	}
8431
8432	BWN_UNLOCK(sc);
8433
8434	return (error);
8435}
8436
8437static void
8438bwn_set_pretbtt(struct bwn_mac *mac)
8439{
8440	struct bwn_softc *sc = mac->mac_sc;
8441	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8442	uint16_t pretbtt;
8443
8444	if (ic->ic_opmode == IEEE80211_M_IBSS)
8445		pretbtt = 2;
8446	else
8447		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8448	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8449	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8450}
8451
8452static int
8453bwn_intr(void *arg)
8454{
8455	struct bwn_mac *mac = arg;
8456	struct bwn_softc *sc = mac->mac_sc;
8457	uint32_t reason;
8458
8459	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8460	    (sc->sc_flags & BWN_FLAG_INVALID))
8461		return (FILTER_STRAY);
8462
8463	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8464	if (reason == 0xffffffff)	/* shared IRQ */
8465		return (FILTER_STRAY);
8466	reason &= mac->mac_intr_mask;
8467	if (reason == 0)
8468		return (FILTER_HANDLED);
8469
8470	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8471	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8472	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8473	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8474	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8475	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8476	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8477	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8478	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8479	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8480	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8481
8482	/* Disable interrupts. */
8483	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8484
8485	mac->mac_reason_intr = reason;
8486
8487	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8488	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8489
8490	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8491	return (FILTER_HANDLED);
8492}
8493
8494static void
8495bwn_intrtask(void *arg, int npending)
8496{
8497	struct bwn_mac *mac = arg;
8498	struct bwn_softc *sc = mac->mac_sc;
8499	struct ifnet *ifp = sc->sc_ifp;
8500	uint32_t merged = 0;
8501	int i, tx = 0, rx = 0;
8502
8503	BWN_LOCK(sc);
8504	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8505	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8506		BWN_UNLOCK(sc);
8507		return;
8508	}
8509
8510	for (i = 0; i < N(mac->mac_reason); i++)
8511		merged |= mac->mac_reason[i];
8512
8513	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8514		device_printf(sc->sc_dev, "MAC trans error\n");
8515
8516	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8517		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8518		mac->mac_phy.txerrors--;
8519		if (mac->mac_phy.txerrors == 0) {
8520			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8521			bwn_restart(mac, "PHY TX errors");
8522		}
8523	}
8524
8525	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8526		if (merged & BWN_DMAINTR_FATALMASK) {
8527			device_printf(sc->sc_dev,
8528			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8529			    mac->mac_reason[0], mac->mac_reason[1],
8530			    mac->mac_reason[2], mac->mac_reason[3],
8531			    mac->mac_reason[4], mac->mac_reason[5]);
8532			bwn_restart(mac, "DMA error");
8533			BWN_UNLOCK(sc);
8534			return;
8535		}
8536		if (merged & BWN_DMAINTR_NONFATALMASK) {
8537			device_printf(sc->sc_dev,
8538			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8539			    mac->mac_reason[0], mac->mac_reason[1],
8540			    mac->mac_reason[2], mac->mac_reason[3],
8541			    mac->mac_reason[4], mac->mac_reason[5]);
8542		}
8543	}
8544
8545	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8546		bwn_intr_ucode_debug(mac);
8547	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8548		bwn_intr_tbtt_indication(mac);
8549	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8550		bwn_intr_atim_end(mac);
8551	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8552		bwn_intr_beacon(mac);
8553	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8554		bwn_intr_pmq(mac);
8555	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8556		bwn_intr_noise(mac);
8557
8558	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8559		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8560			bwn_dma_rx(mac->mac_method.dma.rx);
8561			rx = 1;
8562		}
8563	} else
8564		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8565
8566	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8567	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8568	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8569	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8570	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8571
8572	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8573		bwn_intr_txeof(mac);
8574		tx = 1;
8575	}
8576
8577	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8578
8579	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8580		int evt = BWN_LED_EVENT_NONE;
8581
8582		if (tx && rx) {
8583			if (sc->sc_rx_rate > sc->sc_tx_rate)
8584				evt = BWN_LED_EVENT_RX;
8585			else
8586				evt = BWN_LED_EVENT_TX;
8587		} else if (tx) {
8588			evt = BWN_LED_EVENT_TX;
8589		} else if (rx) {
8590			evt = BWN_LED_EVENT_RX;
8591		} else if (rx == 0) {
8592			evt = BWN_LED_EVENT_POLL;
8593		}
8594
8595		if (evt != BWN_LED_EVENT_NONE)
8596			bwn_led_event(mac, evt);
8597       }
8598
8599	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8600		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8601			bwn_start_locked(ifp);
8602	}
8603
8604	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8605	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8606
8607	BWN_UNLOCK(sc);
8608}
8609
8610static void
8611bwn_restart(struct bwn_mac *mac, const char *msg)
8612{
8613	struct bwn_softc *sc = mac->mac_sc;
8614	struct ifnet *ifp = sc->sc_ifp;
8615	struct ieee80211com *ic = ifp->if_l2com;
8616
8617	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8618		return;
8619
8620	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8621	ieee80211_runtask(ic, &mac->mac_hwreset);
8622}
8623
8624static void
8625bwn_intr_ucode_debug(struct bwn_mac *mac)
8626{
8627	struct bwn_softc *sc = mac->mac_sc;
8628	uint16_t reason;
8629
8630	if (mac->mac_fw.opensource == 0)
8631		return;
8632
8633	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8634	switch (reason) {
8635	case BWN_DEBUGINTR_PANIC:
8636		bwn_handle_fwpanic(mac);
8637		break;
8638	case BWN_DEBUGINTR_DUMP_SHM:
8639		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8640		break;
8641	case BWN_DEBUGINTR_DUMP_REGS:
8642		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8643		break;
8644	case BWN_DEBUGINTR_MARKER:
8645		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8646		break;
8647	default:
8648		device_printf(sc->sc_dev,
8649		    "ucode debug unknown reason: %#x\n", reason);
8650	}
8651
8652	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8653	    BWN_DEBUGINTR_ACK);
8654}
8655
8656static void
8657bwn_intr_tbtt_indication(struct bwn_mac *mac)
8658{
8659	struct bwn_softc *sc = mac->mac_sc;
8660	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8661
8662	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8663		bwn_psctl(mac, 0);
8664	if (ic->ic_opmode == IEEE80211_M_IBSS)
8665		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8666}
8667
8668static void
8669bwn_intr_atim_end(struct bwn_mac *mac)
8670{
8671
8672	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8673		BWN_WRITE_4(mac, BWN_MACCMD,
8674		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8675		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8676	}
8677}
8678
8679static void
8680bwn_intr_beacon(struct bwn_mac *mac)
8681{
8682	struct bwn_softc *sc = mac->mac_sc;
8683	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8684	uint32_t cmd, beacon0, beacon1;
8685
8686	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8687	    ic->ic_opmode == IEEE80211_M_MBSS)
8688		return;
8689
8690	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8691
8692	cmd = BWN_READ_4(mac, BWN_MACCMD);
8693	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8694	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8695
8696	if (beacon0 && beacon1) {
8697		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8698		mac->mac_intr_mask |= BWN_INTR_BEACON;
8699		return;
8700	}
8701
8702	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8703		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8704		bwn_load_beacon0(mac);
8705		bwn_load_beacon1(mac);
8706		cmd = BWN_READ_4(mac, BWN_MACCMD);
8707		cmd |= BWN_MACCMD_BEACON0_VALID;
8708		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8709	} else {
8710		if (!beacon0) {
8711			bwn_load_beacon0(mac);
8712			cmd = BWN_READ_4(mac, BWN_MACCMD);
8713			cmd |= BWN_MACCMD_BEACON0_VALID;
8714			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8715		} else if (!beacon1) {
8716			bwn_load_beacon1(mac);
8717			cmd = BWN_READ_4(mac, BWN_MACCMD);
8718			cmd |= BWN_MACCMD_BEACON1_VALID;
8719			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8720		}
8721	}
8722}
8723
8724static void
8725bwn_intr_pmq(struct bwn_mac *mac)
8726{
8727	uint32_t tmp;
8728
8729	while (1) {
8730		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8731		if (!(tmp & 0x00000008))
8732			break;
8733	}
8734	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8735}
8736
8737static void
8738bwn_intr_noise(struct bwn_mac *mac)
8739{
8740	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8741	uint16_t tmp;
8742	uint8_t noise[4];
8743	uint8_t i, j;
8744	int32_t average;
8745
8746	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8747		return;
8748
8749	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8750	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8751	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8752	    noise[3] == 0x7f)
8753		goto new;
8754
8755	KASSERT(mac->mac_noise.noi_nsamples < 8,
8756	    ("%s:%d: fail", __func__, __LINE__));
8757	i = mac->mac_noise.noi_nsamples;
8758	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8759	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8760	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8761	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8762	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8763	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8764	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8765	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8766	mac->mac_noise.noi_nsamples++;
8767	if (mac->mac_noise.noi_nsamples == 8) {
8768		average = 0;
8769		for (i = 0; i < 8; i++) {
8770			for (j = 0; j < 4; j++)
8771				average += mac->mac_noise.noi_samples[i][j];
8772		}
8773		average = (((average / 32) * 125) + 64) / 128;
8774		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8775		if (tmp >= 8)
8776			average += 2;
8777		else
8778			average -= 25;
8779		average -= (tmp == 8) ? 72 : 48;
8780
8781		mac->mac_stats.link_noise = average;
8782		mac->mac_noise.noi_running = 0;
8783		return;
8784	}
8785new:
8786	bwn_noise_gensample(mac);
8787}
8788
8789static int
8790bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8791{
8792	struct bwn_mac *mac = prq->prq_mac;
8793	struct bwn_softc *sc = mac->mac_sc;
8794	unsigned int i;
8795
8796	BWN_ASSERT_LOCKED(sc);
8797
8798	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8799		return (0);
8800
8801	for (i = 0; i < 5000; i++) {
8802		if (bwn_pio_rxeof(prq) == 0)
8803			break;
8804	}
8805	if (i >= 5000)
8806		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8807	return ((i > 0) ? 1 : 0);
8808}
8809
8810static void
8811bwn_dma_rx(struct bwn_dma_ring *dr)
8812{
8813	int slot, curslot;
8814
8815	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8816	curslot = dr->get_curslot(dr);
8817	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8818	    ("%s:%d: fail", __func__, __LINE__));
8819
8820	slot = dr->dr_curslot;
8821	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8822		bwn_dma_rxeof(dr, &slot);
8823
8824	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8825	    BUS_DMASYNC_PREWRITE);
8826
8827	dr->set_curslot(dr, slot);
8828	dr->dr_curslot = slot;
8829}
8830
8831static void
8832bwn_intr_txeof(struct bwn_mac *mac)
8833{
8834	struct bwn_txstatus stat;
8835	uint32_t stat0, stat1;
8836	uint16_t tmp;
8837
8838	BWN_ASSERT_LOCKED(mac->mac_sc);
8839
8840	while (1) {
8841		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8842		if (!(stat0 & 0x00000001))
8843			break;
8844		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8845
8846		stat.cookie = (stat0 >> 16);
8847		stat.seq = (stat1 & 0x0000ffff);
8848		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8849		tmp = (stat0 & 0x0000ffff);
8850		stat.framecnt = ((tmp & 0xf000) >> 12);
8851		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8852		stat.sreason = ((tmp & 0x001c) >> 2);
8853		stat.pm = (tmp & 0x0080) ? 1 : 0;
8854		stat.im = (tmp & 0x0040) ? 1 : 0;
8855		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8856		stat.ack = (tmp & 0x0002) ? 1 : 0;
8857
8858		bwn_handle_txeof(mac, &stat);
8859	}
8860}
8861
8862static void
8863bwn_hwreset(void *arg, int npending)
8864{
8865	struct bwn_mac *mac = arg;
8866	struct bwn_softc *sc = mac->mac_sc;
8867	int error = 0;
8868	int prev_status;
8869
8870	BWN_LOCK(sc);
8871
8872	prev_status = mac->mac_status;
8873	if (prev_status >= BWN_MAC_STATUS_STARTED)
8874		bwn_core_stop(mac);
8875	if (prev_status >= BWN_MAC_STATUS_INITED)
8876		bwn_core_exit(mac);
8877
8878	if (prev_status >= BWN_MAC_STATUS_INITED) {
8879		error = bwn_core_init(mac);
8880		if (error)
8881			goto out;
8882	}
8883	if (prev_status >= BWN_MAC_STATUS_STARTED)
8884		bwn_core_start(mac);
8885out:
8886	if (error) {
8887		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8888		sc->sc_curmac = NULL;
8889	}
8890	BWN_UNLOCK(sc);
8891}
8892
8893static void
8894bwn_handle_fwpanic(struct bwn_mac *mac)
8895{
8896	struct bwn_softc *sc = mac->mac_sc;
8897	uint16_t reason;
8898
8899	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8900	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8901
8902	if (reason == BWN_FWPANIC_RESTART)
8903		bwn_restart(mac, "ucode panic");
8904}
8905
8906static void
8907bwn_load_beacon0(struct bwn_mac *mac)
8908{
8909
8910	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8911}
8912
8913static void
8914bwn_load_beacon1(struct bwn_mac *mac)
8915{
8916
8917	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8918}
8919
8920static uint32_t
8921bwn_jssi_read(struct bwn_mac *mac)
8922{
8923	uint32_t val = 0;
8924
8925	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8926	val <<= 16;
8927	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8928
8929	return (val);
8930}
8931
8932static void
8933bwn_noise_gensample(struct bwn_mac *mac)
8934{
8935	uint32_t jssi = 0x7f7f7f7f;
8936
8937	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8938	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8939	BWN_WRITE_4(mac, BWN_MACCMD,
8940	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8941}
8942
8943static int
8944bwn_dma_freeslot(struct bwn_dma_ring *dr)
8945{
8946	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8947
8948	return (dr->dr_numslots - dr->dr_usedslot);
8949}
8950
8951static int
8952bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8953{
8954	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8955
8956	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8957	    ("%s:%d: fail", __func__, __LINE__));
8958	if (slot == dr->dr_numslots - 1)
8959		return (0);
8960	return (slot + 1);
8961}
8962
8963static void
8964bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8965{
8966	struct bwn_mac *mac = dr->dr_mac;
8967	struct bwn_softc *sc = mac->mac_sc;
8968	struct bwn_dma *dma = &mac->mac_method.dma;
8969	struct bwn_dmadesc_generic *desc;
8970	struct bwn_dmadesc_meta *meta;
8971	struct bwn_rxhdr4 *rxhdr;
8972	struct ifnet *ifp = sc->sc_ifp;
8973	struct mbuf *m;
8974	uint32_t macstat;
8975	int32_t tmp;
8976	int cnt = 0;
8977	uint16_t len;
8978
8979	dr->getdesc(dr, *slot, &desc, &meta);
8980
8981	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8982	m = meta->mt_m;
8983
8984	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8985		ifp->if_ierrors++;
8986		return;
8987	}
8988
8989	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8990	len = le16toh(rxhdr->frame_len);
8991	if (len <= 0) {
8992		ifp->if_ierrors++;
8993		return;
8994	}
8995	if (bwn_dma_check_redzone(dr, m)) {
8996		device_printf(sc->sc_dev, "redzone error.\n");
8997		bwn_dma_set_redzone(dr, m);
8998		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8999		    BUS_DMASYNC_PREWRITE);
9000		return;
9001	}
9002	if (len > dr->dr_rx_bufsize) {
9003		tmp = len;
9004		while (1) {
9005			dr->getdesc(dr, *slot, &desc, &meta);
9006			bwn_dma_set_redzone(dr, meta->mt_m);
9007			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9008			    BUS_DMASYNC_PREWRITE);
9009			*slot = bwn_dma_nextslot(dr, *slot);
9010			cnt++;
9011			tmp -= dr->dr_rx_bufsize;
9012			if (tmp <= 0)
9013				break;
9014		}
9015		device_printf(sc->sc_dev, "too small buffer "
9016		       "(len %u buffer %u dropped %d)\n",
9017		       len, dr->dr_rx_bufsize, cnt);
9018		return;
9019	}
9020	macstat = le32toh(rxhdr->mac_status);
9021	if (macstat & BWN_RX_MAC_FCSERR) {
9022		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9023			device_printf(sc->sc_dev, "RX drop\n");
9024			return;
9025		}
9026	}
9027
9028	m->m_pkthdr.rcvif = ifp;
9029	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9030	m_adj(m, dr->dr_frameoffset);
9031
9032	bwn_rxeof(dr->dr_mac, m, rxhdr);
9033}
9034
9035static void
9036bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9037{
9038	struct bwn_dma_ring *dr;
9039	struct bwn_dmadesc_generic *desc;
9040	struct bwn_dmadesc_meta *meta;
9041	struct bwn_node *bn;
9042	struct bwn_pio_txqueue *tq;
9043	struct bwn_pio_txpkt *tp = NULL;
9044	struct bwn_softc *sc = mac->mac_sc;
9045	struct bwn_stats *stats = &mac->mac_stats;
9046	struct ieee80211_node *ni;
9047	int slot;
9048
9049	BWN_ASSERT_LOCKED(mac->mac_sc);
9050
9051	if (status->im)
9052		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9053	if (status->ampdu)
9054		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9055	if (status->rtscnt) {
9056		if (status->rtscnt == 0xf)
9057			stats->rtsfail++;
9058		else
9059			stats->rts++;
9060	}
9061
9062	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9063		if (status->ack) {
9064			dr = bwn_dma_parse_cookie(mac, status,
9065			    status->cookie, &slot);
9066			if (dr == NULL) {
9067				device_printf(sc->sc_dev,
9068				    "failed to parse cookie\n");
9069				return;
9070			}
9071			while (1) {
9072				dr->getdesc(dr, slot, &desc, &meta);
9073				if (meta->mt_islast) {
9074					ni = meta->mt_ni;
9075					bn = (struct bwn_node *)ni;
9076					ieee80211_amrr_tx_complete(&bn->bn_amn,
9077					    status->ack, 0);
9078					break;
9079				}
9080				slot = bwn_dma_nextslot(dr, slot);
9081			}
9082		}
9083		bwn_dma_handle_txeof(mac, status);
9084	} else {
9085		if (status->ack) {
9086			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9087			if (tq == NULL) {
9088				device_printf(sc->sc_dev,
9089				    "failed to parse cookie\n");
9090				return;
9091			}
9092			ni = tp->tp_ni;
9093			bn = (struct bwn_node *)ni;
9094			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9095		}
9096		bwn_pio_handle_txeof(mac, status);
9097	}
9098
9099	bwn_phy_txpower_check(mac, 0);
9100}
9101
9102static uint8_t
9103bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9104{
9105	struct bwn_mac *mac = prq->prq_mac;
9106	struct bwn_softc *sc = mac->mac_sc;
9107	struct bwn_rxhdr4 rxhdr;
9108	struct ifnet *ifp = sc->sc_ifp;
9109	struct mbuf *m;
9110	uint32_t ctl32, macstat, v32;
9111	unsigned int i, padding;
9112	uint16_t ctl16, len, v16;
9113	unsigned char *mp;
9114	char *data;
9115
9116	memset(&rxhdr, 0, sizeof(rxhdr));
9117
9118	if (prq->prq_rev >= 8) {
9119		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9120		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9121			return (0);
9122		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9123		    BWN_PIO8_RXCTL_FRAMEREADY);
9124		for (i = 0; i < 10; i++) {
9125			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9126			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9127				goto ready;
9128			DELAY(10);
9129		}
9130	} else {
9131		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9132		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9133			return (0);
9134		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9135		    BWN_PIO_RXCTL_FRAMEREADY);
9136		for (i = 0; i < 10; i++) {
9137			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9138			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9139				goto ready;
9140			DELAY(10);
9141		}
9142	}
9143	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9144	return (1);
9145ready:
9146	if (prq->prq_rev >= 8)
9147		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9148		    prq->prq_base + BWN_PIO8_RXDATA);
9149	else
9150		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9151		    prq->prq_base + BWN_PIO_RXDATA);
9152	len = le16toh(rxhdr.frame_len);
9153	if (len > 0x700) {
9154		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9155		goto error;
9156	}
9157	if (len == 0) {
9158		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9159		goto error;
9160	}
9161
9162	macstat = le32toh(rxhdr.mac_status);
9163	if (macstat & BWN_RX_MAC_FCSERR) {
9164		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9165			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9166			goto error;
9167		}
9168	}
9169
9170	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9171	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9172	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9173	if (m == NULL) {
9174		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9175		goto error;
9176	}
9177	mp = mtod(m, unsigned char *);
9178	if (prq->prq_rev >= 8) {
9179		siba_read_multi_4(sc->sc_dev, mp + padding, (len & ~3),
9180		    prq->prq_base + BWN_PIO8_RXDATA);
9181		if (len & 3) {
9182			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9183			data = &(mp[len + padding - 1]);
9184			switch (len & 3) {
9185			case 3:
9186				*data = (v32 >> 16);
9187				data--;
9188			case 2:
9189				*data = (v32 >> 8);
9190				data--;
9191			case 1:
9192				*data = v32;
9193			}
9194		}
9195	} else {
9196		siba_read_multi_2(sc->sc_dev, mp + padding, (len & ~1),
9197		    prq->prq_base + BWN_PIO_RXDATA);
9198		if (len & 1) {
9199			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9200			mp[len + padding - 1] = v16;
9201		}
9202	}
9203
9204	m->m_pkthdr.rcvif = ifp;
9205	m->m_len = m->m_pkthdr.len = len + padding;
9206
9207	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9208
9209	return (1);
9210error:
9211	if (prq->prq_rev >= 8)
9212		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9213		    BWN_PIO8_RXCTL_DATAREADY);
9214	else
9215		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9216	return (1);
9217}
9218
9219static int
9220bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9221    struct bwn_dmadesc_meta *meta, int init)
9222{
9223	struct bwn_mac *mac = dr->dr_mac;
9224	struct bwn_dma *dma = &mac->mac_method.dma;
9225	struct bwn_rxhdr4 *hdr;
9226	bus_dmamap_t map;
9227	bus_addr_t paddr;
9228	struct mbuf *m;
9229	int error;
9230
9231	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9232	if (m == NULL) {
9233		error = ENOBUFS;
9234
9235		/*
9236		 * If the NIC is up and running, we need to:
9237		 * - Clear RX buffer's header.
9238		 * - Restore RX descriptor settings.
9239		 */
9240		if (init)
9241			return (error);
9242		else
9243			goto back;
9244	}
9245	m->m_len = m->m_pkthdr.len = MCLBYTES;
9246
9247	bwn_dma_set_redzone(dr, m);
9248
9249	/*
9250	 * Try to load RX buf into temporary DMA map
9251	 */
9252	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9253	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9254	if (error) {
9255		m_freem(m);
9256
9257		/*
9258		 * See the comment above
9259		 */
9260		if (init)
9261			return (error);
9262		else
9263			goto back;
9264	}
9265
9266	if (!init)
9267		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9268	meta->mt_m = m;
9269	meta->mt_paddr = paddr;
9270
9271	/*
9272	 * Swap RX buf's DMA map with the loaded temporary one
9273	 */
9274	map = meta->mt_dmap;
9275	meta->mt_dmap = dr->dr_spare_dmap;
9276	dr->dr_spare_dmap = map;
9277
9278back:
9279	/*
9280	 * Clear RX buf header
9281	 */
9282	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9283	bzero(hdr, sizeof(*hdr));
9284	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9285	    BUS_DMASYNC_PREWRITE);
9286
9287	/*
9288	 * Setup RX buf descriptor
9289	 */
9290	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9291	    sizeof(*hdr), 0, 0, 0);
9292	return (error);
9293}
9294
9295static void
9296bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9297		 bus_size_t mapsz __unused, int error)
9298{
9299
9300	if (!error) {
9301		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9302		*((bus_addr_t *)arg) = seg->ds_addr;
9303	}
9304}
9305
9306static int
9307bwn_hwrate2ieeerate(int rate)
9308{
9309
9310	switch (rate) {
9311	case BWN_CCK_RATE_1MB:
9312		return (2);
9313	case BWN_CCK_RATE_2MB:
9314		return (4);
9315	case BWN_CCK_RATE_5MB:
9316		return (11);
9317	case BWN_CCK_RATE_11MB:
9318		return (22);
9319	case BWN_OFDM_RATE_6MB:
9320		return (12);
9321	case BWN_OFDM_RATE_9MB:
9322		return (18);
9323	case BWN_OFDM_RATE_12MB:
9324		return (24);
9325	case BWN_OFDM_RATE_18MB:
9326		return (36);
9327	case BWN_OFDM_RATE_24MB:
9328		return (48);
9329	case BWN_OFDM_RATE_36MB:
9330		return (72);
9331	case BWN_OFDM_RATE_48MB:
9332		return (96);
9333	case BWN_OFDM_RATE_54MB:
9334		return (108);
9335	default:
9336		printf("Ooops\n");
9337		return (0);
9338	}
9339}
9340
9341static void
9342bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9343{
9344	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9345	struct bwn_plcp6 *plcp;
9346	struct bwn_softc *sc = mac->mac_sc;
9347	struct ieee80211_frame_min *wh;
9348	struct ieee80211_node *ni;
9349	struct ifnet *ifp = sc->sc_ifp;
9350	struct ieee80211com *ic = ifp->if_l2com;
9351	uint32_t macstat;
9352	int padding, rate, rssi = 0, noise = 0, type;
9353	uint16_t phytype, phystat0, phystat3, chanstat;
9354	unsigned char *mp = mtod(m, unsigned char *);
9355	static int rx_mac_dec_rpt = 0;
9356
9357	BWN_ASSERT_LOCKED(sc);
9358
9359	phystat0 = le16toh(rxhdr->phy_status0);
9360	phystat3 = le16toh(rxhdr->phy_status3);
9361	macstat = le32toh(rxhdr->mac_status);
9362	chanstat = le16toh(rxhdr->channel);
9363	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9364
9365	if (macstat & BWN_RX_MAC_FCSERR)
9366		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9367	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9368		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9369	if (macstat & BWN_RX_MAC_DECERR)
9370		goto drop;
9371
9372	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9373	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9374		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9375		    m->m_pkthdr.len);
9376		goto drop;
9377	}
9378	plcp = (struct bwn_plcp6 *)(mp + padding);
9379	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9380	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9381		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9382		    m->m_pkthdr.len);
9383		goto drop;
9384	}
9385	wh = mtod(m, struct ieee80211_frame_min *);
9386
9387	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9388		device_printf(sc->sc_dev,
9389		    "RX decryption attempted (old %d keyidx %#x)\n",
9390		    BWN_ISOLDFMT(mac),
9391		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9392
9393	/* XXX calculating RSSI & noise & antenna */
9394
9395	if (phystat0 & BWN_RX_PHYST0_OFDM)
9396		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9397		    phytype == BWN_PHYTYPE_A);
9398	else
9399		rate = bwn_plcp_get_cckrate(mac, plcp);
9400	if (rate == -1) {
9401		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9402			goto drop;
9403	}
9404	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9405
9406	/* RX radio tap */
9407	if (ieee80211_radiotap_active(ic))
9408		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9409	m_adj(m, -IEEE80211_CRC_LEN);
9410
9411	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9412	noise = mac->mac_stats.link_noise;
9413
9414	BWN_UNLOCK(sc);
9415
9416	ni = ieee80211_find_rxnode(ic, wh);
9417	if (ni != NULL) {
9418		type = ieee80211_input(ni, m, rssi, noise);
9419		ieee80211_free_node(ni);
9420	} else
9421		type = ieee80211_input_all(ic, m, rssi, noise);
9422
9423	BWN_LOCK(sc);
9424	return;
9425drop:
9426	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9427}
9428
9429static void
9430bwn_dma_handle_txeof(struct bwn_mac *mac,
9431    const struct bwn_txstatus *status)
9432{
9433	struct bwn_dma *dma = &mac->mac_method.dma;
9434	struct bwn_dma_ring *dr;
9435	struct bwn_dmadesc_generic *desc;
9436	struct bwn_dmadesc_meta *meta;
9437	struct bwn_softc *sc = mac->mac_sc;
9438	struct ieee80211_node *ni;
9439	struct ifnet *ifp = sc->sc_ifp;
9440	struct mbuf *m;
9441	int slot;
9442
9443	BWN_ASSERT_LOCKED(sc);
9444
9445	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9446	if (dr == NULL) {
9447		device_printf(sc->sc_dev, "failed to parse cookie\n");
9448		return;
9449	}
9450	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9451
9452	while (1) {
9453		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9454		    ("%s:%d: fail", __func__, __LINE__));
9455		dr->getdesc(dr, slot, &desc, &meta);
9456
9457		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9458			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9459		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9460			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9461
9462		if (meta->mt_islast) {
9463			KASSERT(meta->mt_m != NULL,
9464			    ("%s:%d: fail", __func__, __LINE__));
9465
9466			ni = meta->mt_ni;
9467			m = meta->mt_m;
9468			if (ni != NULL) {
9469				/*
9470				 * Do any tx complete callback. Note this must
9471				 * be done before releasing the node reference.
9472				 */
9473				if (m->m_flags & M_TXCB)
9474					ieee80211_process_callback(ni, m, 0);
9475				ieee80211_free_node(ni);
9476				meta->mt_ni = NULL;
9477			}
9478			m_freem(m);
9479			meta->mt_m = NULL;
9480		} else {
9481			KASSERT(meta->mt_m == NULL,
9482			    ("%s:%d: fail", __func__, __LINE__));
9483		}
9484
9485		dr->dr_usedslot--;
9486		if (meta->mt_islast) {
9487			ifp->if_opackets++;
9488			break;
9489		}
9490		slot = bwn_dma_nextslot(dr, slot);
9491	}
9492	sc->sc_watchdog_timer = 0;
9493	if (dr->dr_stop) {
9494		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9495		    ("%s:%d: fail", __func__, __LINE__));
9496		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9497		dr->dr_stop = 0;
9498	}
9499}
9500
9501static void
9502bwn_pio_handle_txeof(struct bwn_mac *mac,
9503    const struct bwn_txstatus *status)
9504{
9505	struct bwn_pio_txqueue *tq;
9506	struct bwn_pio_txpkt *tp = NULL;
9507	struct bwn_softc *sc = mac->mac_sc;
9508	struct ifnet *ifp = sc->sc_ifp;
9509
9510	BWN_ASSERT_LOCKED(sc);
9511
9512	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9513	if (tq == NULL)
9514		return;
9515
9516	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9517	tq->tq_free++;
9518
9519	if (tp->tp_ni != NULL) {
9520		/*
9521		 * Do any tx complete callback.  Note this must
9522		 * be done before releasing the node reference.
9523		 */
9524		if (tp->tp_m->m_flags & M_TXCB)
9525			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9526		ieee80211_free_node(tp->tp_ni);
9527		tp->tp_ni = NULL;
9528	}
9529	m_freem(tp->tp_m);
9530	tp->tp_m = NULL;
9531	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9532
9533	ifp->if_opackets++;
9534
9535	sc->sc_watchdog_timer = 0;
9536	if (tq->tq_stop) {
9537		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9538		tq->tq_stop = 0;
9539	}
9540}
9541
9542static void
9543bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9544{
9545	struct bwn_softc *sc = mac->mac_sc;
9546	struct bwn_phy *phy = &mac->mac_phy;
9547	struct ifnet *ifp = sc->sc_ifp;
9548	struct ieee80211com *ic = ifp->if_l2com;
9549	unsigned long now;
9550	int result;
9551
9552	BWN_GETTIME(now);
9553
9554	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9555		return;
9556	phy->nexttime = now + 2 * 1000;
9557
9558	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9559	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9560		return;
9561
9562	if (phy->recalc_txpwr != NULL) {
9563		result = phy->recalc_txpwr(mac,
9564		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9565		if (result == BWN_TXPWR_RES_DONE)
9566			return;
9567		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9568		    ("%s: fail", __func__));
9569		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9570
9571		ieee80211_runtask(ic, &mac->mac_txpower);
9572	}
9573}
9574
9575static uint16_t
9576bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9577{
9578
9579	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9580}
9581
9582static uint32_t
9583bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9584{
9585
9586	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9587}
9588
9589static void
9590bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9591{
9592
9593	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9594}
9595
9596static void
9597bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9598{
9599
9600	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9601}
9602
9603static int
9604bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9605{
9606
9607	switch (rate) {
9608	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9609	case 12:
9610		return (BWN_OFDM_RATE_6MB);
9611	case 18:
9612		return (BWN_OFDM_RATE_9MB);
9613	case 24:
9614		return (BWN_OFDM_RATE_12MB);
9615	case 36:
9616		return (BWN_OFDM_RATE_18MB);
9617	case 48:
9618		return (BWN_OFDM_RATE_24MB);
9619	case 72:
9620		return (BWN_OFDM_RATE_36MB);
9621	case 96:
9622		return (BWN_OFDM_RATE_48MB);
9623	case 108:
9624		return (BWN_OFDM_RATE_54MB);
9625	/* CCK rates (NB: not IEEE std, device-specific) */
9626	case 2:
9627		return (BWN_CCK_RATE_1MB);
9628	case 4:
9629		return (BWN_CCK_RATE_2MB);
9630	case 11:
9631		return (BWN_CCK_RATE_5MB);
9632	case 22:
9633		return (BWN_CCK_RATE_11MB);
9634	}
9635
9636	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9637	return (BWN_CCK_RATE_1MB);
9638}
9639
9640static int
9641bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9642    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9643{
9644	const struct bwn_phy *phy = &mac->mac_phy;
9645	struct bwn_softc *sc = mac->mac_sc;
9646	struct ieee80211_frame *wh;
9647	struct ieee80211_frame *protwh;
9648	struct ieee80211_frame_cts *cts;
9649	struct ieee80211_frame_rts *rts;
9650	const struct ieee80211_txparam *tp;
9651	struct ieee80211vap *vap = ni->ni_vap;
9652	struct ifnet *ifp = sc->sc_ifp;
9653	struct ieee80211com *ic = ifp->if_l2com;
9654	struct mbuf *mprot;
9655	unsigned int len;
9656	uint32_t macctl = 0;
9657	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9658	uint16_t phyctl = 0;
9659	uint8_t rate, rate_fb;
9660
9661	wh = mtod(m, struct ieee80211_frame *);
9662	memset(txhdr, 0, sizeof(*txhdr));
9663
9664	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9665	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9666	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9667
9668	/*
9669	 * Find TX rate
9670	 */
9671	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9672	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9673		rate = rate_fb = tp->mgmtrate;
9674	else if (ismcast)
9675		rate = rate_fb = tp->mcastrate;
9676	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9677		rate = rate_fb = tp->ucastrate;
9678	else {
9679		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9680		rate = ni->ni_txrate;
9681
9682		if (rix > 0)
9683			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9684			    IEEE80211_RATE_VAL;
9685		else
9686			rate_fb = rate;
9687	}
9688
9689	sc->sc_tx_rate = rate;
9690
9691	rate = bwn_ieeerate2hwrate(sc, rate);
9692	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9693
9694	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9695	    bwn_plcp_getcck(rate);
9696	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9697	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9698
9699	if ((rate_fb == rate) ||
9700	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9701	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9702		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9703	else
9704		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9705		    m->m_pkthdr.len, rate, isshort);
9706
9707	/* XXX TX encryption */
9708	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9709	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9710	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9711	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9712	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9713	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9714
9715	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9716	    BWN_TX_EFT_FB_CCK;
9717	txhdr->chan = phy->chan;
9718	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9719	    BWN_TX_PHY_ENC_CCK;
9720	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9721	     rate == BWN_CCK_RATE_11MB))
9722		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9723
9724	/* XXX TX antenna selection */
9725
9726	switch (bwn_antenna_sanitize(mac, 0)) {
9727	case 0:
9728		phyctl |= BWN_TX_PHY_ANT01AUTO;
9729		break;
9730	case 1:
9731		phyctl |= BWN_TX_PHY_ANT0;
9732		break;
9733	case 2:
9734		phyctl |= BWN_TX_PHY_ANT1;
9735		break;
9736	case 3:
9737		phyctl |= BWN_TX_PHY_ANT2;
9738		break;
9739	case 4:
9740		phyctl |= BWN_TX_PHY_ANT3;
9741		break;
9742	default:
9743		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9744	}
9745
9746	if (!ismcast)
9747		macctl |= BWN_TX_MAC_ACK;
9748
9749	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9750	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9751	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9752		macctl |= BWN_TX_MAC_LONGFRAME;
9753
9754	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9755		/* XXX RTS rate is always 1MB??? */
9756		rts_rate = BWN_CCK_RATE_1MB;
9757		rts_rate_fb = bwn_get_fbrate(rts_rate);
9758
9759		protdur = ieee80211_compute_duration(ic->ic_rt,
9760		    m->m_pkthdr.len, rate, isshort) +
9761		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9762
9763		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9764			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9765			    (txhdr->body.old.rts_frame) :
9766			    (txhdr->body.new.rts_frame));
9767			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9768			    protdur);
9769			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9770			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9771			    mprot->m_pkthdr.len);
9772			m_freem(mprot);
9773			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9774			len = sizeof(struct ieee80211_frame_cts);
9775		} else {
9776			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9777			    (txhdr->body.old.rts_frame) :
9778			    (txhdr->body.new.rts_frame));
9779			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9780			    isshort);
9781			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9782			    wh->i_addr2, protdur);
9783			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9784			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9785			    mprot->m_pkthdr.len);
9786			m_freem(mprot);
9787			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9788			len = sizeof(struct ieee80211_frame_rts);
9789		}
9790		len += IEEE80211_CRC_LEN;
9791		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9792		    &txhdr->body.old.rts_plcp :
9793		    &txhdr->body.new.rts_plcp), len, rts_rate);
9794		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9795		    rts_rate_fb);
9796
9797		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9798		    (&txhdr->body.old.rts_frame) :
9799		    (&txhdr->body.new.rts_frame));
9800		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9801
9802		if (BWN_ISOFDMRATE(rts_rate)) {
9803			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9804			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9805		} else {
9806			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9807			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9808		}
9809		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9810		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9811	}
9812
9813	if (BWN_ISOLDFMT(mac))
9814		txhdr->body.old.cookie = htole16(cookie);
9815	else
9816		txhdr->body.new.cookie = htole16(cookie);
9817
9818	txhdr->macctl = htole32(macctl);
9819	txhdr->phyctl = htole16(phyctl);
9820
9821	/*
9822	 * TX radio tap
9823	 */
9824	if (ieee80211_radiotap_active_vap(vap)) {
9825		sc->sc_tx_th.wt_flags = 0;
9826		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9827			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9828		if (isshort &&
9829		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9830		     rate == BWN_CCK_RATE_11MB))
9831			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9832		sc->sc_tx_th.wt_rate = rate;
9833
9834		ieee80211_radiotap_tx(vap, m);
9835	}
9836
9837	return (0);
9838}
9839
9840static void
9841bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9842    const uint8_t rate)
9843{
9844	uint32_t d, plen;
9845	uint8_t *raw = plcp->o.raw;
9846
9847	if (BWN_ISOFDMRATE(rate)) {
9848		d = bwn_plcp_getofdm(rate);
9849		KASSERT(!(octets & 0xf000),
9850		    ("%s:%d: fail", __func__, __LINE__));
9851		d |= (octets << 5);
9852		plcp->o.data = htole32(d);
9853	} else {
9854		plen = octets * 16 / rate;
9855		if ((octets * 16 % rate) > 0) {
9856			plen++;
9857			if ((rate == BWN_CCK_RATE_11MB)
9858			    && ((octets * 8 % 11) < 4)) {
9859				raw[1] = 0x84;
9860			} else
9861				raw[1] = 0x04;
9862		} else
9863			raw[1] = 0x04;
9864		plcp->o.data |= htole32(plen << 16);
9865		raw[0] = bwn_plcp_getcck(rate);
9866	}
9867}
9868
9869static uint8_t
9870bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9871{
9872	struct bwn_softc *sc = mac->mac_sc;
9873	uint8_t mask;
9874
9875	if (n == 0)
9876		return (0);
9877	if (mac->mac_phy.gmode)
9878		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9879	else
9880		mask = siba_sprom_get_ant_a(sc->sc_dev);
9881	if (!(mask & (1 << (n - 1))))
9882		return (0);
9883	return (n);
9884}
9885
9886static uint8_t
9887bwn_get_fbrate(uint8_t bitrate)
9888{
9889	switch (bitrate) {
9890	case BWN_CCK_RATE_1MB:
9891		return (BWN_CCK_RATE_1MB);
9892	case BWN_CCK_RATE_2MB:
9893		return (BWN_CCK_RATE_1MB);
9894	case BWN_CCK_RATE_5MB:
9895		return (BWN_CCK_RATE_2MB);
9896	case BWN_CCK_RATE_11MB:
9897		return (BWN_CCK_RATE_5MB);
9898	case BWN_OFDM_RATE_6MB:
9899		return (BWN_CCK_RATE_5MB);
9900	case BWN_OFDM_RATE_9MB:
9901		return (BWN_OFDM_RATE_6MB);
9902	case BWN_OFDM_RATE_12MB:
9903		return (BWN_OFDM_RATE_9MB);
9904	case BWN_OFDM_RATE_18MB:
9905		return (BWN_OFDM_RATE_12MB);
9906	case BWN_OFDM_RATE_24MB:
9907		return (BWN_OFDM_RATE_18MB);
9908	case BWN_OFDM_RATE_36MB:
9909		return (BWN_OFDM_RATE_24MB);
9910	case BWN_OFDM_RATE_48MB:
9911		return (BWN_OFDM_RATE_36MB);
9912	case BWN_OFDM_RATE_54MB:
9913		return (BWN_OFDM_RATE_48MB);
9914	}
9915	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9916	return (0);
9917}
9918
9919static uint32_t
9920bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9921    uint32_t ctl, const void *_data, int len)
9922{
9923	struct bwn_softc *sc = mac->mac_sc;
9924	uint32_t value = 0;
9925	const uint8_t *data = _data;
9926
9927	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9928	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9929	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9930
9931	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9932	    tq->tq_base + BWN_PIO8_TXDATA);
9933	if (len & 3) {
9934		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9935		    BWN_PIO8_TXCTL_24_31);
9936		data = &(data[len - 1]);
9937		switch (len & 3) {
9938		case 3:
9939			ctl |= BWN_PIO8_TXCTL_16_23;
9940			value |= (uint32_t)(*data) << 16;
9941			data--;
9942		case 2:
9943			ctl |= BWN_PIO8_TXCTL_8_15;
9944			value |= (uint32_t)(*data) << 8;
9945			data--;
9946		case 1:
9947			value |= (uint32_t)(*data);
9948		}
9949		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9950		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9951	}
9952
9953	return (ctl);
9954}
9955
9956static void
9957bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9958    uint16_t offset, uint32_t value)
9959{
9960
9961	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9962}
9963
9964static uint16_t
9965bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9966    uint16_t ctl, const void *_data, int len)
9967{
9968	struct bwn_softc *sc = mac->mac_sc;
9969	const uint8_t *data = _data;
9970
9971	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9972	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9973
9974	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9975	    tq->tq_base + BWN_PIO_TXDATA);
9976	if (len & 1) {
9977		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9978		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9979		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9980	}
9981
9982	return (ctl);
9983}
9984
9985static uint16_t
9986bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9987    uint16_t ctl, struct mbuf *m0)
9988{
9989	int i, j = 0;
9990	uint16_t data = 0;
9991	const uint8_t *buf;
9992	struct mbuf *m = m0;
9993
9994	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9995	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9996
9997	for (; m != NULL; m = m->m_next) {
9998		buf = mtod(m, const uint8_t *);
9999		for (i = 0; i < m->m_len; i++) {
10000			if (!((j++) % 2))
10001				data |= buf[i];
10002			else {
10003				data |= (buf[i] << 8);
10004				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10005				data = 0;
10006			}
10007		}
10008	}
10009	if (m0->m_pkthdr.len % 2) {
10010		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10011		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10012		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10013	}
10014
10015	return (ctl);
10016}
10017
10018static void
10019bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10020{
10021
10022	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10023		return;
10024	BWN_WRITE_2(mac, 0x684, 510 + time);
10025	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10026}
10027
10028static struct bwn_dma_ring *
10029bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10030{
10031
10032	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10033		return (mac->mac_method.dma.wme[WME_AC_BE]);
10034
10035	switch (prio) {
10036	case 3:
10037		return (mac->mac_method.dma.wme[WME_AC_VO]);
10038	case 2:
10039		return (mac->mac_method.dma.wme[WME_AC_VI]);
10040	case 0:
10041		return (mac->mac_method.dma.wme[WME_AC_BE]);
10042	case 1:
10043		return (mac->mac_method.dma.wme[WME_AC_BK]);
10044	}
10045	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10046	return (NULL);
10047}
10048
10049static int
10050bwn_dma_getslot(struct bwn_dma_ring *dr)
10051{
10052	int slot;
10053
10054	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10055
10056	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10057	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10058	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10059
10060	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10061	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10062	dr->dr_curslot = slot;
10063	dr->dr_usedslot++;
10064
10065	return (slot);
10066}
10067
10068static int
10069bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10070{
10071	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10072	unsigned int a, b, c, d;
10073	unsigned int avg;
10074	uint32_t tmp;
10075
10076	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10077	a = tmp & 0xff;
10078	b = (tmp >> 8) & 0xff;
10079	c = (tmp >> 16) & 0xff;
10080	d = (tmp >> 24) & 0xff;
10081	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10082	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10083		return (ENOENT);
10084	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10085	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10086	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10087
10088	if (ofdm) {
10089		a = (a + 32) & 0x3f;
10090		b = (b + 32) & 0x3f;
10091		c = (c + 32) & 0x3f;
10092		d = (d + 32) & 0x3f;
10093	}
10094
10095	avg = (a + b + c + d + 2) / 4;
10096	if (ofdm) {
10097		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10098		    & BWN_HF_4DB_CCK_POWERBOOST)
10099			avg = (avg >= 13) ? (avg - 13) : 0;
10100	}
10101	return (avg);
10102}
10103
10104static void
10105bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10106{
10107	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10108	int rfatt = *rfattp;
10109	int bbatt = *bbattp;
10110
10111	while (1) {
10112		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10113			break;
10114		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10115			break;
10116		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10117			break;
10118		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10119			break;
10120		if (bbatt > lo->bbatt.max) {
10121			bbatt -= 4;
10122			rfatt += 1;
10123			continue;
10124		}
10125		if (bbatt < lo->bbatt.min) {
10126			bbatt += 4;
10127			rfatt -= 1;
10128			continue;
10129		}
10130		if (rfatt > lo->rfatt.max) {
10131			rfatt -= 1;
10132			bbatt += 4;
10133			continue;
10134		}
10135		if (rfatt < lo->rfatt.min) {
10136			rfatt += 1;
10137			bbatt -= 4;
10138			continue;
10139		}
10140		break;
10141	}
10142
10143	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10144	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10145}
10146
10147static void
10148bwn_phy_lock(struct bwn_mac *mac)
10149{
10150	struct bwn_softc *sc = mac->mac_sc;
10151	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10152
10153	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10154	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10155
10156	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10157		bwn_psctl(mac, BWN_PS_AWAKE);
10158}
10159
10160static void
10161bwn_phy_unlock(struct bwn_mac *mac)
10162{
10163	struct bwn_softc *sc = mac->mac_sc;
10164	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10165
10166	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10167	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10168
10169	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10170		bwn_psctl(mac, 0);
10171}
10172
10173static void
10174bwn_rf_lock(struct bwn_mac *mac)
10175{
10176
10177	BWN_WRITE_4(mac, BWN_MACCTL,
10178	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10179	BWN_READ_4(mac, BWN_MACCTL);
10180	DELAY(10);
10181}
10182
10183static void
10184bwn_rf_unlock(struct bwn_mac *mac)
10185{
10186
10187	BWN_READ_2(mac, BWN_PHYVER);
10188	BWN_WRITE_4(mac, BWN_MACCTL,
10189	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10190}
10191
10192static struct bwn_pio_txqueue *
10193bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10194    struct bwn_pio_txpkt **pack)
10195{
10196	struct bwn_pio *pio = &mac->mac_method.pio;
10197	struct bwn_pio_txqueue *tq = NULL;
10198	unsigned int index;
10199
10200	switch (cookie & 0xf000) {
10201	case 0x1000:
10202		tq = &pio->wme[WME_AC_BK];
10203		break;
10204	case 0x2000:
10205		tq = &pio->wme[WME_AC_BE];
10206		break;
10207	case 0x3000:
10208		tq = &pio->wme[WME_AC_VI];
10209		break;
10210	case 0x4000:
10211		tq = &pio->wme[WME_AC_VO];
10212		break;
10213	case 0x5000:
10214		tq = &pio->mcast;
10215		break;
10216	}
10217	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10218	if (tq == NULL)
10219		return (NULL);
10220	index = (cookie & 0x0fff);
10221	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10222	if (index >= N(tq->tq_pkts))
10223		return (NULL);
10224	*pack = &tq->tq_pkts[index];
10225	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10226	return (tq);
10227}
10228
10229static void
10230bwn_txpwr(void *arg, int npending)
10231{
10232	struct bwn_mac *mac = arg;
10233	struct bwn_softc *sc = mac->mac_sc;
10234
10235	BWN_LOCK(sc);
10236	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10237	    mac->mac_phy.set_txpwr != NULL)
10238		mac->mac_phy.set_txpwr(mac);
10239	BWN_UNLOCK(sc);
10240}
10241
10242static void
10243bwn_task_15s(struct bwn_mac *mac)
10244{
10245	uint16_t reg;
10246
10247	if (mac->mac_fw.opensource) {
10248		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10249		if (reg) {
10250			bwn_restart(mac, "fw watchdog");
10251			return;
10252		}
10253		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10254	}
10255	if (mac->mac_phy.task_15s)
10256		mac->mac_phy.task_15s(mac);
10257
10258	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10259}
10260
10261static void
10262bwn_task_30s(struct bwn_mac *mac)
10263{
10264
10265	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10266		return;
10267	mac->mac_noise.noi_running = 1;
10268	mac->mac_noise.noi_nsamples = 0;
10269
10270	bwn_noise_gensample(mac);
10271}
10272
10273static void
10274bwn_task_60s(struct bwn_mac *mac)
10275{
10276
10277	if (mac->mac_phy.task_60s)
10278		mac->mac_phy.task_60s(mac);
10279	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10280}
10281
10282static void
10283bwn_tasks(void *arg)
10284{
10285	struct bwn_mac *mac = arg;
10286	struct bwn_softc *sc = mac->mac_sc;
10287
10288	BWN_ASSERT_LOCKED(sc);
10289	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10290		return;
10291
10292	if (mac->mac_task_state % 4 == 0)
10293		bwn_task_60s(mac);
10294	if (mac->mac_task_state % 2 == 0)
10295		bwn_task_30s(mac);
10296	bwn_task_15s(mac);
10297
10298	mac->mac_task_state++;
10299	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10300}
10301
10302static int
10303bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10304{
10305	struct bwn_softc *sc = mac->mac_sc;
10306
10307	KASSERT(a == 0, ("not support APHY\n"));
10308
10309	switch (plcp->o.raw[0] & 0xf) {
10310	case 0xb:
10311		return (BWN_OFDM_RATE_6MB);
10312	case 0xf:
10313		return (BWN_OFDM_RATE_9MB);
10314	case 0xa:
10315		return (BWN_OFDM_RATE_12MB);
10316	case 0xe:
10317		return (BWN_OFDM_RATE_18MB);
10318	case 0x9:
10319		return (BWN_OFDM_RATE_24MB);
10320	case 0xd:
10321		return (BWN_OFDM_RATE_36MB);
10322	case 0x8:
10323		return (BWN_OFDM_RATE_48MB);
10324	case 0xc:
10325		return (BWN_OFDM_RATE_54MB);
10326	}
10327	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10328	    plcp->o.raw[0] & 0xf);
10329	return (-1);
10330}
10331
10332static int
10333bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10334{
10335	struct bwn_softc *sc = mac->mac_sc;
10336
10337	switch (plcp->o.raw[0]) {
10338	case 0x0a:
10339		return (BWN_CCK_RATE_1MB);
10340	case 0x14:
10341		return (BWN_CCK_RATE_2MB);
10342	case 0x37:
10343		return (BWN_CCK_RATE_5MB);
10344	case 0x6e:
10345		return (BWN_CCK_RATE_11MB);
10346	}
10347	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10348	return (-1);
10349}
10350
10351static void
10352bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10353    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10354    int rssi, int noise)
10355{
10356	struct bwn_softc *sc = mac->mac_sc;
10357	const struct ieee80211_frame_min *wh;
10358	uint64_t tsf;
10359	uint16_t low_mactime_now;
10360
10361	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10362		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10363
10364	wh = mtod(m, const struct ieee80211_frame_min *);
10365	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10366		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10367
10368	bwn_tsf_read(mac, &tsf);
10369	low_mactime_now = tsf;
10370	tsf = tsf & ~0xffffULL;
10371	tsf += le16toh(rxhdr->mac_time);
10372	if (low_mactime_now < le16toh(rxhdr->mac_time))
10373		tsf -= 0x10000;
10374
10375	sc->sc_rx_th.wr_tsf = tsf;
10376	sc->sc_rx_th.wr_rate = rate;
10377	sc->sc_rx_th.wr_antsignal = rssi;
10378	sc->sc_rx_th.wr_antnoise = noise;
10379}
10380
10381static void
10382bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10383{
10384	struct bwn_softc *sc = mac->mac_sc;
10385	uint32_t low, high;
10386
10387	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10388	    ("%s:%d: fail", __func__, __LINE__));
10389
10390	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10391	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10392	*tsf = high;
10393	*tsf <<= 32;
10394	*tsf |= low;
10395}
10396
10397static int
10398bwn_dma_attach(struct bwn_mac *mac)
10399{
10400	struct bwn_dma *dma = &mac->mac_method.dma;
10401	struct bwn_softc *sc = mac->mac_sc;
10402	bus_addr_t lowaddr = 0;
10403	int error;
10404
10405	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10406		return (0);
10407
10408	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10409
10410	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10411
10412	dma->dmatype = bwn_dma_gettype(mac);
10413	if (dma->dmatype == BWN_DMA_30BIT)
10414		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10415	else if (dma->dmatype == BWN_DMA_32BIT)
10416		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10417	else
10418		lowaddr = BUS_SPACE_MAXADDR;
10419
10420	/*
10421	 * Create top level DMA tag
10422	 */
10423	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10424			       BWN_ALIGN, 0,		/* alignment, bounds */
10425			       lowaddr,			/* lowaddr */
10426			       BUS_SPACE_MAXADDR,	/* highaddr */
10427			       NULL, NULL,		/* filter, filterarg */
10428			       MAXBSIZE,		/* maxsize */
10429			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10430			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10431			       0,			/* flags */
10432			       NULL, NULL,		/* lockfunc, lockarg */
10433			       &dma->parent_dtag);
10434	if (error) {
10435		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10436		return (error);
10437	}
10438
10439	/*
10440	 * Create TX/RX mbuf DMA tag
10441	 */
10442	error = bus_dma_tag_create(dma->parent_dtag,
10443				1,
10444				0,
10445				BUS_SPACE_MAXADDR,
10446				BUS_SPACE_MAXADDR,
10447				NULL, NULL,
10448				MCLBYTES,
10449				1,
10450				BUS_SPACE_MAXSIZE_32BIT,
10451				0,
10452				NULL, NULL,
10453				&dma->rxbuf_dtag);
10454	if (error) {
10455		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10456		goto fail0;
10457	}
10458	error = bus_dma_tag_create(dma->parent_dtag,
10459				1,
10460				0,
10461				BUS_SPACE_MAXADDR,
10462				BUS_SPACE_MAXADDR,
10463				NULL, NULL,
10464				MCLBYTES,
10465				1,
10466				BUS_SPACE_MAXSIZE_32BIT,
10467				0,
10468				NULL, NULL,
10469				&dma->txbuf_dtag);
10470	if (error) {
10471		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10472		goto fail1;
10473	}
10474
10475	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10476	if (!dma->wme[WME_AC_BK])
10477		goto fail2;
10478
10479	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10480	if (!dma->wme[WME_AC_BE])
10481		goto fail3;
10482
10483	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10484	if (!dma->wme[WME_AC_VI])
10485		goto fail4;
10486
10487	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10488	if (!dma->wme[WME_AC_VO])
10489		goto fail5;
10490
10491	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10492	if (!dma->mcast)
10493		goto fail6;
10494	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10495	if (!dma->rx)
10496		goto fail7;
10497
10498	return (error);
10499
10500fail7:	bwn_dma_ringfree(&dma->mcast);
10501fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10502fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10503fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10504fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10505fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10506fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10507fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10508	return (error);
10509}
10510
10511static struct bwn_dma_ring *
10512bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10513    uint16_t cookie, int *slot)
10514{
10515	struct bwn_dma *dma = &mac->mac_method.dma;
10516	struct bwn_dma_ring *dr;
10517	struct bwn_softc *sc = mac->mac_sc;
10518
10519	BWN_ASSERT_LOCKED(mac->mac_sc);
10520
10521	switch (cookie & 0xf000) {
10522	case 0x1000:
10523		dr = dma->wme[WME_AC_BK];
10524		break;
10525	case 0x2000:
10526		dr = dma->wme[WME_AC_BE];
10527		break;
10528	case 0x3000:
10529		dr = dma->wme[WME_AC_VI];
10530		break;
10531	case 0x4000:
10532		dr = dma->wme[WME_AC_VO];
10533		break;
10534	case 0x5000:
10535		dr = dma->mcast;
10536		break;
10537	default:
10538		dr = NULL;
10539		KASSERT(0 == 1,
10540		    ("invalid cookie value %d", cookie & 0xf000));
10541	}
10542	*slot = (cookie & 0x0fff);
10543	if (*slot < 0 || *slot >= dr->dr_numslots) {
10544		/*
10545		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10546		 * that it occurs events which have same H/W sequence numbers.
10547		 * When it's occurred just prints a WARNING msgs and ignores.
10548		 */
10549		KASSERT(status->seq == dma->lastseq,
10550		    ("%s:%d: fail", __func__, __LINE__));
10551		device_printf(sc->sc_dev,
10552		    "out of slot ranges (0 < %d < %d)\n", *slot,
10553		    dr->dr_numslots);
10554		return (NULL);
10555	}
10556	dma->lastseq = status->seq;
10557	return (dr);
10558}
10559
10560static void
10561bwn_dma_stop(struct bwn_mac *mac)
10562{
10563	struct bwn_dma *dma;
10564
10565	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10566		return;
10567	dma = &mac->mac_method.dma;
10568
10569	bwn_dma_ringstop(&dma->rx);
10570	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10571	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10572	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10573	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10574	bwn_dma_ringstop(&dma->mcast);
10575}
10576
10577static void
10578bwn_dma_ringstop(struct bwn_dma_ring **dr)
10579{
10580
10581	if (dr == NULL)
10582		return;
10583
10584	bwn_dma_cleanup(*dr);
10585}
10586
10587static void
10588bwn_pio_stop(struct bwn_mac *mac)
10589{
10590	struct bwn_pio *pio;
10591
10592	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10593		return;
10594	pio = &mac->mac_method.pio;
10595
10596	bwn_destroy_queue_tx(&pio->mcast);
10597	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10598	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10599	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10600	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10601}
10602
10603static void
10604bwn_led_attach(struct bwn_mac *mac)
10605{
10606	struct bwn_softc *sc = mac->mac_sc;
10607	const uint8_t *led_act = NULL;
10608	uint16_t val[BWN_LED_MAX];
10609	int i;
10610
10611	sc->sc_led_idle = (2350 * hz) / 1000;
10612	sc->sc_led_blink = 1;
10613
10614	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10615		if (siba_get_pci_subvendor(sc->sc_dev) ==
10616		    bwn_vendor_led_act[i].vid) {
10617			led_act = bwn_vendor_led_act[i].led_act;
10618			break;
10619		}
10620	}
10621	if (led_act == NULL)
10622		led_act = bwn_default_led_act;
10623
10624	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10625	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10626	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10627	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10628
10629	for (i = 0; i < BWN_LED_MAX; ++i) {
10630		struct bwn_led *led = &sc->sc_leds[i];
10631
10632		if (val[i] == 0xff) {
10633			led->led_act = led_act[i];
10634		} else {
10635			if (val[i] & BWN_LED_ACT_LOW)
10636				led->led_flags |= BWN_LED_F_ACTLOW;
10637			led->led_act = val[i] & BWN_LED_ACT_MASK;
10638		}
10639		led->led_mask = (1 << i);
10640
10641		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10642		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10643		    led->led_act == BWN_LED_ACT_BLINK) {
10644			led->led_flags |= BWN_LED_F_BLINK;
10645			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10646				led->led_flags |= BWN_LED_F_POLLABLE;
10647			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10648				led->led_flags |= BWN_LED_F_SLOW;
10649
10650			if (sc->sc_blink_led == NULL) {
10651				sc->sc_blink_led = led;
10652				if (led->led_flags & BWN_LED_F_SLOW)
10653					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10654			}
10655		}
10656
10657		DPRINTF(sc, BWN_DEBUG_LED,
10658		    "%dth led, act %d, lowact %d\n", i,
10659		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10660	}
10661	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10662}
10663
10664static __inline uint16_t
10665bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10666{
10667
10668	if (led->led_flags & BWN_LED_F_ACTLOW)
10669		on = !on;
10670	if (on)
10671		val |= led->led_mask;
10672	else
10673		val &= ~led->led_mask;
10674	return val;
10675}
10676
10677static void
10678bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10679{
10680	struct bwn_softc *sc = mac->mac_sc;
10681	struct ifnet *ifp = sc->sc_ifp;
10682	struct ieee80211com *ic = ifp->if_l2com;
10683	uint16_t val;
10684	int i;
10685
10686	if (nstate == IEEE80211_S_INIT) {
10687		callout_stop(&sc->sc_led_blink_ch);
10688		sc->sc_led_blinking = 0;
10689	}
10690
10691	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10692		return;
10693
10694	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10695	for (i = 0; i < BWN_LED_MAX; ++i) {
10696		struct bwn_led *led = &sc->sc_leds[i];
10697		int on;
10698
10699		if (led->led_act == BWN_LED_ACT_UNKN ||
10700		    led->led_act == BWN_LED_ACT_NULL)
10701			continue;
10702
10703		if ((led->led_flags & BWN_LED_F_BLINK) &&
10704		    nstate != IEEE80211_S_INIT)
10705			continue;
10706
10707		switch (led->led_act) {
10708		case BWN_LED_ACT_ON:    /* Always on */
10709			on = 1;
10710			break;
10711		case BWN_LED_ACT_OFF:   /* Always off */
10712		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10713			on = 0;
10714			break;
10715		default:
10716			on = 1;
10717			switch (nstate) {
10718			case IEEE80211_S_INIT:
10719				on = 0;
10720				break;
10721			case IEEE80211_S_RUN:
10722				if (led->led_act == BWN_LED_ACT_11G &&
10723				    ic->ic_curmode != IEEE80211_MODE_11G)
10724					on = 0;
10725				break;
10726			default:
10727				if (led->led_act == BWN_LED_ACT_ASSOC)
10728					on = 0;
10729				break;
10730			}
10731			break;
10732		}
10733
10734		val = bwn_led_onoff(led, val, on);
10735	}
10736	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10737}
10738
10739static void
10740bwn_led_event(struct bwn_mac *mac, int event)
10741{
10742	struct bwn_softc *sc = mac->mac_sc;
10743	struct bwn_led *led = sc->sc_blink_led;
10744	int rate;
10745
10746	if (event == BWN_LED_EVENT_POLL) {
10747		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10748			return;
10749		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10750			return;
10751	}
10752
10753	sc->sc_led_ticks = ticks;
10754	if (sc->sc_led_blinking)
10755		return;
10756
10757	switch (event) {
10758	case BWN_LED_EVENT_RX:
10759		rate = sc->sc_rx_rate;
10760		break;
10761	case BWN_LED_EVENT_TX:
10762		rate = sc->sc_tx_rate;
10763		break;
10764	case BWN_LED_EVENT_POLL:
10765		rate = 0;
10766		break;
10767	default:
10768		panic("unknown LED event %d\n", event);
10769		break;
10770	}
10771	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10772	    bwn_led_duration[rate].off_dur);
10773}
10774
10775static void
10776bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10777{
10778	struct bwn_softc *sc = mac->mac_sc;
10779	struct bwn_led *led = sc->sc_blink_led;
10780	uint16_t val;
10781
10782	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10783	val = bwn_led_onoff(led, val, 1);
10784	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10785
10786	if (led->led_flags & BWN_LED_F_SLOW) {
10787		BWN_LED_SLOWDOWN(on_dur);
10788		BWN_LED_SLOWDOWN(off_dur);
10789	}
10790
10791	sc->sc_led_blinking = 1;
10792	sc->sc_led_blink_offdur = off_dur;
10793
10794	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10795}
10796
10797static void
10798bwn_led_blink_next(void *arg)
10799{
10800	struct bwn_mac *mac = arg;
10801	struct bwn_softc *sc = mac->mac_sc;
10802	uint16_t val;
10803
10804	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10805	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10806	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10807
10808	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10809	    bwn_led_blink_end, mac);
10810}
10811
10812static void
10813bwn_led_blink_end(void *arg)
10814{
10815	struct bwn_mac *mac = arg;
10816	struct bwn_softc *sc = mac->mac_sc;
10817
10818	sc->sc_led_blinking = 0;
10819}
10820
10821static int
10822bwn_suspend(device_t dev)
10823{
10824	struct bwn_softc *sc = device_get_softc(dev);
10825
10826	bwn_stop(sc, 1);
10827	return (0);
10828}
10829
10830static int
10831bwn_resume(device_t dev)
10832{
10833	struct bwn_softc *sc = device_get_softc(dev);
10834	struct ifnet *ifp = sc->sc_ifp;
10835
10836	if (ifp->if_flags & IFF_UP)
10837		bwn_init(sc);
10838	return (0);
10839}
10840
10841static void
10842bwn_rfswitch(void *arg)
10843{
10844	struct bwn_softc *sc = arg;
10845	struct bwn_mac *mac = sc->sc_curmac;
10846	int cur = 0, prev = 0;
10847
10848	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10849	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10850
10851	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10852		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10853			& BWN_RF_HWENABLED_HI_MASK))
10854			cur = 1;
10855	} else {
10856		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10857		    & BWN_RF_HWENABLED_LO_MASK)
10858			cur = 1;
10859	}
10860
10861	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10862		prev = 1;
10863
10864	if (cur != prev) {
10865		if (cur)
10866			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10867		else
10868			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10869
10870		device_printf(sc->sc_dev,
10871		    "status of RF switch is changed to %s\n",
10872		    cur ? "ON" : "OFF");
10873		if (cur != mac->mac_phy.rf_on) {
10874			if (cur)
10875				bwn_rf_turnon(mac);
10876			else
10877				bwn_rf_turnoff(mac);
10878		}
10879	}
10880
10881	callout_schedule(&sc->sc_rfswitch_ch, hz);
10882}
10883
10884static void
10885bwn_phy_lp_init_pre(struct bwn_mac *mac)
10886{
10887	struct bwn_phy *phy = &mac->mac_phy;
10888	struct bwn_phy_lp *plp = &phy->phy_lp;
10889
10890	plp->plp_antenna = BWN_ANT_DEFAULT;
10891}
10892
10893static int
10894bwn_phy_lp_init(struct bwn_mac *mac)
10895{
10896	static const struct bwn_stxtable tables[] = {
10897		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10898		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10899		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10900		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10901		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10902		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10903		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10904		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10905		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10906		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10907		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10908		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10909		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10910		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10911		{ 2, 11, 0x40, 0, 0x0f }
10912	};
10913	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10914	struct bwn_softc *sc = mac->mac_sc;
10915	const struct bwn_stxtable *st;
10916	struct ifnet *ifp = sc->sc_ifp;
10917	struct ieee80211com *ic = ifp->if_l2com;
10918	int i, error;
10919	uint16_t tmp;
10920
10921	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10922	bwn_phy_lp_bbinit(mac);
10923
10924	/* initialize RF */
10925	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10926	DELAY(1);
10927	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10928	DELAY(1);
10929
10930	if (mac->mac_phy.rf_ver == 0x2062)
10931		bwn_phy_lp_b2062_init(mac);
10932	else {
10933		bwn_phy_lp_b2063_init(mac);
10934
10935		/* synchronize stx table. */
10936		for (i = 0; i < N(tables); i++) {
10937			st = &tables[i];
10938			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10939			tmp >>= st->st_rfshift;
10940			tmp <<= st->st_physhift;
10941			BWN_PHY_SETMASK(mac,
10942			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10943			    ~(st->st_mask << st->st_physhift), tmp);
10944		}
10945
10946		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10947		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10948	}
10949
10950	/* calibrate RC */
10951	if (mac->mac_phy.rev >= 2)
10952		bwn_phy_lp_rxcal_r2(mac);
10953	else if (!plp->plp_rccap) {
10954		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10955			bwn_phy_lp_rccal_r12(mac);
10956	} else
10957		bwn_phy_lp_set_rccap(mac);
10958
10959	error = bwn_phy_lp_switch_channel(mac, 7);
10960	if (error)
10961		device_printf(sc->sc_dev,
10962		    "failed to change channel 7 (%d)\n", error);
10963	bwn_phy_lp_txpctl_init(mac);
10964	bwn_phy_lp_calib(mac);
10965	return (0);
10966}
10967
10968static uint16_t
10969bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10970{
10971
10972	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10973	return (BWN_READ_2(mac, BWN_PHYDATA));
10974}
10975
10976static void
10977bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10978{
10979
10980	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10981	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10982}
10983
10984static void
10985bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10986    uint16_t set)
10987{
10988
10989	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10990	BWN_WRITE_2(mac, BWN_PHYDATA,
10991	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10992}
10993
10994static uint16_t
10995bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10996{
10997
10998	KASSERT(reg != 1, ("unaccessible register %d", reg));
10999	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11000		reg |= 0x100;
11001	if (mac->mac_phy.rev >= 2)
11002		reg |= 0x200;
11003	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11004	return BWN_READ_2(mac, BWN_RFDATALO);
11005}
11006
11007static void
11008bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11009{
11010
11011	KASSERT(reg != 1, ("unaccessible register %d", reg));
11012	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11013	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11014}
11015
11016static void
11017bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11018{
11019
11020	if (on) {
11021		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11022		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11023		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11024		return;
11025	}
11026
11027	if (mac->mac_phy.rev >= 2) {
11028		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11029		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11030		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11031		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11032		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11033		return;
11034	}
11035
11036	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11037	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11038	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11039	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11040}
11041
11042static int
11043bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11044{
11045	struct bwn_phy *phy = &mac->mac_phy;
11046	struct bwn_phy_lp *plp = &phy->phy_lp;
11047	int error;
11048
11049	if (phy->rf_ver == 0x2063) {
11050		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11051		if (error)
11052			return (error);
11053	} else {
11054		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11055		if (error)
11056			return (error);
11057		bwn_phy_lp_set_anafilter(mac, chan);
11058		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11059	}
11060
11061	plp->plp_chan = chan;
11062	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11063	return (0);
11064}
11065
11066static uint32_t
11067bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11068{
11069	struct bwn_softc *sc = mac->mac_sc;
11070	struct ifnet *ifp = sc->sc_ifp;
11071	struct ieee80211com *ic = ifp->if_l2com;
11072
11073	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11074}
11075
11076static void
11077bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11078{
11079	struct bwn_phy *phy = &mac->mac_phy;
11080	struct bwn_phy_lp *plp = &phy->phy_lp;
11081
11082	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11083		return;
11084
11085	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11086	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11087	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11088	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11089	plp->plp_antenna = antenna;
11090}
11091
11092static void
11093bwn_phy_lp_task_60s(struct bwn_mac *mac)
11094{
11095
11096	bwn_phy_lp_calib(mac);
11097}
11098
11099static void
11100bwn_phy_lp_readsprom(struct bwn_mac *mac)
11101{
11102	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11103	struct bwn_softc *sc = mac->mac_sc;
11104	struct ifnet *ifp = sc->sc_ifp;
11105	struct ieee80211com *ic = ifp->if_l2com;
11106
11107	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11108		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11109		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11110		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11111		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11112		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11113		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11114		return;
11115	}
11116
11117	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11118	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11119	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11120	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11121	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11122	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11123	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11124	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11125}
11126
11127static void
11128bwn_phy_lp_bbinit(struct bwn_mac *mac)
11129{
11130
11131	bwn_phy_lp_tblinit(mac);
11132	if (mac->mac_phy.rev >= 2)
11133		bwn_phy_lp_bbinit_r2(mac);
11134	else
11135		bwn_phy_lp_bbinit_r01(mac);
11136}
11137
11138static void
11139bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11140{
11141	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11142	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11143	struct bwn_softc *sc = mac->mac_sc;
11144	struct ifnet *ifp = sc->sc_ifp;
11145	struct ieee80211com *ic = ifp->if_l2com;
11146
11147	bwn_phy_lp_set_txgain(mac,
11148	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11149	bwn_phy_lp_set_bbmult(mac, 150);
11150}
11151
11152static void
11153bwn_phy_lp_calib(struct bwn_mac *mac)
11154{
11155	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11156	struct bwn_softc *sc = mac->mac_sc;
11157	struct ifnet *ifp = sc->sc_ifp;
11158	struct ieee80211com *ic = ifp->if_l2com;
11159	const struct bwn_rxcompco *rc = NULL;
11160	struct bwn_txgain ogain;
11161	int i, omode, oafeovr, orf, obbmult;
11162	uint8_t mode, fc = 0;
11163
11164	if (plp->plp_chanfullcal != plp->plp_chan) {
11165		plp->plp_chanfullcal = plp->plp_chan;
11166		fc = 1;
11167	}
11168
11169	bwn_mac_suspend(mac);
11170
11171	/* BlueTooth Coexistance Override */
11172	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11173	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11174
11175	if (mac->mac_phy.rev >= 2)
11176		bwn_phy_lp_digflt_save(mac);
11177	bwn_phy_lp_get_txpctlmode(mac);
11178	mode = plp->plp_txpctlmode;
11179	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11180	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11181		bwn_phy_lp_bugfix(mac);
11182	if (mac->mac_phy.rev >= 2 && fc == 1) {
11183		bwn_phy_lp_get_txpctlmode(mac);
11184		omode = plp->plp_txpctlmode;
11185		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11186		if (oafeovr)
11187			ogain = bwn_phy_lp_get_txgain(mac);
11188		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11189		obbmult = bwn_phy_lp_get_bbmult(mac);
11190		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11191		if (oafeovr)
11192			bwn_phy_lp_set_txgain(mac, &ogain);
11193		bwn_phy_lp_set_bbmult(mac, obbmult);
11194		bwn_phy_lp_set_txpctlmode(mac, omode);
11195		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11196	}
11197	bwn_phy_lp_set_txpctlmode(mac, mode);
11198	if (mac->mac_phy.rev >= 2)
11199		bwn_phy_lp_digflt_restore(mac);
11200
11201	/* do RX IQ Calculation; assumes that noise is true. */
11202	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11203		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11204			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11205				rc = &bwn_rxcompco_5354[i];
11206		}
11207	} else if (mac->mac_phy.rev >= 2)
11208		rc = &bwn_rxcompco_r2;
11209	else {
11210		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11211			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11212				rc = &bwn_rxcompco_r12[i];
11213		}
11214	}
11215	if (rc == NULL)
11216		goto fail;
11217
11218	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11219	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11220
11221	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11222
11223	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11224		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11225		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11226	} else {
11227		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11228		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11229	}
11230
11231	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11232	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11233	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11234	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11235	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11236	bwn_phy_lp_set_deaf(mac, 0);
11237	/* XXX no checking return value? */
11238	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11239	bwn_phy_lp_clear_deaf(mac, 0);
11240	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11241	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11242	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11243
11244	/* disable RX GAIN override. */
11245	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11246	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11247	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11248	if (mac->mac_phy.rev >= 2) {
11249		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11250		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11251			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11252			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11253		}
11254	} else {
11255		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11256	}
11257
11258	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11259	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11260fail:
11261	bwn_mac_enable(mac);
11262}
11263
11264static void
11265bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11266{
11267
11268	if (on) {
11269		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11270		return;
11271	}
11272
11273	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11274	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11275}
11276
11277static int
11278bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11279{
11280	static const struct bwn_b206x_chan *bc = NULL;
11281	struct bwn_softc *sc = mac->mac_sc;
11282	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11283	    tmp[6];
11284	uint16_t old, scale, tmp16;
11285	int i, div;
11286
11287	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11288		if (bwn_b2063_chantable[i].bc_chan == chan) {
11289			bc = &bwn_b2063_chantable[i];
11290			break;
11291		}
11292	}
11293	if (bc == NULL)
11294		return (EINVAL);
11295
11296	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11297	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11298	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11299	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11300	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11301	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11302	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11303	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11304	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11305	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11306	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11307	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11308
11309	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11310	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11311
11312	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11313	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11314	freqref = freqxtal * 3;
11315	div = (freqxtal <= 26000000 ? 1 : 2);
11316	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11317	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11318		999999) / 1000000) + 1;
11319
11320	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11321	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11322	    0xfff8, timeout >> 2);
11323	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11324	    0xff9f,timeout << 5);
11325	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11326
11327	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11328	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11329	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11330
11331	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11332	    (timeoutref + 1)) - 1;
11333	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11334	    0xf0, count >> 8);
11335	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11336
11337	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11338	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11339	while (tmp[1] >= freqref) {
11340		tmp[0]++;
11341		tmp[1] -= freqref;
11342	}
11343	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11344	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11345	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11346	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11347	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11348
11349	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11351	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11352	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11353
11354	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11355	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11356
11357	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11358		scale = 1;
11359		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11360	} else {
11361		scale = 0;
11362		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11363	}
11364	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11365	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11366
11367	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11368	    (scale + 1);
11369	if (tmp[5] > 150)
11370		tmp[5] = 0;
11371
11372	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11373	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11374
11375	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11376	if (freqxtal > 26000000)
11377		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11378	else
11379		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11380
11381	if (val[0] == 45)
11382		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11383	else
11384		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11385
11386	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11387	DELAY(1);
11388	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11389
11390	/* VCO Calibration */
11391	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11392	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11393	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11394	DELAY(1);
11395	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11396	DELAY(1);
11397	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11398	DELAY(1);
11399	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11400	DELAY(300);
11401	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11402
11403	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11404	return (0);
11405}
11406
11407static int
11408bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11409{
11410	struct bwn_softc *sc = mac->mac_sc;
11411	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11412	const struct bwn_b206x_chan *bc = NULL;
11413	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11414	uint32_t tmp[9];
11415	int i;
11416
11417	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11418		if (bwn_b2062_chantable[i].bc_chan == chan) {
11419			bc = &bwn_b2062_chantable[i];
11420			break;
11421		}
11422	}
11423
11424	if (bc == NULL)
11425		return (EINVAL);
11426
11427	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11428	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11429	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11430	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11431	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11432	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11433	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11434	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11435	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11436	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11437
11438	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11439	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11440	bwn_phy_lp_b2062_reset_pllbias(mac);
11441	tmp[0] = freqxtal / 1000;
11442	tmp[1] = plp->plp_div * 1000;
11443	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11444	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11445		tmp[2] *= 2;
11446	tmp[3] = 48 * tmp[0];
11447	tmp[5] = tmp[2] / tmp[3];
11448	tmp[6] = tmp[2] % tmp[3];
11449	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11450	tmp[4] = tmp[6] * 0x100;
11451	tmp[5] = tmp[4] / tmp[3];
11452	tmp[6] = tmp[4] % tmp[3];
11453	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11454	tmp[4] = tmp[6] * 0x100;
11455	tmp[5] = tmp[4] / tmp[3];
11456	tmp[6] = tmp[4] % tmp[3];
11457	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11458	tmp[4] = tmp[6] * 0x100;
11459	tmp[5] = tmp[4] / tmp[3];
11460	tmp[6] = tmp[4] % tmp[3];
11461	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11462	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11463	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11464	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11465	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11466	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11467
11468	bwn_phy_lp_b2062_vco_calib(mac);
11469	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11470		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11471		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11472		bwn_phy_lp_b2062_reset_pllbias(mac);
11473		bwn_phy_lp_b2062_vco_calib(mac);
11474		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11475			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11476			return (EIO);
11477		}
11478	}
11479	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11480	return (0);
11481}
11482
11483static void
11484bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11485{
11486	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11487	uint16_t tmp = (channel == 14);
11488
11489	if (mac->mac_phy.rev < 2) {
11490		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11491		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11492			bwn_phy_lp_set_rccap(mac);
11493		return;
11494	}
11495
11496	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11497}
11498
11499static void
11500bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11501{
11502	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11503	struct bwn_softc *sc = mac->mac_sc;
11504	struct ifnet *ifp = sc->sc_ifp;
11505	struct ieee80211com *ic = ifp->if_l2com;
11506	uint16_t iso, tmp[3];
11507
11508	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11509
11510	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11511		iso = plp->plp_txisoband_m;
11512	else if (freq <= 5320)
11513		iso = plp->plp_txisoband_l;
11514	else if (freq <= 5700)
11515		iso = plp->plp_txisoband_m;
11516	else
11517		iso = plp->plp_txisoband_h;
11518
11519	tmp[0] = ((iso - 26) / 12) << 12;
11520	tmp[1] = tmp[0] + 0x1000;
11521	tmp[2] = tmp[0] + 0x2000;
11522
11523	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11524	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11525}
11526
11527static void
11528bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11529{
11530	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11531	int i;
11532	static const uint16_t addr[] = {
11533		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11534		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11535		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11536		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11537		BWN_PHY_OFDM(0xcf),
11538	};
11539	static const uint16_t val[] = {
11540		0xde5e, 0xe832, 0xe331, 0x4d26,
11541		0x0026, 0x1420, 0x0020, 0xfe08,
11542		0x0008,
11543	};
11544
11545	for (i = 0; i < N(addr); i++) {
11546		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11547		BWN_PHY_WRITE(mac, addr[i], val[i]);
11548	}
11549}
11550
11551static void
11552bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11553{
11554	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11555	struct bwn_softc *sc = mac->mac_sc;
11556	uint16_t ctl;
11557
11558	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11559	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11560	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11561		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11562		break;
11563	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11564		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11565		break;
11566	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11567		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11568		break;
11569	default:
11570		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11571		device_printf(sc->sc_dev, "unknown command mode\n");
11572		break;
11573	}
11574}
11575
11576static void
11577bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11578{
11579	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11580	uint16_t ctl;
11581	uint8_t old;
11582
11583	bwn_phy_lp_get_txpctlmode(mac);
11584	old = plp->plp_txpctlmode;
11585	if (old == mode)
11586		return;
11587	plp->plp_txpctlmode = mode;
11588
11589	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11590		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11591		    plp->plp_tssiidx);
11592		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11593		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11594
11595		/* disable TX GAIN override */
11596		if (mac->mac_phy.rev < 2)
11597			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11598		else {
11599			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11600			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11601		}
11602		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11603
11604		plp->plp_txpwridx = -1;
11605	}
11606	if (mac->mac_phy.rev >= 2) {
11607		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11608			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11609		else
11610			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11611	}
11612
11613	/* writes TX Power Control mode */
11614	switch (plp->plp_txpctlmode) {
11615	case BWN_PHYLP_TXPCTL_OFF:
11616		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11617		break;
11618	case BWN_PHYLP_TXPCTL_ON_HW:
11619		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11620		break;
11621	case BWN_PHYLP_TXPCTL_ON_SW:
11622		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11623		break;
11624	default:
11625		ctl = 0;
11626		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11627	}
11628	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11629	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11630}
11631
11632static void
11633bwn_phy_lp_bugfix(struct bwn_mac *mac)
11634{
11635	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11636	struct bwn_softc *sc = mac->mac_sc;
11637	const unsigned int size = 256;
11638	struct bwn_txgain tg;
11639	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11640	uint16_t tssinpt, tssiidx, value[2];
11641	uint8_t mode;
11642	int8_t txpwridx;
11643
11644	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11645	    M_NOWAIT | M_ZERO);
11646	if (tabs == NULL) {
11647		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11648		return;
11649	}
11650
11651	bwn_phy_lp_get_txpctlmode(mac);
11652	mode = plp->plp_txpctlmode;
11653	txpwridx = plp->plp_txpwridx;
11654	tssinpt = plp->plp_tssinpt;
11655	tssiidx = plp->plp_tssiidx;
11656
11657	bwn_tab_read_multi(mac,
11658	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11659	    BWN_TAB_4(7, 0x140), size, tabs);
11660
11661	bwn_phy_lp_tblinit(mac);
11662	bwn_phy_lp_bbinit(mac);
11663	bwn_phy_lp_txpctl_init(mac);
11664	bwn_phy_lp_rf_onoff(mac, 1);
11665	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11666
11667	bwn_tab_write_multi(mac,
11668	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11669	    BWN_TAB_4(7, 0x140), size, tabs);
11670
11671	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11672	plp->plp_tssinpt = tssinpt;
11673	plp->plp_tssiidx = tssiidx;
11674	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11675	if (txpwridx != -1) {
11676		/* set TX power by index */
11677		plp->plp_txpwridx = txpwridx;
11678		bwn_phy_lp_get_txpctlmode(mac);
11679		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11680			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11681		if (mac->mac_phy.rev >= 2) {
11682			rxcomp = bwn_tab_read(mac,
11683			    BWN_TAB_4(7, txpwridx + 320));
11684			txgain = bwn_tab_read(mac,
11685			    BWN_TAB_4(7, txpwridx + 192));
11686			tg.tg_pad = (txgain >> 16) & 0xff;
11687			tg.tg_gm = txgain & 0xff;
11688			tg.tg_pga = (txgain >> 8) & 0xff;
11689			tg.tg_dac = (rxcomp >> 28) & 0xff;
11690			bwn_phy_lp_set_txgain(mac, &tg);
11691		} else {
11692			rxcomp = bwn_tab_read(mac,
11693			    BWN_TAB_4(10, txpwridx + 320));
11694			txgain = bwn_tab_read(mac,
11695			    BWN_TAB_4(10, txpwridx + 192));
11696			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11697			    0xf800, (txgain >> 4) & 0x7fff);
11698			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11699			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11700		}
11701		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11702
11703		/* set TX IQCC */
11704		value[0] = (rxcomp >> 10) & 0x3ff;
11705		value[1] = rxcomp & 0x3ff;
11706		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11707
11708		coeff = bwn_tab_read(mac,
11709		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11710		    BWN_TAB_4(10, txpwridx + 448));
11711		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11712		if (mac->mac_phy.rev >= 2) {
11713			rfpwr = bwn_tab_read(mac,
11714			    BWN_TAB_4(7, txpwridx + 576));
11715			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11716			    rfpwr & 0xffff);
11717		}
11718		bwn_phy_lp_set_txgain_override(mac);
11719	}
11720	if (plp->plp_rccap)
11721		bwn_phy_lp_set_rccap(mac);
11722	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11723	bwn_phy_lp_set_txpctlmode(mac, mode);
11724	free(tabs, M_DEVBUF);
11725}
11726
11727static void
11728bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11729{
11730	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11731	int i;
11732	static const uint16_t addr[] = {
11733		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11734		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11735		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11736		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11737		BWN_PHY_OFDM(0xcf),
11738	};
11739
11740	for (i = 0; i < N(addr); i++)
11741		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11742}
11743
11744static void
11745bwn_phy_lp_tblinit(struct bwn_mac *mac)
11746{
11747	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11748
11749	if (mac->mac_phy.rev < 2) {
11750		bwn_phy_lp_tblinit_r01(mac);
11751		bwn_phy_lp_tblinit_txgain(mac);
11752		bwn_phy_lp_set_gaintbl(mac, freq);
11753		return;
11754	}
11755
11756	bwn_phy_lp_tblinit_r2(mac);
11757	bwn_phy_lp_tblinit_txgain(mac);
11758}
11759
11760struct bwn_wpair {
11761	uint16_t		reg;
11762	uint16_t		value;
11763};
11764
11765struct bwn_smpair {
11766	uint16_t		offset;
11767	uint16_t		mask;
11768	uint16_t		set;
11769};
11770
11771static void
11772bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11773{
11774	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11775	struct bwn_softc *sc = mac->mac_sc;
11776	struct ifnet *ifp = sc->sc_ifp;
11777	struct ieee80211com *ic = ifp->if_l2com;
11778	static const struct bwn_wpair v1[] = {
11779		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11780		{ BWN_PHY_AFE_CTL, 0x8800 },
11781		{ BWN_PHY_AFE_CTL_OVR, 0 },
11782		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11783		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11784		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11785		{ BWN_PHY_OFDM(0xf9), 0 },
11786		{ BWN_PHY_TR_LOOKUP_1, 0 }
11787	};
11788	static const struct bwn_smpair v2[] = {
11789		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11790		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11791		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11792		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11793		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11794	};
11795	static const struct bwn_smpair v3[] = {
11796		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11797		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11798		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11799		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11800		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11801		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11802		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11803		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11804		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11805		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11806
11807	};
11808	int i;
11809
11810	for (i = 0; i < N(v1); i++)
11811		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11812	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11813	for (i = 0; i < N(v2); i++)
11814		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11815
11816	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11817	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11818	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11819	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11820		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11821		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11822	} else {
11823		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11824	}
11825	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11826	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11827	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11828	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11829	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11830	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11831	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11832	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11833	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11834	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11835	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11836	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11837	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11838		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11839		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11840	} else {
11841		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11842		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11843	}
11844	for (i = 0; i < N(v3); i++)
11845		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11846	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11847	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11848		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11849		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11850	}
11851
11852	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11853		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11854		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11855		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11856		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11857		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11858		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11859	} else
11860		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11861
11862	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11863	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11864	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11865	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11866	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11867	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11868	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11869	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11870	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11871
11872	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11873	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11874		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11875		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11876		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11877	}
11878
11879	bwn_phy_lp_digflt_save(mac);
11880}
11881
11882static void
11883bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11884{
11885	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11886	struct bwn_softc *sc = mac->mac_sc;
11887	struct ifnet *ifp = sc->sc_ifp;
11888	struct ieee80211com *ic = ifp->if_l2com;
11889	static const struct bwn_smpair v1[] = {
11890		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11891		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11892		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11893		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11894		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11895		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11896		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11897	};
11898	static const struct bwn_smpair v2[] = {
11899		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11900		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11901		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11902		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11903		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11904		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11905		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11906		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11907		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11908		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11909		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11910		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11911		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11912		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11913		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11914		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11915	};
11916	static const struct bwn_smpair v3[] = {
11917		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11918		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11919		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11920		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11921		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11922		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11923		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11924		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11925	};
11926	static const struct bwn_smpair v4[] = {
11927		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11928		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11929		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11930		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11931		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11932		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11933		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11934		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11935	};
11936	static const struct bwn_smpair v5[] = {
11937		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11938		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11939		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11940		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11941		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11942		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11943		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11944		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11945	};
11946	int i;
11947	uint16_t tmp, tmp2;
11948
11949	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11950	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11951	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11952	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11953	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11954	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11955	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11956	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11957	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11958	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11959	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11960	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11961	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11962	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11963	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11964	for (i = 0; i < N(v1); i++)
11965		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11966	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11967	    0xff00, plp->plp_rxpwroffset);
11968	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11969	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11970	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11971		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11972		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11973		if (mac->mac_phy.rev == 0)
11974			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11975			    0xffcf, 0x0010);
11976		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11977	} else {
11978		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11979		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11980		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11981	}
11982	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11983	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11984	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11985		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11986	else
11987		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11988	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11989	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11990	    0xfff9, (plp->plp_bxarch << 1));
11991	if (mac->mac_phy.rev == 1 &&
11992	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11993		for (i = 0; i < N(v2); i++)
11994			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11995			    v2[i].set);
11996	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11997	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11998	    ((mac->mac_phy.rev == 0) &&
11999	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
12000		for (i = 0; i < N(v3); i++)
12001			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12002			    v3[i].set);
12003	} else if (mac->mac_phy.rev == 1 ||
12004		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12005		for (i = 0; i < N(v4); i++)
12006			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12007			    v4[i].set);
12008	} else {
12009		for (i = 0; i < N(v5); i++)
12010			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12011			    v5[i].set);
12012	}
12013	if (mac->mac_phy.rev == 1 &&
12014	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12015		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12016		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12017		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12018		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12019	}
12020	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12021	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12022	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12023		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12024		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12025		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12026		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12027	}
12028	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12029		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12030		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12031		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12032		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12033		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12034		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12035		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12036		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12037	} else {
12038		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12039		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12040	}
12041	if (mac->mac_phy.rev == 1) {
12042		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12043		tmp2 = (tmp & 0x03e0) >> 5;
12044		tmp2 |= tmp2 << 5;
12045		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12046		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12047		tmp2 = (tmp & 0x1f00) >> 8;
12048		tmp2 |= tmp2 << 5;
12049		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12050		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12051		tmp2 = tmp & 0x00ff;
12052		tmp2 |= tmp << 8;
12053		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12054	}
12055}
12056
12057struct bwn_b2062_freq {
12058	uint16_t		freq;
12059	uint8_t			value[6];
12060};
12061
12062static void
12063bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12064{
12065#define	CALC_CTL7(freq, div)						\
12066	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12067#define	CALC_CTL18(freq, div)						\
12068	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12069#define	CALC_CTL19(freq, div)						\
12070	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12071	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12072	struct bwn_softc *sc = mac->mac_sc;
12073	struct ifnet *ifp = sc->sc_ifp;
12074	struct ieee80211com *ic = ifp->if_l2com;
12075	static const struct bwn_b2062_freq freqdata_tab[] = {
12076		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12077		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12078		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12079		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12080		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12081		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12082	};
12083	static const struct bwn_wpair v1[] = {
12084		{ BWN_B2062_N_TXCTL3, 0 },
12085		{ BWN_B2062_N_TXCTL4, 0 },
12086		{ BWN_B2062_N_TXCTL5, 0 },
12087		{ BWN_B2062_N_TXCTL6, 0 },
12088		{ BWN_B2062_N_PDNCTL0, 0x40 },
12089		{ BWN_B2062_N_PDNCTL0, 0 },
12090		{ BWN_B2062_N_CALIB_TS, 0x10 },
12091		{ BWN_B2062_N_CALIB_TS, 0 }
12092	};
12093	const struct bwn_b2062_freq *f = NULL;
12094	uint32_t xtalfreq, ref;
12095	unsigned int i;
12096
12097	bwn_phy_lp_b2062_tblinit(mac);
12098
12099	for (i = 0; i < N(v1); i++)
12100		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12101	if (mac->mac_phy.rev > 0)
12102		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12103		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12104	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12105		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12106	else
12107		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12108
12109	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12110	    ("%s:%d: fail", __func__, __LINE__));
12111	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12112	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12113
12114	if (xtalfreq <= 30000000) {
12115		plp->plp_div = 1;
12116		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12117	} else {
12118		plp->plp_div = 2;
12119		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12120	}
12121
12122	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12123	    CALC_CTL7(xtalfreq, plp->plp_div));
12124	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12125	    CALC_CTL18(xtalfreq, plp->plp_div));
12126	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12127	    CALC_CTL19(xtalfreq, plp->plp_div));
12128
12129	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12130	ref &= 0xffff;
12131	for (i = 0; i < N(freqdata_tab); i++) {
12132		if (ref < freqdata_tab[i].freq) {
12133			f = &freqdata_tab[i];
12134			break;
12135		}
12136	}
12137	if (f == NULL)
12138		f = &freqdata_tab[N(freqdata_tab) - 1];
12139	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12140	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12141	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12142	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12143	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12144	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12145#undef CALC_CTL7
12146#undef CALC_CTL18
12147#undef CALC_CTL19
12148}
12149
12150static void
12151bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12152{
12153
12154	bwn_phy_lp_b2063_tblinit(mac);
12155	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12156	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12157	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12158	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12159	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12160	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12161	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12162	if (mac->mac_phy.rev == 2) {
12163		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12164		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12165		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12166	} else {
12167		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12168		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12169	}
12170}
12171
12172static void
12173bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12174{
12175	struct bwn_softc *sc = mac->mac_sc;
12176	static const struct bwn_wpair v1[] = {
12177		{ BWN_B2063_RX_BB_SP8, 0x0 },
12178		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12179		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12180		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12181		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12182		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12183		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12184		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12185	};
12186	static const struct bwn_wpair v2[] = {
12187		{ BWN_B2063_TX_BB_SP3, 0x0 },
12188		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12189		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12190		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12191		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12192	};
12193	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12194	int i;
12195	uint8_t tmp;
12196
12197	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12198
12199	for (i = 0; i < 2; i++)
12200		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12201	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12202	for (i = 2; i < N(v1); i++)
12203		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12204	for (i = 0; i < 10000; i++) {
12205		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12206			break;
12207		DELAY(1000);
12208	}
12209
12210	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12211		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12212
12213	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12214
12215	for (i = 0; i < N(v2); i++)
12216		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12217	if (freqxtal == 24000000) {
12218		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12219		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12220	} else {
12221		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12222		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12223	}
12224	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12225	for (i = 0; i < 10000; i++) {
12226		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12227			break;
12228		DELAY(1000);
12229	}
12230	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12231		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12232	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12233}
12234
12235static void
12236bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12237{
12238	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12239	struct bwn_softc *sc = mac->mac_sc;
12240	struct bwn_phy_lp_iq_est ie;
12241	struct bwn_txgain tx_gains;
12242	static const uint32_t pwrtbl[21] = {
12243		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12244		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12245		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12246		0x0004c, 0x0002c, 0x0001a,
12247	};
12248	uint32_t npwr, ipwr, sqpwr, tmp;
12249	int loopback, i, j, sum, error;
12250	uint16_t save[7];
12251	uint8_t txo, bbmult, txpctlmode;
12252
12253	error = bwn_phy_lp_switch_channel(mac, 7);
12254	if (error)
12255		device_printf(sc->sc_dev,
12256		    "failed to change channel to 7 (%d)\n", error);
12257	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12258	bbmult = bwn_phy_lp_get_bbmult(mac);
12259	if (txo)
12260		tx_gains = bwn_phy_lp_get_txgain(mac);
12261
12262	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12263	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12264	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12265	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12266	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12267	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12268	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12269
12270	bwn_phy_lp_get_txpctlmode(mac);
12271	txpctlmode = plp->plp_txpctlmode;
12272	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12273
12274	/* disable CRS */
12275	bwn_phy_lp_set_deaf(mac, 1);
12276	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12277	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12278	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12279	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12280	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12281	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12282	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12283	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12284	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12285	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12286	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12287	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12288	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12289	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12290	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12291	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12292	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12293	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12294	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12295	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12296	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12297	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12298	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12299	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12300
12301	loopback = bwn_phy_lp_loopback(mac);
12302	if (loopback == -1)
12303		goto done;
12304	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12305	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12306	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12307	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12308	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12309
12310	tmp = 0;
12311	memset(&ie, 0, sizeof(ie));
12312	for (i = 128; i <= 159; i++) {
12313		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12314		sum = 0;
12315		for (j = 5; j <= 25; j++) {
12316			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12317			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12318				goto done;
12319			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12320			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12321			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12322			    12);
12323			sum += ((ipwr - npwr) * (ipwr - npwr));
12324			if ((i == 128) || (sum < tmp)) {
12325				plp->plp_rccap = i;
12326				tmp = sum;
12327			}
12328		}
12329	}
12330	bwn_phy_lp_ddfs_turnoff(mac);
12331done:
12332	/* restore CRS */
12333	bwn_phy_lp_clear_deaf(mac, 1);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12335	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12336
12337	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12338	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12339	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12340	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12341	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12342	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12343	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12344
12345	bwn_phy_lp_set_bbmult(mac, bbmult);
12346	if (txo)
12347		bwn_phy_lp_set_txgain(mac, &tx_gains);
12348	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12349	if (plp->plp_rccap)
12350		bwn_phy_lp_set_rccap(mac);
12351}
12352
12353static void
12354bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12355{
12356	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12357	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12358
12359	if (mac->mac_phy.rev == 1)
12360		rc_cap = MIN(rc_cap + 5, 15);
12361
12362	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12363	    MAX(plp->plp_rccap - 4, 0x80));
12364	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12365	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12366	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12367}
12368
12369static uint32_t
12370bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12371{
12372	uint32_t i, q, r;
12373
12374	if (div == 0)
12375		return (0);
12376
12377	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12378		q <<= 1;
12379		if (r << 1 >= div) {
12380			q++;
12381			r = (r << 1) - div;
12382		}
12383	}
12384	if (r << 1 >= div)
12385		q++;
12386	return (q);
12387}
12388
12389static void
12390bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12391{
12392	struct bwn_softc *sc = mac->mac_sc;
12393
12394	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12395	DELAY(20);
12396	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12397		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12398		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12399	} else {
12400		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12401	}
12402	DELAY(5);
12403}
12404
12405static void
12406bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12407{
12408
12409	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12410	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12411	DELAY(200);
12412}
12413
12414static void
12415bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12416{
12417#define	FLAG_A	0x01
12418#define	FLAG_G	0x02
12419	struct bwn_softc *sc = mac->mac_sc;
12420	struct ifnet *ifp = sc->sc_ifp;
12421	struct ieee80211com *ic = ifp->if_l2com;
12422	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12423		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12425		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12427		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12428		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12429		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12430		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12431		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12432		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12433		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12434		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12435		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12436		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12437		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12438		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12439		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12440		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12441		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12442		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12443		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12444		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12445		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12446		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12447		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12448		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12449		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12450		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12451		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12452		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12453		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12454		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12455		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12456		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12457		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12458		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12459		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12460		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12461		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12462		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12463		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12464		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12465		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12466		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12467		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12468		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12469		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12470	};
12471	const struct bwn_b206x_rfinit_entry *br;
12472	unsigned int i;
12473
12474	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12475		br = &bwn_b2062_init_tab[i];
12476		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12477			if (br->br_flags & FLAG_G)
12478				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12479		} else {
12480			if (br->br_flags & FLAG_A)
12481				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12482		}
12483	}
12484#undef FLAG_A
12485#undef FLAG_B
12486}
12487
12488static void
12489bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12490{
12491#define	FLAG_A	0x01
12492#define	FLAG_G	0x02
12493	struct bwn_softc *sc = mac->mac_sc;
12494	struct ifnet *ifp = sc->sc_ifp;
12495	struct ieee80211com *ic = ifp->if_l2com;
12496	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12497		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12498		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12499		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12500		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12501		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12502		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12503		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12504		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12505		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12506		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12507		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12508		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12509		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12510		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12511		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12512		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12513		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12514		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12515		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12516		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12517		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12518		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12519		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12520		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12521		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12522		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12523		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12524		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12525		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12526		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12527		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12528		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12529		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12530		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12531		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12532		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12533		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12534		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12535		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12536		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12537		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12538		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12539	};
12540	const struct bwn_b206x_rfinit_entry *br;
12541	unsigned int i;
12542
12543	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12544		br = &bwn_b2063_init_tab[i];
12545		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12546			if (br->br_flags & FLAG_G)
12547				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12548		} else {
12549			if (br->br_flags & FLAG_A)
12550				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12551		}
12552	}
12553#undef FLAG_A
12554#undef FLAG_B
12555}
12556
12557static void
12558bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12559    int count, void *_data)
12560{
12561	unsigned int i;
12562	uint32_t offset, type;
12563	uint8_t *data = _data;
12564
12565	type = BWN_TAB_GETTYPE(typenoffset);
12566	offset = BWN_TAB_GETOFFSET(typenoffset);
12567	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12568
12569	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12570
12571	for (i = 0; i < count; i++) {
12572		switch (type) {
12573		case BWN_TAB_8BIT:
12574			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12575			data++;
12576			break;
12577		case BWN_TAB_16BIT:
12578			*((uint16_t *)data) = BWN_PHY_READ(mac,
12579			    BWN_PHY_TABLEDATALO);
12580			data += 2;
12581			break;
12582		case BWN_TAB_32BIT:
12583			*((uint32_t *)data) = BWN_PHY_READ(mac,
12584			    BWN_PHY_TABLEDATAHI);
12585			*((uint32_t *)data) <<= 16;
12586			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12587			    BWN_PHY_TABLEDATALO);
12588			data += 4;
12589			break;
12590		default:
12591			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12592		}
12593	}
12594}
12595
12596static void
12597bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12598    int count, const void *_data)
12599{
12600	uint32_t offset, type, value;
12601	const uint8_t *data = _data;
12602	unsigned int i;
12603
12604	type = BWN_TAB_GETTYPE(typenoffset);
12605	offset = BWN_TAB_GETOFFSET(typenoffset);
12606	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12607
12608	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12609
12610	for (i = 0; i < count; i++) {
12611		switch (type) {
12612		case BWN_TAB_8BIT:
12613			value = *data;
12614			data++;
12615			KASSERT(!(value & ~0xff),
12616			    ("%s:%d: fail", __func__, __LINE__));
12617			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12618			break;
12619		case BWN_TAB_16BIT:
12620			value = *((const uint16_t *)data);
12621			data += 2;
12622			KASSERT(!(value & ~0xffff),
12623			    ("%s:%d: fail", __func__, __LINE__));
12624			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12625			break;
12626		case BWN_TAB_32BIT:
12627			value = *((const uint32_t *)data);
12628			data += 4;
12629			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12630			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12631			break;
12632		default:
12633			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12634		}
12635	}
12636}
12637
12638static struct bwn_txgain
12639bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12640{
12641	struct bwn_txgain tg;
12642	uint16_t tmp;
12643
12644	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12645	if (mac->mac_phy.rev < 2) {
12646		tmp = BWN_PHY_READ(mac,
12647		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12648		tg.tg_gm = tmp & 0x0007;
12649		tg.tg_pga = (tmp & 0x0078) >> 3;
12650		tg.tg_pad = (tmp & 0x780) >> 7;
12651		return (tg);
12652	}
12653
12654	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12655	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12656	tg.tg_gm = tmp & 0xff;
12657	tg.tg_pga = (tmp >> 8) & 0xff;
12658	return (tg);
12659}
12660
12661static uint8_t
12662bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12663{
12664
12665	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12666}
12667
12668static void
12669bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12670{
12671	uint16_t pa;
12672
12673	if (mac->mac_phy.rev < 2) {
12674		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12675		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12676		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12677		bwn_phy_lp_set_txgain_override(mac);
12678		return;
12679	}
12680
12681	pa = bwn_phy_lp_get_pa_gain(mac);
12682	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12683	    (tg->tg_pga << 8) | tg->tg_gm);
12684	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12685	    tg->tg_pad | (pa << 6));
12686	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12687	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12688	    tg->tg_pad | (pa << 8));
12689	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12690	bwn_phy_lp_set_txgain_override(mac);
12691}
12692
12693static void
12694bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12695{
12696
12697	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12698}
12699
12700static void
12701bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12702{
12703	uint16_t trsw = (tx << 1) | rx;
12704
12705	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12706	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12707}
12708
12709static void
12710bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12711{
12712	struct bwn_softc *sc = mac->mac_sc;
12713	struct ifnet *ifp = sc->sc_ifp;
12714	struct ieee80211com *ic = ifp->if_l2com;
12715	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12716
12717	if (mac->mac_phy.rev < 2) {
12718		trsw = gain & 0x1;
12719		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12720		ext_lna = (gain & 2) >> 1;
12721
12722		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12723		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12724		    0xfbff, ext_lna << 10);
12725		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12726		    0xf7ff, ext_lna << 11);
12727		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12728	} else {
12729		low_gain = gain & 0xffff;
12730		high_gain = (gain >> 16) & 0xf;
12731		ext_lna = (gain >> 21) & 0x1;
12732		trsw = ~(gain >> 20) & 0x1;
12733
12734		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12735		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12736		    0xfdff, ext_lna << 9);
12737		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12738		    0xfbff, ext_lna << 10);
12739		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12740		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12741		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12742			tmp = (gain >> 2) & 0x3;
12743			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12744			    0xe7ff, tmp<<11);
12745			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12746			    tmp << 3);
12747		}
12748	}
12749
12750	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12751	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12752	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12753	if (mac->mac_phy.rev >= 2) {
12754		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12755		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12756			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12757			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12758		}
12759		return;
12760	}
12761	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12762}
12763
12764static void
12765bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12766{
12767	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12768
12769	if (user)
12770		plp->plp_crsusr_off = 1;
12771	else
12772		plp->plp_crssys_off = 1;
12773
12774	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12775}
12776
12777static void
12778bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12779{
12780	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12781	struct bwn_softc *sc = mac->mac_sc;
12782	struct ifnet *ifp = sc->sc_ifp;
12783	struct ieee80211com *ic = ifp->if_l2com;
12784
12785	if (user)
12786		plp->plp_crsusr_off = 0;
12787	else
12788		plp->plp_crssys_off = 0;
12789
12790	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12791		return;
12792
12793	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12794		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12795	else
12796		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12797}
12798
12799static unsigned int
12800bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12801{
12802	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12803	static uint8_t sqrt_table[256] = {
12804		10, 14, 17, 20, 22, 24, 26, 28,
12805		30, 31, 33, 34, 36, 37, 38, 40,
12806		41, 42, 43, 44, 45, 46, 47, 48,
12807		50, 50, 51, 52, 53, 54, 55, 56,
12808		57, 58, 59, 60, 60, 61, 62, 63,
12809		64, 64, 65, 66, 67, 67, 68, 69,
12810		70, 70, 71, 72, 72, 73, 74, 74,
12811		75, 76, 76, 77, 78, 78, 79, 80,
12812		80, 81, 81, 82, 83, 83, 84, 84,
12813		85, 86, 86, 87, 87, 88, 88, 89,
12814		90, 90, 91, 91, 92, 92, 93, 93,
12815		94, 94, 95, 95, 96, 96, 97, 97,
12816		98, 98, 99, 100, 100, 100, 101, 101,
12817		102, 102, 103, 103, 104, 104, 105, 105,
12818		106, 106, 107, 107, 108, 108, 109, 109,
12819		110, 110, 110, 111, 111, 112, 112, 113,
12820		113, 114, 114, 114, 115, 115, 116, 116,
12821		117, 117, 117, 118, 118, 119, 119, 120,
12822		120, 120, 121, 121, 122, 122, 122, 123,
12823		123, 124, 124, 124, 125, 125, 126, 126,
12824		126, 127, 127, 128, 128, 128, 129, 129,
12825		130, 130, 130, 131, 131, 131, 132, 132,
12826		133, 133, 133, 134, 134, 134, 135, 135,
12827		136, 136, 136, 137, 137, 137, 138, 138,
12828		138, 139, 139, 140, 140, 140, 141, 141,
12829		141, 142, 142, 142, 143, 143, 143, 144,
12830		144, 144, 145, 145, 145, 146, 146, 146,
12831		147, 147, 147, 148, 148, 148, 149, 149,
12832		150, 150, 150, 150, 151, 151, 151, 152,
12833		152, 152, 153, 153, 153, 154, 154, 154,
12834		155, 155, 155, 156, 156, 156, 157, 157,
12835		157, 158, 158, 158, 159, 159, 159, 160
12836	};
12837
12838	if (x == 0)
12839		return (0);
12840	if (x >= 256) {
12841		unsigned int tmp;
12842
12843		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12844			/* do nothing */ ;
12845		return (tmp);
12846	}
12847	return (sqrt_table[x - 1] / 10);
12848}
12849
12850static int
12851bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12852{
12853#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12854	int _t;								\
12855	_t = _x - 20;							\
12856	if (_t >= 0) {							\
12857		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12858	} else {							\
12859		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12860	}								\
12861} while (0)
12862#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12863	int _t;								\
12864	_t = _x - 11;							\
12865	if (_t >= 0)							\
12866		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12867	else								\
12868		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12869} while (0)
12870	struct bwn_phy_lp_iq_est ie;
12871	uint16_t v0, v1;
12872	int tmp[2], ret;
12873
12874	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12875	v0 = v1 >> 8;
12876	v1 |= 0xff;
12877
12878	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12879	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12880
12881	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12882	if (ret == 0)
12883		goto done;
12884
12885	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12886		ret = 0;
12887		goto done;
12888	}
12889
12890	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12891	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12892
12893	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12894	v0 = tmp[0] >> 3;
12895	v1 = tmp[1] >> 4;
12896done:
12897	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12898	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12899	return ret;
12900#undef CALC_COEFF
12901#undef CALC_COEFF2
12902}
12903
12904static void
12905bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12906{
12907	static const uint16_t noisescale[] = {
12908		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12909		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12910		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12911		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12912		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12913	};
12914	static const uint16_t crsgainnft[] = {
12915		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12916		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12917		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12918		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12919		0x013d,
12920	};
12921	static const uint16_t filterctl[] = {
12922		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12923		0xff53, 0x0127,
12924	};
12925	static const uint32_t psctl[] = {
12926		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12927		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12928		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12929		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12930		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12931		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12932		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12933		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12934	};
12935	static const uint16_t ofdmcckgain_r0[] = {
12936		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12937		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12938		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12939		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12940		0x755d,
12941	};
12942	static const uint16_t ofdmcckgain_r1[] = {
12943		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12944		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12945		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12946		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12947		0x755d,
12948	};
12949	static const uint16_t gaindelta[] = {
12950		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12951		0x0000,
12952	};
12953	static const uint32_t txpwrctl[] = {
12954		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12955		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12956		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12957		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12958		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12959		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12960		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12961		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12962		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12963		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12964		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12965		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12966		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12967		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12968		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12969		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12970		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12971		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12972		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12973		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12974		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12975		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12976		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12977		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12978		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12979		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12980		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12981		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12982		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12983		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12984		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12985		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12989		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12992		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12993		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12994		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12995		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12996		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12997		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12998		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12999		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13000		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13001		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13002		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13003		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13004		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13005		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13006		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13007		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13008		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13009		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13010		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13011		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13012		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13013		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13014		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13015		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13016		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13017		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13018		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13019		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13020		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13021		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13022		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13023		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13024		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13025		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13026		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13027		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13028		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13029		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13030		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13031		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13032		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13033		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13034		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13035		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13036		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13037		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13038		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13039		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13040		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13041		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13042		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13043		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13044		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13045		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13046		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13047		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13048		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13049		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13050		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13051		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13052		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13053		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13054		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13055		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13056		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13057		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13058		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13059		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13060		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13061		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13062		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13063		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13064		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13065		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13066		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13067		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13068		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13069		0x00000702,
13070	};
13071
13072	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13073
13074	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13075	    bwn_tab_sigsq_tbl);
13076	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13077	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13078	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13079	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13080	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13081	    bwn_tab_pllfrac_tbl);
13082	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13083	    bwn_tabl_iqlocal_tbl);
13084	if (mac->mac_phy.rev == 0) {
13085		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13086		    ofdmcckgain_r0);
13087		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13088		    ofdmcckgain_r0);
13089	} else {
13090		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13091		    ofdmcckgain_r1);
13092		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13093		    ofdmcckgain_r1);
13094	}
13095	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13096	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13097}
13098
13099static void
13100bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13101{
13102	struct bwn_softc *sc = mac->mac_sc;
13103	int i;
13104	static const uint16_t noisescale[] = {
13105		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13106		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13111		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13112	};
13113	static const uint32_t filterctl[] = {
13114		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13115		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13116	};
13117	static const uint32_t psctl[] = {
13118		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13119		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13120		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13121		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13122	};
13123	static const uint32_t gainidx[] = {
13124		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13125		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13127		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13128		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13129		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13130		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13131		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13132		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13133		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13134		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13135		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13136		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13137		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13138		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13139		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13142		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13143		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13144		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13145		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13146		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13147		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13148		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13149		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13150		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13151		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13152		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13153		0x0000001a, 0x64ca55ad, 0x0000001a
13154	};
13155	static const uint16_t auxgainidx[] = {
13156		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13158		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13159		0x0004, 0x0016
13160	};
13161	static const uint16_t swctl[] = {
13162		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13163		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13164		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13165		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13166		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13167		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13168		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13169		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13170	};
13171	static const uint8_t hf[] = {
13172		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13173		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13174	};
13175	static const uint32_t gainval[] = {
13176		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13177		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13178		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13179		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13180		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13181		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13182		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13183		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13184		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13185		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13186		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13187		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13188		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13189		0x000000f1, 0x00000000, 0x00000000
13190	};
13191	static const uint16_t gain[] = {
13192		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13193		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13194		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13195		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13196		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13197		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13198		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13199		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13200		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13201		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13202		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13203		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13204	};
13205	static const uint32_t papdeps[] = {
13206		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13207		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13208		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13209		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13210		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13211		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13212		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13213		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13214		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13215		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13216		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13217		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13218		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13219	};
13220	static const uint32_t papdmult[] = {
13221		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13222		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13223		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13224		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13225		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13226		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13227		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13228		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13229		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13230		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13231		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13232		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13233		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13234	};
13235	static const uint32_t gainidx_a0[] = {
13236		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13237		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13238		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13239		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13240		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13241		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13242		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13243		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13244		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13245		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13246		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13247		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13248		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13249	};
13250	static const uint16_t auxgainidx_a0[] = {
13251		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13252		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13253		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13254		0x0002, 0x0014
13255	};
13256	static const uint32_t gainval_a0[] = {
13257		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13258		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13259		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13260		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13261		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13262		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13263		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13264		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13265		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13266		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13267		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13268		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13269		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13270		0x000000f7, 0x00000000, 0x00000000
13271	};
13272	static const uint16_t gain_a0[] = {
13273		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13274		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13275		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13276		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13277		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13278		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13279		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13280		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13281		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13282		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13283		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13284		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13285	};
13286
13287	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13288
13289	for (i = 0; i < 704; i++)
13290		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13291
13292	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13293	    bwn_tab_sigsq_tbl);
13294	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13295	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13296	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13297	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13298	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13299	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13300	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13301	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13302	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13303	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13304	    bwn_tab_pllfrac_tbl);
13305	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13306	    bwn_tabl_iqlocal_tbl);
13307	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13308	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13309
13310	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13311	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13312		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13313		    gainidx_a0);
13314		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13315		    auxgainidx_a0);
13316		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13317		    gainval_a0);
13318		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13319	}
13320}
13321
13322static void
13323bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13324{
13325	struct bwn_softc *sc = mac->mac_sc;
13326	struct ifnet *ifp = sc->sc_ifp;
13327	struct ieee80211com *ic = ifp->if_l2com;
13328	static struct bwn_txgain_entry txgain_r2[] = {
13329		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13330		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13331		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13332		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13333		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13334		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13335		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13336		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13337		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13338		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13339		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13340		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13341		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13342		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13343		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13344		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13345		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13346		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13347		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13348		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13349		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13350		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13351		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13352		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13353		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13354		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13355		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13356		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13357		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13358		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13359		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13360		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13361		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13362		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13363		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13364		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13365		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13366		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13367		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13368		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13369		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13370		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13371		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13372		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13373		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13374		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13375		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13376		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13377		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13378		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13379		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13380		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13381		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13382		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13383		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13384		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13385		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13386		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13387		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13388		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13389		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13390		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13391		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13392		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13393	};
13394	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13395		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13396		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13397		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13398		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13399		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13400		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13401		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13402		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13403		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13404		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13405		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13406		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13407		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13408		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13409		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13410		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13411		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13412		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13413		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13414		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13415		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13416		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13417		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13418		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13419		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13420		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13421		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13422		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13423		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13424		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13425		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13426		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13427		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13428		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13429		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13430		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13431		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13432		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13433		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13434		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13435		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13436		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13437		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13438		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13439		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13440		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13441		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13442		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13443		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13444		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13445		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13446		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13447		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13448		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13449		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13450		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13451		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13452		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13453		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13454		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13455		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13456		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13457		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13458		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13459	};
13460	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13461		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13462		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13463		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13464		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13465		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13466		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13467		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13468		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13469		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13470		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13471		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13472		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13473		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13474		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13475		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13476		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13477		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13478		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13479		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13480		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13481		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13482		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13483		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13484		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13485		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13486		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13487		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13488		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13489		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13490		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13491		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13492		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13493		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13494		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13495		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13496		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13497		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13498		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13499		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13500		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13501		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13502		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13503		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13504		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13505		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13506		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13507		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13508		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13509		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13510		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13511		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13512		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13513		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13514		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13515		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13516		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13517		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13518		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13519		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13520		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13521		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13522		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13523		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13524		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13525	};
13526	static struct bwn_txgain_entry txgain_r0[] = {
13527		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13528		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13529		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13530		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13531		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13532		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13533		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13534		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13535		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13536		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13537		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13538		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13539		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13540		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13541		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13542		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13543		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13544		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13545		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13546		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13547		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13548		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13549		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13550		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13551		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13552		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13553		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13554		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13555		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13556		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13557		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13558		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13559		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13560		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13561		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13562		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13563		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13564		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13565		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13566		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13567		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13568		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13569		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13570		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13571		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13572		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13573		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13574		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13575		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13576		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13577		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13578		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13579		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13580		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13581		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13582		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13583		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13584		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13585		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13586		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13587		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13588		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13589		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13590		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13591	};
13592	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13593		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13594		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13595		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13596		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13597		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13598		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13599		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13600		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13601		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13602		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13603		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13604		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13605		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13606		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13607		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13608		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13609		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13610		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13611		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13612		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13613		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13614		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13615		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13616		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13617		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13618		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13619		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13620		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13621		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13622		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13623		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13624		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13625		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13626		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13627		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13628		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13629		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13630		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13631		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13632		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13633		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13634		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13635		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13636		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13637		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13638		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13639		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13640		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13641		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13642		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13643		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13644		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13645		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13646		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13647		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13648		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13649		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13650		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13651		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13652		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13653		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13654		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13655		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13656		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13657	};
13658	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13659		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13660		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13661		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13662		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13663		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13664		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13665		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13666		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13667		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13668		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13669		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13670		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13671		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13672		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13673		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13674		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13675		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13676		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13677		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13678		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13679		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13680		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13681		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13682		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13683		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13684		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13685		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13686		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13687		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13688		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13689		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13690		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13691		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13692		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13693		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13694		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13695		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13696		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13697		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13698		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13699		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13700		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13701		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13702		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13703		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13704		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13705		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13706		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13707		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13708		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13709		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13710		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13711		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13712		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13713		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13714		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13715		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13716		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13717		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13718		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13719		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13720		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13721		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13722		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13723	};
13724	static struct bwn_txgain_entry txgain_r1[] = {
13725		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13726		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13727		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13728		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13729		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13730		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13731		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13732		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13733		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13734		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13735		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13736		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13737		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13738		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13739		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13740		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13741		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13742		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13743		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13744		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13745		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13746		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13747		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13748		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13749		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13750		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13751		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13752		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13753		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13754		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13755		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13756		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13757		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13758		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13759		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13760		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13761		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13762		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13763		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13764		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13765		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13766		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13767		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13768		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13769		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13770		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13771		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13772		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13773		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13774		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13775		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13776		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13777		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13778		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13779		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13780		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13781		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13782		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13783		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13784		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13785		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13786		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13787		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13788		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13789		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13790		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13791		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13792		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13793		{ 7, 11, 6, 0, 71 }
13794	};
13795	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13796		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13797		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13798		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13799		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13800		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13801		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13802		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13803		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13804		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13805		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13806		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13807		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13808		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13809		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13810		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13811		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13812		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13813		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13814		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13815		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13816		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13817		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13818		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13819		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13820		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13821		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13822		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13823		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13824		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13825		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13826		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13827		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13828		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13829		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13830		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13831		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13832		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13833		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13834		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13835		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13836		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13837		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13838		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13839		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13840		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13841		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13842		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13843		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13844		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13845		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13846		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13847		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13848		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13849		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13850		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13851		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13852		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13853		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13854		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13855		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13856		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13857		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13858		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13859		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13860	};
13861	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13862		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13863		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13864		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13865		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13866		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13867		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13868		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13869		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13870		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13871		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13872		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13873		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13874		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13875		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13876		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13877		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13878		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13879		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13880		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13881		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13882		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13883		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13884		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13885		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13886		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13887		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13888		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13889		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13890		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13891		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13892		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13893		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13894		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13895		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13896		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13897		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13898		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13899		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13900		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13901		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13902		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13903		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13904		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13905		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13906		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13907		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13908		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13909		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13910		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13911		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13912		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13913		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13914		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13915		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13916		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13917		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13918		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13919		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13920		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13921		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13922		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13923		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13924		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13925		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13926	};
13927
13928	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13929		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13930			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13931		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13932			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13933			    txgain_2ghz_r2);
13934		else
13935			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13936			    txgain_5ghz_r2);
13937		return;
13938	}
13939
13940	if (mac->mac_phy.rev == 0) {
13941		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13942		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13943			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13944		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13945			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13946			    txgain_2ghz_r0);
13947		else
13948			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13949			    txgain_5ghz_r0);
13950		return;
13951	}
13952
13953	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13954	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13955		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13956	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13957		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13958	else
13959		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13960}
13961
13962static void
13963bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13964{
13965	uint32_t offset, type;
13966
13967	type = BWN_TAB_GETTYPE(typeoffset);
13968	offset = BWN_TAB_GETOFFSET(typeoffset);
13969	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13970
13971	switch (type) {
13972	case BWN_TAB_8BIT:
13973		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13974		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13975		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13976		break;
13977	case BWN_TAB_16BIT:
13978		KASSERT(!(value & ~0xffff),
13979		    ("%s:%d: fail", __func__, __LINE__));
13980		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13981		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13982		break;
13983	case BWN_TAB_32BIT:
13984		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13985		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13986		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13987		break;
13988	default:
13989		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13990	}
13991}
13992
13993static int
13994bwn_phy_lp_loopback(struct bwn_mac *mac)
13995{
13996	struct bwn_phy_lp_iq_est ie;
13997	int i, index = -1;
13998	uint32_t tmp;
13999
14000	memset(&ie, 0, sizeof(ie));
14001
14002	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14003	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14004	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14005	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14006	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14007	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14008	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14009	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14010	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14011	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14012	for (i = 0; i < 32; i++) {
14013		bwn_phy_lp_set_rxgain_idx(mac, i);
14014		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14015		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14016			continue;
14017		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14018		if ((tmp > 4000) && (tmp < 10000)) {
14019			index = i;
14020			break;
14021		}
14022	}
14023	bwn_phy_lp_ddfs_turnoff(mac);
14024	return (index);
14025}
14026
14027static void
14028bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14029{
14030
14031	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14032}
14033
14034static void
14035bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14036    int incr1, int incr2, int scale_idx)
14037{
14038
14039	bwn_phy_lp_ddfs_turnoff(mac);
14040	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14041	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14042	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14043	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14044	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14045	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14046	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14047	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14048	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14049	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14050}
14051
14052static uint8_t
14053bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14054    struct bwn_phy_lp_iq_est *ie)
14055{
14056	int i;
14057
14058	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14059	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14060	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14061	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14062	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14063
14064	for (i = 0; i < 500; i++) {
14065		if (!(BWN_PHY_READ(mac,
14066		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14067			break;
14068		DELAY(1000);
14069	}
14070	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14071		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14072		return 0;
14073	}
14074
14075	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14076	ie->ie_iqprod <<= 16;
14077	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14078	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14079	ie->ie_ipwr <<= 16;
14080	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14081	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14082	ie->ie_qpwr <<= 16;
14083	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14084
14085	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14086	return 1;
14087}
14088
14089static uint32_t
14090bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14091{
14092	uint32_t offset, type, value;
14093
14094	type = BWN_TAB_GETTYPE(typeoffset);
14095	offset = BWN_TAB_GETOFFSET(typeoffset);
14096	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14097
14098	switch (type) {
14099	case BWN_TAB_8BIT:
14100		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14101		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14102		break;
14103	case BWN_TAB_16BIT:
14104		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14105		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14106		break;
14107	case BWN_TAB_32BIT:
14108		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14109		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14110		value <<= 16;
14111		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14112		break;
14113	default:
14114		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14115		value = 0;
14116	}
14117
14118	return (value);
14119}
14120
14121static void
14122bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14123{
14124
14125	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14126	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14127}
14128
14129static void
14130bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14131{
14132	uint16_t ctl;
14133
14134	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14135	ctl |= dac << 7;
14136	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14137}
14138
14139static void
14140bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14141{
14142
14143	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14144	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14145}
14146
14147static void
14148bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14149{
14150
14151	if (mac->mac_phy.rev < 2)
14152		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14153	else {
14154		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14155		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14156	}
14157	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14158}
14159
14160static uint16_t
14161bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14162{
14163
14164	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14165}
14166
14167static uint8_t
14168bwn_nbits(int32_t val)
14169{
14170	uint32_t tmp;
14171	uint8_t nbits = 0;
14172
14173	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14174		nbits++;
14175	return (nbits);
14176}
14177
14178static void
14179bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14180    struct bwn_txgain_entry *table)
14181{
14182	int i;
14183
14184	for (i = offset; i < count; i++)
14185		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14186}
14187
14188static void
14189bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14190    struct bwn_txgain_entry data)
14191{
14192
14193	if (mac->mac_phy.rev >= 2)
14194		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14195	else
14196		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14197}
14198
14199static void
14200bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14201    struct bwn_txgain_entry te)
14202{
14203	struct bwn_softc *sc = mac->mac_sc;
14204	struct ifnet *ifp = sc->sc_ifp;
14205	struct ieee80211com *ic = ifp->if_l2com;
14206	uint32_t tmp;
14207
14208	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14209
14210	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14211	if (mac->mac_phy.rev >= 3) {
14212		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14213		    (0x10 << 24) : (0x70 << 24));
14214	} else {
14215		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14216		    (0x14 << 24) : (0x7f << 24));
14217	}
14218	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14219	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14220	    te.te_bbmult << 20 | te.te_dac << 28);
14221}
14222
14223static void
14224bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14225    struct bwn_txgain_entry te)
14226{
14227
14228	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14229
14230	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14231	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14232	    te.te_dac);
14233	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14234}
14235
14236static void
14237bwn_sysctl_node(struct bwn_softc *sc)
14238{
14239	device_t dev = sc->sc_dev;
14240	struct bwn_mac *mac;
14241	struct bwn_stats *stats;
14242
14243	/* XXX assume that count of MAC is only 1. */
14244
14245	if ((mac = sc->sc_curmac) == NULL)
14246		return;
14247	stats = &mac->mac_stats;
14248
14249	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14250	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14251	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14252	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14253	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14254	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14255	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14256	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14257	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14258
14259#ifdef BWN_DEBUG
14260	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14261	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14262	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14263#endif
14264}
14265
14266static device_method_t bwn_methods[] = {
14267	/* Device interface */
14268	DEVMETHOD(device_probe,		bwn_probe),
14269	DEVMETHOD(device_attach,	bwn_attach),
14270	DEVMETHOD(device_detach,	bwn_detach),
14271	DEVMETHOD(device_suspend,	bwn_suspend),
14272	DEVMETHOD(device_resume,	bwn_resume),
14273	{ 0,0 }
14274};
14275static driver_t bwn_driver = {
14276	"bwn",
14277	bwn_methods,
14278	sizeof(struct bwn_softc)
14279};
14280static devclass_t bwn_devclass;
14281DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14282MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14283MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14284MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14285MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14286