if_bwn.c revision 204983
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 204983 2010-03-10 21:45:40Z yongari $");
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	uint32_t low, high;
10385
10386	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10387	    ("%s:%d: fail", __func__, __LINE__));
10388
10389	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10390	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10391	*tsf = high;
10392	*tsf <<= 32;
10393	*tsf |= low;
10394}
10395
10396static int
10397bwn_dma_attach(struct bwn_mac *mac)
10398{
10399	struct bwn_dma *dma = &mac->mac_method.dma;
10400	struct bwn_softc *sc = mac->mac_sc;
10401	bus_addr_t lowaddr = 0;
10402	int error;
10403
10404	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10405		return (0);
10406
10407	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10408
10409	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10410
10411	dma->dmatype = bwn_dma_gettype(mac);
10412	if (dma->dmatype == BWN_DMA_30BIT)
10413		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10414	else if (dma->dmatype == BWN_DMA_32BIT)
10415		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10416	else
10417		lowaddr = BUS_SPACE_MAXADDR;
10418
10419	/*
10420	 * Create top level DMA tag
10421	 */
10422	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10423			       BWN_ALIGN, 0,		/* alignment, bounds */
10424			       lowaddr,			/* lowaddr */
10425			       BUS_SPACE_MAXADDR,	/* highaddr */
10426			       NULL, NULL,		/* filter, filterarg */
10427			       MAXBSIZE,		/* maxsize */
10428			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10429			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10430			       0,			/* flags */
10431			       NULL, NULL,		/* lockfunc, lockarg */
10432			       &dma->parent_dtag);
10433	if (error) {
10434		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10435		return (error);
10436	}
10437
10438	/*
10439	 * Create TX/RX mbuf DMA tag
10440	 */
10441	error = bus_dma_tag_create(dma->parent_dtag,
10442				1,
10443				0,
10444				BUS_SPACE_MAXADDR,
10445				BUS_SPACE_MAXADDR,
10446				NULL, NULL,
10447				MCLBYTES,
10448				1,
10449				BUS_SPACE_MAXSIZE_32BIT,
10450				0,
10451				NULL, NULL,
10452				&dma->rxbuf_dtag);
10453	if (error) {
10454		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10455		goto fail0;
10456	}
10457	error = bus_dma_tag_create(dma->parent_dtag,
10458				1,
10459				0,
10460				BUS_SPACE_MAXADDR,
10461				BUS_SPACE_MAXADDR,
10462				NULL, NULL,
10463				MCLBYTES,
10464				1,
10465				BUS_SPACE_MAXSIZE_32BIT,
10466				0,
10467				NULL, NULL,
10468				&dma->txbuf_dtag);
10469	if (error) {
10470		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10471		goto fail1;
10472	}
10473
10474	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10475	if (!dma->wme[WME_AC_BK])
10476		goto fail2;
10477
10478	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10479	if (!dma->wme[WME_AC_BE])
10480		goto fail3;
10481
10482	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10483	if (!dma->wme[WME_AC_VI])
10484		goto fail4;
10485
10486	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10487	if (!dma->wme[WME_AC_VO])
10488		goto fail5;
10489
10490	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10491	if (!dma->mcast)
10492		goto fail6;
10493	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10494	if (!dma->rx)
10495		goto fail7;
10496
10497	return (error);
10498
10499fail7:	bwn_dma_ringfree(&dma->mcast);
10500fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10501fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10502fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10503fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10504fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10505fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10506fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10507	return (error);
10508}
10509
10510static struct bwn_dma_ring *
10511bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10512    uint16_t cookie, int *slot)
10513{
10514	struct bwn_dma *dma = &mac->mac_method.dma;
10515	struct bwn_dma_ring *dr;
10516	struct bwn_softc *sc = mac->mac_sc;
10517
10518	BWN_ASSERT_LOCKED(mac->mac_sc);
10519
10520	switch (cookie & 0xf000) {
10521	case 0x1000:
10522		dr = dma->wme[WME_AC_BK];
10523		break;
10524	case 0x2000:
10525		dr = dma->wme[WME_AC_BE];
10526		break;
10527	case 0x3000:
10528		dr = dma->wme[WME_AC_VI];
10529		break;
10530	case 0x4000:
10531		dr = dma->wme[WME_AC_VO];
10532		break;
10533	case 0x5000:
10534		dr = dma->mcast;
10535		break;
10536	default:
10537		dr = NULL;
10538		KASSERT(0 == 1,
10539		    ("invalid cookie value %d", cookie & 0xf000));
10540	}
10541	*slot = (cookie & 0x0fff);
10542	if (*slot < 0 || *slot >= dr->dr_numslots) {
10543		/*
10544		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10545		 * that it occurs events which have same H/W sequence numbers.
10546		 * When it's occurred just prints a WARNING msgs and ignores.
10547		 */
10548		KASSERT(status->seq == dma->lastseq,
10549		    ("%s:%d: fail", __func__, __LINE__));
10550		device_printf(sc->sc_dev,
10551		    "out of slot ranges (0 < %d < %d)\n", *slot,
10552		    dr->dr_numslots);
10553		return (NULL);
10554	}
10555	dma->lastseq = status->seq;
10556	return (dr);
10557}
10558
10559static void
10560bwn_dma_stop(struct bwn_mac *mac)
10561{
10562	struct bwn_dma *dma;
10563
10564	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10565		return;
10566	dma = &mac->mac_method.dma;
10567
10568	bwn_dma_ringstop(&dma->rx);
10569	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10570	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10571	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10572	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10573	bwn_dma_ringstop(&dma->mcast);
10574}
10575
10576static void
10577bwn_dma_ringstop(struct bwn_dma_ring **dr)
10578{
10579
10580	if (dr == NULL)
10581		return;
10582
10583	bwn_dma_cleanup(*dr);
10584}
10585
10586static void
10587bwn_pio_stop(struct bwn_mac *mac)
10588{
10589	struct bwn_pio *pio;
10590
10591	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10592		return;
10593	pio = &mac->mac_method.pio;
10594
10595	bwn_destroy_queue_tx(&pio->mcast);
10596	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10597	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10598	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10599	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10600}
10601
10602static void
10603bwn_led_attach(struct bwn_mac *mac)
10604{
10605	struct bwn_softc *sc = mac->mac_sc;
10606	const uint8_t *led_act = NULL;
10607	uint16_t val[BWN_LED_MAX];
10608	int i;
10609
10610	sc->sc_led_idle = (2350 * hz) / 1000;
10611	sc->sc_led_blink = 1;
10612
10613	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10614		if (siba_get_pci_subvendor(sc->sc_dev) ==
10615		    bwn_vendor_led_act[i].vid) {
10616			led_act = bwn_vendor_led_act[i].led_act;
10617			break;
10618		}
10619	}
10620	if (led_act == NULL)
10621		led_act = bwn_default_led_act;
10622
10623	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10624	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10625	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10626	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10627
10628	for (i = 0; i < BWN_LED_MAX; ++i) {
10629		struct bwn_led *led = &sc->sc_leds[i];
10630
10631		if (val[i] == 0xff) {
10632			led->led_act = led_act[i];
10633		} else {
10634			if (val[i] & BWN_LED_ACT_LOW)
10635				led->led_flags |= BWN_LED_F_ACTLOW;
10636			led->led_act = val[i] & BWN_LED_ACT_MASK;
10637		}
10638		led->led_mask = (1 << i);
10639
10640		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10641		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10642		    led->led_act == BWN_LED_ACT_BLINK) {
10643			led->led_flags |= BWN_LED_F_BLINK;
10644			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10645				led->led_flags |= BWN_LED_F_POLLABLE;
10646			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10647				led->led_flags |= BWN_LED_F_SLOW;
10648
10649			if (sc->sc_blink_led == NULL) {
10650				sc->sc_blink_led = led;
10651				if (led->led_flags & BWN_LED_F_SLOW)
10652					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10653			}
10654		}
10655
10656		DPRINTF(sc, BWN_DEBUG_LED,
10657		    "%dth led, act %d, lowact %d\n", i,
10658		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10659	}
10660	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10661}
10662
10663static __inline uint16_t
10664bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10665{
10666
10667	if (led->led_flags & BWN_LED_F_ACTLOW)
10668		on = !on;
10669	if (on)
10670		val |= led->led_mask;
10671	else
10672		val &= ~led->led_mask;
10673	return val;
10674}
10675
10676static void
10677bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10678{
10679	struct bwn_softc *sc = mac->mac_sc;
10680	struct ifnet *ifp = sc->sc_ifp;
10681	struct ieee80211com *ic = ifp->if_l2com;
10682	uint16_t val;
10683	int i;
10684
10685	if (nstate == IEEE80211_S_INIT) {
10686		callout_stop(&sc->sc_led_blink_ch);
10687		sc->sc_led_blinking = 0;
10688	}
10689
10690	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10691		return;
10692
10693	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10694	for (i = 0; i < BWN_LED_MAX; ++i) {
10695		struct bwn_led *led = &sc->sc_leds[i];
10696		int on;
10697
10698		if (led->led_act == BWN_LED_ACT_UNKN ||
10699		    led->led_act == BWN_LED_ACT_NULL)
10700			continue;
10701
10702		if ((led->led_flags & BWN_LED_F_BLINK) &&
10703		    nstate != IEEE80211_S_INIT)
10704			continue;
10705
10706		switch (led->led_act) {
10707		case BWN_LED_ACT_ON:    /* Always on */
10708			on = 1;
10709			break;
10710		case BWN_LED_ACT_OFF:   /* Always off */
10711		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10712			on = 0;
10713			break;
10714		default:
10715			on = 1;
10716			switch (nstate) {
10717			case IEEE80211_S_INIT:
10718				on = 0;
10719				break;
10720			case IEEE80211_S_RUN:
10721				if (led->led_act == BWN_LED_ACT_11G &&
10722				    ic->ic_curmode != IEEE80211_MODE_11G)
10723					on = 0;
10724				break;
10725			default:
10726				if (led->led_act == BWN_LED_ACT_ASSOC)
10727					on = 0;
10728				break;
10729			}
10730			break;
10731		}
10732
10733		val = bwn_led_onoff(led, val, on);
10734	}
10735	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10736}
10737
10738static void
10739bwn_led_event(struct bwn_mac *mac, int event)
10740{
10741	struct bwn_softc *sc = mac->mac_sc;
10742	struct bwn_led *led = sc->sc_blink_led;
10743	int rate;
10744
10745	if (event == BWN_LED_EVENT_POLL) {
10746		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10747			return;
10748		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10749			return;
10750	}
10751
10752	sc->sc_led_ticks = ticks;
10753	if (sc->sc_led_blinking)
10754		return;
10755
10756	switch (event) {
10757	case BWN_LED_EVENT_RX:
10758		rate = sc->sc_rx_rate;
10759		break;
10760	case BWN_LED_EVENT_TX:
10761		rate = sc->sc_tx_rate;
10762		break;
10763	case BWN_LED_EVENT_POLL:
10764		rate = 0;
10765		break;
10766	default:
10767		panic("unknown LED event %d\n", event);
10768		break;
10769	}
10770	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10771	    bwn_led_duration[rate].off_dur);
10772}
10773
10774static void
10775bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10776{
10777	struct bwn_softc *sc = mac->mac_sc;
10778	struct bwn_led *led = sc->sc_blink_led;
10779	uint16_t val;
10780
10781	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10782	val = bwn_led_onoff(led, val, 1);
10783	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10784
10785	if (led->led_flags & BWN_LED_F_SLOW) {
10786		BWN_LED_SLOWDOWN(on_dur);
10787		BWN_LED_SLOWDOWN(off_dur);
10788	}
10789
10790	sc->sc_led_blinking = 1;
10791	sc->sc_led_blink_offdur = off_dur;
10792
10793	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10794}
10795
10796static void
10797bwn_led_blink_next(void *arg)
10798{
10799	struct bwn_mac *mac = arg;
10800	struct bwn_softc *sc = mac->mac_sc;
10801	uint16_t val;
10802
10803	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10804	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10805	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10806
10807	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10808	    bwn_led_blink_end, mac);
10809}
10810
10811static void
10812bwn_led_blink_end(void *arg)
10813{
10814	struct bwn_mac *mac = arg;
10815	struct bwn_softc *sc = mac->mac_sc;
10816
10817	sc->sc_led_blinking = 0;
10818}
10819
10820static int
10821bwn_suspend(device_t dev)
10822{
10823	struct bwn_softc *sc = device_get_softc(dev);
10824
10825	bwn_stop(sc, 1);
10826	return (0);
10827}
10828
10829static int
10830bwn_resume(device_t dev)
10831{
10832	struct bwn_softc *sc = device_get_softc(dev);
10833	struct ifnet *ifp = sc->sc_ifp;
10834
10835	if (ifp->if_flags & IFF_UP)
10836		bwn_init(sc);
10837	return (0);
10838}
10839
10840static void
10841bwn_rfswitch(void *arg)
10842{
10843	struct bwn_softc *sc = arg;
10844	struct bwn_mac *mac = sc->sc_curmac;
10845	int cur = 0, prev = 0;
10846
10847	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10848	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10849
10850	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10851		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10852			& BWN_RF_HWENABLED_HI_MASK))
10853			cur = 1;
10854	} else {
10855		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10856		    & BWN_RF_HWENABLED_LO_MASK)
10857			cur = 1;
10858	}
10859
10860	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10861		prev = 1;
10862
10863	if (cur != prev) {
10864		if (cur)
10865			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10866		else
10867			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10868
10869		device_printf(sc->sc_dev,
10870		    "status of RF switch is changed to %s\n",
10871		    cur ? "ON" : "OFF");
10872		if (cur != mac->mac_phy.rf_on) {
10873			if (cur)
10874				bwn_rf_turnon(mac);
10875			else
10876				bwn_rf_turnoff(mac);
10877		}
10878	}
10879
10880	callout_schedule(&sc->sc_rfswitch_ch, hz);
10881}
10882
10883static void
10884bwn_phy_lp_init_pre(struct bwn_mac *mac)
10885{
10886	struct bwn_phy *phy = &mac->mac_phy;
10887	struct bwn_phy_lp *plp = &phy->phy_lp;
10888
10889	plp->plp_antenna = BWN_ANT_DEFAULT;
10890}
10891
10892static int
10893bwn_phy_lp_init(struct bwn_mac *mac)
10894{
10895	static const struct bwn_stxtable tables[] = {
10896		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10897		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10898		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10899		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10900		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10901		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10902		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10903		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10904		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10905		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10906		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10907		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10908		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10909		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10910		{ 2, 11, 0x40, 0, 0x0f }
10911	};
10912	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10913	struct bwn_softc *sc = mac->mac_sc;
10914	const struct bwn_stxtable *st;
10915	struct ifnet *ifp = sc->sc_ifp;
10916	struct ieee80211com *ic = ifp->if_l2com;
10917	int i, error;
10918	uint16_t tmp;
10919
10920	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10921	bwn_phy_lp_bbinit(mac);
10922
10923	/* initialize RF */
10924	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10925	DELAY(1);
10926	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10927	DELAY(1);
10928
10929	if (mac->mac_phy.rf_ver == 0x2062)
10930		bwn_phy_lp_b2062_init(mac);
10931	else {
10932		bwn_phy_lp_b2063_init(mac);
10933
10934		/* synchronize stx table. */
10935		for (i = 0; i < N(tables); i++) {
10936			st = &tables[i];
10937			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10938			tmp >>= st->st_rfshift;
10939			tmp <<= st->st_physhift;
10940			BWN_PHY_SETMASK(mac,
10941			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10942			    ~(st->st_mask << st->st_physhift), tmp);
10943		}
10944
10945		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10946		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10947	}
10948
10949	/* calibrate RC */
10950	if (mac->mac_phy.rev >= 2)
10951		bwn_phy_lp_rxcal_r2(mac);
10952	else if (!plp->plp_rccap) {
10953		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10954			bwn_phy_lp_rccal_r12(mac);
10955	} else
10956		bwn_phy_lp_set_rccap(mac);
10957
10958	error = bwn_phy_lp_switch_channel(mac, 7);
10959	if (error)
10960		device_printf(sc->sc_dev,
10961		    "failed to change channel 7 (%d)\n", error);
10962	bwn_phy_lp_txpctl_init(mac);
10963	bwn_phy_lp_calib(mac);
10964	return (0);
10965}
10966
10967static uint16_t
10968bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10969{
10970
10971	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10972	return (BWN_READ_2(mac, BWN_PHYDATA));
10973}
10974
10975static void
10976bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10977{
10978
10979	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10980	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10981}
10982
10983static void
10984bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10985    uint16_t set)
10986{
10987
10988	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10989	BWN_WRITE_2(mac, BWN_PHYDATA,
10990	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10991}
10992
10993static uint16_t
10994bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10995{
10996
10997	KASSERT(reg != 1, ("unaccessible register %d", reg));
10998	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10999		reg |= 0x100;
11000	if (mac->mac_phy.rev >= 2)
11001		reg |= 0x200;
11002	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11003	return BWN_READ_2(mac, BWN_RFDATALO);
11004}
11005
11006static void
11007bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11008{
11009
11010	KASSERT(reg != 1, ("unaccessible register %d", reg));
11011	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11012	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11013}
11014
11015static void
11016bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11017{
11018
11019	if (on) {
11020		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11021		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11022		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11023		return;
11024	}
11025
11026	if (mac->mac_phy.rev >= 2) {
11027		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11028		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11029		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11030		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11031		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11032		return;
11033	}
11034
11035	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11036	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11037	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11038	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11039}
11040
11041static int
11042bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11043{
11044	struct bwn_phy *phy = &mac->mac_phy;
11045	struct bwn_phy_lp *plp = &phy->phy_lp;
11046	int error;
11047
11048	if (phy->rf_ver == 0x2063) {
11049		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11050		if (error)
11051			return (error);
11052	} else {
11053		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11054		if (error)
11055			return (error);
11056		bwn_phy_lp_set_anafilter(mac, chan);
11057		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11058	}
11059
11060	plp->plp_chan = chan;
11061	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11062	return (0);
11063}
11064
11065static uint32_t
11066bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11067{
11068	struct bwn_softc *sc = mac->mac_sc;
11069	struct ifnet *ifp = sc->sc_ifp;
11070	struct ieee80211com *ic = ifp->if_l2com;
11071
11072	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11073}
11074
11075static void
11076bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11077{
11078	struct bwn_phy *phy = &mac->mac_phy;
11079	struct bwn_phy_lp *plp = &phy->phy_lp;
11080
11081	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11082		return;
11083
11084	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11085	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11086	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11087	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11088	plp->plp_antenna = antenna;
11089}
11090
11091static void
11092bwn_phy_lp_task_60s(struct bwn_mac *mac)
11093{
11094
11095	bwn_phy_lp_calib(mac);
11096}
11097
11098static void
11099bwn_phy_lp_readsprom(struct bwn_mac *mac)
11100{
11101	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11102	struct bwn_softc *sc = mac->mac_sc;
11103	struct ifnet *ifp = sc->sc_ifp;
11104	struct ieee80211com *ic = ifp->if_l2com;
11105
11106	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11107		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11108		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11109		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11110		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11111		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11112		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11113		return;
11114	}
11115
11116	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11117	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11118	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11119	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11120	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11121	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11122	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11123	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11124}
11125
11126static void
11127bwn_phy_lp_bbinit(struct bwn_mac *mac)
11128{
11129
11130	bwn_phy_lp_tblinit(mac);
11131	if (mac->mac_phy.rev >= 2)
11132		bwn_phy_lp_bbinit_r2(mac);
11133	else
11134		bwn_phy_lp_bbinit_r01(mac);
11135}
11136
11137static void
11138bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11139{
11140	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11141	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11142	struct bwn_softc *sc = mac->mac_sc;
11143	struct ifnet *ifp = sc->sc_ifp;
11144	struct ieee80211com *ic = ifp->if_l2com;
11145
11146	bwn_phy_lp_set_txgain(mac,
11147	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11148	bwn_phy_lp_set_bbmult(mac, 150);
11149}
11150
11151static void
11152bwn_phy_lp_calib(struct bwn_mac *mac)
11153{
11154	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11155	struct bwn_softc *sc = mac->mac_sc;
11156	struct ifnet *ifp = sc->sc_ifp;
11157	struct ieee80211com *ic = ifp->if_l2com;
11158	const struct bwn_rxcompco *rc = NULL;
11159	struct bwn_txgain ogain;
11160	int i, omode, oafeovr, orf, obbmult;
11161	uint8_t mode, fc = 0;
11162
11163	if (plp->plp_chanfullcal != plp->plp_chan) {
11164		plp->plp_chanfullcal = plp->plp_chan;
11165		fc = 1;
11166	}
11167
11168	bwn_mac_suspend(mac);
11169
11170	/* BlueTooth Coexistance Override */
11171	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11172	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11173
11174	if (mac->mac_phy.rev >= 2)
11175		bwn_phy_lp_digflt_save(mac);
11176	bwn_phy_lp_get_txpctlmode(mac);
11177	mode = plp->plp_txpctlmode;
11178	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11179	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11180		bwn_phy_lp_bugfix(mac);
11181	if (mac->mac_phy.rev >= 2 && fc == 1) {
11182		bwn_phy_lp_get_txpctlmode(mac);
11183		omode = plp->plp_txpctlmode;
11184		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11185		if (oafeovr)
11186			ogain = bwn_phy_lp_get_txgain(mac);
11187		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11188		obbmult = bwn_phy_lp_get_bbmult(mac);
11189		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11190		if (oafeovr)
11191			bwn_phy_lp_set_txgain(mac, &ogain);
11192		bwn_phy_lp_set_bbmult(mac, obbmult);
11193		bwn_phy_lp_set_txpctlmode(mac, omode);
11194		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11195	}
11196	bwn_phy_lp_set_txpctlmode(mac, mode);
11197	if (mac->mac_phy.rev >= 2)
11198		bwn_phy_lp_digflt_restore(mac);
11199
11200	/* do RX IQ Calculation; assumes that noise is true. */
11201	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11202		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11203			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11204				rc = &bwn_rxcompco_5354[i];
11205		}
11206	} else if (mac->mac_phy.rev >= 2)
11207		rc = &bwn_rxcompco_r2;
11208	else {
11209		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11210			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11211				rc = &bwn_rxcompco_r12[i];
11212		}
11213	}
11214	if (rc == NULL)
11215		goto fail;
11216
11217	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11218	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11219
11220	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11221
11222	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11223		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11224		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11225	} else {
11226		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11227		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11228	}
11229
11230	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11231	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11232	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11233	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11234	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11235	bwn_phy_lp_set_deaf(mac, 0);
11236	/* XXX no checking return value? */
11237	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11238	bwn_phy_lp_clear_deaf(mac, 0);
11239	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11240	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11241	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11242
11243	/* disable RX GAIN override. */
11244	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11245	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11246	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11247	if (mac->mac_phy.rev >= 2) {
11248		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11249		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11250			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11251			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11252		}
11253	} else {
11254		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11255	}
11256
11257	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11258	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11259fail:
11260	bwn_mac_enable(mac);
11261}
11262
11263static void
11264bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11265{
11266
11267	if (on) {
11268		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11269		return;
11270	}
11271
11272	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11273	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11274}
11275
11276static int
11277bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11278{
11279	static const struct bwn_b206x_chan *bc = NULL;
11280	struct bwn_softc *sc = mac->mac_sc;
11281	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11282	    tmp[6];
11283	uint16_t old, scale, tmp16;
11284	int i, div;
11285
11286	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11287		if (bwn_b2063_chantable[i].bc_chan == chan) {
11288			bc = &bwn_b2063_chantable[i];
11289			break;
11290		}
11291	}
11292	if (bc == NULL)
11293		return (EINVAL);
11294
11295	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11296	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11297	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11298	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11299	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11300	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11301	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11302	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11303	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11304	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11305	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11306	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11307
11308	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11309	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11310
11311	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11312	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11313	freqref = freqxtal * 3;
11314	div = (freqxtal <= 26000000 ? 1 : 2);
11315	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11316	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11317		999999) / 1000000) + 1;
11318
11319	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11320	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11321	    0xfff8, timeout >> 2);
11322	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11323	    0xff9f,timeout << 5);
11324	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11325
11326	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11327	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11328	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11329
11330	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11331	    (timeoutref + 1)) - 1;
11332	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11333	    0xf0, count >> 8);
11334	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11335
11336	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11337	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11338	while (tmp[1] >= freqref) {
11339		tmp[0]++;
11340		tmp[1] -= freqref;
11341	}
11342	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11343	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11344	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11345	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11346	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11347
11348	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11349	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11350	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11351	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11352
11353	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11354	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11355
11356	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11357		scale = 1;
11358		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11359	} else {
11360		scale = 0;
11361		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11362	}
11363	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11364	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11365
11366	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11367	    (scale + 1);
11368	if (tmp[5] > 150)
11369		tmp[5] = 0;
11370
11371	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11372	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11373
11374	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11375	if (freqxtal > 26000000)
11376		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11377	else
11378		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11379
11380	if (val[0] == 45)
11381		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11382	else
11383		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11384
11385	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11386	DELAY(1);
11387	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11388
11389	/* VCO Calibration */
11390	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11391	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11392	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11393	DELAY(1);
11394	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11395	DELAY(1);
11396	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11397	DELAY(1);
11398	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11399	DELAY(300);
11400	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11401
11402	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11403	return (0);
11404}
11405
11406static int
11407bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11408{
11409	struct bwn_softc *sc = mac->mac_sc;
11410	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11411	const struct bwn_b206x_chan *bc = NULL;
11412	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11413	uint32_t tmp[9];
11414	int i;
11415
11416	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11417		if (bwn_b2062_chantable[i].bc_chan == chan) {
11418			bc = &bwn_b2062_chantable[i];
11419			break;
11420		}
11421	}
11422
11423	if (bc == NULL)
11424		return (EINVAL);
11425
11426	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11427	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11428	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11429	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11430	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11431	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11432	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11433	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11434	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11435	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11436
11437	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11438	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11439	bwn_phy_lp_b2062_reset_pllbias(mac);
11440	tmp[0] = freqxtal / 1000;
11441	tmp[1] = plp->plp_div * 1000;
11442	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11443	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11444		tmp[2] *= 2;
11445	tmp[3] = 48 * tmp[0];
11446	tmp[5] = tmp[2] / tmp[3];
11447	tmp[6] = tmp[2] % tmp[3];
11448	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11449	tmp[4] = tmp[6] * 0x100;
11450	tmp[5] = tmp[4] / tmp[3];
11451	tmp[6] = tmp[4] % tmp[3];
11452	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11453	tmp[4] = tmp[6] * 0x100;
11454	tmp[5] = tmp[4] / tmp[3];
11455	tmp[6] = tmp[4] % tmp[3];
11456	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11457	tmp[4] = tmp[6] * 0x100;
11458	tmp[5] = tmp[4] / tmp[3];
11459	tmp[6] = tmp[4] % tmp[3];
11460	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11461	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11462	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11463	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11464	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11465	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11466
11467	bwn_phy_lp_b2062_vco_calib(mac);
11468	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11469		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11470		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11471		bwn_phy_lp_b2062_reset_pllbias(mac);
11472		bwn_phy_lp_b2062_vco_calib(mac);
11473		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11474			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11475			return (EIO);
11476		}
11477	}
11478	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11479	return (0);
11480}
11481
11482static void
11483bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11484{
11485	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11486	uint16_t tmp = (channel == 14);
11487
11488	if (mac->mac_phy.rev < 2) {
11489		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11490		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11491			bwn_phy_lp_set_rccap(mac);
11492		return;
11493	}
11494
11495	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11496}
11497
11498static void
11499bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11500{
11501	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11502	struct bwn_softc *sc = mac->mac_sc;
11503	struct ifnet *ifp = sc->sc_ifp;
11504	struct ieee80211com *ic = ifp->if_l2com;
11505	uint16_t iso, tmp[3];
11506
11507	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11508
11509	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11510		iso = plp->plp_txisoband_m;
11511	else if (freq <= 5320)
11512		iso = plp->plp_txisoband_l;
11513	else if (freq <= 5700)
11514		iso = plp->plp_txisoband_m;
11515	else
11516		iso = plp->plp_txisoband_h;
11517
11518	tmp[0] = ((iso - 26) / 12) << 12;
11519	tmp[1] = tmp[0] + 0x1000;
11520	tmp[2] = tmp[0] + 0x2000;
11521
11522	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11523	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11524}
11525
11526static void
11527bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11528{
11529	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11530	int i;
11531	static const uint16_t addr[] = {
11532		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11533		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11534		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11535		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11536		BWN_PHY_OFDM(0xcf),
11537	};
11538	static const uint16_t val[] = {
11539		0xde5e, 0xe832, 0xe331, 0x4d26,
11540		0x0026, 0x1420, 0x0020, 0xfe08,
11541		0x0008,
11542	};
11543
11544	for (i = 0; i < N(addr); i++) {
11545		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11546		BWN_PHY_WRITE(mac, addr[i], val[i]);
11547	}
11548}
11549
11550static void
11551bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11552{
11553	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11554	struct bwn_softc *sc = mac->mac_sc;
11555	uint16_t ctl;
11556
11557	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11558	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11559	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11560		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11561		break;
11562	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11563		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11564		break;
11565	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11566		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11567		break;
11568	default:
11569		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11570		device_printf(sc->sc_dev, "unknown command mode\n");
11571		break;
11572	}
11573}
11574
11575static void
11576bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11577{
11578	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11579	uint16_t ctl;
11580	uint8_t old;
11581
11582	bwn_phy_lp_get_txpctlmode(mac);
11583	old = plp->plp_txpctlmode;
11584	if (old == mode)
11585		return;
11586	plp->plp_txpctlmode = mode;
11587
11588	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11589		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11590		    plp->plp_tssiidx);
11591		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11592		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11593
11594		/* disable TX GAIN override */
11595		if (mac->mac_phy.rev < 2)
11596			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11597		else {
11598			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11599			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11600		}
11601		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11602
11603		plp->plp_txpwridx = -1;
11604	}
11605	if (mac->mac_phy.rev >= 2) {
11606		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11607			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11608		else
11609			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11610	}
11611
11612	/* writes TX Power Control mode */
11613	switch (plp->plp_txpctlmode) {
11614	case BWN_PHYLP_TXPCTL_OFF:
11615		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11616		break;
11617	case BWN_PHYLP_TXPCTL_ON_HW:
11618		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11619		break;
11620	case BWN_PHYLP_TXPCTL_ON_SW:
11621		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11622		break;
11623	default:
11624		ctl = 0;
11625		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11626	}
11627	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11628	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11629}
11630
11631static void
11632bwn_phy_lp_bugfix(struct bwn_mac *mac)
11633{
11634	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11635	struct bwn_softc *sc = mac->mac_sc;
11636	const unsigned int size = 256;
11637	struct bwn_txgain tg;
11638	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11639	uint16_t tssinpt, tssiidx, value[2];
11640	uint8_t mode;
11641	int8_t txpwridx;
11642
11643	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11644	    M_NOWAIT | M_ZERO);
11645	if (tabs == NULL) {
11646		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11647		return;
11648	}
11649
11650	bwn_phy_lp_get_txpctlmode(mac);
11651	mode = plp->plp_txpctlmode;
11652	txpwridx = plp->plp_txpwridx;
11653	tssinpt = plp->plp_tssinpt;
11654	tssiidx = plp->plp_tssiidx;
11655
11656	bwn_tab_read_multi(mac,
11657	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11658	    BWN_TAB_4(7, 0x140), size, tabs);
11659
11660	bwn_phy_lp_tblinit(mac);
11661	bwn_phy_lp_bbinit(mac);
11662	bwn_phy_lp_txpctl_init(mac);
11663	bwn_phy_lp_rf_onoff(mac, 1);
11664	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11665
11666	bwn_tab_write_multi(mac,
11667	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11668	    BWN_TAB_4(7, 0x140), size, tabs);
11669
11670	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11671	plp->plp_tssinpt = tssinpt;
11672	plp->plp_tssiidx = tssiidx;
11673	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11674	if (txpwridx != -1) {
11675		/* set TX power by index */
11676		plp->plp_txpwridx = txpwridx;
11677		bwn_phy_lp_get_txpctlmode(mac);
11678		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11679			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11680		if (mac->mac_phy.rev >= 2) {
11681			rxcomp = bwn_tab_read(mac,
11682			    BWN_TAB_4(7, txpwridx + 320));
11683			txgain = bwn_tab_read(mac,
11684			    BWN_TAB_4(7, txpwridx + 192));
11685			tg.tg_pad = (txgain >> 16) & 0xff;
11686			tg.tg_gm = txgain & 0xff;
11687			tg.tg_pga = (txgain >> 8) & 0xff;
11688			tg.tg_dac = (rxcomp >> 28) & 0xff;
11689			bwn_phy_lp_set_txgain(mac, &tg);
11690		} else {
11691			rxcomp = bwn_tab_read(mac,
11692			    BWN_TAB_4(10, txpwridx + 320));
11693			txgain = bwn_tab_read(mac,
11694			    BWN_TAB_4(10, txpwridx + 192));
11695			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11696			    0xf800, (txgain >> 4) & 0x7fff);
11697			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11698			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11699		}
11700		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11701
11702		/* set TX IQCC */
11703		value[0] = (rxcomp >> 10) & 0x3ff;
11704		value[1] = rxcomp & 0x3ff;
11705		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11706
11707		coeff = bwn_tab_read(mac,
11708		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11709		    BWN_TAB_4(10, txpwridx + 448));
11710		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11711		if (mac->mac_phy.rev >= 2) {
11712			rfpwr = bwn_tab_read(mac,
11713			    BWN_TAB_4(7, txpwridx + 576));
11714			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11715			    rfpwr & 0xffff);
11716		}
11717		bwn_phy_lp_set_txgain_override(mac);
11718	}
11719	if (plp->plp_rccap)
11720		bwn_phy_lp_set_rccap(mac);
11721	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11722	bwn_phy_lp_set_txpctlmode(mac, mode);
11723	free(tabs, M_DEVBUF);
11724}
11725
11726static void
11727bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11728{
11729	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11730	int i;
11731	static const uint16_t addr[] = {
11732		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11733		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11734		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11735		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11736		BWN_PHY_OFDM(0xcf),
11737	};
11738
11739	for (i = 0; i < N(addr); i++)
11740		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11741}
11742
11743static void
11744bwn_phy_lp_tblinit(struct bwn_mac *mac)
11745{
11746	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11747
11748	if (mac->mac_phy.rev < 2) {
11749		bwn_phy_lp_tblinit_r01(mac);
11750		bwn_phy_lp_tblinit_txgain(mac);
11751		bwn_phy_lp_set_gaintbl(mac, freq);
11752		return;
11753	}
11754
11755	bwn_phy_lp_tblinit_r2(mac);
11756	bwn_phy_lp_tblinit_txgain(mac);
11757}
11758
11759struct bwn_wpair {
11760	uint16_t		reg;
11761	uint16_t		value;
11762};
11763
11764struct bwn_smpair {
11765	uint16_t		offset;
11766	uint16_t		mask;
11767	uint16_t		set;
11768};
11769
11770static void
11771bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11772{
11773	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11774	struct bwn_softc *sc = mac->mac_sc;
11775	struct ifnet *ifp = sc->sc_ifp;
11776	struct ieee80211com *ic = ifp->if_l2com;
11777	static const struct bwn_wpair v1[] = {
11778		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11779		{ BWN_PHY_AFE_CTL, 0x8800 },
11780		{ BWN_PHY_AFE_CTL_OVR, 0 },
11781		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11782		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11783		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11784		{ BWN_PHY_OFDM(0xf9), 0 },
11785		{ BWN_PHY_TR_LOOKUP_1, 0 }
11786	};
11787	static const struct bwn_smpair v2[] = {
11788		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11789		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11790		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11791		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11792		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11793	};
11794	static const struct bwn_smpair v3[] = {
11795		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11796		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11797		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11798		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11799		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11800		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11801		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11802		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11803		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11804		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11805
11806	};
11807	int i;
11808
11809	for (i = 0; i < N(v1); i++)
11810		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11811	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11812	for (i = 0; i < N(v2); i++)
11813		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11814
11815	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11816	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11817	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11818	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11819		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11820		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11821	} else {
11822		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11823	}
11824	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11825	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11826	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11827	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11828	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11829	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11830	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11831	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11832	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11833	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11834	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11835	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11836	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11837		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11838		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11839	} else {
11840		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11841		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11842	}
11843	for (i = 0; i < N(v3); i++)
11844		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11845	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11846	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11847		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11848		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11849	}
11850
11851	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11852		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11853		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11854		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11855		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11856		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11857		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11858	} else
11859		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11860
11861	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11862	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11863	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11864	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11865	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11866	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11867	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11868	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11869	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11870
11871	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11872	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11873		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11874		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11875		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11876	}
11877
11878	bwn_phy_lp_digflt_save(mac);
11879}
11880
11881static void
11882bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11883{
11884	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11885	struct bwn_softc *sc = mac->mac_sc;
11886	struct ifnet *ifp = sc->sc_ifp;
11887	struct ieee80211com *ic = ifp->if_l2com;
11888	static const struct bwn_smpair v1[] = {
11889		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11890		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11891		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11892		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11893		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11894		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11895		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11896	};
11897	static const struct bwn_smpair v2[] = {
11898		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11899		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11900		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11901		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11902		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11903		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11904		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11905		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11906		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11907		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11908		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11909		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11910		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11911		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11912		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11913		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11914	};
11915	static const struct bwn_smpair v3[] = {
11916		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11917		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11918		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11919		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11920		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11921		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11922		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11923		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11924	};
11925	static const struct bwn_smpair v4[] = {
11926		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11927		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11928		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11929		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11930		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11931		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11932		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11933		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11934	};
11935	static const struct bwn_smpair v5[] = {
11936		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11937		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11938		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11939		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11940		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11941		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11942		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11943		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11944	};
11945	int i;
11946	uint16_t tmp, tmp2;
11947
11948	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11949	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11950	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11951	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11952	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11953	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11954	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11955	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11956	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11957	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11958	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11959	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11960	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11961	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11962	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11963	for (i = 0; i < N(v1); i++)
11964		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11965	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11966	    0xff00, plp->plp_rxpwroffset);
11967	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11968	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11969	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11970		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11971		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11972		if (mac->mac_phy.rev == 0)
11973			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11974			    0xffcf, 0x0010);
11975		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11976	} else {
11977		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11978		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11979		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11980	}
11981	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11982	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11983	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11984		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11985	else
11986		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11987	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11988	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11989	    0xfff9, (plp->plp_bxarch << 1));
11990	if (mac->mac_phy.rev == 1 &&
11991	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11992		for (i = 0; i < N(v2); i++)
11993			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11994			    v2[i].set);
11995	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11996	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11997	    ((mac->mac_phy.rev == 0) &&
11998	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11999		for (i = 0; i < N(v3); i++)
12000			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12001			    v3[i].set);
12002	} else if (mac->mac_phy.rev == 1 ||
12003		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
12004		for (i = 0; i < N(v4); i++)
12005			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12006			    v4[i].set);
12007	} else {
12008		for (i = 0; i < N(v5); i++)
12009			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12010			    v5[i].set);
12011	}
12012	if (mac->mac_phy.rev == 1 &&
12013	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
12014		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12015		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12016		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12017		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12018	}
12019	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
12020	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
12021	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
12022		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12023		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12024		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12025		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12026	}
12027	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12028		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12029		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12030		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12031		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12032		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12033		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12034		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12035		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12036	} else {
12037		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12038		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12039	}
12040	if (mac->mac_phy.rev == 1) {
12041		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12042		tmp2 = (tmp & 0x03e0) >> 5;
12043		tmp2 |= tmp2 << 5;
12044		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12045		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12046		tmp2 = (tmp & 0x1f00) >> 8;
12047		tmp2 |= tmp2 << 5;
12048		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12049		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12050		tmp2 = tmp & 0x00ff;
12051		tmp2 |= tmp << 8;
12052		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12053	}
12054}
12055
12056struct bwn_b2062_freq {
12057	uint16_t		freq;
12058	uint8_t			value[6];
12059};
12060
12061static void
12062bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12063{
12064#define	CALC_CTL7(freq, div)						\
12065	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12066#define	CALC_CTL18(freq, div)						\
12067	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12068#define	CALC_CTL19(freq, div)						\
12069	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12070	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12071	struct bwn_softc *sc = mac->mac_sc;
12072	struct ifnet *ifp = sc->sc_ifp;
12073	struct ieee80211com *ic = ifp->if_l2com;
12074	static const struct bwn_b2062_freq freqdata_tab[] = {
12075		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12076		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12077		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12078		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12079		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12080		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12081	};
12082	static const struct bwn_wpair v1[] = {
12083		{ BWN_B2062_N_TXCTL3, 0 },
12084		{ BWN_B2062_N_TXCTL4, 0 },
12085		{ BWN_B2062_N_TXCTL5, 0 },
12086		{ BWN_B2062_N_TXCTL6, 0 },
12087		{ BWN_B2062_N_PDNCTL0, 0x40 },
12088		{ BWN_B2062_N_PDNCTL0, 0 },
12089		{ BWN_B2062_N_CALIB_TS, 0x10 },
12090		{ BWN_B2062_N_CALIB_TS, 0 }
12091	};
12092	const struct bwn_b2062_freq *f = NULL;
12093	uint32_t xtalfreq, ref;
12094	unsigned int i;
12095
12096	bwn_phy_lp_b2062_tblinit(mac);
12097
12098	for (i = 0; i < N(v1); i++)
12099		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12100	if (mac->mac_phy.rev > 0)
12101		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12102		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12103	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12104		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12105	else
12106		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12107
12108	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12109	    ("%s:%d: fail", __func__, __LINE__));
12110	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12111	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12112
12113	if (xtalfreq <= 30000000) {
12114		plp->plp_div = 1;
12115		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12116	} else {
12117		plp->plp_div = 2;
12118		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12119	}
12120
12121	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12122	    CALC_CTL7(xtalfreq, plp->plp_div));
12123	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12124	    CALC_CTL18(xtalfreq, plp->plp_div));
12125	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12126	    CALC_CTL19(xtalfreq, plp->plp_div));
12127
12128	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12129	ref &= 0xffff;
12130	for (i = 0; i < N(freqdata_tab); i++) {
12131		if (ref < freqdata_tab[i].freq) {
12132			f = &freqdata_tab[i];
12133			break;
12134		}
12135	}
12136	if (f == NULL)
12137		f = &freqdata_tab[N(freqdata_tab) - 1];
12138	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12139	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12140	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12141	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12142	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12143	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12144#undef CALC_CTL7
12145#undef CALC_CTL18
12146#undef CALC_CTL19
12147}
12148
12149static void
12150bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12151{
12152
12153	bwn_phy_lp_b2063_tblinit(mac);
12154	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12155	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12156	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12157	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12158	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12159	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12160	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12161	if (mac->mac_phy.rev == 2) {
12162		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12163		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12164		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12165	} else {
12166		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12167		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12168	}
12169}
12170
12171static void
12172bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12173{
12174	struct bwn_softc *sc = mac->mac_sc;
12175	static const struct bwn_wpair v1[] = {
12176		{ BWN_B2063_RX_BB_SP8, 0x0 },
12177		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12178		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12179		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12180		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12181		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12182		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12183		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12184	};
12185	static const struct bwn_wpair v2[] = {
12186		{ BWN_B2063_TX_BB_SP3, 0x0 },
12187		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12188		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12189		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12190		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12191	};
12192	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12193	int i;
12194	uint8_t tmp;
12195
12196	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12197
12198	for (i = 0; i < 2; i++)
12199		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12200	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12201	for (i = 2; i < N(v1); i++)
12202		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12203	for (i = 0; i < 10000; i++) {
12204		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12205			break;
12206		DELAY(1000);
12207	}
12208
12209	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12210		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12211
12212	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12213
12214	for (i = 0; i < N(v2); i++)
12215		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12216	if (freqxtal == 24000000) {
12217		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12218		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12219	} else {
12220		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12221		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12222	}
12223	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12224	for (i = 0; i < 10000; i++) {
12225		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12226			break;
12227		DELAY(1000);
12228	}
12229	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12230		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12231	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12232}
12233
12234static void
12235bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12236{
12237	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12238	struct bwn_softc *sc = mac->mac_sc;
12239	struct bwn_phy_lp_iq_est ie;
12240	struct bwn_txgain tx_gains;
12241	static const uint32_t pwrtbl[21] = {
12242		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12243		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12244		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12245		0x0004c, 0x0002c, 0x0001a,
12246	};
12247	uint32_t npwr, ipwr, sqpwr, tmp;
12248	int loopback, i, j, sum, error;
12249	uint16_t save[7];
12250	uint8_t txo, bbmult, txpctlmode;
12251
12252	error = bwn_phy_lp_switch_channel(mac, 7);
12253	if (error)
12254		device_printf(sc->sc_dev,
12255		    "failed to change channel to 7 (%d)\n", error);
12256	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12257	bbmult = bwn_phy_lp_get_bbmult(mac);
12258	if (txo)
12259		tx_gains = bwn_phy_lp_get_txgain(mac);
12260
12261	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12262	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12263	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12264	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12265	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12266	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12267	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12268
12269	bwn_phy_lp_get_txpctlmode(mac);
12270	txpctlmode = plp->plp_txpctlmode;
12271	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12272
12273	/* disable CRS */
12274	bwn_phy_lp_set_deaf(mac, 1);
12275	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12276	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12277	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12278	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12279	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12280	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12281	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12282	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12283	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12284	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12285	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12286	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12287	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12288	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12289	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12290	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12291	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12292	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12293	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12294	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12295	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12296	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12297	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12298	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12299
12300	loopback = bwn_phy_lp_loopback(mac);
12301	if (loopback == -1)
12302		goto done;
12303	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12304	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12305	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12306	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12307	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12308
12309	tmp = 0;
12310	memset(&ie, 0, sizeof(ie));
12311	for (i = 128; i <= 159; i++) {
12312		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12313		sum = 0;
12314		for (j = 5; j <= 25; j++) {
12315			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12316			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12317				goto done;
12318			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12319			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12320			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12321			    12);
12322			sum += ((ipwr - npwr) * (ipwr - npwr));
12323			if ((i == 128) || (sum < tmp)) {
12324				plp->plp_rccap = i;
12325				tmp = sum;
12326			}
12327		}
12328	}
12329	bwn_phy_lp_ddfs_turnoff(mac);
12330done:
12331	/* restore CRS */
12332	bwn_phy_lp_clear_deaf(mac, 1);
12333	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12334	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12335
12336	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12337	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12338	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12339	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12340	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12341	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12342	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12343
12344	bwn_phy_lp_set_bbmult(mac, bbmult);
12345	if (txo)
12346		bwn_phy_lp_set_txgain(mac, &tx_gains);
12347	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12348	if (plp->plp_rccap)
12349		bwn_phy_lp_set_rccap(mac);
12350}
12351
12352static void
12353bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12354{
12355	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12356	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12357
12358	if (mac->mac_phy.rev == 1)
12359		rc_cap = MIN(rc_cap + 5, 15);
12360
12361	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12362	    MAX(plp->plp_rccap - 4, 0x80));
12363	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12364	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12365	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12366}
12367
12368static uint32_t
12369bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12370{
12371	uint32_t i, q, r;
12372
12373	if (div == 0)
12374		return (0);
12375
12376	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12377		q <<= 1;
12378		if (r << 1 >= div) {
12379			q++;
12380			r = (r << 1) - div;
12381		}
12382	}
12383	if (r << 1 >= div)
12384		q++;
12385	return (q);
12386}
12387
12388static void
12389bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12390{
12391	struct bwn_softc *sc = mac->mac_sc;
12392
12393	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12394	DELAY(20);
12395	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12396		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12397		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12398	} else {
12399		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12400	}
12401	DELAY(5);
12402}
12403
12404static void
12405bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12406{
12407
12408	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12409	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12410	DELAY(200);
12411}
12412
12413static void
12414bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12415{
12416#define	FLAG_A	0x01
12417#define	FLAG_G	0x02
12418	struct bwn_softc *sc = mac->mac_sc;
12419	struct ifnet *ifp = sc->sc_ifp;
12420	struct ieee80211com *ic = ifp->if_l2com;
12421	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12422		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12424		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12427		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12428		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12429		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12430		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12431		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12432		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12433		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12434		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12435		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12436		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12437		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12438		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12439		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12440		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12441		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12442		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12443		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12444		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12445		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12446		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12447		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12448		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12449		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12450		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12451		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12452		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12453		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12454		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12455		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12456		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12457		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12458		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12459		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12460		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12461		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12462		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12463		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12464		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12465		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12466		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12467		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12468		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12469	};
12470	const struct bwn_b206x_rfinit_entry *br;
12471	unsigned int i;
12472
12473	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12474		br = &bwn_b2062_init_tab[i];
12475		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12476			if (br->br_flags & FLAG_G)
12477				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12478		} else {
12479			if (br->br_flags & FLAG_A)
12480				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12481		}
12482	}
12483#undef FLAG_A
12484#undef FLAG_B
12485}
12486
12487static void
12488bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12489{
12490#define	FLAG_A	0x01
12491#define	FLAG_G	0x02
12492	struct bwn_softc *sc = mac->mac_sc;
12493	struct ifnet *ifp = sc->sc_ifp;
12494	struct ieee80211com *ic = ifp->if_l2com;
12495	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12496		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12497		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12498		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12499		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12500		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12501		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12502		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12503		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12504		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12505		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12506		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12507		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12508		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12509		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12510		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12511		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12512		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12513		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12514		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12515		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12516		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12517		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12518		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12519		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12520		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12521		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12522		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12523		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12524		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12525		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12526		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12527		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12528		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12529		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12530		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12531		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12532		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12533		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12534		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12535		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12536		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12537		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12538	};
12539	const struct bwn_b206x_rfinit_entry *br;
12540	unsigned int i;
12541
12542	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12543		br = &bwn_b2063_init_tab[i];
12544		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12545			if (br->br_flags & FLAG_G)
12546				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12547		} else {
12548			if (br->br_flags & FLAG_A)
12549				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12550		}
12551	}
12552#undef FLAG_A
12553#undef FLAG_B
12554}
12555
12556static void
12557bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12558    int count, void *_data)
12559{
12560	unsigned int i;
12561	uint32_t offset, type;
12562	uint8_t *data = _data;
12563
12564	type = BWN_TAB_GETTYPE(typenoffset);
12565	offset = BWN_TAB_GETOFFSET(typenoffset);
12566	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12567
12568	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12569
12570	for (i = 0; i < count; i++) {
12571		switch (type) {
12572		case BWN_TAB_8BIT:
12573			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12574			data++;
12575			break;
12576		case BWN_TAB_16BIT:
12577			*((uint16_t *)data) = BWN_PHY_READ(mac,
12578			    BWN_PHY_TABLEDATALO);
12579			data += 2;
12580			break;
12581		case BWN_TAB_32BIT:
12582			*((uint32_t *)data) = BWN_PHY_READ(mac,
12583			    BWN_PHY_TABLEDATAHI);
12584			*((uint32_t *)data) <<= 16;
12585			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12586			    BWN_PHY_TABLEDATALO);
12587			data += 4;
12588			break;
12589		default:
12590			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12591		}
12592	}
12593}
12594
12595static void
12596bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12597    int count, const void *_data)
12598{
12599	uint32_t offset, type, value;
12600	const uint8_t *data = _data;
12601	unsigned int i;
12602
12603	type = BWN_TAB_GETTYPE(typenoffset);
12604	offset = BWN_TAB_GETOFFSET(typenoffset);
12605	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12606
12607	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12608
12609	for (i = 0; i < count; i++) {
12610		switch (type) {
12611		case BWN_TAB_8BIT:
12612			value = *data;
12613			data++;
12614			KASSERT(!(value & ~0xff),
12615			    ("%s:%d: fail", __func__, __LINE__));
12616			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12617			break;
12618		case BWN_TAB_16BIT:
12619			value = *((const uint16_t *)data);
12620			data += 2;
12621			KASSERT(!(value & ~0xffff),
12622			    ("%s:%d: fail", __func__, __LINE__));
12623			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12624			break;
12625		case BWN_TAB_32BIT:
12626			value = *((const uint32_t *)data);
12627			data += 4;
12628			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12629			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12630			break;
12631		default:
12632			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12633		}
12634	}
12635}
12636
12637static struct bwn_txgain
12638bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12639{
12640	struct bwn_txgain tg;
12641	uint16_t tmp;
12642
12643	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12644	if (mac->mac_phy.rev < 2) {
12645		tmp = BWN_PHY_READ(mac,
12646		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12647		tg.tg_gm = tmp & 0x0007;
12648		tg.tg_pga = (tmp & 0x0078) >> 3;
12649		tg.tg_pad = (tmp & 0x780) >> 7;
12650		return (tg);
12651	}
12652
12653	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12654	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12655	tg.tg_gm = tmp & 0xff;
12656	tg.tg_pga = (tmp >> 8) & 0xff;
12657	return (tg);
12658}
12659
12660static uint8_t
12661bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12662{
12663
12664	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12665}
12666
12667static void
12668bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12669{
12670	uint16_t pa;
12671
12672	if (mac->mac_phy.rev < 2) {
12673		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12674		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12675		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12676		bwn_phy_lp_set_txgain_override(mac);
12677		return;
12678	}
12679
12680	pa = bwn_phy_lp_get_pa_gain(mac);
12681	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12682	    (tg->tg_pga << 8) | tg->tg_gm);
12683	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12684	    tg->tg_pad | (pa << 6));
12685	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12686	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12687	    tg->tg_pad | (pa << 8));
12688	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12689	bwn_phy_lp_set_txgain_override(mac);
12690}
12691
12692static void
12693bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12694{
12695
12696	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12697}
12698
12699static void
12700bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12701{
12702	uint16_t trsw = (tx << 1) | rx;
12703
12704	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12705	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12706}
12707
12708static void
12709bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12710{
12711	struct bwn_softc *sc = mac->mac_sc;
12712	struct ifnet *ifp = sc->sc_ifp;
12713	struct ieee80211com *ic = ifp->if_l2com;
12714	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12715
12716	if (mac->mac_phy.rev < 2) {
12717		trsw = gain & 0x1;
12718		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12719		ext_lna = (gain & 2) >> 1;
12720
12721		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12722		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12723		    0xfbff, ext_lna << 10);
12724		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12725		    0xf7ff, ext_lna << 11);
12726		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12727	} else {
12728		low_gain = gain & 0xffff;
12729		high_gain = (gain >> 16) & 0xf;
12730		ext_lna = (gain >> 21) & 0x1;
12731		trsw = ~(gain >> 20) & 0x1;
12732
12733		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12734		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12735		    0xfdff, ext_lna << 9);
12736		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12737		    0xfbff, ext_lna << 10);
12738		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12739		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12740		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12741			tmp = (gain >> 2) & 0x3;
12742			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12743			    0xe7ff, tmp<<11);
12744			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12745			    tmp << 3);
12746		}
12747	}
12748
12749	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12750	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12751	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12752	if (mac->mac_phy.rev >= 2) {
12753		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12754		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12755			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12756			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12757		}
12758		return;
12759	}
12760	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12761}
12762
12763static void
12764bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12765{
12766	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12767
12768	if (user)
12769		plp->plp_crsusr_off = 1;
12770	else
12771		plp->plp_crssys_off = 1;
12772
12773	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12774}
12775
12776static void
12777bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12778{
12779	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12780	struct bwn_softc *sc = mac->mac_sc;
12781	struct ifnet *ifp = sc->sc_ifp;
12782	struct ieee80211com *ic = ifp->if_l2com;
12783
12784	if (user)
12785		plp->plp_crsusr_off = 0;
12786	else
12787		plp->plp_crssys_off = 0;
12788
12789	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12790		return;
12791
12792	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12793		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12794	else
12795		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12796}
12797
12798static unsigned int
12799bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12800{
12801	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12802	static uint8_t sqrt_table[256] = {
12803		10, 14, 17, 20, 22, 24, 26, 28,
12804		30, 31, 33, 34, 36, 37, 38, 40,
12805		41, 42, 43, 44, 45, 46, 47, 48,
12806		50, 50, 51, 52, 53, 54, 55, 56,
12807		57, 58, 59, 60, 60, 61, 62, 63,
12808		64, 64, 65, 66, 67, 67, 68, 69,
12809		70, 70, 71, 72, 72, 73, 74, 74,
12810		75, 76, 76, 77, 78, 78, 79, 80,
12811		80, 81, 81, 82, 83, 83, 84, 84,
12812		85, 86, 86, 87, 87, 88, 88, 89,
12813		90, 90, 91, 91, 92, 92, 93, 93,
12814		94, 94, 95, 95, 96, 96, 97, 97,
12815		98, 98, 99, 100, 100, 100, 101, 101,
12816		102, 102, 103, 103, 104, 104, 105, 105,
12817		106, 106, 107, 107, 108, 108, 109, 109,
12818		110, 110, 110, 111, 111, 112, 112, 113,
12819		113, 114, 114, 114, 115, 115, 116, 116,
12820		117, 117, 117, 118, 118, 119, 119, 120,
12821		120, 120, 121, 121, 122, 122, 122, 123,
12822		123, 124, 124, 124, 125, 125, 126, 126,
12823		126, 127, 127, 128, 128, 128, 129, 129,
12824		130, 130, 130, 131, 131, 131, 132, 132,
12825		133, 133, 133, 134, 134, 134, 135, 135,
12826		136, 136, 136, 137, 137, 137, 138, 138,
12827		138, 139, 139, 140, 140, 140, 141, 141,
12828		141, 142, 142, 142, 143, 143, 143, 144,
12829		144, 144, 145, 145, 145, 146, 146, 146,
12830		147, 147, 147, 148, 148, 148, 149, 149,
12831		150, 150, 150, 150, 151, 151, 151, 152,
12832		152, 152, 153, 153, 153, 154, 154, 154,
12833		155, 155, 155, 156, 156, 156, 157, 157,
12834		157, 158, 158, 158, 159, 159, 159, 160
12835	};
12836
12837	if (x == 0)
12838		return (0);
12839	if (x >= 256) {
12840		unsigned int tmp;
12841
12842		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12843			/* do nothing */ ;
12844		return (tmp);
12845	}
12846	return (sqrt_table[x - 1] / 10);
12847}
12848
12849static int
12850bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12851{
12852#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12853	int _t;								\
12854	_t = _x - 20;							\
12855	if (_t >= 0) {							\
12856		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12857	} else {							\
12858		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12859	}								\
12860} while (0)
12861#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12862	int _t;								\
12863	_t = _x - 11;							\
12864	if (_t >= 0)							\
12865		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12866	else								\
12867		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12868} while (0)
12869	struct bwn_phy_lp_iq_est ie;
12870	uint16_t v0, v1;
12871	int tmp[2], ret;
12872
12873	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12874	v0 = v1 >> 8;
12875	v1 |= 0xff;
12876
12877	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12878	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12879
12880	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12881	if (ret == 0)
12882		goto done;
12883
12884	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12885		ret = 0;
12886		goto done;
12887	}
12888
12889	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12890	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12891
12892	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12893	v0 = tmp[0] >> 3;
12894	v1 = tmp[1] >> 4;
12895done:
12896	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12897	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12898	return ret;
12899#undef CALC_COEFF
12900#undef CALC_COEFF2
12901}
12902
12903static void
12904bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12905{
12906	static const uint16_t noisescale[] = {
12907		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12908		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12909		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12910		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12911		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12912	};
12913	static const uint16_t crsgainnft[] = {
12914		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12915		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12916		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12917		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12918		0x013d,
12919	};
12920	static const uint16_t filterctl[] = {
12921		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12922		0xff53, 0x0127,
12923	};
12924	static const uint32_t psctl[] = {
12925		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12926		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12927		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12928		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12929		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12930		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12931		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12932		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12933	};
12934	static const uint16_t ofdmcckgain_r0[] = {
12935		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12936		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12937		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12938		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12939		0x755d,
12940	};
12941	static const uint16_t ofdmcckgain_r1[] = {
12942		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12943		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12944		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12945		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12946		0x755d,
12947	};
12948	static const uint16_t gaindelta[] = {
12949		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12950		0x0000,
12951	};
12952	static const uint32_t txpwrctl[] = {
12953		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12954		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12955		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12956		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12957		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12958		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12959		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12960		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12961		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12962		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12963		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12964		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12965		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12966		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
12992		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12993		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12994		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12995		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12996		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12997		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12998		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12999		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13000		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13001		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13002		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13003		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13004		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13005		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13006		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13007		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13008		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13009		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13010		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13011		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13012		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13013		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13014		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13015		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13016		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13017		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13018		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13019		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13020		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13021		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13022		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13023		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13024		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13025		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13026		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13027		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13028		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13029		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13030		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13031		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13032		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13033		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13034		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13035		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13036		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13037		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13038		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13039		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13040		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13041		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13042		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13043		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13044		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13045		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13046		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13047		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13048		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13049		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13050		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13051		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13052		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13053		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13054		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13055		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13056		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13057		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13058		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13059		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13060		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13061		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13062		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13063		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13064		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13065		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13066		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13067		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13068		0x00000702,
13069	};
13070
13071	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13072
13073	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13074	    bwn_tab_sigsq_tbl);
13075	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13076	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13077	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13078	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13079	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13080	    bwn_tab_pllfrac_tbl);
13081	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13082	    bwn_tabl_iqlocal_tbl);
13083	if (mac->mac_phy.rev == 0) {
13084		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13085		    ofdmcckgain_r0);
13086		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13087		    ofdmcckgain_r0);
13088	} else {
13089		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13090		    ofdmcckgain_r1);
13091		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13092		    ofdmcckgain_r1);
13093	}
13094	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13095	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13096}
13097
13098static void
13099bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13100{
13101	struct bwn_softc *sc = mac->mac_sc;
13102	int i;
13103	static const uint16_t noisescale[] = {
13104		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13105		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13106		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13107		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13108		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13109		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13110		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13111	};
13112	static const uint32_t filterctl[] = {
13113		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13114		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13115	};
13116	static const uint32_t psctl[] = {
13117		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13118		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13119		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13120		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13121	};
13122	static const uint32_t gainidx[] = {
13123		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13124		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13125		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13126		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13127		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13128		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13129		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13130		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13131		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13132		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13133		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13134		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13135		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13136		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13137		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13138		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13142		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13143		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13144		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13145		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13146		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13147		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13148		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13149		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13150		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13151		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13152		0x0000001a, 0x64ca55ad, 0x0000001a
13153	};
13154	static const uint16_t auxgainidx[] = {
13155		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13157		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13158		0x0004, 0x0016
13159	};
13160	static const uint16_t swctl[] = {
13161		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13162		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13163		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13164		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13165		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13166		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13167		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13168		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13169	};
13170	static const uint8_t hf[] = {
13171		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13172		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13173	};
13174	static const uint32_t gainval[] = {
13175		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13176		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13177		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13178		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13179		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13180		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13181		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13182		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13183		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13184		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13185		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13186		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13187		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13188		0x000000f1, 0x00000000, 0x00000000
13189	};
13190	static const uint16_t gain[] = {
13191		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13192		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13193		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13194		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13195		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13196		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13197		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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	};
13204	static const uint32_t papdeps[] = {
13205		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13206		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13207		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13208		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13209		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13210		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13211		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13212		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13213		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13214		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13215		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13216		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13217		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13218	};
13219	static const uint32_t papdmult[] = {
13220		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13221		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13222		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13223		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13224		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13225		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13226		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13227		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13228		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13229		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13230		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13231		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13232		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13233	};
13234	static const uint32_t gainidx_a0[] = {
13235		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13236		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13237		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13238		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13239		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13240		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13241		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13242		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13243		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13244		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13245		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13246		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13247		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13248	};
13249	static const uint16_t auxgainidx_a0[] = {
13250		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13251		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13252		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13253		0x0002, 0x0014
13254	};
13255	static const uint32_t gainval_a0[] = {
13256		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13257		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13258		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13259		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13260		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13261		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13262		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13263		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13264		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13265		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13266		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13267		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13268		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13269		0x000000f7, 0x00000000, 0x00000000
13270	};
13271	static const uint16_t gain_a0[] = {
13272		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13273		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13274		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13275		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13276		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13277		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13278		0x0000, 0x0000, 0x0000, 0x0000, 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	};
13285
13286	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13287
13288	for (i = 0; i < 704; i++)
13289		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13290
13291	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13292	    bwn_tab_sigsq_tbl);
13293	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13294	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13295	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13296	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13297	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13298	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13299	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13300	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13301	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13302	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13303	    bwn_tab_pllfrac_tbl);
13304	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13305	    bwn_tabl_iqlocal_tbl);
13306	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13307	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13308
13309	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13310	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13311		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13312		    gainidx_a0);
13313		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13314		    auxgainidx_a0);
13315		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13316		    gainval_a0);
13317		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13318	}
13319}
13320
13321static void
13322bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13323{
13324	struct bwn_softc *sc = mac->mac_sc;
13325	struct ifnet *ifp = sc->sc_ifp;
13326	struct ieee80211com *ic = ifp->if_l2com;
13327	static struct bwn_txgain_entry txgain_r2[] = {
13328		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13329		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13330		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13331		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13332		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13333		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13334		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13335		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13336		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13337		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13338		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13339		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13340		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13341		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13342		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13343		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13344		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13345		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13346		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13347		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13348		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13349		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13350		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13351		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13352		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13353		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13354		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13355		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13356		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13357		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13358		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13359		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13360		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13361		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13362		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13363		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13364		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13365		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13366		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13367		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13368		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13369		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13370		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13371		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13372		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13373		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13374		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13375		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13376		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13377		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13378		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13379		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13380		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13381		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13382		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13383		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13384		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13385		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13386		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13387		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13388		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13389		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13390		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13391		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13392	};
13393	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13394		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13395		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13396		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13397		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13398		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13399		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13400		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13401		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13402		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13403		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13404		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13405		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13406		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13407		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13408		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13409		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13410		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13411		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13412		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13413		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13414		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13415		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13416		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13417		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13418		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13419		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13420		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13421		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13422		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13423		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13424		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13425		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13426		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13427		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13428		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13429		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13430		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13431		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13432		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13433		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13434		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13435		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13436		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13437		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13438		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13439		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13440		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13441		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13442		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13443		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13444		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13445		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13446		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13447		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13448		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13449		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13450		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13451		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13452		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13453		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13454		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13455		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13456		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13457		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13458	};
13459	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13460		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13461		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13462		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13463		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13464		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13465		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13466		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13467		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13468		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13469		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13470		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13471		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13472		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13473		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13474		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13475		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13476		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13477		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13478		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13479		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13480		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13481		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13482		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13483		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13484		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13485		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13486		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13487		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13488		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13489		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13490		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13491		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13492		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13493		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13494		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13495		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13496		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13497		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13498		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13499		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13500		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13501		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13502		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13503		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13504		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13505		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13506		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13507		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13508		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13509		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13510		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13511		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13512		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13513		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13514		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13515		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13516		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13517		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13518		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13519		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13520		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13521		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13522		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13523		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13524	};
13525	static struct bwn_txgain_entry txgain_r0[] = {
13526		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13527		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13528		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13529		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13530		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13531		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13532		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13533		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13534		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13535		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13536		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13537		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13538		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13539		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13540		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13541		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13542		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13543		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13544		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13545		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13546		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13547		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13548		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13549		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13550		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13551		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13552		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13553		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13554		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13555		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13556		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13557		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13558		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13559		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13560		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13561		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13562		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13563		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13564		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13565		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13566		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13567		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13568		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13569		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13570		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13571		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13572		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13573		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13574		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13575		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13576		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13577		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13578		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13579		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13580		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13581		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13582		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13583		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13584		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13585		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13586		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13587		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13588		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13589		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13590	};
13591	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13592		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13593		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13594		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13595		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13596		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13597		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13598		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13599		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13600		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13601		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13602		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13603		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13604		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13605		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13606		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13607		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13608		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13609		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13610		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13611		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13612		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13613		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13614		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13615		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13616		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13617		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13618		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13619		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13620		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13621		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13622		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13623		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13624		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13625		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13626		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13627		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13628		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13629		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13630		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13631		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13632		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13633		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13634		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13635		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13636		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13637		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13638		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13639		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13640		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13641		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13642		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13643		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13644		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13645		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13646		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13647		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13648		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13649		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13650		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13651		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13652		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13653		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13654		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13655		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13656	};
13657	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13658		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13659		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13660		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13661		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13662		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13663		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13664		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13665		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13666		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13667		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13668		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13669		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13670		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13671		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13672		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13673		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13674		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13675		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13676		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13677		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13678		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13679		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13680		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13681		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13682		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13683		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13684		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13685		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13686		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13687		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13688		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13689		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13690		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13691		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13692		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13693		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13694		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13695		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13696		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13697		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13698		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13699		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13700		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13701		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13702		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13703		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13704		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13705		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13706		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13707		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13708		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13709		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13710		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13711		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13712		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13713		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13714		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13715		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13716		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13717		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13718		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13719		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13720		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13721		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13722	};
13723	static struct bwn_txgain_entry txgain_r1[] = {
13724		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13725		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13726		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13727		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13728		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13729		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13730		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13731		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13732		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13733		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13734		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13735		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13736		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13737		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13738		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13739		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13740		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13741		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13742		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13743		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13744		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13745		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13746		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13747		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13748		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13749		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13750		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13751		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13752		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13753		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13754		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13755		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13756		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13757		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13758		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13759		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13760		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13761		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13762		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13763		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13764		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13765		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13766		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13767		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13768		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13769		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13770		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13771		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13772		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13773		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13774		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13775		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13776		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13777		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13778		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13779		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13780		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13781		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13782		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13783		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13784		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13785		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13786		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13787		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13788		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13789		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13790		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13791		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13792		{ 7, 11, 6, 0, 71 }
13793	};
13794	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13795		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13796		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13797		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13798		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13799		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13800		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13801		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13802		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13803		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13804		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13805		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13806		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13807		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13808		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13809		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13810		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13811		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13812		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13813		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13814		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13815		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13816		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13817		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13818		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13819		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13820		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13821		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13822		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13823		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13824		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13825		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13826		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13827		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13828		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13829		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13830		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13831		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13832		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13833		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13834		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13835		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13836		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13837		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13838		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13839		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13840		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13841		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13842		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13843		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13844		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13845		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13846		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13847		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13848		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13849		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13850		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13851		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13852		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13853		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13854		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13855		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13856		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13857		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13858		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13859	};
13860	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13861		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13862		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13863		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13864		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13865		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13866		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13867		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13868		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13869		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13870		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13871		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13872		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13873		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13874		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13875		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13876		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13877		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13878		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13879		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13880		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13881		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13882		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13883		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13884		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13885		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13886		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13887		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13888		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13889		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13890		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13891		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13892		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13893		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13894		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13895		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13896		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13897		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13898		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13899		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13900		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13901		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13902		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13903		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13904		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13905		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13906		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13907		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13908		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13909		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13910		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13911		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13912		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13913		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13914		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13915		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13916		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13917		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13918		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13919		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13920		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13921		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13922		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13923		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13924		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13925	};
13926
13927	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13928		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13929			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13930		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13931			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13932			    txgain_2ghz_r2);
13933		else
13934			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13935			    txgain_5ghz_r2);
13936		return;
13937	}
13938
13939	if (mac->mac_phy.rev == 0) {
13940		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13941		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13942			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13943		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13944			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13945			    txgain_2ghz_r0);
13946		else
13947			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13948			    txgain_5ghz_r0);
13949		return;
13950	}
13951
13952	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13953	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13954		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13955	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13956		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13957	else
13958		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13959}
13960
13961static void
13962bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13963{
13964	uint32_t offset, type;
13965
13966	type = BWN_TAB_GETTYPE(typeoffset);
13967	offset = BWN_TAB_GETOFFSET(typeoffset);
13968	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13969
13970	switch (type) {
13971	case BWN_TAB_8BIT:
13972		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13973		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13974		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13975		break;
13976	case BWN_TAB_16BIT:
13977		KASSERT(!(value & ~0xffff),
13978		    ("%s:%d: fail", __func__, __LINE__));
13979		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13980		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13981		break;
13982	case BWN_TAB_32BIT:
13983		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13984		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13985		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13986		break;
13987	default:
13988		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13989	}
13990}
13991
13992static int
13993bwn_phy_lp_loopback(struct bwn_mac *mac)
13994{
13995	struct bwn_phy_lp_iq_est ie;
13996	int i, index = -1;
13997	uint32_t tmp;
13998
13999	memset(&ie, 0, sizeof(ie));
14000
14001	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14002	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14003	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14004	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14005	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14006	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14007	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14008	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14009	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14010	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14011	for (i = 0; i < 32; i++) {
14012		bwn_phy_lp_set_rxgain_idx(mac, i);
14013		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14014		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14015			continue;
14016		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14017		if ((tmp > 4000) && (tmp < 10000)) {
14018			index = i;
14019			break;
14020		}
14021	}
14022	bwn_phy_lp_ddfs_turnoff(mac);
14023	return (index);
14024}
14025
14026static void
14027bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14028{
14029
14030	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14031}
14032
14033static void
14034bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14035    int incr1, int incr2, int scale_idx)
14036{
14037
14038	bwn_phy_lp_ddfs_turnoff(mac);
14039	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14040	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14041	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14042	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14043	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14044	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14045	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14046	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14047	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14048	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14049}
14050
14051static uint8_t
14052bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14053    struct bwn_phy_lp_iq_est *ie)
14054{
14055	int i;
14056
14057	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14058	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14059	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14060	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14061	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14062
14063	for (i = 0; i < 500; i++) {
14064		if (!(BWN_PHY_READ(mac,
14065		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14066			break;
14067		DELAY(1000);
14068	}
14069	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14070		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14071		return 0;
14072	}
14073
14074	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14075	ie->ie_iqprod <<= 16;
14076	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14077	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14078	ie->ie_ipwr <<= 16;
14079	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14080	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14081	ie->ie_qpwr <<= 16;
14082	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14083
14084	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14085	return 1;
14086}
14087
14088static uint32_t
14089bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14090{
14091	uint32_t offset, type, value;
14092
14093	type = BWN_TAB_GETTYPE(typeoffset);
14094	offset = BWN_TAB_GETOFFSET(typeoffset);
14095	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14096
14097	switch (type) {
14098	case BWN_TAB_8BIT:
14099		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14100		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14101		break;
14102	case BWN_TAB_16BIT:
14103		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14104		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14105		break;
14106	case BWN_TAB_32BIT:
14107		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14108		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14109		value <<= 16;
14110		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14111		break;
14112	default:
14113		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14114		value = 0;
14115	}
14116
14117	return (value);
14118}
14119
14120static void
14121bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14122{
14123
14124	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14125	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14126}
14127
14128static void
14129bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14130{
14131	uint16_t ctl;
14132
14133	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14134	ctl |= dac << 7;
14135	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14136}
14137
14138static void
14139bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14140{
14141
14142	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14143	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14144}
14145
14146static void
14147bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14148{
14149
14150	if (mac->mac_phy.rev < 2)
14151		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14152	else {
14153		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14154		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14155	}
14156	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14157}
14158
14159static uint16_t
14160bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14161{
14162
14163	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14164}
14165
14166static uint8_t
14167bwn_nbits(int32_t val)
14168{
14169	uint32_t tmp;
14170	uint8_t nbits = 0;
14171
14172	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14173		nbits++;
14174	return (nbits);
14175}
14176
14177static void
14178bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14179    struct bwn_txgain_entry *table)
14180{
14181	int i;
14182
14183	for (i = offset; i < count; i++)
14184		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14185}
14186
14187static void
14188bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14189    struct bwn_txgain_entry data)
14190{
14191
14192	if (mac->mac_phy.rev >= 2)
14193		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14194	else
14195		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14196}
14197
14198static void
14199bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14200    struct bwn_txgain_entry te)
14201{
14202	struct bwn_softc *sc = mac->mac_sc;
14203	struct ifnet *ifp = sc->sc_ifp;
14204	struct ieee80211com *ic = ifp->if_l2com;
14205	uint32_t tmp;
14206
14207	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14208
14209	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14210	if (mac->mac_phy.rev >= 3) {
14211		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14212		    (0x10 << 24) : (0x70 << 24));
14213	} else {
14214		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14215		    (0x14 << 24) : (0x7f << 24));
14216	}
14217	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14218	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14219	    te.te_bbmult << 20 | te.te_dac << 28);
14220}
14221
14222static void
14223bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14224    struct bwn_txgain_entry te)
14225{
14226
14227	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14228
14229	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14230	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14231	    te.te_dac);
14232	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14233}
14234
14235static void
14236bwn_sysctl_node(struct bwn_softc *sc)
14237{
14238	device_t dev = sc->sc_dev;
14239	struct bwn_mac *mac;
14240	struct bwn_stats *stats;
14241
14242	/* XXX assume that count of MAC is only 1. */
14243
14244	if ((mac = sc->sc_curmac) == NULL)
14245		return;
14246	stats = &mac->mac_stats;
14247
14248	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14249	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14250	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14251	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14252	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14253	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14254	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14255	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14256	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14257
14258#ifdef BWN_DEBUG
14259	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14260	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14261	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14262#endif
14263}
14264
14265static device_method_t bwn_methods[] = {
14266	/* Device interface */
14267	DEVMETHOD(device_probe,		bwn_probe),
14268	DEVMETHOD(device_attach,	bwn_attach),
14269	DEVMETHOD(device_detach,	bwn_detach),
14270	DEVMETHOD(device_suspend,	bwn_suspend),
14271	DEVMETHOD(device_resume,	bwn_resume),
14272	KOBJMETHOD_END
14273};
14274static driver_t bwn_driver = {
14275	"bwn",
14276	bwn_methods,
14277	sizeof(struct bwn_softc)
14278};
14279static devclass_t bwn_devclass;
14280DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14281MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14282MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14283MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14284MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14285