if_bwn.c revision 214894
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 214894 2010-11-06 18:17:20Z bschmidt $");
32
33/*
34 * The Broadcom Wireless LAN controller driver.
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/module.h>
40#include <sys/kernel.h>
41#include <sys/endian.h>
42#include <sys/errno.h>
43#include <sys/firmware.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <machine/bus.h>
47#include <machine/resource.h>
48#include <sys/bus.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52
53#include <net/ethernet.h>
54#include <net/if.h>
55#include <net/if_arp.h>
56#include <net/if_dl.h>
57#include <net/if_llc.h>
58#include <net/if_media.h>
59#include <net/if_types.h>
60
61#include <dev/pci/pcivar.h>
62#include <dev/pci/pcireg.h>
63#include <dev/siba/siba_ids.h>
64#include <dev/siba/sibareg.h>
65#include <dev/siba/sibavar.h>
66
67#include <net80211/ieee80211_var.h>
68#include <net80211/ieee80211_radiotap.h>
69#include <net80211/ieee80211_regdomain.h>
70#include <net80211/ieee80211_phy.h>
71#include <net80211/ieee80211_ratectl.h>
72
73#include <dev/bwn/if_bwnreg.h>
74#include <dev/bwn/if_bwnvar.h>
75
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_updateslot(struct ifnet *);
184static void	bwn_update_promisc(struct ifnet *);
185static void	bwn_wme_init(struct bwn_mac *);
186static int	bwn_wme_update(struct ieee80211com *);
187static void	bwn_wme_clear(struct bwn_softc *);
188static void	bwn_wme_load(struct bwn_mac *);
189static void	bwn_wme_loadparams(struct bwn_mac *,
190		    const struct wmeParams *, uint16_t);
191static void	bwn_scan_start(struct ieee80211com *);
192static void	bwn_scan_end(struct ieee80211com *);
193static void	bwn_set_channel(struct ieee80211com *);
194static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
195		    const char [IFNAMSIZ], int, int,
196		    int, const uint8_t [IEEE80211_ADDR_LEN],
197		    const uint8_t [IEEE80211_ADDR_LEN]);
198static void	bwn_vap_delete(struct ieee80211vap *);
199static void	bwn_stop(struct bwn_softc *, int);
200static void	bwn_stop_locked(struct bwn_softc *, int);
201static int	bwn_core_init(struct bwn_mac *);
202static void	bwn_core_start(struct bwn_mac *);
203static void	bwn_core_exit(struct bwn_mac *);
204static void	bwn_bt_disable(struct bwn_mac *);
205static int	bwn_chip_init(struct bwn_mac *);
206static uint64_t	bwn_hf_read(struct bwn_mac *);
207static void	bwn_hf_write(struct bwn_mac *, uint64_t);
208static void	bwn_set_txretry(struct bwn_mac *, int, int);
209static void	bwn_rate_init(struct bwn_mac *);
210static void	bwn_set_phytxctl(struct bwn_mac *);
211static void	bwn_spu_setdelay(struct bwn_mac *, int);
212static void	bwn_bt_enable(struct bwn_mac *);
213static void	bwn_set_macaddr(struct bwn_mac *);
214static void	bwn_crypt_init(struct bwn_mac *);
215static void	bwn_chip_exit(struct bwn_mac *);
216static int	bwn_fw_fillinfo(struct bwn_mac *);
217static int	bwn_fw_loaducode(struct bwn_mac *);
218static int	bwn_gpio_init(struct bwn_mac *);
219static int	bwn_fw_loadinitvals(struct bwn_mac *);
220static int	bwn_phy_init(struct bwn_mac *);
221static void	bwn_set_txantenna(struct bwn_mac *, int);
222static void	bwn_set_opmode(struct bwn_mac *);
223static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
224static uint8_t	bwn_plcp_getcck(const uint8_t);
225static uint8_t	bwn_plcp_getofdm(const uint8_t);
226static void	bwn_pio_init(struct bwn_mac *);
227static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
228static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
229		    int);
230static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
231		    struct bwn_pio_rxqueue *, int);
232static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
233static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
234		    uint16_t);
235static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
236static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
237static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
238static void	bwn_pio_handle_txeof(struct bwn_mac *,
239		    const struct bwn_txstatus *);
240static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
241static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
242static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
243		    uint16_t);
244static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
245		    uint32_t);
246static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
247		    struct mbuf *);
248static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
249static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
250		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
251static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
252		    uint16_t, uint32_t);
253static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
254		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
255static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
256		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
257static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
258		    uint16_t, struct bwn_pio_txpkt **);
259static void	bwn_dma_init(struct bwn_mac *);
260static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
261static int	bwn_dma_mask2type(uint64_t);
262static uint64_t	bwn_dma_mask(struct bwn_mac *);
263static uint16_t	bwn_dma_base(int, int);
264static void	bwn_dma_ringfree(struct bwn_dma_ring **);
265static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
266		    int, struct bwn_dmadesc_generic **,
267		    struct bwn_dmadesc_meta **);
268static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
269		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
270		    int, int);
271static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
272static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
273static void	bwn_dma_32_resume(struct bwn_dma_ring *);
274static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
275static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
276static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
277		    int, struct bwn_dmadesc_generic **,
278		    struct bwn_dmadesc_meta **);
279static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
280		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
281		    int, int);
282static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
283static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
284static void	bwn_dma_64_resume(struct bwn_dma_ring *);
285static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
286static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
287static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
288static void	bwn_dma_setup(struct bwn_dma_ring *);
289static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
290static void	bwn_dma_cleanup(struct bwn_dma_ring *);
291static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
292static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
293static void	bwn_dma_rx(struct bwn_dma_ring *);
294static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
295static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
296		    struct bwn_dmadesc_meta *);
297static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
298static int	bwn_dma_gettype(struct bwn_mac *);
299static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
300static int	bwn_dma_freeslot(struct bwn_dma_ring *);
301static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
302static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
303static int	bwn_dma_newbuf(struct bwn_dma_ring *,
304		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
305		    int);
306static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
307		    bus_size_t, int);
308static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
309static void	bwn_dma_handle_txeof(struct bwn_mac *,
310		    const struct bwn_txstatus *);
311static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
312		    struct mbuf *);
313static int	bwn_dma_getslot(struct bwn_dma_ring *);
314static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
315		    uint8_t);
316static int	bwn_dma_attach(struct bwn_mac *);
317static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
318		    int, int, int);
319static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
320		    const struct bwn_txstatus *, uint16_t, int *);
321static void	bwn_dma_free(struct bwn_mac *);
322static void	bwn_phy_g_init_sub(struct bwn_mac *);
323static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
324static void	bwn_phy_init_b5(struct bwn_mac *);
325static void	bwn_phy_init_b6(struct bwn_mac *);
326static void	bwn_phy_init_a(struct bwn_mac *);
327static void	bwn_loopback_calcgain(struct bwn_mac *);
328static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
329static void	bwn_lo_g_init(struct bwn_mac *);
330static void	bwn_lo_g_adjust(struct bwn_mac *);
331static void	bwn_lo_get_powervector(struct bwn_mac *);
332static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
333		    const struct bwn_bbatt *, const struct bwn_rfatt *);
334static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
335static void	bwn_phy_hwpctl_init(struct bwn_mac *);
336static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
337static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
338		    const struct bwn_bbatt *, const struct bwn_rfatt *,
339		    uint8_t);
340static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
341static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
342static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
343static void	bwn_wa_init(struct bwn_mac *);
344static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
345		    uint16_t);
346static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
347static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
348		    uint32_t);
349static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
350		    uint16_t);
351static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
352static void	bwn_mac_suspend(struct bwn_mac *);
353static void	bwn_mac_enable(struct bwn_mac *);
354static void	bwn_psctl(struct bwn_mac *, uint32_t);
355static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
356static void	bwn_nrssi_offset(struct bwn_mac *);
357static void	bwn_nrssi_threshold(struct bwn_mac *);
358static void	bwn_nrssi_slope_11g(struct bwn_mac *);
359static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
360		    int16_t);
361static void	bwn_set_original_gains(struct bwn_mac *);
362static void	bwn_hwpctl_early_init(struct bwn_mac *);
363static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
364static uint16_t	bwn_phy_g_chan2freq(uint8_t);
365static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
366static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
367		    const char *, struct bwn_fwfile *);
368static void	bwn_release_firmware(struct bwn_mac *);
369static void	bwn_do_release_fw(struct bwn_fwfile *);
370static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
371static int	bwn_fwinitvals_write(struct bwn_mac *,
372		    const struct bwn_fwinitvals *, size_t, size_t);
373static int	bwn_switch_channel(struct bwn_mac *, int);
374static uint16_t	bwn_ant2phy(int);
375static void	bwn_mac_write_bssid(struct bwn_mac *);
376static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
377		    const uint8_t *);
378static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
379		    const uint8_t *, size_t, const uint8_t *);
380static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
381		    const uint8_t *);
382static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
383		    const uint8_t *);
384static void	bwn_phy_exit(struct bwn_mac *);
385static void	bwn_core_stop(struct bwn_mac *);
386static int	bwn_switch_band(struct bwn_softc *,
387		    struct ieee80211_channel *);
388static void	bwn_phy_reset(struct bwn_mac *);
389static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
390static void	bwn_set_pretbtt(struct bwn_mac *);
391static int	bwn_intr(void *);
392static void	bwn_intrtask(void *, int);
393static void	bwn_restart(struct bwn_mac *, const char *);
394static void	bwn_intr_ucode_debug(struct bwn_mac *);
395static void	bwn_intr_tbtt_indication(struct bwn_mac *);
396static void	bwn_intr_atim_end(struct bwn_mac *);
397static void	bwn_intr_beacon(struct bwn_mac *);
398static void	bwn_intr_pmq(struct bwn_mac *);
399static void	bwn_intr_noise(struct bwn_mac *);
400static void	bwn_intr_txeof(struct bwn_mac *);
401static void	bwn_hwreset(void *, int);
402static void	bwn_handle_fwpanic(struct bwn_mac *);
403static void	bwn_load_beacon0(struct bwn_mac *);
404static void	bwn_load_beacon1(struct bwn_mac *);
405static uint32_t	bwn_jssi_read(struct bwn_mac *);
406static void	bwn_noise_gensample(struct bwn_mac *);
407static void	bwn_handle_txeof(struct bwn_mac *,
408		    const struct bwn_txstatus *);
409static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
410static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
411static void	bwn_start_locked(struct ifnet *);
412static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
413		    struct mbuf *);
414static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
415static int	bwn_set_txhdr(struct bwn_mac *,
416		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
417		    uint16_t);
418static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
419		    const uint8_t);
420static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
421static uint8_t	bwn_get_fbrate(uint8_t);
422static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
423static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
424static void	bwn_phy_lock(struct bwn_mac *);
425static void	bwn_phy_unlock(struct bwn_mac *);
426static void	bwn_rf_lock(struct bwn_mac *);
427static void	bwn_rf_unlock(struct bwn_mac *);
428static void	bwn_txpwr(void *, int);
429static void	bwn_tasks(void *);
430static void	bwn_task_15s(struct bwn_mac *);
431static void	bwn_task_30s(struct bwn_mac *);
432static void	bwn_task_60s(struct bwn_mac *);
433static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
434		    uint8_t);
435static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
436static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
437		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
438		    int, int);
439static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
440static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
441static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
442static void	bwn_watchdog(void *);
443static void	bwn_dma_stop(struct bwn_mac *);
444static void	bwn_pio_stop(struct bwn_mac *);
445static void	bwn_dma_ringstop(struct bwn_dma_ring **);
446static void	bwn_led_attach(struct bwn_mac *);
447static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
448static void	bwn_led_event(struct bwn_mac *, int);
449static void	bwn_led_blink_start(struct bwn_mac *, int, int);
450static void	bwn_led_blink_next(void *);
451static void	bwn_led_blink_end(void *);
452static void	bwn_rfswitch(void *);
453static void	bwn_rf_turnon(struct bwn_mac *);
454static void	bwn_rf_turnoff(struct bwn_mac *);
455static void	bwn_phy_lp_init_pre(struct bwn_mac *);
456static int	bwn_phy_lp_init(struct bwn_mac *);
457static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
458static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
459static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
460		    uint16_t);
461static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
462static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
463static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
464static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
465static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
466static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
467static void	bwn_phy_lp_task_60s(struct bwn_mac *);
468static void	bwn_phy_lp_readsprom(struct bwn_mac *);
469static void	bwn_phy_lp_bbinit(struct bwn_mac *);
470static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
471static void	bwn_phy_lp_calib(struct bwn_mac *);
472static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
473static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
474static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
475static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
476static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
477static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
478static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
479static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
480static void	bwn_phy_lp_bugfix(struct bwn_mac *);
481static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
482static void	bwn_phy_lp_tblinit(struct bwn_mac *);
483static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
484static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
485static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
486static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
487static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
488static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
489static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
490static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
491static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
492static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
493static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
494		    const void *);
495static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
496static struct bwn_txgain
497		bwn_phy_lp_get_txgain(struct bwn_mac *);
498static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
499static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
500static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
501static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
502static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
503static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
504static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
505static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
506static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
507static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
508static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
509static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
510static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
511static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
512static int	bwn_phy_lp_loopback(struct bwn_mac *);
513static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
514static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
515		    int);
516static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
517		    struct bwn_phy_lp_iq_est *);
518static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
519static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
520static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
521static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
522static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
523static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
524static uint8_t	bwn_nbits(int32_t);
525static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
526		    struct bwn_txgain_entry *);
527static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
528		    struct bwn_txgain_entry);
529static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
530		    struct bwn_txgain_entry);
531static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
532		    struct bwn_txgain_entry);
533static void	bwn_sysctl_node(struct bwn_softc *);
534
535static struct resource_spec bwn_res_spec_legacy[] = {
536	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
537	{ -1,			0,		0 }
538};
539
540static struct resource_spec bwn_res_spec_msi[] = {
541	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
542	{ -1,			0,		0 }
543};
544
545static const struct bwn_channelinfo bwn_chantable_bg = {
546	.channels = {
547		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
548		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
549		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
550		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
551		{ 2472, 13, 30 }, { 2484, 14, 30 } },
552	.nchannels = 14
553};
554
555static const struct bwn_channelinfo bwn_chantable_a = {
556	.channels = {
557		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
558		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
559		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
560		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
561		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
562		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
563		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
564		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
565		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
566		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
567		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
568		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
569		{ 6080, 216, 30 } },
570	.nchannels = 37
571};
572
573static const struct bwn_channelinfo bwn_chantable_n = {
574	.channels = {
575		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
576		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
577		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
578		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
579		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
580		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
581		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
582		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
583		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
584		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
585		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
586		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
587		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
588		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
589		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
590		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
591		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
592		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
593		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
594		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
595		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
596		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
597		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
598		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
599		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
600		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
601		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
602		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
603		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
604		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
605		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
606		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
607		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
608		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
609		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
610		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
611		{ 6130, 226, 30 }, { 6140, 228, 30 } },
612	.nchannels = 110
613};
614
615static const uint8_t bwn_b2063_chantable_data[33][12] = {
616	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
617	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
622	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
623	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
624	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
625	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
626	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
627	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
628	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
629	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
630	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
631	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
633	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
634	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
635	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
636	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
638	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
641	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
642	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
644	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
647	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
649};
650
651static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
652	{ 1, 2412, bwn_b2063_chantable_data[0] },
653	{ 2, 2417, bwn_b2063_chantable_data[0] },
654	{ 3, 2422, bwn_b2063_chantable_data[0] },
655	{ 4, 2427, bwn_b2063_chantable_data[1] },
656	{ 5, 2432, bwn_b2063_chantable_data[1] },
657	{ 6, 2437, bwn_b2063_chantable_data[1] },
658	{ 7, 2442, bwn_b2063_chantable_data[1] },
659	{ 8, 2447, bwn_b2063_chantable_data[1] },
660	{ 9, 2452, bwn_b2063_chantable_data[2] },
661	{ 10, 2457, bwn_b2063_chantable_data[2] },
662	{ 11, 2462, bwn_b2063_chantable_data[3] },
663	{ 12, 2467, bwn_b2063_chantable_data[3] },
664	{ 13, 2472, bwn_b2063_chantable_data[3] },
665	{ 14, 2484, bwn_b2063_chantable_data[4] },
666	{ 34, 5170, bwn_b2063_chantable_data[5] },
667	{ 36, 5180, bwn_b2063_chantable_data[6] },
668	{ 38, 5190, bwn_b2063_chantable_data[7] },
669	{ 40, 5200, bwn_b2063_chantable_data[8] },
670	{ 42, 5210, bwn_b2063_chantable_data[9] },
671	{ 44, 5220, bwn_b2063_chantable_data[10] },
672	{ 46, 5230, bwn_b2063_chantable_data[11] },
673	{ 48, 5240, bwn_b2063_chantable_data[12] },
674	{ 52, 5260, bwn_b2063_chantable_data[13] },
675	{ 56, 5280, bwn_b2063_chantable_data[14] },
676	{ 60, 5300, bwn_b2063_chantable_data[14] },
677	{ 64, 5320, bwn_b2063_chantable_data[15] },
678	{ 100, 5500, bwn_b2063_chantable_data[16] },
679	{ 104, 5520, bwn_b2063_chantable_data[17] },
680	{ 108, 5540, bwn_b2063_chantable_data[18] },
681	{ 112, 5560, bwn_b2063_chantable_data[19] },
682	{ 116, 5580, bwn_b2063_chantable_data[20] },
683	{ 120, 5600, bwn_b2063_chantable_data[21] },
684	{ 124, 5620, bwn_b2063_chantable_data[21] },
685	{ 128, 5640, bwn_b2063_chantable_data[22] },
686	{ 132, 5660, bwn_b2063_chantable_data[22] },
687	{ 136, 5680, bwn_b2063_chantable_data[22] },
688	{ 140, 5700, bwn_b2063_chantable_data[23] },
689	{ 149, 5745, bwn_b2063_chantable_data[23] },
690	{ 153, 5765, bwn_b2063_chantable_data[23] },
691	{ 157, 5785, bwn_b2063_chantable_data[23] },
692	{ 161, 5805, bwn_b2063_chantable_data[23] },
693	{ 165, 5825, bwn_b2063_chantable_data[23] },
694	{ 184, 4920, bwn_b2063_chantable_data[24] },
695	{ 188, 4940, bwn_b2063_chantable_data[25] },
696	{ 192, 4960, bwn_b2063_chantable_data[26] },
697	{ 196, 4980, bwn_b2063_chantable_data[27] },
698	{ 200, 5000, bwn_b2063_chantable_data[28] },
699	{ 204, 5020, bwn_b2063_chantable_data[29] },
700	{ 208, 5040, bwn_b2063_chantable_data[30] },
701	{ 212, 5060, bwn_b2063_chantable_data[31] },
702	{ 216, 5080, bwn_b2063_chantable_data[32] }
703};
704
705static const uint8_t bwn_b2062_chantable_data[22][12] = {
706	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
707	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
716	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
727	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
728};
729
730static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
731	{ 1, 2412, bwn_b2062_chantable_data[0] },
732	{ 2, 2417, bwn_b2062_chantable_data[0] },
733	{ 3, 2422, bwn_b2062_chantable_data[0] },
734	{ 4, 2427, bwn_b2062_chantable_data[0] },
735	{ 5, 2432, bwn_b2062_chantable_data[0] },
736	{ 6, 2437, bwn_b2062_chantable_data[0] },
737	{ 7, 2442, bwn_b2062_chantable_data[0] },
738	{ 8, 2447, bwn_b2062_chantable_data[0] },
739	{ 9, 2452, bwn_b2062_chantable_data[0] },
740	{ 10, 2457, bwn_b2062_chantable_data[0] },
741	{ 11, 2462, bwn_b2062_chantable_data[0] },
742	{ 12, 2467, bwn_b2062_chantable_data[0] },
743	{ 13, 2472, bwn_b2062_chantable_data[0] },
744	{ 14, 2484, bwn_b2062_chantable_data[0] },
745	{ 34, 5170, bwn_b2062_chantable_data[1] },
746	{ 38, 5190, bwn_b2062_chantable_data[2] },
747	{ 42, 5210, bwn_b2062_chantable_data[2] },
748	{ 46, 5230, bwn_b2062_chantable_data[3] },
749	{ 36, 5180, bwn_b2062_chantable_data[4] },
750	{ 40, 5200, bwn_b2062_chantable_data[5] },
751	{ 44, 5220, bwn_b2062_chantable_data[6] },
752	{ 48, 5240, bwn_b2062_chantable_data[3] },
753	{ 52, 5260, bwn_b2062_chantable_data[3] },
754	{ 56, 5280, bwn_b2062_chantable_data[3] },
755	{ 60, 5300, bwn_b2062_chantable_data[7] },
756	{ 64, 5320, bwn_b2062_chantable_data[8] },
757	{ 100, 5500, bwn_b2062_chantable_data[9] },
758	{ 104, 5520, bwn_b2062_chantable_data[10] },
759	{ 108, 5540, bwn_b2062_chantable_data[10] },
760	{ 112, 5560, bwn_b2062_chantable_data[10] },
761	{ 116, 5580, bwn_b2062_chantable_data[11] },
762	{ 120, 5600, bwn_b2062_chantable_data[12] },
763	{ 124, 5620, bwn_b2062_chantable_data[12] },
764	{ 128, 5640, bwn_b2062_chantable_data[12] },
765	{ 132, 5660, bwn_b2062_chantable_data[12] },
766	{ 136, 5680, bwn_b2062_chantable_data[12] },
767	{ 140, 5700, bwn_b2062_chantable_data[12] },
768	{ 149, 5745, bwn_b2062_chantable_data[12] },
769	{ 153, 5765, bwn_b2062_chantable_data[12] },
770	{ 157, 5785, bwn_b2062_chantable_data[12] },
771	{ 161, 5805, bwn_b2062_chantable_data[12] },
772	{ 165, 5825, bwn_b2062_chantable_data[12] },
773	{ 184, 4920, bwn_b2062_chantable_data[13] },
774	{ 188, 4940, bwn_b2062_chantable_data[14] },
775	{ 192, 4960, bwn_b2062_chantable_data[15] },
776	{ 196, 4980, bwn_b2062_chantable_data[16] },
777	{ 200, 5000, bwn_b2062_chantable_data[17] },
778	{ 204, 5020, bwn_b2062_chantable_data[18] },
779	{ 208, 5040, bwn_b2062_chantable_data[19] },
780	{ 212, 5060, bwn_b2062_chantable_data[20] },
781	{ 216, 5080, bwn_b2062_chantable_data[21] }
782};
783
784/* for LP PHY */
785static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
786	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
787	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
788	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
789	{ 13, -66, 13 }, { 14, -66, 13 },
790};
791
792/* for LP PHY */
793static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
794	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
795	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
796	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
797	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
798	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
799	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
800	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
801	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
802	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
803	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
804	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
805	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
806	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
807};
808
809static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
810
811static const uint8_t bwn_tab_sigsq_tbl[] = {
812	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
813	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
814	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
815	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
816	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
817	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
818};
819
820static const uint8_t bwn_tab_pllfrac_tbl[] = {
821	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
822	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
823};
824
825static const uint16_t bwn_tabl_iqlocal_tbl[] = {
826	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
827	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
828	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
829	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
830	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
831	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
832	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
833	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
836	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838};
839
840static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
841static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
842static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
843static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
844static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
845const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
846
847#define	VENDOR_LED_ACT(vendor)				\
848{							\
849	.vid = PCI_VENDOR_##vendor,			\
850	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
851}
852
853static const struct {
854	uint16_t	vid;
855	uint8_t		led_act[BWN_LED_MAX];
856} bwn_vendor_led_act[] = {
857	VENDOR_LED_ACT(COMPAQ),
858	VENDOR_LED_ACT(ASUSTEK)
859};
860
861static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
862	{ BWN_VENDOR_LED_ACT_DEFAULT };
863
864#undef VENDOR_LED_ACT
865
866static const struct {
867	int		on_dur;
868	int		off_dur;
869} bwn_led_duration[109] = {
870	[0]	= { 400, 100 },
871	[2]	= { 150, 75 },
872	[4]	= { 90, 45 },
873	[11]	= { 66, 34 },
874	[12]	= { 53, 26 },
875	[18]	= { 42, 21 },
876	[22]	= { 35, 17 },
877	[24]	= { 32, 16 },
878	[36]	= { 21, 10 },
879	[48]	= { 16, 8 },
880	[72]	= { 11, 5 },
881	[96]	= { 9, 4 },
882	[108]	= { 7, 3 }
883};
884
885static const uint16_t bwn_wme_shm_offsets[] = {
886	[0] = BWN_WME_BESTEFFORT,
887	[1] = BWN_WME_BACKGROUND,
888	[2] = BWN_WME_VOICE,
889	[3] = BWN_WME_VIDEO,
890};
891
892static const struct siba_devid bwn_devs[] = {
893	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
894	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
895	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
896	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
897	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
898	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
899	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
900	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
901	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
902};
903
904static int
905bwn_probe(device_t dev)
906{
907	int i;
908
909	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
910		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
911		    siba_get_device(dev) == bwn_devs[i].sd_device &&
912		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
913			return (BUS_PROBE_DEFAULT);
914	}
915
916	return (ENXIO);
917}
918
919static int
920bwn_attach(device_t dev)
921{
922	struct bwn_mac *mac;
923	struct bwn_softc *sc = device_get_softc(dev);
924	int error, i, msic, reg;
925
926	sc->sc_dev = dev;
927#ifdef BWN_DEBUG
928	sc->sc_debug = bwn_debug;
929#endif
930
931	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
932		error = bwn_attach_pre(sc);
933		if (error != 0)
934			return (error);
935		bwn_sprom_bugfixes(dev);
936		sc->sc_flags |= BWN_FLAG_ATTACHED;
937	}
938
939	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
940		if (siba_get_pci_device(dev) != 0x4313 &&
941		    siba_get_pci_device(dev) != 0x431a &&
942		    siba_get_pci_device(dev) != 0x4321) {
943			device_printf(sc->sc_dev,
944			    "skip 802.11 cores\n");
945			return (ENODEV);
946		}
947	}
948
949	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
950	    M_NOWAIT | M_ZERO);
951	if (mac == NULL)
952		return (ENOMEM);
953	mac->mac_sc = sc;
954	mac->mac_status = BWN_MAC_STATUS_UNINIT;
955	if (bwn_bfp != 0)
956		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
957
958	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
959	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
960	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
961
962	error = bwn_attach_core(mac);
963	if (error)
964		goto fail0;
965	bwn_led_attach(mac);
966
967	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
968	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
969	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
970	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
971	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
972	    mac->mac_phy.rf_rev);
973	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
974		device_printf(sc->sc_dev, "DMA (%d bits)\n",
975		    mac->mac_method.dma.dmatype);
976	else
977		device_printf(sc->sc_dev, "PIO\n");
978
979	/*
980	 * setup PCI resources and interrupt.
981	 */
982	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
983		msic = pci_msi_count(dev);
984		if (bootverbose)
985			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
986	} else
987		msic = 0;
988
989	mac->mac_intr_spec = bwn_res_spec_legacy;
990	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
991		if (pci_alloc_msi(dev, &msic) == 0) {
992			device_printf(sc->sc_dev,
993			    "Using %d MSI messages\n", msic);
994			mac->mac_intr_spec = bwn_res_spec_msi;
995			mac->mac_msi = 1;
996		}
997	}
998
999	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1000	    mac->mac_res_irq);
1001	if (error) {
1002		device_printf(sc->sc_dev,
1003		    "couldn't allocate IRQ resources (%d)\n", error);
1004		goto fail1;
1005	}
1006
1007	if (mac->mac_msi == 0)
1008		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1009		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1010		    &mac->mac_intrhand[0]);
1011	else {
1012		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1013			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1014			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1015			    &mac->mac_intrhand[i]);
1016			if (error != 0) {
1017				device_printf(sc->sc_dev,
1018				    "couldn't setup interrupt (%d)\n", error);
1019				break;
1020			}
1021		}
1022	}
1023
1024	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1025
1026	/*
1027	 * calls attach-post routine
1028	 */
1029	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1030		bwn_attach_post(sc);
1031
1032	return (0);
1033fail1:
1034	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1035		pci_release_msi(dev);
1036fail0:
1037	free(mac, M_DEVBUF);
1038	return (error);
1039}
1040
1041static int
1042bwn_is_valid_ether_addr(uint8_t *addr)
1043{
1044	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1045
1046	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1047		return (FALSE);
1048
1049	return (TRUE);
1050}
1051
1052static int
1053bwn_attach_post(struct bwn_softc *sc)
1054{
1055	struct ieee80211com *ic;
1056	struct ifnet *ifp = sc->sc_ifp;
1057
1058	ic = ifp->if_l2com;
1059	ic->ic_ifp = ifp;
1060	/* XXX not right but it's not used anywhere important */
1061	ic->ic_phytype = IEEE80211_T_OFDM;
1062	ic->ic_opmode = IEEE80211_M_STA;
1063	ic->ic_caps =
1064		  IEEE80211_C_STA		/* station mode supported */
1065		| IEEE80211_C_MONITOR		/* monitor mode */
1066		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1067		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1068		| IEEE80211_C_SHSLOT		/* short slot time supported */
1069		| IEEE80211_C_WME		/* WME/WMM supported */
1070		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1071		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1072		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1073		;
1074
1075	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1076
1077	/* call MI attach routine. */
1078	ieee80211_ifattach(ic,
1079	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1080	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1081	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1082
1083	ic->ic_headroom = sizeof(struct bwn_txhdr);
1084
1085	/* override default methods */
1086	ic->ic_raw_xmit = bwn_raw_xmit;
1087	ic->ic_updateslot = bwn_updateslot;
1088	ic->ic_update_promisc = bwn_update_promisc;
1089	ic->ic_wme.wme_update = bwn_wme_update;
1090
1091	ic->ic_scan_start = bwn_scan_start;
1092	ic->ic_scan_end = bwn_scan_end;
1093	ic->ic_set_channel = bwn_set_channel;
1094
1095	ic->ic_vap_create = bwn_vap_create;
1096	ic->ic_vap_delete = bwn_vap_delete;
1097
1098	ieee80211_radiotap_attach(ic,
1099	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1100	    BWN_TX_RADIOTAP_PRESENT,
1101	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1102	    BWN_RX_RADIOTAP_PRESENT);
1103
1104	bwn_sysctl_node(sc);
1105
1106	if (bootverbose)
1107		ieee80211_announce(ic);
1108	return (0);
1109}
1110
1111static void
1112bwn_phy_detach(struct bwn_mac *mac)
1113{
1114
1115	if (mac->mac_phy.detach != NULL)
1116		mac->mac_phy.detach(mac);
1117}
1118
1119static int
1120bwn_detach(device_t dev)
1121{
1122	struct bwn_softc *sc = device_get_softc(dev);
1123	struct bwn_mac *mac = sc->sc_curmac;
1124	struct ifnet *ifp = sc->sc_ifp;
1125	struct ieee80211com *ic = ifp->if_l2com;
1126	int i;
1127
1128	sc->sc_flags |= BWN_FLAG_INVALID;
1129
1130	if (device_is_attached(sc->sc_dev)) {
1131		bwn_stop(sc, 1);
1132		bwn_dma_free(mac);
1133		callout_drain(&sc->sc_led_blink_ch);
1134		callout_drain(&sc->sc_rfswitch_ch);
1135		callout_drain(&sc->sc_task_ch);
1136		callout_drain(&sc->sc_watchdog_ch);
1137		bwn_phy_detach(mac);
1138		if (ifp != NULL) {
1139			ieee80211_draintask(ic, &mac->mac_hwreset);
1140			ieee80211_draintask(ic, &mac->mac_txpower);
1141			ieee80211_ifdetach(ic);
1142			if_free(ifp);
1143		}
1144	}
1145	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1146	taskqueue_free(sc->sc_tq);
1147
1148	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1149		if (mac->mac_intrhand[i] != NULL) {
1150			bus_teardown_intr(dev, mac->mac_res_irq[i],
1151			    mac->mac_intrhand[i]);
1152			mac->mac_intrhand[i] = NULL;
1153		}
1154	}
1155	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1156	if (mac->mac_msi != 0)
1157		pci_release_msi(dev);
1158
1159	BWN_LOCK_DESTROY(sc);
1160	return (0);
1161}
1162
1163static int
1164bwn_attach_pre(struct bwn_softc *sc)
1165{
1166	struct ifnet *ifp;
1167	int error = 0;
1168
1169	BWN_LOCK_INIT(sc);
1170	TAILQ_INIT(&sc->sc_maclist);
1171	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1172	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1173	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1174
1175	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1176		taskqueue_thread_enqueue, &sc->sc_tq);
1177	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1178		"%s taskq", device_get_nameunit(sc->sc_dev));
1179
1180	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1181	if (ifp == NULL) {
1182		device_printf(sc->sc_dev, "can not if_alloc()\n");
1183		error = ENOSPC;
1184		goto fail;
1185	}
1186
1187	/* set these up early for if_printf use */
1188	if_initname(ifp, device_get_name(sc->sc_dev),
1189	    device_get_unit(sc->sc_dev));
1190
1191	ifp->if_softc = sc;
1192	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1193	ifp->if_init = bwn_init;
1194	ifp->if_ioctl = bwn_ioctl;
1195	ifp->if_start = bwn_start;
1196	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1197	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1198	IFQ_SET_READY(&ifp->if_snd);
1199
1200	return (0);
1201
1202fail:	BWN_LOCK_DESTROY(sc);
1203	return (error);
1204}
1205
1206static void
1207bwn_sprom_bugfixes(device_t dev)
1208{
1209#define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1210	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1211	 (siba_get_pci_device(dev) == _device) &&			\
1212	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1213	 (siba_get_pci_subdevice(dev) == _subdevice))
1214
1215	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1216	    siba_get_pci_subdevice(dev) == 0x4e &&
1217	    siba_get_pci_revid(dev) > 0x40)
1218		siba_sprom_set_bf_lo(dev,
1219		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1220	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1221	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1222		siba_sprom_set_bf_lo(dev,
1223		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1224	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1225		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1226		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1227		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1228		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1229		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1230		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1231		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1232			siba_sprom_set_bf_lo(dev,
1233			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1234	}
1235#undef	BWN_ISDEV
1236}
1237
1238static int
1239bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1240{
1241#define	IS_RUNNING(ifp) \
1242	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1243	struct bwn_softc *sc = ifp->if_softc;
1244	struct ieee80211com *ic = ifp->if_l2com;
1245	struct ifreq *ifr = (struct ifreq *)data;
1246	int error = 0, startall;
1247
1248	switch (cmd) {
1249	case SIOCSIFFLAGS:
1250		startall = 0;
1251		if (IS_RUNNING(ifp)) {
1252			bwn_update_promisc(ifp);
1253		} else if (ifp->if_flags & IFF_UP) {
1254			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1255				bwn_init(sc);
1256				startall = 1;
1257			}
1258		} else
1259			bwn_stop(sc, 1);
1260		if (startall)
1261			ieee80211_start_all(ic);
1262		break;
1263	case SIOCGIFMEDIA:
1264		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1265		break;
1266	case SIOCGIFADDR:
1267		error = ether_ioctl(ifp, cmd, data);
1268		break;
1269	default:
1270		error = EINVAL;
1271		break;
1272	}
1273	return (error);
1274}
1275
1276static void
1277bwn_start(struct ifnet *ifp)
1278{
1279	struct bwn_softc *sc = ifp->if_softc;
1280
1281	BWN_LOCK(sc);
1282	bwn_start_locked(ifp);
1283	BWN_UNLOCK(sc);
1284}
1285
1286static void
1287bwn_start_locked(struct ifnet *ifp)
1288{
1289	struct bwn_softc *sc = ifp->if_softc;
1290	struct bwn_mac *mac = sc->sc_curmac;
1291	struct ieee80211_frame *wh;
1292	struct ieee80211_node *ni;
1293	struct ieee80211_key *k;
1294	struct mbuf *m;
1295
1296	BWN_ASSERT_LOCKED(sc);
1297
1298	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1299	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1300		return;
1301
1302	for (;;) {
1303		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1304		if (m == NULL)
1305			break;
1306
1307		if (bwn_tx_isfull(sc, m))
1308			break;
1309		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1310		if (ni == NULL) {
1311			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1312			m_freem(m);
1313			ifp->if_oerrors++;
1314			continue;
1315		}
1316		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1317		wh = mtod(m, struct ieee80211_frame *);
1318		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1319			k = ieee80211_crypto_encap(ni, m);
1320			if (k == NULL) {
1321				ieee80211_free_node(ni);
1322				m_freem(m);
1323				ifp->if_oerrors++;
1324				continue;
1325			}
1326		}
1327		wh = NULL;	/* Catch any invalid use */
1328
1329		if (bwn_tx_start(sc, ni, m) != 0) {
1330			if (ni != NULL)
1331				ieee80211_free_node(ni);
1332			ifp->if_oerrors++;
1333			continue;
1334		}
1335
1336		sc->sc_watchdog_timer = 5;
1337	}
1338}
1339
1340static int
1341bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1342{
1343	struct bwn_dma_ring *dr;
1344	struct bwn_mac *mac = sc->sc_curmac;
1345	struct bwn_pio_txqueue *tq;
1346	struct ifnet *ifp = sc->sc_ifp;
1347	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1348
1349	BWN_ASSERT_LOCKED(sc);
1350
1351	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1352		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1353		if (dr->dr_stop == 1 ||
1354		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1355			dr->dr_stop = 1;
1356			goto full;
1357		}
1358	} else {
1359		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1360		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1361		    pktlen > (tq->tq_size - tq->tq_used)) {
1362			tq->tq_stop = 1;
1363			goto full;
1364		}
1365	}
1366	return (0);
1367full:
1368	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1369	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1370	return (1);
1371}
1372
1373static int
1374bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1375{
1376	struct bwn_mac *mac = sc->sc_curmac;
1377	int error;
1378
1379	BWN_ASSERT_LOCKED(sc);
1380
1381	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1382		m_freem(m);
1383		return (ENXIO);
1384	}
1385
1386	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1387	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1388	if (error) {
1389		m_freem(m);
1390		return (error);
1391	}
1392	return (0);
1393}
1394
1395static int
1396bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1397{
1398	struct bwn_pio_txpkt *tp;
1399	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1400	struct bwn_softc *sc = mac->mac_sc;
1401	struct bwn_txhdr txhdr;
1402	struct mbuf *m_new;
1403	uint32_t ctl32;
1404	int error;
1405	uint16_t ctl16;
1406
1407	BWN_ASSERT_LOCKED(sc);
1408
1409	/* XXX TODO send packets after DTIM */
1410
1411	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1412	tp = TAILQ_FIRST(&tq->tq_pktlist);
1413	tp->tp_ni = ni;
1414	tp->tp_m = m;
1415
1416	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1417	if (error) {
1418		device_printf(sc->sc_dev, "tx fail\n");
1419		return (error);
1420	}
1421
1422	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1423	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1424	tq->tq_free--;
1425
1426	if (siba_get_revid(sc->sc_dev) >= 8) {
1427		/*
1428		 * XXX please removes m_defrag(9)
1429		 */
1430		m_new = m_defrag(m, M_DONTWAIT);
1431		if (m_new == NULL) {
1432			device_printf(sc->sc_dev,
1433			    "%s: can't defrag TX buffer\n",
1434			    __func__);
1435			return (ENOBUFS);
1436		}
1437		if (m_new->m_next != NULL)
1438			device_printf(sc->sc_dev,
1439			    "TODO: fragmented packets for PIO\n");
1440		tp->tp_m = m_new;
1441
1442		/* send HEADER */
1443		ctl32 = bwn_pio_write_multi_4(mac, tq,
1444		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1445			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1446		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1447		/* send BODY */
1448		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1449		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1450		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1451		    ctl32 | BWN_PIO8_TXCTL_EOF);
1452	} else {
1453		ctl16 = bwn_pio_write_multi_2(mac, tq,
1454		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1455			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1456		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1457		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1458		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1459		    ctl16 | BWN_PIO_TXCTL_EOF);
1460	}
1461
1462	return (0);
1463}
1464
1465static struct bwn_pio_txqueue *
1466bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1467{
1468
1469	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1470		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1471
1472	switch (prio) {
1473	case 0:
1474		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1475	case 1:
1476		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1477	case 2:
1478		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1479	case 3:
1480		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1481	}
1482	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1483	return (NULL);
1484}
1485
1486static int
1487bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1488{
1489#define	BWN_GET_TXHDRCACHE(slot)					\
1490	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1491	struct bwn_dma *dma = &mac->mac_method.dma;
1492	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1493	struct bwn_dmadesc_generic *desc;
1494	struct bwn_dmadesc_meta *mt;
1495	struct bwn_softc *sc = mac->mac_sc;
1496	struct ifnet *ifp = sc->sc_ifp;
1497	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1498	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1499
1500	BWN_ASSERT_LOCKED(sc);
1501	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1502
1503	/* XXX send after DTIM */
1504
1505	slot = bwn_dma_getslot(dr);
1506	dr->getdesc(dr, slot, &desc, &mt);
1507	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1508	    ("%s:%d: fail", __func__, __LINE__));
1509
1510	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1511	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1512	    BWN_DMA_COOKIE(dr, slot));
1513	if (error)
1514		goto fail;
1515	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1516	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1517	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1518	if (error) {
1519		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1520		    __func__, error);
1521		goto fail;
1522	}
1523	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1524	    BUS_DMASYNC_PREWRITE);
1525	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1526	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1527	    BUS_DMASYNC_PREWRITE);
1528
1529	slot = bwn_dma_getslot(dr);
1530	dr->getdesc(dr, slot, &desc, &mt);
1531	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1532	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1533	mt->mt_m = m;
1534	mt->mt_ni = ni;
1535
1536	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1537	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1538	if (error && error != EFBIG) {
1539		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1540		    __func__, error);
1541		goto fail;
1542	}
1543	if (error) {    /* error == EFBIG */
1544		struct mbuf *m_new;
1545
1546		m_new = m_defrag(m, M_DONTWAIT);
1547		if (m_new == NULL) {
1548			if_printf(ifp, "%s: can't defrag TX buffer\n",
1549			    __func__);
1550			error = ENOBUFS;
1551			goto fail;
1552		} else {
1553			m = m_new;
1554		}
1555
1556		mt->mt_m = m;
1557		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1558		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1559		if (error) {
1560			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1561			    __func__, error);
1562			goto fail;
1563		}
1564	}
1565	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1566	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1567	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1568	    BUS_DMASYNC_PREWRITE);
1569
1570	/* XXX send after DTIM */
1571
1572	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1573	return (0);
1574fail:
1575	dr->dr_curslot = backup[0];
1576	dr->dr_usedslot = backup[1];
1577	return (error);
1578#undef BWN_GET_TXHDRCACHE
1579}
1580
1581static void
1582bwn_watchdog(void *arg)
1583{
1584	struct bwn_softc *sc = arg;
1585	struct ifnet *ifp = sc->sc_ifp;
1586
1587	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1588		if_printf(ifp, "device timeout\n");
1589		ifp->if_oerrors++;
1590	}
1591	callout_schedule(&sc->sc_watchdog_ch, hz);
1592}
1593
1594static int
1595bwn_attach_core(struct bwn_mac *mac)
1596{
1597	struct bwn_softc *sc = mac->mac_sc;
1598	int error, have_bg = 0, have_a = 0;
1599	uint32_t high;
1600
1601	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1602	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1603
1604	siba_powerup(sc->sc_dev, 0);
1605
1606	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1607	bwn_reset_core(mac,
1608	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1609	error = bwn_phy_getinfo(mac, high);
1610	if (error)
1611		goto fail;
1612
1613	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1614	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1615	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1616	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1617	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1618		have_a = have_bg = 0;
1619		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1620			have_a = 1;
1621		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1622		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1623		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1624			have_bg = 1;
1625		else
1626			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1627			    mac->mac_phy.type));
1628	}
1629	/* XXX turns off PHY A because it's not supported */
1630	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1631	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1632		have_a = 0;
1633		have_bg = 1;
1634	}
1635
1636	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1637		mac->mac_phy.attach = bwn_phy_g_attach;
1638		mac->mac_phy.detach = bwn_phy_g_detach;
1639		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1640		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1641		mac->mac_phy.init = bwn_phy_g_init;
1642		mac->mac_phy.exit = bwn_phy_g_exit;
1643		mac->mac_phy.phy_read = bwn_phy_g_read;
1644		mac->mac_phy.phy_write = bwn_phy_g_write;
1645		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1646		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1647		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1648		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1649		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1650		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1651		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1652		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1653		mac->mac_phy.set_im = bwn_phy_g_im;
1654		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1655		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1656		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1657		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1658	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1659		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1660		mac->mac_phy.init = bwn_phy_lp_init;
1661		mac->mac_phy.phy_read = bwn_phy_lp_read;
1662		mac->mac_phy.phy_write = bwn_phy_lp_write;
1663		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1664		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1665		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1666		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1667		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1668		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1669		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1670		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1671		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1672	} else {
1673		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1674		    mac->mac_phy.type);
1675		error = ENXIO;
1676		goto fail;
1677	}
1678
1679	mac->mac_phy.gmode = have_bg;
1680	if (mac->mac_phy.attach != NULL) {
1681		error = mac->mac_phy.attach(mac);
1682		if (error) {
1683			device_printf(sc->sc_dev, "failed\n");
1684			goto fail;
1685		}
1686	}
1687
1688	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1689
1690	error = bwn_chiptest(mac);
1691	if (error)
1692		goto fail;
1693	error = bwn_setup_channels(mac, have_bg, have_a);
1694	if (error) {
1695		device_printf(sc->sc_dev, "failed to setup channels\n");
1696		goto fail;
1697	}
1698
1699	if (sc->sc_curmac == NULL)
1700		sc->sc_curmac = mac;
1701
1702	error = bwn_dma_attach(mac);
1703	if (error != 0) {
1704		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1705		goto fail;
1706	}
1707
1708	mac->mac_phy.switch_analog(mac, 0);
1709
1710	siba_dev_down(sc->sc_dev, 0);
1711fail:
1712	siba_powerdown(sc->sc_dev);
1713	return (error);
1714}
1715
1716static void
1717bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1718{
1719	struct bwn_softc *sc = mac->mac_sc;
1720	uint32_t low, ctl;
1721
1722	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1723
1724	siba_dev_up(sc->sc_dev, flags);
1725	DELAY(2000);
1726
1727	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1728	    ~BWN_TGSLOW_PHYRESET;
1729	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1730	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1731	DELAY(1000);
1732	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1733	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734	DELAY(1000);
1735
1736	if (mac->mac_phy.switch_analog != NULL)
1737		mac->mac_phy.switch_analog(mac, 1);
1738
1739	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1740	if (flags & BWN_TGSLOW_SUPPORT_G)
1741		ctl |= BWN_MACCTL_GMODE;
1742	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1743}
1744
1745static int
1746bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1747{
1748	struct bwn_phy *phy = &mac->mac_phy;
1749	struct bwn_softc *sc = mac->mac_sc;
1750	uint32_t tmp;
1751
1752	/* PHY */
1753	tmp = BWN_READ_2(mac, BWN_PHYVER);
1754	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1755	phy->rf_on = 1;
1756	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1757	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1758	phy->rev = (tmp & BWN_PHYVER_VERSION);
1759	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1760	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1761		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1762	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1763	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1764	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1765		goto unsupphy;
1766
1767	/* RADIO */
1768	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1769		if (siba_get_chiprev(sc->sc_dev) == 0)
1770			tmp = 0x3205017f;
1771		else if (siba_get_chiprev(sc->sc_dev) == 1)
1772			tmp = 0x4205017f;
1773		else
1774			tmp = 0x5205017f;
1775	} else {
1776		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1777		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1778		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1779		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1780	}
1781	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1782	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1783	phy->rf_manuf = (tmp & 0x00000fff);
1784	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1785		goto unsupradio;
1786	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1787	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1788	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1789	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1790	    (phy->type == BWN_PHYTYPE_N &&
1791	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1792	    (phy->type == BWN_PHYTYPE_LP &&
1793	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1794		goto unsupradio;
1795
1796	return (0);
1797unsupphy:
1798	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1799	    "analog %#x)\n",
1800	    phy->type, phy->rev, phy->analog);
1801	return (ENXIO);
1802unsupradio:
1803	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1804	    "rev %#x)\n",
1805	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1806	return (ENXIO);
1807}
1808
1809static int
1810bwn_chiptest(struct bwn_mac *mac)
1811{
1812#define	TESTVAL0	0x55aaaa55
1813#define	TESTVAL1	0xaa5555aa
1814	struct bwn_softc *sc = mac->mac_sc;
1815	uint32_t v, backup;
1816
1817	BWN_LOCK(sc);
1818
1819	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1820
1821	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1822	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1823		goto error;
1824	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1825	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1826		goto error;
1827
1828	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1829
1830	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1831	    (siba_get_revid(sc->sc_dev) <= 10)) {
1832		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1833		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1834		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1835			goto error;
1836		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1837			goto error;
1838	}
1839	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1840
1841	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1842	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1843		goto error;
1844
1845	BWN_UNLOCK(sc);
1846	return (0);
1847error:
1848	BWN_UNLOCK(sc);
1849	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1850	return (ENODEV);
1851}
1852
1853#define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1854#define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1855
1856static int
1857bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1858{
1859	struct bwn_softc *sc = mac->mac_sc;
1860	struct ifnet *ifp = sc->sc_ifp;
1861	struct ieee80211com *ic = ifp->if_l2com;
1862
1863	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1864	ic->ic_nchans = 0;
1865
1866	if (have_bg)
1867		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1868		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1869	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1870		if (have_a)
1871			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1872			    &ic->ic_nchans, &bwn_chantable_n,
1873			    IEEE80211_CHAN_HTA);
1874	} else {
1875		if (have_a)
1876			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1877			    &ic->ic_nchans, &bwn_chantable_a,
1878			    IEEE80211_CHAN_A);
1879	}
1880
1881	mac->mac_phy.supports_2ghz = have_bg;
1882	mac->mac_phy.supports_5ghz = have_a;
1883
1884	return (ic->ic_nchans == 0 ? ENXIO : 0);
1885}
1886
1887static uint32_t
1888bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1889{
1890	uint32_t ret;
1891
1892	BWN_ASSERT_LOCKED(mac->mac_sc);
1893
1894	if (way == BWN_SHARED) {
1895		KASSERT((offset & 0x0001) == 0,
1896		    ("%s:%d warn", __func__, __LINE__));
1897		if (offset & 0x0003) {
1898			bwn_shm_ctlword(mac, way, offset >> 2);
1899			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1900			ret <<= 16;
1901			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1902			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1903			goto out;
1904		}
1905		offset >>= 2;
1906	}
1907	bwn_shm_ctlword(mac, way, offset);
1908	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1909out:
1910	return (ret);
1911}
1912
1913static uint16_t
1914bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1915{
1916	uint16_t ret;
1917
1918	BWN_ASSERT_LOCKED(mac->mac_sc);
1919
1920	if (way == BWN_SHARED) {
1921		KASSERT((offset & 0x0001) == 0,
1922		    ("%s:%d warn", __func__, __LINE__));
1923		if (offset & 0x0003) {
1924			bwn_shm_ctlword(mac, way, offset >> 2);
1925			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1926			goto out;
1927		}
1928		offset >>= 2;
1929	}
1930	bwn_shm_ctlword(mac, way, offset);
1931	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1932out:
1933
1934	return (ret);
1935}
1936
1937static void
1938bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1939    uint16_t offset)
1940{
1941	uint32_t control;
1942
1943	control = way;
1944	control <<= 16;
1945	control |= offset;
1946	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1947}
1948
1949static void
1950bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1951    uint32_t value)
1952{
1953	BWN_ASSERT_LOCKED(mac->mac_sc);
1954
1955	if (way == BWN_SHARED) {
1956		KASSERT((offset & 0x0001) == 0,
1957		    ("%s:%d warn", __func__, __LINE__));
1958		if (offset & 0x0003) {
1959			bwn_shm_ctlword(mac, way, offset >> 2);
1960			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1961				    (value >> 16) & 0xffff);
1962			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1963			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1964			return;
1965		}
1966		offset >>= 2;
1967	}
1968	bwn_shm_ctlword(mac, way, offset);
1969	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1970}
1971
1972static void
1973bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1974    uint16_t value)
1975{
1976	BWN_ASSERT_LOCKED(mac->mac_sc);
1977
1978	if (way == BWN_SHARED) {
1979		KASSERT((offset & 0x0001) == 0,
1980		    ("%s:%d warn", __func__, __LINE__));
1981		if (offset & 0x0003) {
1982			bwn_shm_ctlword(mac, way, offset >> 2);
1983			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1984			return;
1985		}
1986		offset >>= 2;
1987	}
1988	bwn_shm_ctlword(mac, way, offset);
1989	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1990}
1991
1992static void
1993bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1994    int txpow)
1995{
1996
1997	c->ic_freq = freq;
1998	c->ic_flags = flags;
1999	c->ic_ieee = ieee;
2000	c->ic_minpower = 0;
2001	c->ic_maxpower = 2 * txpow;
2002	c->ic_maxregpower = txpow;
2003}
2004
2005static void
2006bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2007    const struct bwn_channelinfo *ci, int flags)
2008{
2009	struct ieee80211_channel *c;
2010	int i;
2011
2012	c = &chans[*nchans];
2013
2014	for (i = 0; i < ci->nchannels; i++) {
2015		const struct bwn_channel *hc;
2016
2017		hc = &ci->channels[i];
2018		if (*nchans >= maxchans)
2019			break;
2020		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2021		c++, (*nchans)++;
2022		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2023			/* g channel have a separate b-only entry */
2024			if (*nchans >= maxchans)
2025				break;
2026			c[0] = c[-1];
2027			c[-1].ic_flags = IEEE80211_CHAN_B;
2028			c++, (*nchans)++;
2029		}
2030		if (flags == IEEE80211_CHAN_HTG) {
2031			/* HT g channel have a separate g-only entry */
2032			if (*nchans >= maxchans)
2033				break;
2034			c[-1].ic_flags = IEEE80211_CHAN_G;
2035			c[0] = c[-1];
2036			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2037			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2038			c++, (*nchans)++;
2039		}
2040		if (flags == IEEE80211_CHAN_HTA) {
2041			/* HT a channel have a separate a-only entry */
2042			if (*nchans >= maxchans)
2043				break;
2044			c[-1].ic_flags = IEEE80211_CHAN_A;
2045			c[0] = c[-1];
2046			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2047			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2048			c++, (*nchans)++;
2049		}
2050	}
2051}
2052
2053static int
2054bwn_phy_g_attach(struct bwn_mac *mac)
2055{
2056	struct bwn_softc *sc = mac->mac_sc;
2057	struct bwn_phy *phy = &mac->mac_phy;
2058	struct bwn_phy_g *pg = &phy->phy_g;
2059	unsigned int i;
2060	int16_t pab0, pab1, pab2;
2061	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2062	int8_t bg;
2063
2064	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2065	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2066	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2067	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2068
2069	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2070		device_printf(sc->sc_dev, "not supported anymore\n");
2071
2072	pg->pg_flags = 0;
2073	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2074	    pab2 == -1) {
2075		pg->pg_idletssi = 52;
2076		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2077		return (0);
2078	}
2079
2080	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2081	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2082	if (pg->pg_tssi2dbm == NULL) {
2083		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2084		return (ENOMEM);
2085	}
2086	for (i = 0; i < 64; i++) {
2087		int32_t m1, m2, f, q, delta;
2088		int8_t j = 0;
2089
2090		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2091		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2092		f = 256;
2093
2094		do {
2095			if (j > 15) {
2096				device_printf(sc->sc_dev,
2097				    "failed to generate tssi2dBm\n");
2098				free(pg->pg_tssi2dbm, M_DEVBUF);
2099				return (ENOMEM);
2100			}
2101			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2102			    f, 2048);
2103			delta = abs(q - f);
2104			f = q;
2105			j++;
2106		} while (delta >= 2);
2107
2108		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2109		    128);
2110	}
2111
2112	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2113	return (0);
2114}
2115
2116static void
2117bwn_phy_g_detach(struct bwn_mac *mac)
2118{
2119	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2120
2121	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2122		free(pg->pg_tssi2dbm, M_DEVBUF);
2123		pg->pg_tssi2dbm = NULL;
2124	}
2125	pg->pg_flags = 0;
2126}
2127
2128static void
2129bwn_phy_g_init_pre(struct bwn_mac *mac)
2130{
2131	struct bwn_phy *phy = &mac->mac_phy;
2132	struct bwn_phy_g *pg = &phy->phy_g;
2133	void *tssi2dbm;
2134	int idletssi;
2135	unsigned int i;
2136
2137	tssi2dbm = pg->pg_tssi2dbm;
2138	idletssi = pg->pg_idletssi;
2139
2140	memset(pg, 0, sizeof(*pg));
2141
2142	pg->pg_tssi2dbm = tssi2dbm;
2143	pg->pg_idletssi = idletssi;
2144
2145	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2146
2147	for (i = 0; i < N(pg->pg_nrssi); i++)
2148		pg->pg_nrssi[i] = -1000;
2149	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2150		pg->pg_nrssi_lt[i] = i;
2151	pg->pg_lofcal = 0xffff;
2152	pg->pg_initval = 0xffff;
2153	pg->pg_immode = BWN_IMMODE_NONE;
2154	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2155	pg->pg_avgtssi = 0xff;
2156
2157	pg->pg_loctl.tx_bias = 0xff;
2158	TAILQ_INIT(&pg->pg_loctl.calib_list);
2159}
2160
2161static int
2162bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2163{
2164	struct bwn_phy *phy = &mac->mac_phy;
2165	struct bwn_phy_g *pg = &phy->phy_g;
2166	struct bwn_softc *sc = mac->mac_sc;
2167	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2168	static const struct bwn_rfatt rfatt0[] = {
2169		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2170		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2171		{ 3, 1 }, { 4, 1 }
2172	};
2173	static const struct bwn_rfatt rfatt1[] = {
2174		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2175		{ 14, 1 }
2176	};
2177	static const struct bwn_rfatt rfatt2[] = {
2178		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2179		{ 9, 1 }
2180	};
2181	static const struct bwn_bbatt bbatt_0[] = {
2182		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2183	};
2184
2185	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2186
2187	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2188		pg->pg_bbatt.att = 0;
2189	else
2190		pg->pg_bbatt.att = 2;
2191
2192	/* prepare Radio Attenuation */
2193	pg->pg_rfatt.padmix = 0;
2194
2195	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2196	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2197		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2198			pg->pg_rfatt.att = 2;
2199			goto done;
2200		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2201			pg->pg_rfatt.att = 3;
2202			goto done;
2203		}
2204	}
2205
2206	if (phy->type == BWN_PHYTYPE_A) {
2207		pg->pg_rfatt.att = 0x60;
2208		goto done;
2209	}
2210
2211	switch (phy->rf_ver) {
2212	case 0x2050:
2213		switch (phy->rf_rev) {
2214		case 0:
2215			pg->pg_rfatt.att = 5;
2216			goto done;
2217		case 1:
2218			if (phy->type == BWN_PHYTYPE_G) {
2219				if (siba_get_pci_subvendor(sc->sc_dev) ==
2220				    SIBA_BOARDVENDOR_BCM &&
2221				    siba_get_pci_subdevice(sc->sc_dev) ==
2222				    SIBA_BOARD_BCM4309G &&
2223				    siba_get_pci_revid(sc->sc_dev) >= 30)
2224					pg->pg_rfatt.att = 3;
2225				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2226				    SIBA_BOARDVENDOR_BCM &&
2227				    siba_get_pci_subdevice(sc->sc_dev) ==
2228				    SIBA_BOARD_BU4306)
2229					pg->pg_rfatt.att = 3;
2230				else
2231					pg->pg_rfatt.att = 1;
2232			} else {
2233				if (siba_get_pci_subvendor(sc->sc_dev) ==
2234				    SIBA_BOARDVENDOR_BCM &&
2235				    siba_get_pci_subdevice(sc->sc_dev) ==
2236				    SIBA_BOARD_BCM4309G &&
2237				    siba_get_pci_revid(sc->sc_dev) >= 30)
2238					pg->pg_rfatt.att = 7;
2239				else
2240					pg->pg_rfatt.att = 6;
2241			}
2242			goto done;
2243		case 2:
2244			if (phy->type == BWN_PHYTYPE_G) {
2245				if (siba_get_pci_subvendor(sc->sc_dev) ==
2246				    SIBA_BOARDVENDOR_BCM &&
2247				    siba_get_pci_subdevice(sc->sc_dev) ==
2248				    SIBA_BOARD_BCM4309G &&
2249				    siba_get_pci_revid(sc->sc_dev) >= 30)
2250					pg->pg_rfatt.att = 3;
2251				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2252				    SIBA_BOARDVENDOR_BCM &&
2253				    siba_get_pci_subdevice(sc->sc_dev) ==
2254				    SIBA_BOARD_BU4306)
2255					pg->pg_rfatt.att = 5;
2256				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2257					pg->pg_rfatt.att = 4;
2258				else
2259					pg->pg_rfatt.att = 3;
2260			} else
2261				pg->pg_rfatt.att = 6;
2262			goto done;
2263		case 3:
2264			pg->pg_rfatt.att = 5;
2265			goto done;
2266		case 4:
2267		case 5:
2268			pg->pg_rfatt.att = 1;
2269			goto done;
2270		case 6:
2271		case 7:
2272			pg->pg_rfatt.att = 5;
2273			goto done;
2274		case 8:
2275			pg->pg_rfatt.att = 0xa;
2276			pg->pg_rfatt.padmix = 1;
2277			goto done;
2278		case 9:
2279		default:
2280			pg->pg_rfatt.att = 5;
2281			goto done;
2282		}
2283		break;
2284	case 0x2053:
2285		switch (phy->rf_rev) {
2286		case 1:
2287			pg->pg_rfatt.att = 6;
2288			goto done;
2289		}
2290		break;
2291	}
2292	pg->pg_rfatt.att = 5;
2293done:
2294	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2295
2296	if (!bwn_has_hwpctl(mac)) {
2297		lo->rfatt.array = rfatt0;
2298		lo->rfatt.len = N(rfatt0);
2299		lo->rfatt.min = 0;
2300		lo->rfatt.max = 9;
2301		goto genbbatt;
2302	}
2303	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2304		lo->rfatt.array = rfatt1;
2305		lo->rfatt.len = N(rfatt1);
2306		lo->rfatt.min = 0;
2307		lo->rfatt.max = 14;
2308		goto genbbatt;
2309	}
2310	lo->rfatt.array = rfatt2;
2311	lo->rfatt.len = N(rfatt2);
2312	lo->rfatt.min = 0;
2313	lo->rfatt.max = 9;
2314genbbatt:
2315	lo->bbatt.array = bbatt_0;
2316	lo->bbatt.len = N(bbatt_0);
2317	lo->bbatt.min = 0;
2318	lo->bbatt.max = 8;
2319
2320	BWN_READ_4(mac, BWN_MACCTL);
2321	if (phy->rev == 1) {
2322		phy->gmode = 0;
2323		bwn_reset_core(mac, 0);
2324		bwn_phy_g_init_sub(mac);
2325		phy->gmode = 1;
2326		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2327	}
2328	return (0);
2329}
2330
2331static uint16_t
2332bwn_phy_g_txctl(struct bwn_mac *mac)
2333{
2334	struct bwn_phy *phy = &mac->mac_phy;
2335
2336	if (phy->rf_ver != 0x2050)
2337		return (0);
2338	if (phy->rf_rev == 1)
2339		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2340	if (phy->rf_rev < 6)
2341		return (BWN_TXCTL_PA2DB);
2342	if (phy->rf_rev == 8)
2343		return (BWN_TXCTL_TXMIX);
2344	return (0);
2345}
2346
2347static int
2348bwn_phy_g_init(struct bwn_mac *mac)
2349{
2350
2351	bwn_phy_g_init_sub(mac);
2352	return (0);
2353}
2354
2355static void
2356bwn_phy_g_exit(struct bwn_mac *mac)
2357{
2358	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2359	struct bwn_lo_calib *cal, *tmp;
2360
2361	if (lo == NULL)
2362		return;
2363	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2364		TAILQ_REMOVE(&lo->calib_list, cal, list);
2365		free(cal, M_DEVBUF);
2366	}
2367}
2368
2369static uint16_t
2370bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2371{
2372
2373	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2374	return (BWN_READ_2(mac, BWN_PHYDATA));
2375}
2376
2377static void
2378bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2379{
2380
2381	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2382	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2383}
2384
2385static uint16_t
2386bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2387{
2388
2389	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2390	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2391	return (BWN_READ_2(mac, BWN_RFDATALO));
2392}
2393
2394static void
2395bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2396{
2397
2398	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2400	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2401}
2402
2403static int
2404bwn_phy_g_hwpctl(struct bwn_mac *mac)
2405{
2406
2407	return (mac->mac_phy.rev >= 6);
2408}
2409
2410static void
2411bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2412{
2413	struct bwn_phy *phy = &mac->mac_phy;
2414	struct bwn_phy_g *pg = &phy->phy_g;
2415	unsigned int channel;
2416	uint16_t rfover, rfoverval;
2417
2418	if (on) {
2419		if (phy->rf_on)
2420			return;
2421
2422		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2423		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2424		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2425		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2426			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2427			    pg->pg_radioctx_over);
2428			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2429			    pg->pg_radioctx_overval);
2430			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2431		}
2432		channel = phy->chan;
2433		bwn_phy_g_switch_chan(mac, 6, 1);
2434		bwn_phy_g_switch_chan(mac, channel, 0);
2435		return;
2436	}
2437
2438	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2439	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2440	pg->pg_radioctx_over = rfover;
2441	pg->pg_radioctx_overval = rfoverval;
2442	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2443	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2444	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2445}
2446
2447static int
2448bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2449{
2450
2451	if ((newchan < 1) || (newchan > 14))
2452		return (EINVAL);
2453	bwn_phy_g_switch_chan(mac, newchan, 0);
2454
2455	return (0);
2456}
2457
2458static uint32_t
2459bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2460{
2461
2462	return (1);
2463}
2464
2465static void
2466bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2467{
2468	struct bwn_phy *phy = &mac->mac_phy;
2469	uint64_t hf;
2470	int autodiv = 0;
2471	uint16_t tmp;
2472
2473	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2474		autodiv = 1;
2475
2476	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2477	bwn_hf_write(mac, hf);
2478
2479	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2480	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2481	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2482		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2483
2484	if (autodiv) {
2485		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2486		if (antenna == BWN_ANTAUTO1)
2487			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2488		else
2489			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2490		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2491	}
2492	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2493	if (autodiv)
2494		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2495	else
2496		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2497	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2498	if (phy->rev >= 2) {
2499		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2500		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2501		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2502		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2503		    0x15);
2504		if (phy->rev == 2)
2505			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2506		else
2507			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2508			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2509			    8);
2510	}
2511	if (phy->rev >= 6)
2512		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2513
2514	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2515	bwn_hf_write(mac, hf);
2516}
2517
2518static int
2519bwn_phy_g_im(struct bwn_mac *mac, int mode)
2520{
2521	struct bwn_phy *phy = &mac->mac_phy;
2522	struct bwn_phy_g *pg = &phy->phy_g;
2523
2524	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2525	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2526
2527	if (phy->rev == 0 || !phy->gmode)
2528		return (ENODEV);
2529
2530	pg->pg_aci_wlan_automatic = 0;
2531	return (0);
2532}
2533
2534static int
2535bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2536{
2537	struct bwn_phy *phy = &mac->mac_phy;
2538	struct bwn_phy_g *pg = &phy->phy_g;
2539	struct bwn_softc *sc = mac->mac_sc;
2540	unsigned int tssi;
2541	int cck, ofdm;
2542	int power;
2543	int rfatt, bbatt;
2544	unsigned int max;
2545
2546	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2547
2548	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2549	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2550	if (cck < 0 && ofdm < 0) {
2551		if (ignore_tssi == 0)
2552			return (BWN_TXPWR_RES_DONE);
2553		cck = 0;
2554		ofdm = 0;
2555	}
2556	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2557	if (pg->pg_avgtssi != 0xff)
2558		tssi = (tssi + pg->pg_avgtssi) / 2;
2559	pg->pg_avgtssi = tssi;
2560	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2561
2562	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2563	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2564		max -= 3;
2565	if (max >= 120) {
2566		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2567		max = 80;
2568		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2569	}
2570
2571	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2572	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2573	     tssi, 0x00), 0x3f)]);
2574	if (power == 0)
2575		return (BWN_TXPWR_RES_DONE);
2576
2577	rfatt = -((power + 7) / 8);
2578	bbatt = (-(power / 2)) - (4 * rfatt);
2579	if ((rfatt == 0) && (bbatt == 0))
2580		return (BWN_TXPWR_RES_DONE);
2581	pg->pg_bbatt_delta = bbatt;
2582	pg->pg_rfatt_delta = rfatt;
2583	return (BWN_TXPWR_RES_NEED_ADJUST);
2584}
2585
2586static void
2587bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2588{
2589	struct bwn_phy *phy = &mac->mac_phy;
2590	struct bwn_phy_g *pg = &phy->phy_g;
2591	struct bwn_softc *sc = mac->mac_sc;
2592	int rfatt, bbatt;
2593	uint8_t txctl;
2594
2595	bwn_mac_suspend(mac);
2596
2597	BWN_ASSERT_LOCKED(sc);
2598
2599	bbatt = pg->pg_bbatt.att;
2600	bbatt += pg->pg_bbatt_delta;
2601	rfatt = pg->pg_rfatt.att;
2602	rfatt += pg->pg_rfatt_delta;
2603
2604	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2605	txctl = pg->pg_txctl;
2606	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2607		if (rfatt <= 1) {
2608			if (txctl == 0) {
2609				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2610				rfatt += 2;
2611				bbatt += 2;
2612			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2613			    BWN_BFL_PACTRL) {
2614				bbatt += 4 * (rfatt - 2);
2615				rfatt = 2;
2616			}
2617		} else if (rfatt > 4 && txctl) {
2618			txctl = 0;
2619			if (bbatt < 3) {
2620				rfatt -= 3;
2621				bbatt += 2;
2622			} else {
2623				rfatt -= 2;
2624				bbatt -= 2;
2625			}
2626		}
2627	}
2628	pg->pg_txctl = txctl;
2629	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2630	pg->pg_rfatt.att = rfatt;
2631	pg->pg_bbatt.att = bbatt;
2632
2633	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2634
2635	bwn_phy_lock(mac);
2636	bwn_rf_lock(mac);
2637	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2638	    pg->pg_txctl);
2639	bwn_rf_unlock(mac);
2640	bwn_phy_unlock(mac);
2641
2642	bwn_mac_enable(mac);
2643}
2644
2645static void
2646bwn_phy_g_task_15s(struct bwn_mac *mac)
2647{
2648	struct bwn_phy *phy = &mac->mac_phy;
2649	struct bwn_phy_g *pg = &phy->phy_g;
2650	struct bwn_softc *sc = mac->mac_sc;
2651	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2652	unsigned long expire, now;
2653	struct bwn_lo_calib *cal, *tmp;
2654	uint8_t expired = 0;
2655
2656	bwn_mac_suspend(mac);
2657
2658	if (lo == NULL)
2659		goto fail;
2660
2661	BWN_GETTIME(now);
2662	if (bwn_has_hwpctl(mac)) {
2663		expire = now - BWN_LO_PWRVEC_EXPIRE;
2664		if (time_before(lo->pwr_vec_read_time, expire)) {
2665			bwn_lo_get_powervector(mac);
2666			bwn_phy_g_dc_lookup_init(mac, 0);
2667		}
2668		goto fail;
2669	}
2670
2671	expire = now - BWN_LO_CALIB_EXPIRE;
2672	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2673		if (!time_before(cal->calib_time, expire))
2674			continue;
2675		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2676		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2677			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2678			expired = 1;
2679		}
2680
2681		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2682		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2683		    cal->ctl.i, cal->ctl.q);
2684
2685		TAILQ_REMOVE(&lo->calib_list, cal, list);
2686		free(cal, M_DEVBUF);
2687	}
2688	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2689		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2690		    &pg->pg_rfatt);
2691		if (cal == NULL) {
2692			device_printf(sc->sc_dev,
2693			    "failed to recalibrate LO\n");
2694			goto fail;
2695		}
2696		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2697		bwn_lo_write(mac, &cal->ctl);
2698	}
2699
2700fail:
2701	bwn_mac_enable(mac);
2702}
2703
2704static void
2705bwn_phy_g_task_60s(struct bwn_mac *mac)
2706{
2707	struct bwn_phy *phy = &mac->mac_phy;
2708	struct bwn_softc *sc = mac->mac_sc;
2709	uint8_t old = phy->chan;
2710
2711	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2712		return;
2713
2714	bwn_mac_suspend(mac);
2715	bwn_nrssi_slope_11g(mac);
2716	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2717		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2718		bwn_switch_channel(mac, old);
2719	}
2720	bwn_mac_enable(mac);
2721}
2722
2723static void
2724bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2725{
2726
2727	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2728}
2729
2730static int
2731bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2732	const struct ieee80211_bpf_params *params)
2733{
2734	struct ieee80211com *ic = ni->ni_ic;
2735	struct ifnet *ifp = ic->ic_ifp;
2736	struct bwn_softc *sc = ifp->if_softc;
2737	struct bwn_mac *mac = sc->sc_curmac;
2738
2739	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2740	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2741		ieee80211_free_node(ni);
2742		m_freem(m);
2743		return (ENETDOWN);
2744	}
2745
2746	BWN_LOCK(sc);
2747	if (bwn_tx_isfull(sc, m)) {
2748		ieee80211_free_node(ni);
2749		m_freem(m);
2750		ifp->if_oerrors++;
2751		BWN_UNLOCK(sc);
2752		return (ENOBUFS);
2753	}
2754
2755	if (bwn_tx_start(sc, ni, m) != 0) {
2756		if (ni != NULL)
2757			ieee80211_free_node(ni);
2758		ifp->if_oerrors++;
2759	}
2760	sc->sc_watchdog_timer = 5;
2761	BWN_UNLOCK(sc);
2762	return (0);
2763}
2764
2765/*
2766 * Callback from the 802.11 layer to update the slot time
2767 * based on the current setting.  We use it to notify the
2768 * firmware of ERP changes and the f/w takes care of things
2769 * like slot time and preamble.
2770 */
2771static void
2772bwn_updateslot(struct ifnet *ifp)
2773{
2774	struct bwn_softc *sc = ifp->if_softc;
2775	struct ieee80211com *ic = ifp->if_l2com;
2776	struct bwn_mac *mac;
2777
2778	BWN_LOCK(sc);
2779	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2780		mac = (struct bwn_mac *)sc->sc_curmac;
2781		bwn_set_slot_time(mac,
2782		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2783	}
2784	BWN_UNLOCK(sc);
2785}
2786
2787/*
2788 * Callback from the 802.11 layer after a promiscuous mode change.
2789 * Note this interface does not check the operating mode as this
2790 * is an internal callback and we are expected to honor the current
2791 * state (e.g. this is used for setting the interface in promiscuous
2792 * mode when operating in hostap mode to do ACS).
2793 */
2794static void
2795bwn_update_promisc(struct ifnet *ifp)
2796{
2797	struct bwn_softc *sc = ifp->if_softc;
2798	struct bwn_mac *mac = sc->sc_curmac;
2799
2800	BWN_LOCK(sc);
2801	mac = sc->sc_curmac;
2802	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2803		if (ifp->if_flags & IFF_PROMISC)
2804			sc->sc_filters |= BWN_MACCTL_PROMISC;
2805		else
2806			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2807		bwn_set_opmode(mac);
2808	}
2809	BWN_UNLOCK(sc);
2810}
2811
2812/*
2813 * Callback from the 802.11 layer to update WME parameters.
2814 */
2815static int
2816bwn_wme_update(struct ieee80211com *ic)
2817{
2818	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2819	struct bwn_mac *mac = sc->sc_curmac;
2820	struct wmeParams *wmep;
2821	int i;
2822
2823	BWN_LOCK(sc);
2824	mac = sc->sc_curmac;
2825	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826		bwn_mac_suspend(mac);
2827		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2828			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2829			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2830		}
2831		bwn_mac_enable(mac);
2832	}
2833	BWN_UNLOCK(sc);
2834	return (0);
2835}
2836
2837static void
2838bwn_scan_start(struct ieee80211com *ic)
2839{
2840	struct ifnet *ifp = ic->ic_ifp;
2841	struct bwn_softc *sc = ifp->if_softc;
2842	struct bwn_mac *mac;
2843
2844	BWN_LOCK(sc);
2845	mac = sc->sc_curmac;
2846	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2848		bwn_set_opmode(mac);
2849		/* disable CFP update during scan */
2850		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2851	}
2852	BWN_UNLOCK(sc);
2853}
2854
2855static void
2856bwn_scan_end(struct ieee80211com *ic)
2857{
2858	struct ifnet *ifp = ic->ic_ifp;
2859	struct bwn_softc *sc = ifp->if_softc;
2860	struct bwn_mac *mac;
2861
2862	BWN_LOCK(sc);
2863	mac = sc->sc_curmac;
2864	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2865		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2866		bwn_set_opmode(mac);
2867		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2868	}
2869	BWN_UNLOCK(sc);
2870}
2871
2872static void
2873bwn_set_channel(struct ieee80211com *ic)
2874{
2875	struct ifnet *ifp = ic->ic_ifp;
2876	struct bwn_softc *sc = ifp->if_softc;
2877	struct bwn_mac *mac = sc->sc_curmac;
2878	struct bwn_phy *phy = &mac->mac_phy;
2879	int chan, error;
2880
2881	BWN_LOCK(sc);
2882
2883	error = bwn_switch_band(sc, ic->ic_curchan);
2884	if (error)
2885		goto fail;;
2886	bwn_mac_suspend(mac);
2887	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2888	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2889	if (chan != phy->chan)
2890		bwn_switch_channel(mac, chan);
2891
2892	/* TX power level */
2893	if (ic->ic_curchan->ic_maxpower != 0 &&
2894	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2895		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2896		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2897		    BWN_TXPWR_IGNORE_TSSI);
2898	}
2899
2900	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2901	if (phy->set_antenna)
2902		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2903
2904	if (sc->sc_rf_enabled != phy->rf_on) {
2905		if (sc->sc_rf_enabled) {
2906			bwn_rf_turnon(mac);
2907			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2908				device_printf(sc->sc_dev,
2909				    "please turn on the RF switch\n");
2910		} else
2911			bwn_rf_turnoff(mac);
2912	}
2913
2914	bwn_mac_enable(mac);
2915
2916fail:
2917	/*
2918	 * Setup radio tap channel freq and flags
2919	 */
2920	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2921		htole16(ic->ic_curchan->ic_freq);
2922	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2923		htole16(ic->ic_curchan->ic_flags & 0xffff);
2924
2925	BWN_UNLOCK(sc);
2926}
2927
2928static struct ieee80211vap *
2929bwn_vap_create(struct ieee80211com *ic,
2930	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2931	const uint8_t bssid[IEEE80211_ADDR_LEN],
2932	const uint8_t mac0[IEEE80211_ADDR_LEN])
2933{
2934	struct ifnet *ifp = ic->ic_ifp;
2935	struct bwn_softc *sc = ifp->if_softc;
2936	struct ieee80211vap *vap;
2937	struct bwn_vap *bvp;
2938	uint8_t mac[IEEE80211_ADDR_LEN];
2939
2940	IEEE80211_ADDR_COPY(mac, mac0);
2941	switch (opmode) {
2942	case IEEE80211_M_HOSTAP:
2943	case IEEE80211_M_MBSS:
2944	case IEEE80211_M_STA:
2945	case IEEE80211_M_WDS:
2946	case IEEE80211_M_MONITOR:
2947	case IEEE80211_M_IBSS:
2948	case IEEE80211_M_AHDEMO:
2949		break;
2950	default:
2951		return (NULL);
2952	}
2953
2954	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2955
2956	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2957	    M_80211_VAP, M_NOWAIT | M_ZERO);
2958	if (bvp == NULL) {
2959		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2960		return (NULL);
2961	}
2962	vap = &bvp->bv_vap;
2963	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2964	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2965	/* override with driver methods */
2966	bvp->bv_newstate = vap->iv_newstate;
2967	vap->iv_newstate = bwn_newstate;
2968
2969	/* override max aid so sta's cannot assoc when we're out of sta id's */
2970	vap->iv_max_aid = BWN_STAID_MAX;
2971
2972	ieee80211_ratectl_init(vap);
2973
2974	/* complete setup */
2975	ieee80211_vap_attach(vap, ieee80211_media_change,
2976	    ieee80211_media_status);
2977	return (vap);
2978}
2979
2980static void
2981bwn_vap_delete(struct ieee80211vap *vap)
2982{
2983	struct bwn_vap *bvp = BWN_VAP(vap);
2984
2985	ieee80211_ratectl_deinit(vap);
2986	ieee80211_vap_detach(vap);
2987	free(bvp, M_80211_VAP);
2988}
2989
2990static void
2991bwn_init(void *arg)
2992{
2993	struct bwn_softc *sc = arg;
2994	struct ifnet *ifp = sc->sc_ifp;
2995	struct ieee80211com *ic = ifp->if_l2com;
2996	int error = 0;
2997
2998	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2999		__func__, ifp->if_flags);
3000
3001	BWN_LOCK(sc);
3002	error = bwn_init_locked(sc);
3003	BWN_UNLOCK(sc);
3004
3005	if (error == 0)
3006		ieee80211_start_all(ic);	/* start all vap's */
3007}
3008
3009static int
3010bwn_init_locked(struct bwn_softc *sc)
3011{
3012	struct bwn_mac *mac;
3013	struct ifnet *ifp = sc->sc_ifp;
3014	int error;
3015
3016	BWN_ASSERT_LOCKED(sc);
3017
3018	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3019	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3020	sc->sc_filters = 0;
3021	bwn_wme_clear(sc);
3022	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3023	sc->sc_rf_enabled = 1;
3024
3025	mac = sc->sc_curmac;
3026	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3027		error = bwn_core_init(mac);
3028		if (error != 0)
3029			return (error);
3030	}
3031	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3032		bwn_core_start(mac);
3033
3034	bwn_set_opmode(mac);
3035	bwn_set_pretbtt(mac);
3036	bwn_spu_setdelay(mac, 0);
3037	bwn_set_macaddr(mac);
3038
3039	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3040	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3041	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3042
3043	return (0);
3044}
3045
3046static void
3047bwn_stop(struct bwn_softc *sc, int statechg)
3048{
3049
3050	BWN_LOCK(sc);
3051	bwn_stop_locked(sc, statechg);
3052	BWN_UNLOCK(sc);
3053}
3054
3055static void
3056bwn_stop_locked(struct bwn_softc *sc, int statechg)
3057{
3058	struct bwn_mac *mac = sc->sc_curmac;
3059	struct ifnet *ifp = sc->sc_ifp;
3060
3061	BWN_ASSERT_LOCKED(sc);
3062
3063	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3064		/* XXX FIXME opmode not based on VAP */
3065		bwn_set_opmode(mac);
3066		bwn_set_macaddr(mac);
3067	}
3068
3069	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3070		bwn_core_stop(mac);
3071
3072	callout_stop(&sc->sc_led_blink_ch);
3073	sc->sc_led_blinking = 0;
3074
3075	bwn_core_exit(mac);
3076	sc->sc_rf_enabled = 0;
3077
3078	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3079}
3080
3081static void
3082bwn_wme_clear(struct bwn_softc *sc)
3083{
3084#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3085	struct wmeParams *p;
3086	unsigned int i;
3087
3088	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3089	    ("%s:%d: fail", __func__, __LINE__));
3090
3091	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3092		p = &(sc->sc_wmeParams[i]);
3093
3094		switch (bwn_wme_shm_offsets[i]) {
3095		case BWN_WME_VOICE:
3096			p->wmep_txopLimit = 0;
3097			p->wmep_aifsn = 2;
3098			/* XXX FIXME: log2(cwmin) */
3099			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3100			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3101			break;
3102		case BWN_WME_VIDEO:
3103			p->wmep_txopLimit = 0;
3104			p->wmep_aifsn = 2;
3105			/* XXX FIXME: log2(cwmin) */
3106			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3107			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3108			break;
3109		case BWN_WME_BESTEFFORT:
3110			p->wmep_txopLimit = 0;
3111			p->wmep_aifsn = 3;
3112			/* XXX FIXME: log2(cwmin) */
3113			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3114			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3115			break;
3116		case BWN_WME_BACKGROUND:
3117			p->wmep_txopLimit = 0;
3118			p->wmep_aifsn = 7;
3119			/* XXX FIXME: log2(cwmin) */
3120			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3121			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3122			break;
3123		default:
3124			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3125		}
3126	}
3127}
3128
3129static int
3130bwn_core_init(struct bwn_mac *mac)
3131{
3132	struct bwn_softc *sc = mac->mac_sc;
3133	uint64_t hf;
3134	int error;
3135
3136	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3137	    ("%s:%d: fail", __func__, __LINE__));
3138
3139	siba_powerup(sc->sc_dev, 0);
3140	if (!siba_dev_isup(sc->sc_dev))
3141		bwn_reset_core(mac,
3142		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3143
3144	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3145	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3146	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3147	BWN_GETTIME(mac->mac_phy.nexttime);
3148	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3149	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3150	mac->mac_stats.link_noise = -95;
3151	mac->mac_reason_intr = 0;
3152	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3153	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3154#ifdef BWN_DEBUG
3155	if (sc->sc_debug & BWN_DEBUG_XMIT)
3156		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3157#endif
3158	mac->mac_suspended = 1;
3159	mac->mac_task_state = 0;
3160	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3161
3162	mac->mac_phy.init_pre(mac);
3163
3164	siba_pcicore_intr(sc->sc_dev);
3165
3166	siba_fix_imcfglobug(sc->sc_dev);
3167	bwn_bt_disable(mac);
3168	if (mac->mac_phy.prepare_hw) {
3169		error = mac->mac_phy.prepare_hw(mac);
3170		if (error)
3171			goto fail0;
3172	}
3173	error = bwn_chip_init(mac);
3174	if (error)
3175		goto fail0;
3176	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3177	    siba_get_revid(sc->sc_dev));
3178	hf = bwn_hf_read(mac);
3179	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3180		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3181		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3182			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3183		if (mac->mac_phy.rev == 1)
3184			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3185	}
3186	if (mac->mac_phy.rf_ver == 0x2050) {
3187		if (mac->mac_phy.rf_rev < 6)
3188			hf |= BWN_HF_FORCE_VCO_RECALC;
3189		if (mac->mac_phy.rf_rev == 6)
3190			hf |= BWN_HF_4318_TSSI;
3191	}
3192	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3193		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3194	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3195	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3196		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3197	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3198	bwn_hf_write(mac, hf);
3199
3200	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3201	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3202	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3203	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3204
3205	bwn_rate_init(mac);
3206	bwn_set_phytxctl(mac);
3207
3208	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3209	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3210	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3211
3212	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3213		bwn_pio_init(mac);
3214	else
3215		bwn_dma_init(mac);
3216	if (error)
3217		goto fail1;
3218	bwn_wme_init(mac);
3219	bwn_spu_setdelay(mac, 1);
3220	bwn_bt_enable(mac);
3221
3222	siba_powerup(sc->sc_dev,
3223	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3224	bwn_set_macaddr(mac);
3225	bwn_crypt_init(mac);
3226
3227	/* XXX LED initializatin */
3228
3229	mac->mac_status = BWN_MAC_STATUS_INITED;
3230
3231	return (error);
3232
3233fail1:
3234	bwn_chip_exit(mac);
3235fail0:
3236	siba_powerdown(sc->sc_dev);
3237	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3238	    ("%s:%d: fail", __func__, __LINE__));
3239	return (error);
3240}
3241
3242static void
3243bwn_core_start(struct bwn_mac *mac)
3244{
3245	struct bwn_softc *sc = mac->mac_sc;
3246	uint32_t tmp;
3247
3248	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3249	    ("%s:%d: fail", __func__, __LINE__));
3250
3251	if (siba_get_revid(sc->sc_dev) < 5)
3252		return;
3253
3254	while (1) {
3255		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3256		if (!(tmp & 0x00000001))
3257			break;
3258		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3259	}
3260
3261	bwn_mac_enable(mac);
3262	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3263	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3264
3265	mac->mac_status = BWN_MAC_STATUS_STARTED;
3266}
3267
3268static void
3269bwn_core_exit(struct bwn_mac *mac)
3270{
3271	struct bwn_softc *sc = mac->mac_sc;
3272	uint32_t macctl;
3273
3274	BWN_ASSERT_LOCKED(mac->mac_sc);
3275
3276	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3277	    ("%s:%d: fail", __func__, __LINE__));
3278
3279	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3280		return;
3281	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3282
3283	macctl = BWN_READ_4(mac, BWN_MACCTL);
3284	macctl &= ~BWN_MACCTL_MCODE_RUN;
3285	macctl |= BWN_MACCTL_MCODE_JMP0;
3286	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3287
3288	bwn_dma_stop(mac);
3289	bwn_pio_stop(mac);
3290	bwn_chip_exit(mac);
3291	mac->mac_phy.switch_analog(mac, 0);
3292	siba_dev_down(sc->sc_dev, 0);
3293	siba_powerdown(sc->sc_dev);
3294}
3295
3296static void
3297bwn_bt_disable(struct bwn_mac *mac)
3298{
3299	struct bwn_softc *sc = mac->mac_sc;
3300
3301	(void)sc;
3302	/* XXX do nothing yet */
3303}
3304
3305static int
3306bwn_chip_init(struct bwn_mac *mac)
3307{
3308	struct bwn_softc *sc = mac->mac_sc;
3309	struct bwn_phy *phy = &mac->mac_phy;
3310	uint32_t macctl;
3311	int error;
3312
3313	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3314	if (phy->gmode)
3315		macctl |= BWN_MACCTL_GMODE;
3316	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3317
3318	error = bwn_fw_fillinfo(mac);
3319	if (error)
3320		return (error);
3321	error = bwn_fw_loaducode(mac);
3322	if (error)
3323		return (error);
3324
3325	error = bwn_gpio_init(mac);
3326	if (error)
3327		return (error);
3328
3329	error = bwn_fw_loadinitvals(mac);
3330	if (error) {
3331		siba_gpio_set(sc->sc_dev, 0);
3332		return (error);
3333	}
3334	phy->switch_analog(mac, 1);
3335	error = bwn_phy_init(mac);
3336	if (error) {
3337		siba_gpio_set(sc->sc_dev, 0);
3338		return (error);
3339	}
3340	if (phy->set_im)
3341		phy->set_im(mac, BWN_IMMODE_NONE);
3342	if (phy->set_antenna)
3343		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3344	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3345
3346	if (phy->type == BWN_PHYTYPE_B)
3347		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3348	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3349	if (siba_get_revid(sc->sc_dev) < 5)
3350		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3351
3352	BWN_WRITE_4(mac, BWN_MACCTL,
3353	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3354	BWN_WRITE_4(mac, BWN_MACCTL,
3355	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3356	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3357
3358	bwn_set_opmode(mac);
3359	if (siba_get_revid(sc->sc_dev) < 3) {
3360		BWN_WRITE_2(mac, 0x060e, 0x0000);
3361		BWN_WRITE_2(mac, 0x0610, 0x8000);
3362		BWN_WRITE_2(mac, 0x0604, 0x0000);
3363		BWN_WRITE_2(mac, 0x0606, 0x0200);
3364	} else {
3365		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3366		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3367	}
3368	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3369	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3370	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3371	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3372	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3373	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3374	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3375	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3376	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3377	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3378	return (error);
3379}
3380
3381/* read hostflags */
3382static uint64_t
3383bwn_hf_read(struct bwn_mac *mac)
3384{
3385	uint64_t ret;
3386
3387	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3388	ret <<= 16;
3389	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3390	ret <<= 16;
3391	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3392	return (ret);
3393}
3394
3395static void
3396bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3397{
3398
3399	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3400	    (value & 0x00000000ffffull));
3401	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3402	    (value & 0x0000ffff0000ull) >> 16);
3403	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3404	    (value & 0xffff00000000ULL) >> 32);
3405}
3406
3407static void
3408bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3409{
3410
3411	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3412	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3413}
3414
3415static void
3416bwn_rate_init(struct bwn_mac *mac)
3417{
3418
3419	switch (mac->mac_phy.type) {
3420	case BWN_PHYTYPE_A:
3421	case BWN_PHYTYPE_G:
3422	case BWN_PHYTYPE_LP:
3423	case BWN_PHYTYPE_N:
3424		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3425		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3426		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3427		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3428		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3429		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3430		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3431		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3432			break;
3433		/* FALLTHROUGH */
3434	case BWN_PHYTYPE_B:
3435		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3436		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3437		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3438		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3439		break;
3440	default:
3441		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3442	}
3443}
3444
3445static void
3446bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3447{
3448	uint16_t offset;
3449
3450	if (ofdm) {
3451		offset = 0x480;
3452		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3453	} else {
3454		offset = 0x4c0;
3455		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3456	}
3457	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3458	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3459}
3460
3461static uint8_t
3462bwn_plcp_getcck(const uint8_t bitrate)
3463{
3464
3465	switch (bitrate) {
3466	case BWN_CCK_RATE_1MB:
3467		return (0x0a);
3468	case BWN_CCK_RATE_2MB:
3469		return (0x14);
3470	case BWN_CCK_RATE_5MB:
3471		return (0x37);
3472	case BWN_CCK_RATE_11MB:
3473		return (0x6e);
3474	}
3475	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3476	return (0);
3477}
3478
3479static uint8_t
3480bwn_plcp_getofdm(const uint8_t bitrate)
3481{
3482
3483	switch (bitrate) {
3484	case BWN_OFDM_RATE_6MB:
3485		return (0xb);
3486	case BWN_OFDM_RATE_9MB:
3487		return (0xf);
3488	case BWN_OFDM_RATE_12MB:
3489		return (0xa);
3490	case BWN_OFDM_RATE_18MB:
3491		return (0xe);
3492	case BWN_OFDM_RATE_24MB:
3493		return (0x9);
3494	case BWN_OFDM_RATE_36MB:
3495		return (0xd);
3496	case BWN_OFDM_RATE_48MB:
3497		return (0x8);
3498	case BWN_OFDM_RATE_54MB:
3499		return (0xc);
3500	}
3501	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3502	return (0);
3503}
3504
3505static void
3506bwn_set_phytxctl(struct bwn_mac *mac)
3507{
3508	uint16_t ctl;
3509
3510	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3511	    BWN_TX_PHY_TXPWR);
3512	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3513	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3514	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3515}
3516
3517static void
3518bwn_pio_init(struct bwn_mac *mac)
3519{
3520	struct bwn_pio *pio = &mac->mac_method.pio;
3521
3522	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3523	    & ~BWN_MACCTL_BIGENDIAN);
3524	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3525
3526	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3527	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3528	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3529	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3530	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3531	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3532}
3533
3534static void
3535bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3536    int index)
3537{
3538	struct bwn_pio_txpkt *tp;
3539	struct bwn_softc *sc = mac->mac_sc;
3540	unsigned int i;
3541
3542	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3543	tq->tq_index = index;
3544
3545	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3546	if (siba_get_revid(sc->sc_dev) >= 8)
3547		tq->tq_size = 1920;
3548	else {
3549		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3550		tq->tq_size -= 80;
3551	}
3552
3553	TAILQ_INIT(&tq->tq_pktlist);
3554	for (i = 0; i < N(tq->tq_pkts); i++) {
3555		tp = &(tq->tq_pkts[i]);
3556		tp->tp_index = i;
3557		tp->tp_queue = tq;
3558		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3559	}
3560}
3561
3562static uint16_t
3563bwn_pio_idx2base(struct bwn_mac *mac, int index)
3564{
3565	struct bwn_softc *sc = mac->mac_sc;
3566	static const uint16_t bases[] = {
3567		BWN_PIO_BASE0,
3568		BWN_PIO_BASE1,
3569		BWN_PIO_BASE2,
3570		BWN_PIO_BASE3,
3571		BWN_PIO_BASE4,
3572		BWN_PIO_BASE5,
3573		BWN_PIO_BASE6,
3574		BWN_PIO_BASE7,
3575	};
3576	static const uint16_t bases_rev11[] = {
3577		BWN_PIO11_BASE0,
3578		BWN_PIO11_BASE1,
3579		BWN_PIO11_BASE2,
3580		BWN_PIO11_BASE3,
3581		BWN_PIO11_BASE4,
3582		BWN_PIO11_BASE5,
3583	};
3584
3585	if (siba_get_revid(sc->sc_dev) >= 11) {
3586		if (index >= N(bases_rev11))
3587			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3588		return (bases_rev11[index]);
3589	}
3590	if (index >= N(bases))
3591		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3592	return (bases[index]);
3593}
3594
3595static void
3596bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3597    int index)
3598{
3599	struct bwn_softc *sc = mac->mac_sc;
3600
3601	prq->prq_mac = mac;
3602	prq->prq_rev = siba_get_revid(sc->sc_dev);
3603	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3604	bwn_dma_rxdirectfifo(mac, index, 1);
3605}
3606
3607static void
3608bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3609{
3610	if (tq == NULL)
3611		return;
3612	bwn_pio_cancel_tx_packets(tq);
3613}
3614
3615static void
3616bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3617{
3618
3619	bwn_destroy_pioqueue_tx(pio);
3620}
3621
3622static uint16_t
3623bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3624    uint16_t offset)
3625{
3626
3627	return (BWN_READ_2(mac, tq->tq_base + offset));
3628}
3629
3630static void
3631bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3632{
3633	uint32_t ctl;
3634	int type;
3635	uint16_t base;
3636
3637	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3638	base = bwn_dma_base(type, idx);
3639	if (type == BWN_DMA_64BIT) {
3640		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3641		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3642		if (enable)
3643			ctl |= BWN_DMA64_RXDIRECTFIFO;
3644		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3645	} else {
3646		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3647		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3648		if (enable)
3649			ctl |= BWN_DMA32_RXDIRECTFIFO;
3650		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3651	}
3652}
3653
3654static uint64_t
3655bwn_dma_mask(struct bwn_mac *mac)
3656{
3657	uint32_t tmp;
3658	uint16_t base;
3659
3660	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3661	if (tmp & SIBA_TGSHIGH_DMA64)
3662		return (BWN_DMA_BIT_MASK(64));
3663	base = bwn_dma_base(0, 0);
3664	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3665	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3666	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3667		return (BWN_DMA_BIT_MASK(32));
3668
3669	return (BWN_DMA_BIT_MASK(30));
3670}
3671
3672static int
3673bwn_dma_mask2type(uint64_t dmamask)
3674{
3675
3676	if (dmamask == BWN_DMA_BIT_MASK(30))
3677		return (BWN_DMA_30BIT);
3678	if (dmamask == BWN_DMA_BIT_MASK(32))
3679		return (BWN_DMA_32BIT);
3680	if (dmamask == BWN_DMA_BIT_MASK(64))
3681		return (BWN_DMA_64BIT);
3682	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3683	return (BWN_DMA_30BIT);
3684}
3685
3686static void
3687bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3688{
3689	struct bwn_pio_txpkt *tp;
3690	unsigned int i;
3691
3692	for (i = 0; i < N(tq->tq_pkts); i++) {
3693		tp = &(tq->tq_pkts[i]);
3694		if (tp->tp_m) {
3695			m_freem(tp->tp_m);
3696			tp->tp_m = NULL;
3697		}
3698	}
3699}
3700
3701static uint16_t
3702bwn_dma_base(int type, int controller_idx)
3703{
3704	static const uint16_t map64[] = {
3705		BWN_DMA64_BASE0,
3706		BWN_DMA64_BASE1,
3707		BWN_DMA64_BASE2,
3708		BWN_DMA64_BASE3,
3709		BWN_DMA64_BASE4,
3710		BWN_DMA64_BASE5,
3711	};
3712	static const uint16_t map32[] = {
3713		BWN_DMA32_BASE0,
3714		BWN_DMA32_BASE1,
3715		BWN_DMA32_BASE2,
3716		BWN_DMA32_BASE3,
3717		BWN_DMA32_BASE4,
3718		BWN_DMA32_BASE5,
3719	};
3720
3721	if (type == BWN_DMA_64BIT) {
3722		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3723		    ("%s:%d: fail", __func__, __LINE__));
3724		return (map64[controller_idx]);
3725	}
3726	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3727	    ("%s:%d: fail", __func__, __LINE__));
3728	return (map32[controller_idx]);
3729}
3730
3731static void
3732bwn_dma_init(struct bwn_mac *mac)
3733{
3734	struct bwn_dma *dma = &mac->mac_method.dma;
3735
3736	/* setup TX DMA channels. */
3737	bwn_dma_setup(dma->wme[WME_AC_BK]);
3738	bwn_dma_setup(dma->wme[WME_AC_BE]);
3739	bwn_dma_setup(dma->wme[WME_AC_VI]);
3740	bwn_dma_setup(dma->wme[WME_AC_VO]);
3741	bwn_dma_setup(dma->mcast);
3742	/* setup RX DMA channel. */
3743	bwn_dma_setup(dma->rx);
3744}
3745
3746static struct bwn_dma_ring *
3747bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3748    int for_tx, int type)
3749{
3750	struct bwn_dma *dma = &mac->mac_method.dma;
3751	struct bwn_dma_ring *dr;
3752	struct bwn_dmadesc_generic *desc;
3753	struct bwn_dmadesc_meta *mt;
3754	struct bwn_softc *sc = mac->mac_sc;
3755	int error, i;
3756
3757	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3758	if (dr == NULL)
3759		goto out;
3760	dr->dr_numslots = BWN_RXRING_SLOTS;
3761	if (for_tx)
3762		dr->dr_numslots = BWN_TXRING_SLOTS;
3763
3764	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3765	    M_DEVBUF, M_NOWAIT | M_ZERO);
3766	if (dr->dr_meta == NULL)
3767		goto fail0;
3768
3769	dr->dr_type = type;
3770	dr->dr_mac = mac;
3771	dr->dr_base = bwn_dma_base(type, controller_index);
3772	dr->dr_index = controller_index;
3773	if (type == BWN_DMA_64BIT) {
3774		dr->getdesc = bwn_dma_64_getdesc;
3775		dr->setdesc = bwn_dma_64_setdesc;
3776		dr->start_transfer = bwn_dma_64_start_transfer;
3777		dr->suspend = bwn_dma_64_suspend;
3778		dr->resume = bwn_dma_64_resume;
3779		dr->get_curslot = bwn_dma_64_get_curslot;
3780		dr->set_curslot = bwn_dma_64_set_curslot;
3781	} else {
3782		dr->getdesc = bwn_dma_32_getdesc;
3783		dr->setdesc = bwn_dma_32_setdesc;
3784		dr->start_transfer = bwn_dma_32_start_transfer;
3785		dr->suspend = bwn_dma_32_suspend;
3786		dr->resume = bwn_dma_32_resume;
3787		dr->get_curslot = bwn_dma_32_get_curslot;
3788		dr->set_curslot = bwn_dma_32_set_curslot;
3789	}
3790	if (for_tx) {
3791		dr->dr_tx = 1;
3792		dr->dr_curslot = -1;
3793	} else {
3794		if (dr->dr_index == 0) {
3795			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3796			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3797		} else
3798			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3799	}
3800
3801	error = bwn_dma_allocringmemory(dr);
3802	if (error)
3803		goto fail2;
3804
3805	if (for_tx) {
3806		/*
3807		 * Assumption: BWN_TXRING_SLOTS can be divided by
3808		 * BWN_TX_SLOTS_PER_FRAME
3809		 */
3810		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3811		    ("%s:%d: fail", __func__, __LINE__));
3812
3813		dr->dr_txhdr_cache =
3814		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3815			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3816		KASSERT(dr->dr_txhdr_cache != NULL,
3817		    ("%s:%d: fail", __func__, __LINE__));
3818
3819		/*
3820		 * Create TX ring DMA stuffs
3821		 */
3822		error = bus_dma_tag_create(dma->parent_dtag,
3823				    BWN_ALIGN, 0,
3824				    BUS_SPACE_MAXADDR,
3825				    BUS_SPACE_MAXADDR,
3826				    NULL, NULL,
3827				    BWN_HDRSIZE(mac),
3828				    1,
3829				    BUS_SPACE_MAXSIZE_32BIT,
3830				    0,
3831				    NULL, NULL,
3832				    &dr->dr_txring_dtag);
3833		if (error) {
3834			device_printf(sc->sc_dev,
3835			    "can't create TX ring DMA tag: TODO frees\n");
3836			goto fail1;
3837		}
3838
3839		for (i = 0; i < dr->dr_numslots; i += 2) {
3840			dr->getdesc(dr, i, &desc, &mt);
3841
3842			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3843			mt->mt_m = NULL;
3844			mt->mt_ni = NULL;
3845			mt->mt_islast = 0;
3846			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3847			    &mt->mt_dmap);
3848			if (error) {
3849				device_printf(sc->sc_dev,
3850				     "can't create RX buf DMA map\n");
3851				goto fail1;
3852			}
3853
3854			dr->getdesc(dr, i + 1, &desc, &mt);
3855
3856			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3857			mt->mt_m = NULL;
3858			mt->mt_ni = NULL;
3859			mt->mt_islast = 1;
3860			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3861			    &mt->mt_dmap);
3862			if (error) {
3863				device_printf(sc->sc_dev,
3864				     "can't create RX buf DMA map\n");
3865				goto fail1;
3866			}
3867		}
3868	} else {
3869		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3870		    &dr->dr_spare_dmap);
3871		if (error) {
3872			device_printf(sc->sc_dev,
3873			    "can't create RX buf DMA map\n");
3874			goto out;		/* XXX wrong! */
3875		}
3876
3877		for (i = 0; i < dr->dr_numslots; i++) {
3878			dr->getdesc(dr, i, &desc, &mt);
3879
3880			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3881			    &mt->mt_dmap);
3882			if (error) {
3883				device_printf(sc->sc_dev,
3884				    "can't create RX buf DMA map\n");
3885				goto out;	/* XXX wrong! */
3886			}
3887			error = bwn_dma_newbuf(dr, desc, mt, 1);
3888			if (error) {
3889				device_printf(sc->sc_dev,
3890				    "failed to allocate RX buf\n");
3891				goto out;	/* XXX wrong! */
3892			}
3893		}
3894
3895		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3896		    BUS_DMASYNC_PREWRITE);
3897
3898		dr->dr_usedslot = dr->dr_numslots;
3899	}
3900
3901      out:
3902	return (dr);
3903
3904fail2:
3905	free(dr->dr_txhdr_cache, M_DEVBUF);
3906fail1:
3907	free(dr->dr_meta, M_DEVBUF);
3908fail0:
3909	free(dr, M_DEVBUF);
3910	return (NULL);
3911}
3912
3913static void
3914bwn_dma_ringfree(struct bwn_dma_ring **dr)
3915{
3916
3917	if (dr == NULL)
3918		return;
3919
3920	bwn_dma_free_descbufs(*dr);
3921	bwn_dma_free_ringmemory(*dr);
3922
3923	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3924	free((*dr)->dr_meta, M_DEVBUF);
3925	free(*dr, M_DEVBUF);
3926
3927	*dr = NULL;
3928}
3929
3930static void
3931bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3932    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3933{
3934	struct bwn_dmadesc32 *desc;
3935
3936	*meta = &(dr->dr_meta[slot]);
3937	desc = dr->dr_ring_descbase;
3938	desc = &(desc[slot]);
3939
3940	*gdesc = (struct bwn_dmadesc_generic *)desc;
3941}
3942
3943static void
3944bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3945    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3946    int start, int end, int irq)
3947{
3948	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3949	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3950	uint32_t addr, addrext, ctl;
3951	int slot;
3952
3953	slot = (int)(&(desc->dma.dma32) - descbase);
3954	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3955	    ("%s:%d: fail", __func__, __LINE__));
3956
3957	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3958	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3959	addr |= siba_dma_translation(sc->sc_dev);
3960	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3961	if (slot == dr->dr_numslots - 1)
3962		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3963	if (start)
3964		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3965	if (end)
3966		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3967	if (irq)
3968		ctl |= BWN_DMA32_DCTL_IRQ;
3969	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3970	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3971
3972	desc->dma.dma32.control = htole32(ctl);
3973	desc->dma.dma32.address = htole32(addr);
3974}
3975
3976static void
3977bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3978{
3979
3980	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3981	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3982}
3983
3984static void
3985bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3986{
3987
3988	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3989	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3990}
3991
3992static void
3993bwn_dma_32_resume(struct bwn_dma_ring *dr)
3994{
3995
3996	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3997	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3998}
3999
4000static int
4001bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4002{
4003	uint32_t val;
4004
4005	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4006	val &= BWN_DMA32_RXDPTR;
4007
4008	return (val / sizeof(struct bwn_dmadesc32));
4009}
4010
4011static void
4012bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4013{
4014
4015	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4016	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4017}
4018
4019static void
4020bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4021    struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4022{
4023	struct bwn_dmadesc64 *desc;
4024
4025	*meta = &(dr->dr_meta[slot]);
4026	desc = dr->dr_ring_descbase;
4027	desc = &(desc[slot]);
4028
4029	*gdesc = (struct bwn_dmadesc_generic *)desc;
4030}
4031
4032static void
4033bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4034    struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4035    int start, int end, int irq)
4036{
4037	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4038	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4039	int slot;
4040	uint32_t ctl0 = 0, ctl1 = 0;
4041	uint32_t addrlo, addrhi;
4042	uint32_t addrext;
4043
4044	slot = (int)(&(desc->dma.dma64) - descbase);
4045	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4046	    ("%s:%d: fail", __func__, __LINE__));
4047
4048	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4049	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4050	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4051	    30;
4052	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4053	if (slot == dr->dr_numslots - 1)
4054		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4055	if (start)
4056		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4057	if (end)
4058		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4059	if (irq)
4060		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4061	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4062	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4063	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4064
4065	desc->dma.dma64.control0 = htole32(ctl0);
4066	desc->dma.dma64.control1 = htole32(ctl1);
4067	desc->dma.dma64.address_low = htole32(addrlo);
4068	desc->dma.dma64.address_high = htole32(addrhi);
4069}
4070
4071static void
4072bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4073{
4074
4075	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4076	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4077}
4078
4079static void
4080bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4081{
4082
4083	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4084	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4085}
4086
4087static void
4088bwn_dma_64_resume(struct bwn_dma_ring *dr)
4089{
4090
4091	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4092	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4093}
4094
4095static int
4096bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4097{
4098	uint32_t val;
4099
4100	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4101	val &= BWN_DMA64_RXSTATDPTR;
4102
4103	return (val / sizeof(struct bwn_dmadesc64));
4104}
4105
4106static void
4107bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4108{
4109
4110	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4111	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4112}
4113
4114static int
4115bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4116{
4117	struct bwn_mac *mac = dr->dr_mac;
4118	struct bwn_dma *dma = &mac->mac_method.dma;
4119	struct bwn_softc *sc = mac->mac_sc;
4120	int error;
4121
4122	error = bus_dma_tag_create(dma->parent_dtag,
4123			    BWN_ALIGN, 0,
4124			    BUS_SPACE_MAXADDR,
4125			    BUS_SPACE_MAXADDR,
4126			    NULL, NULL,
4127			    BWN_DMA_RINGMEMSIZE,
4128			    1,
4129			    BUS_SPACE_MAXSIZE_32BIT,
4130			    0,
4131			    NULL, NULL,
4132			    &dr->dr_ring_dtag);
4133	if (error) {
4134		device_printf(sc->sc_dev,
4135		    "can't create TX ring DMA tag: TODO frees\n");
4136		return (-1);
4137	}
4138
4139	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4140	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4141	    &dr->dr_ring_dmap);
4142	if (error) {
4143		device_printf(sc->sc_dev,
4144		    "can't allocate DMA mem: TODO frees\n");
4145		return (-1);
4146	}
4147	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4148	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4149	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4150	if (error) {
4151		device_printf(sc->sc_dev,
4152		    "can't load DMA mem: TODO free\n");
4153		return (-1);
4154	}
4155
4156	return (0);
4157}
4158
4159static void
4160bwn_dma_setup(struct bwn_dma_ring *dr)
4161{
4162	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4163	uint64_t ring64;
4164	uint32_t addrext, ring32, value;
4165	uint32_t trans = siba_dma_translation(sc->sc_dev);
4166
4167	if (dr->dr_tx) {
4168		dr->dr_curslot = -1;
4169
4170		if (dr->dr_type == BWN_DMA_64BIT) {
4171			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4172			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4173			    >> 30;
4174			value = BWN_DMA64_TXENABLE;
4175			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4176			    & BWN_DMA64_TXADDREXT_MASK;
4177			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4178			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4179			    (ring64 & 0xffffffff));
4180			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4181			    ((ring64 >> 32) &
4182			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4183		} else {
4184			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4185			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4186			value = BWN_DMA32_TXENABLE;
4187			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4188			    & BWN_DMA32_TXADDREXT_MASK;
4189			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4190			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4191			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4192		}
4193		return;
4194	}
4195
4196	/*
4197	 * set for RX
4198	 */
4199	dr->dr_usedslot = dr->dr_numslots;
4200
4201	if (dr->dr_type == BWN_DMA_64BIT) {
4202		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4203		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4204		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4205		value |= BWN_DMA64_RXENABLE;
4206		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4207		    & BWN_DMA64_RXADDREXT_MASK;
4208		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4209		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4210		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4211		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4212		    | (trans << 1));
4213		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4214		    sizeof(struct bwn_dmadesc64));
4215	} else {
4216		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4217		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4218		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4219		value |= BWN_DMA32_RXENABLE;
4220		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4221		    & BWN_DMA32_RXADDREXT_MASK;
4222		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4223		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4224		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4225		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4226		    sizeof(struct bwn_dmadesc32));
4227	}
4228}
4229
4230static void
4231bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4232{
4233
4234	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4235	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4236	    dr->dr_ring_dmap);
4237}
4238
4239static void
4240bwn_dma_cleanup(struct bwn_dma_ring *dr)
4241{
4242
4243	if (dr->dr_tx) {
4244		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4245		if (dr->dr_type == BWN_DMA_64BIT) {
4246			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4247			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4248		} else
4249			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4250	} else {
4251		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4252		if (dr->dr_type == BWN_DMA_64BIT) {
4253			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4254			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4255		} else
4256			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4257	}
4258}
4259
4260static void
4261bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4262{
4263	struct bwn_dmadesc_generic *desc;
4264	struct bwn_dmadesc_meta *meta;
4265	struct bwn_mac *mac = dr->dr_mac;
4266	struct bwn_dma *dma = &mac->mac_method.dma;
4267	struct bwn_softc *sc = mac->mac_sc;
4268	int i;
4269
4270	if (!dr->dr_usedslot)
4271		return;
4272	for (i = 0; i < dr->dr_numslots; i++) {
4273		dr->getdesc(dr, i, &desc, &meta);
4274
4275		if (meta->mt_m == NULL) {
4276			if (!dr->dr_tx)
4277				device_printf(sc->sc_dev, "%s: not TX?\n",
4278				    __func__);
4279			continue;
4280		}
4281		if (dr->dr_tx) {
4282			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4283				bus_dmamap_unload(dr->dr_txring_dtag,
4284				    meta->mt_dmap);
4285			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4286				bus_dmamap_unload(dma->txbuf_dtag,
4287				    meta->mt_dmap);
4288		} else
4289			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4290		bwn_dma_free_descbuf(dr, meta);
4291	}
4292}
4293
4294static int
4295bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4296    int type)
4297{
4298	struct bwn_softc *sc = mac->mac_sc;
4299	uint32_t value;
4300	int i;
4301	uint16_t offset;
4302
4303	for (i = 0; i < 10; i++) {
4304		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4305		    BWN_DMA32_TXSTATUS;
4306		value = BWN_READ_4(mac, base + offset);
4307		if (type == BWN_DMA_64BIT) {
4308			value &= BWN_DMA64_TXSTAT;
4309			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4310			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4311			    value == BWN_DMA64_TXSTAT_STOPPED)
4312				break;
4313		} else {
4314			value &= BWN_DMA32_TXSTATE;
4315			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4316			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4317			    value == BWN_DMA32_TXSTAT_STOPPED)
4318				break;
4319		}
4320		DELAY(1000);
4321	}
4322	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4323	BWN_WRITE_4(mac, base + offset, 0);
4324	for (i = 0; i < 10; i++) {
4325		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4326						   BWN_DMA32_TXSTATUS;
4327		value = BWN_READ_4(mac, base + offset);
4328		if (type == BWN_DMA_64BIT) {
4329			value &= BWN_DMA64_TXSTAT;
4330			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4331				i = -1;
4332				break;
4333			}
4334		} else {
4335			value &= BWN_DMA32_TXSTATE;
4336			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4337				i = -1;
4338				break;
4339			}
4340		}
4341		DELAY(1000);
4342	}
4343	if (i != -1) {
4344		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4345		return (ENODEV);
4346	}
4347	DELAY(1000);
4348
4349	return (0);
4350}
4351
4352static int
4353bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4354    int type)
4355{
4356	struct bwn_softc *sc = mac->mac_sc;
4357	uint32_t value;
4358	int i;
4359	uint16_t offset;
4360
4361	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4362	BWN_WRITE_4(mac, base + offset, 0);
4363	for (i = 0; i < 10; i++) {
4364		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4365		    BWN_DMA32_RXSTATUS;
4366		value = BWN_READ_4(mac, base + offset);
4367		if (type == BWN_DMA_64BIT) {
4368			value &= BWN_DMA64_RXSTAT;
4369			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4370				i = -1;
4371				break;
4372			}
4373		} else {
4374			value &= BWN_DMA32_RXSTATE;
4375			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4376				i = -1;
4377				break;
4378			}
4379		}
4380		DELAY(1000);
4381	}
4382	if (i != -1) {
4383		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4384		return (ENODEV);
4385	}
4386
4387	return (0);
4388}
4389
4390static void
4391bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4392    struct bwn_dmadesc_meta *meta)
4393{
4394
4395	if (meta->mt_m != NULL) {
4396		m_freem(meta->mt_m);
4397		meta->mt_m = NULL;
4398	}
4399	if (meta->mt_ni != NULL) {
4400		ieee80211_free_node(meta->mt_ni);
4401		meta->mt_ni = NULL;
4402	}
4403}
4404
4405static void
4406bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4407{
4408	struct bwn_rxhdr4 *rxhdr;
4409	unsigned char *frame;
4410
4411	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4412	rxhdr->frame_len = 0;
4413
4414	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4415	    sizeof(struct bwn_plcp6) + 2,
4416	    ("%s:%d: fail", __func__, __LINE__));
4417	frame = mtod(m, char *) + dr->dr_frameoffset;
4418	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4419}
4420
4421static uint8_t
4422bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4423{
4424	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4425
4426	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4427	    == 0xff);
4428}
4429
4430static void
4431bwn_wme_init(struct bwn_mac *mac)
4432{
4433
4434	bwn_wme_load(mac);
4435
4436	/* enable WME support. */
4437	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4438	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4439	    BWN_IFSCTL_USE_EDCF);
4440}
4441
4442static void
4443bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4444{
4445	struct bwn_softc *sc = mac->mac_sc;
4446	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4447	uint16_t delay;	/* microsec */
4448
4449	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4450	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4451		delay = 500;
4452	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4453		delay = max(delay, (uint16_t)2400);
4454
4455	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4456}
4457
4458static void
4459bwn_bt_enable(struct bwn_mac *mac)
4460{
4461	struct bwn_softc *sc = mac->mac_sc;
4462	uint64_t hf;
4463
4464	if (bwn_bluetooth == 0)
4465		return;
4466	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4467		return;
4468	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4469		return;
4470
4471	hf = bwn_hf_read(mac);
4472	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4473		hf |= BWN_HF_BT_COEXISTALT;
4474	else
4475		hf |= BWN_HF_BT_COEXIST;
4476	bwn_hf_write(mac, hf);
4477}
4478
4479static void
4480bwn_set_macaddr(struct bwn_mac *mac)
4481{
4482
4483	bwn_mac_write_bssid(mac);
4484	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4485}
4486
4487static void
4488bwn_clear_keys(struct bwn_mac *mac)
4489{
4490	int i;
4491
4492	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4493		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4494		    ("%s:%d: fail", __func__, __LINE__));
4495
4496		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4497		    NULL, BWN_SEC_KEYSIZE, NULL);
4498		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4499			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4500			    NULL, BWN_SEC_KEYSIZE, NULL);
4501		}
4502		mac->mac_key[i].keyconf = NULL;
4503	}
4504}
4505
4506static void
4507bwn_crypt_init(struct bwn_mac *mac)
4508{
4509	struct bwn_softc *sc = mac->mac_sc;
4510
4511	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4512	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4513	    ("%s:%d: fail", __func__, __LINE__));
4514	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4515	mac->mac_ktp *= 2;
4516	if (siba_get_revid(sc->sc_dev) >= 5)
4517		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4518	bwn_clear_keys(mac);
4519}
4520
4521static void
4522bwn_chip_exit(struct bwn_mac *mac)
4523{
4524	struct bwn_softc *sc = mac->mac_sc;
4525
4526	bwn_phy_exit(mac);
4527	siba_gpio_set(sc->sc_dev, 0);
4528}
4529
4530static int
4531bwn_fw_fillinfo(struct bwn_mac *mac)
4532{
4533	int error;
4534
4535	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4536	if (error == 0)
4537		return (0);
4538	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4539	if (error == 0)
4540		return (0);
4541	return (error);
4542}
4543
4544static int
4545bwn_gpio_init(struct bwn_mac *mac)
4546{
4547	struct bwn_softc *sc = mac->mac_sc;
4548	uint32_t mask = 0x1f, set = 0xf, value;
4549
4550	BWN_WRITE_4(mac, BWN_MACCTL,
4551	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4552	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4553	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4554
4555	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4556		mask |= 0x0060;
4557		set |= 0x0060;
4558	}
4559	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4560		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4561		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4562		mask |= 0x0200;
4563		set |= 0x0200;
4564	}
4565	if (siba_get_revid(sc->sc_dev) >= 2)
4566		mask |= 0x0010;
4567
4568	value = siba_gpio_get(sc->sc_dev);
4569	if (value == -1)
4570		return (0);
4571	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4572
4573	return (0);
4574}
4575
4576static int
4577bwn_fw_loadinitvals(struct bwn_mac *mac)
4578{
4579#define	GETFWOFFSET(fwp, offset)				\
4580	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4581	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4582	const struct bwn_fwhdr *hdr;
4583	struct bwn_fw *fw = &mac->mac_fw;
4584	int error;
4585
4586	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4587	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4588	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4589	if (error)
4590		return (error);
4591	if (fw->initvals_band.fw) {
4592		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4593		error = bwn_fwinitvals_write(mac,
4594		    GETFWOFFSET(fw->initvals_band, hdr_len),
4595		    be32toh(hdr->size),
4596		    fw->initvals_band.fw->datasize - hdr_len);
4597	}
4598	return (error);
4599#undef GETFWOFFSET
4600}
4601
4602static int
4603bwn_phy_init(struct bwn_mac *mac)
4604{
4605	struct bwn_softc *sc = mac->mac_sc;
4606	int error;
4607
4608	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4609	mac->mac_phy.rf_onoff(mac, 1);
4610	error = mac->mac_phy.init(mac);
4611	if (error) {
4612		device_printf(sc->sc_dev, "PHY init failed\n");
4613		goto fail0;
4614	}
4615	error = bwn_switch_channel(mac,
4616	    mac->mac_phy.get_default_chan(mac));
4617	if (error) {
4618		device_printf(sc->sc_dev,
4619		    "failed to switch default channel\n");
4620		goto fail1;
4621	}
4622	return (0);
4623fail1:
4624	if (mac->mac_phy.exit)
4625		mac->mac_phy.exit(mac);
4626fail0:
4627	mac->mac_phy.rf_onoff(mac, 0);
4628
4629	return (error);
4630}
4631
4632static void
4633bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4634{
4635	uint16_t ant;
4636	uint16_t tmp;
4637
4638	ant = bwn_ant2phy(antenna);
4639
4640	/* For ACK/CTS */
4641	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4642	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4643	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4644	/* For Probe Resposes */
4645	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4646	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4647	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4648}
4649
4650static void
4651bwn_set_opmode(struct bwn_mac *mac)
4652{
4653	struct bwn_softc *sc = mac->mac_sc;
4654	struct ifnet *ifp = sc->sc_ifp;
4655	struct ieee80211com *ic = ifp->if_l2com;
4656	uint32_t ctl;
4657	uint16_t cfp_pretbtt;
4658
4659	ctl = BWN_READ_4(mac, BWN_MACCTL);
4660	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4661	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4662	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4663	ctl |= BWN_MACCTL_STA;
4664
4665	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4666	    ic->ic_opmode == IEEE80211_M_MBSS)
4667		ctl |= BWN_MACCTL_HOSTAP;
4668	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4669		ctl &= ~BWN_MACCTL_STA;
4670	ctl |= sc->sc_filters;
4671
4672	if (siba_get_revid(sc->sc_dev) <= 4)
4673		ctl |= BWN_MACCTL_PROMISC;
4674
4675	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4676
4677	cfp_pretbtt = 2;
4678	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4679		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4680		    siba_get_chiprev(sc->sc_dev) == 3)
4681			cfp_pretbtt = 100;
4682		else
4683			cfp_pretbtt = 50;
4684	}
4685	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4686}
4687
4688static int
4689bwn_dma_gettype(struct bwn_mac *mac)
4690{
4691	uint32_t tmp;
4692	uint16_t base;
4693
4694	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4695	if (tmp & SIBA_TGSHIGH_DMA64)
4696		return (BWN_DMA_64BIT);
4697	base = bwn_dma_base(0, 0);
4698	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4699	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4700	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4701		return (BWN_DMA_32BIT);
4702
4703	return (BWN_DMA_30BIT);
4704}
4705
4706static void
4707bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4708{
4709	if (!error) {
4710		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4711		*((bus_addr_t *)arg) = seg->ds_addr;
4712	}
4713}
4714
4715static void
4716bwn_phy_g_init_sub(struct bwn_mac *mac)
4717{
4718	struct bwn_phy *phy = &mac->mac_phy;
4719	struct bwn_phy_g *pg = &phy->phy_g;
4720	struct bwn_softc *sc = mac->mac_sc;
4721	uint16_t i, tmp;
4722
4723	if (phy->rev == 1)
4724		bwn_phy_init_b5(mac);
4725	else
4726		bwn_phy_init_b6(mac);
4727
4728	if (phy->rev >= 2 || phy->gmode)
4729		bwn_phy_init_a(mac);
4730
4731	if (phy->rev >= 2) {
4732		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4733		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4734	}
4735	if (phy->rev == 2) {
4736		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4737		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4738	}
4739	if (phy->rev > 5) {
4740		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4741		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4742	}
4743	if (phy->gmode || phy->rev >= 2) {
4744		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4745		tmp &= BWN_PHYVER_VERSION;
4746		if (tmp == 3 || tmp == 5) {
4747			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4748			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4749		}
4750		if (tmp == 5) {
4751			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4752			    0x1f00);
4753		}
4754	}
4755	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4756		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4757	if (phy->rf_rev == 8) {
4758		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4759		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4760	}
4761	if (BWN_HAS_LOOPBACK(phy))
4762		bwn_loopback_calcgain(mac);
4763
4764	if (phy->rf_rev != 8) {
4765		if (pg->pg_initval == 0xffff)
4766			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4767		else
4768			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4769	}
4770	bwn_lo_g_init(mac);
4771	if (BWN_HAS_TXMAG(phy)) {
4772		BWN_RF_WRITE(mac, 0x52,
4773		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4774		    | pg->pg_loctl.tx_bias |
4775		    pg->pg_loctl.tx_magn);
4776	} else {
4777		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4778	}
4779	if (phy->rev >= 6) {
4780		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4781		    (pg->pg_loctl.tx_bias << 12));
4782	}
4783	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4784		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4785	else
4786		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4787	if (phy->rev < 2)
4788		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4789	else
4790		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4791	if (phy->gmode || phy->rev >= 2) {
4792		bwn_lo_g_adjust(mac);
4793		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4794	}
4795
4796	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4797		for (i = 0; i < 64; i++) {
4798			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4799			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4800			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4801			    -32), 31));
4802		}
4803		bwn_nrssi_threshold(mac);
4804	} else if (phy->gmode || phy->rev >= 2) {
4805		if (pg->pg_nrssi[0] == -1000) {
4806			KASSERT(pg->pg_nrssi[1] == -1000,
4807			    ("%s:%d: fail", __func__, __LINE__));
4808			bwn_nrssi_slope_11g(mac);
4809		} else
4810			bwn_nrssi_threshold(mac);
4811	}
4812	if (phy->rf_rev == 8)
4813		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4814	bwn_phy_hwpctl_init(mac);
4815	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4816	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4817		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4818		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4819	}
4820}
4821
4822static uint8_t
4823bwn_has_hwpctl(struct bwn_mac *mac)
4824{
4825
4826	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4827		return (0);
4828	return (mac->mac_phy.use_hwpctl(mac));
4829}
4830
4831static void
4832bwn_phy_init_b5(struct bwn_mac *mac)
4833{
4834	struct bwn_phy *phy = &mac->mac_phy;
4835	struct bwn_phy_g *pg = &phy->phy_g;
4836	struct bwn_softc *sc = mac->mac_sc;
4837	uint16_t offset, value;
4838	uint8_t old_channel;
4839
4840	if (phy->analog == 1)
4841		BWN_RF_SET(mac, 0x007a, 0x0050);
4842	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4843	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4844		value = 0x2120;
4845		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4846			BWN_PHY_WRITE(mac, offset, value);
4847			value += 0x202;
4848		}
4849	}
4850	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4851	if (phy->rf_ver == 0x2050)
4852		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4853
4854	if (phy->gmode || phy->rev >= 2) {
4855		if (phy->rf_ver == 0x2050) {
4856			BWN_RF_SET(mac, 0x007a, 0x0020);
4857			BWN_RF_SET(mac, 0x0051, 0x0004);
4858		}
4859		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4860
4861		BWN_PHY_SET(mac, 0x0802, 0x0100);
4862		BWN_PHY_SET(mac, 0x042b, 0x2000);
4863
4864		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4865
4866		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4867		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4868		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4869	}
4870
4871	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4872		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4873
4874	if (phy->analog == 1) {
4875		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4876		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4877		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4878		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4879		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4880	} else
4881		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4882	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4883	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4884
4885	if (phy->analog == 1)
4886		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4887	else
4888		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4889
4890	if (phy->analog == 0)
4891		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4892
4893	old_channel = phy->chan;
4894	bwn_phy_g_switch_chan(mac, 7, 0);
4895
4896	if (phy->rf_ver != 0x2050) {
4897		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4898		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4899	}
4900
4901	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4902	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4903
4904	if (phy->rf_ver == 0x2050) {
4905		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4906		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4907	}
4908
4909	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4910	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4911	BWN_RF_SET(mac, 0x007a, 0x0007);
4912
4913	bwn_phy_g_switch_chan(mac, old_channel, 0);
4914	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4915	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4916	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4917
4918	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4919	    pg->pg_txctl);
4920
4921	if (phy->rf_ver == 0x2050)
4922		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4923
4924	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4925}
4926
4927static void
4928bwn_loopback_calcgain(struct bwn_mac *mac)
4929{
4930	struct bwn_phy *phy = &mac->mac_phy;
4931	struct bwn_phy_g *pg = &phy->phy_g;
4932	struct bwn_softc *sc = mac->mac_sc;
4933	uint16_t backup_phy[16] = { 0 };
4934	uint16_t backup_radio[3];
4935	uint16_t backup_bband;
4936	uint16_t i, j, loop_i_max;
4937	uint16_t trsw_rx;
4938	uint16_t loop1_outer_done, loop1_inner_done;
4939
4940	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4941	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4942	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4943	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4944	if (phy->rev != 1) {
4945		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4946		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4947	}
4948	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4949	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4950	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4951	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4952	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4953	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4954	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4955	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4956	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4957	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4958	backup_bband = pg->pg_bbatt.att;
4959	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4960	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4961	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4962
4963	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4964	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4965	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4966	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4967	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4968	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4969	if (phy->rev != 1) {
4970		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4971		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4972		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4973		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4974	}
4975	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4976	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4977	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4978	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4979
4980	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4981	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4982	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4983
4984	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4985	if (phy->rev != 1) {
4986		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4987		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4988	}
4989	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4990
4991	if (phy->rf_rev == 8)
4992		BWN_RF_WRITE(mac, 0x43, 0x000f);
4993	else {
4994		BWN_RF_WRITE(mac, 0x52, 0);
4995		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4996	}
4997	bwn_phy_g_set_bbatt(mac, 11);
4998
4999	if (phy->rev >= 3)
5000		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5001	else
5002		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5003	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5004
5005	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5006	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5007
5008	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5009	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5010
5011	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5012		if (phy->rev >= 7) {
5013			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5014			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5015		}
5016	}
5017	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5018
5019	j = 0;
5020	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5021	for (i = 0; i < loop_i_max; i++) {
5022		for (j = 0; j < 16; j++) {
5023			BWN_RF_WRITE(mac, 0x43, i);
5024			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5025			    (j << 8));
5026			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5027			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5028			DELAY(20);
5029			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5030				goto done0;
5031		}
5032	}
5033done0:
5034	loop1_outer_done = i;
5035	loop1_inner_done = j;
5036	if (j >= 8) {
5037		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5038		trsw_rx = 0x1b;
5039		for (j = j - 8; j < 16; j++) {
5040			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5041			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5042			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5043			DELAY(20);
5044			trsw_rx -= 3;
5045			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5046				goto done1;
5047		}
5048	} else
5049		trsw_rx = 0x18;
5050done1:
5051
5052	if (phy->rev != 1) {
5053		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5054		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5055	}
5056	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5057	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5058	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5059	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5060	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5061	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5062	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5063	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5064	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5065
5066	bwn_phy_g_set_bbatt(mac, backup_bband);
5067
5068	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5069	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5070	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5071
5072	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5073	DELAY(10);
5074	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5075	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5076	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5077	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5078
5079	pg->pg_max_lb_gain =
5080	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5081	pg->pg_trsw_rx_gain = trsw_rx * 2;
5082}
5083
5084static uint16_t
5085bwn_rf_init_bcm2050(struct bwn_mac *mac)
5086{
5087	struct bwn_phy *phy = &mac->mac_phy;
5088	uint32_t tmp1 = 0, tmp2 = 0;
5089	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5090	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5091	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5092	static const uint8_t rcc_table[] = {
5093		0x02, 0x03, 0x01, 0x0f,
5094		0x06, 0x07, 0x05, 0x0f,
5095		0x0a, 0x0b, 0x09, 0x0f,
5096		0x0e, 0x0f, 0x0d, 0x0f,
5097	};
5098
5099	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5100	    rfoverval = rfover = cck3 = 0;
5101	radio0 = BWN_RF_READ(mac, 0x43);
5102	radio1 = BWN_RF_READ(mac, 0x51);
5103	radio2 = BWN_RF_READ(mac, 0x52);
5104	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5105	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5106	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5107	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5108
5109	if (phy->type == BWN_PHYTYPE_B) {
5110		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5111		reg0 = BWN_READ_2(mac, 0x3ec);
5112
5113		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5114		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5115	} else if (phy->gmode || phy->rev >= 2) {
5116		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5117		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5118		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5119		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5120		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5121		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5122
5123		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5124		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5125		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5126		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5127		if (BWN_HAS_LOOPBACK(phy)) {
5128			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5129			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5130			if (phy->rev >= 3)
5131				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5132			else
5133				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5134			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5135		}
5136
5137		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5138		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5139			BWN_LPD(0, 1, 1)));
5140		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5141		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5142	}
5143	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5144
5145	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5146	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5147	reg1 = BWN_READ_2(mac, 0x3e6);
5148	reg2 = BWN_READ_2(mac, 0x3f4);
5149
5150	if (phy->analog == 0)
5151		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5152	else {
5153		if (phy->analog >= 2)
5154			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5155		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5156		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5157	}
5158
5159	reg = BWN_RF_READ(mac, 0x60);
5160	index = (reg & 0x001e) >> 1;
5161	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5162
5163	if (phy->type == BWN_PHYTYPE_B)
5164		BWN_RF_WRITE(mac, 0x78, 0x26);
5165	if (phy->gmode || phy->rev >= 2) {
5166		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5167		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5168			BWN_LPD(0, 1, 1)));
5169	}
5170	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5171	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5172	if (phy->gmode || phy->rev >= 2) {
5173		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5174		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5175			BWN_LPD(0, 0, 1)));
5176	}
5177	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5178	BWN_RF_SET(mac, 0x51, 0x0004);
5179	if (phy->rf_rev == 8)
5180		BWN_RF_WRITE(mac, 0x43, 0x1f);
5181	else {
5182		BWN_RF_WRITE(mac, 0x52, 0);
5183		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5184	}
5185	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5186
5187	for (i = 0; i < 16; i++) {
5188		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5189		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5190		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5191		if (phy->gmode || phy->rev >= 2) {
5192			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5193			    bwn_rf_2050_rfoverval(mac,
5194				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5195		}
5196		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5197		DELAY(10);
5198		if (phy->gmode || phy->rev >= 2) {
5199			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5200			    bwn_rf_2050_rfoverval(mac,
5201				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5202		}
5203		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5204		DELAY(10);
5205		if (phy->gmode || phy->rev >= 2) {
5206			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5207			    bwn_rf_2050_rfoverval(mac,
5208				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5209		}
5210		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5211		DELAY(20);
5212		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5213		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5214		if (phy->gmode || phy->rev >= 2) {
5215			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5216			    bwn_rf_2050_rfoverval(mac,
5217				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5218		}
5219		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5220	}
5221	DELAY(10);
5222
5223	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5224	tmp1++;
5225	tmp1 >>= 9;
5226
5227	for (i = 0; i < 16; i++) {
5228		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5229		BWN_RF_WRITE(mac, 0x78, radio78);
5230		DELAY(10);
5231		for (j = 0; j < 16; j++) {
5232			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5233			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5234			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5235			if (phy->gmode || phy->rev >= 2) {
5236				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5237				    bwn_rf_2050_rfoverval(mac,
5238					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5239			}
5240			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5241			DELAY(10);
5242			if (phy->gmode || phy->rev >= 2) {
5243				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5244				    bwn_rf_2050_rfoverval(mac,
5245					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5246			}
5247			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5248			DELAY(10);
5249			if (phy->gmode || phy->rev >= 2) {
5250				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5251				    bwn_rf_2050_rfoverval(mac,
5252					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5253			}
5254			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5255			DELAY(10);
5256			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5257			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5258			if (phy->gmode || phy->rev >= 2) {
5259				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5260				    bwn_rf_2050_rfoverval(mac,
5261					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5262			}
5263			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5264		}
5265		tmp2++;
5266		tmp2 >>= 8;
5267		if (tmp1 < tmp2)
5268			break;
5269	}
5270
5271	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5272	BWN_RF_WRITE(mac, 0x51, radio1);
5273	BWN_RF_WRITE(mac, 0x52, radio2);
5274	BWN_RF_WRITE(mac, 0x43, radio0);
5275	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5276	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5277	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5278	BWN_WRITE_2(mac, 0x3e6, reg1);
5279	if (phy->analog != 0)
5280		BWN_WRITE_2(mac, 0x3f4, reg2);
5281	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5282	bwn_spu_workaround(mac, phy->chan);
5283	if (phy->type == BWN_PHYTYPE_B) {
5284		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5285		BWN_WRITE_2(mac, 0x3ec, reg0);
5286	} else if (phy->gmode) {
5287		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5288			    BWN_READ_2(mac, BWN_PHY_RADIO)
5289			    & 0x7fff);
5290		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5291		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5292		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5293		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5294			      analogoverval);
5295		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5296		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5297		if (BWN_HAS_LOOPBACK(phy)) {
5298			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5299			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5300		}
5301	}
5302
5303	return ((i > 15) ? radio78 : rcc);
5304}
5305
5306static void
5307bwn_phy_init_b6(struct bwn_mac *mac)
5308{
5309	struct bwn_phy *phy = &mac->mac_phy;
5310	struct bwn_phy_g *pg = &phy->phy_g;
5311	struct bwn_softc *sc = mac->mac_sc;
5312	uint16_t offset, val;
5313	uint8_t old_channel;
5314
5315	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5316	    ("%s:%d: fail", __func__, __LINE__));
5317
5318	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5319	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5320	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5321		BWN_RF_WRITE(mac, 0x51, 0x37);
5322		BWN_RF_WRITE(mac, 0x52, 0x70);
5323		BWN_RF_WRITE(mac, 0x53, 0xb3);
5324		BWN_RF_WRITE(mac, 0x54, 0x9b);
5325		BWN_RF_WRITE(mac, 0x5a, 0x88);
5326		BWN_RF_WRITE(mac, 0x5b, 0x88);
5327		BWN_RF_WRITE(mac, 0x5d, 0x88);
5328		BWN_RF_WRITE(mac, 0x5e, 0x88);
5329		BWN_RF_WRITE(mac, 0x7d, 0x88);
5330		bwn_hf_write(mac,
5331		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5332	}
5333	if (phy->rf_rev == 8) {
5334		BWN_RF_WRITE(mac, 0x51, 0);
5335		BWN_RF_WRITE(mac, 0x52, 0x40);
5336		BWN_RF_WRITE(mac, 0x53, 0xb7);
5337		BWN_RF_WRITE(mac, 0x54, 0x98);
5338		BWN_RF_WRITE(mac, 0x5a, 0x88);
5339		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5340		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5341		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5342			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5343			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5344		} else {
5345			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5346			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5347		}
5348		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5349		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5350		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5351		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5352	}
5353	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5354		BWN_PHY_WRITE(mac, offset, val);
5355		val -= 0x0202;
5356	}
5357	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5358		BWN_PHY_WRITE(mac, offset, val);
5359		val -= 0x0202;
5360	}
5361	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5362		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5363		val += 0x0202;
5364	}
5365	if (phy->type == BWN_PHYTYPE_G) {
5366		BWN_RF_SET(mac, 0x007a, 0x0020);
5367		BWN_RF_SET(mac, 0x0051, 0x0004);
5368		BWN_PHY_SET(mac, 0x0802, 0x0100);
5369		BWN_PHY_SET(mac, 0x042b, 0x2000);
5370		BWN_PHY_WRITE(mac, 0x5b, 0);
5371		BWN_PHY_WRITE(mac, 0x5c, 0);
5372	}
5373
5374	old_channel = phy->chan;
5375	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5376
5377	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5378	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5379	DELAY(40);
5380	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5381		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5382		BWN_RF_WRITE(mac, 0x50, 0x20);
5383	}
5384	if (phy->rf_rev <= 2) {
5385		BWN_RF_WRITE(mac, 0x7c, 0x20);
5386		BWN_RF_WRITE(mac, 0x5a, 0x70);
5387		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5388		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5389	}
5390	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5391
5392	bwn_phy_g_switch_chan(mac, old_channel, 0);
5393
5394	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5395	if (phy->rf_rev >= 6)
5396		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5397	else
5398		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5399	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5400	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5401	    pg->pg_txctl);
5402	if (phy->rf_rev <= 5)
5403		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5404	if (phy->rf_rev <= 2)
5405		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5406
5407	if (phy->analog == 4) {
5408		BWN_WRITE_2(mac, 0x3e4, 9);
5409		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5410	} else
5411		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5412	if (phy->type == BWN_PHYTYPE_B)
5413		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5414	else if (phy->type == BWN_PHYTYPE_G)
5415		BWN_WRITE_2(mac, 0x03e6, 0x0);
5416}
5417
5418static void
5419bwn_phy_init_a(struct bwn_mac *mac)
5420{
5421	struct bwn_phy *phy = &mac->mac_phy;
5422	struct bwn_softc *sc = mac->mac_sc;
5423
5424	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5425	    ("%s:%d: fail", __func__, __LINE__));
5426
5427	if (phy->rev >= 6) {
5428		if (phy->type == BWN_PHYTYPE_A)
5429			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5430		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5431			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5432		else
5433			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5434	}
5435
5436	bwn_wa_init(mac);
5437
5438	if (phy->type == BWN_PHYTYPE_G &&
5439	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5440		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5441}
5442
5443static void
5444bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5445{
5446	int i;
5447
5448	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5449		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5450}
5451
5452static void
5453bwn_wa_agc(struct bwn_mac *mac)
5454{
5455	struct bwn_phy *phy = &mac->mac_phy;
5456
5457	if (phy->rev == 1) {
5458		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5459		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5460		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5461		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5462		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5463		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5464		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5465		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5466		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5467	} else {
5468		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5469		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5470		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5471		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5472	}
5473
5474	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5475	    0x5700);
5476	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5477	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5478	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5479	BWN_RF_SET(mac, 0x7a, 0x0008);
5480	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5481	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5482	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5483	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5484	if (phy->rev == 1)
5485		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5486	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5487	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5488	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5489	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5490	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5491	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5492	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5493	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5494	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5495	if (phy->rev == 1) {
5496		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5497		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5498	} else {
5499		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5500		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5501		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5502		if (phy->rev >= 6) {
5503			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5504			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5505			    (uint16_t)~0xf000, 0x3000);
5506		}
5507	}
5508	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5509	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5510	if (phy->rev == 1) {
5511		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5512		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5513		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5514		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5515		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5516		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5517		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5518		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5519	} else {
5520		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5521		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5522		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5523		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5524	}
5525	if (phy->rev >= 6) {
5526		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5527		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5528	}
5529	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5530}
5531
5532static void
5533bwn_wa_grev1(struct bwn_mac *mac)
5534{
5535	struct bwn_phy *phy = &mac->mac_phy;
5536	int i;
5537	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5538	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5539	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5540
5541	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5542
5543	/* init CRSTHRES and ANTDWELL */
5544	if (phy->rev == 1) {
5545		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5546	} else if (phy->rev == 2) {
5547		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5548		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5549		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5550	} else {
5551		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5552		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5553		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5554		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5555	}
5556	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5557	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5558	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5559
5560	/* XXX support PHY-A??? */
5561	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5562		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5563		    bwn_tab_finefreqg[i]);
5564
5565	/* XXX support PHY-A??? */
5566	if (phy->rev == 1)
5567		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5568			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5569			    bwn_tab_noise_g1[i]);
5570	else
5571		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5572			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5573			    bwn_tab_noise_g2[i]);
5574
5575
5576	for (i = 0; i < N(bwn_tab_rotor); i++)
5577		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5578		    bwn_tab_rotor[i]);
5579
5580	/* XXX support PHY-A??? */
5581	if (phy->rev >= 6) {
5582		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5583		    BWN_PHY_ENCORE_EN)
5584			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5585		else
5586			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5587	} else
5588		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5589
5590	for (i = 0; i < N(bwn_tab_retard); i++)
5591		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5592		    bwn_tab_retard[i]);
5593
5594	if (phy->rev == 1) {
5595		for (i = 0; i < 16; i++)
5596			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5597			    i, 0x0020);
5598	} else {
5599		for (i = 0; i < 32; i++)
5600			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5601	}
5602
5603	bwn_wa_agc(mac);
5604}
5605
5606static void
5607bwn_wa_grev26789(struct bwn_mac *mac)
5608{
5609	struct bwn_phy *phy = &mac->mac_phy;
5610	int i;
5611	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5612	uint16_t ofdmrev;
5613
5614	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5615
5616	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5617
5618	/* init CRSTHRES and ANTDWELL */
5619	if (phy->rev == 1)
5620		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5621	else if (phy->rev == 2) {
5622		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5623		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5624		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5625	} else {
5626		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5627		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5628		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5629		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5630	}
5631
5632	for (i = 0; i < 64; i++)
5633		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5634
5635	/* XXX support PHY-A??? */
5636	if (phy->rev == 1)
5637		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5638			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5639			    bwn_tab_noise_g1[i]);
5640	else
5641		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5642			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5643			    bwn_tab_noise_g2[i]);
5644
5645	/* XXX support PHY-A??? */
5646	if (phy->rev >= 6) {
5647		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5648		    BWN_PHY_ENCORE_EN)
5649			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5650		else
5651			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5652	} else
5653		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5654
5655	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5656		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5657		    bwn_tab_sigmasqr2[i]);
5658
5659	if (phy->rev == 1) {
5660		for (i = 0; i < 16; i++)
5661			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5662			    0x0020);
5663	} else {
5664		for (i = 0; i < 32; i++)
5665			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5666	}
5667
5668	bwn_wa_agc(mac);
5669
5670	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5671	if (ofdmrev > 2) {
5672		if (phy->type == BWN_PHYTYPE_A)
5673			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5674		else
5675			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5676	} else {
5677		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5678		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5679		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5680	}
5681
5682	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5683	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5684}
5685
5686static void
5687bwn_wa_init(struct bwn_mac *mac)
5688{
5689	struct bwn_phy *phy = &mac->mac_phy;
5690	struct bwn_softc *sc = mac->mac_sc;
5691
5692	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5693
5694	switch (phy->rev) {
5695	case 1:
5696		bwn_wa_grev1(mac);
5697		break;
5698	case 2:
5699	case 6:
5700	case 7:
5701	case 8:
5702	case 9:
5703		bwn_wa_grev26789(mac);
5704		break;
5705	default:
5706		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5707	}
5708
5709	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5710	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5711	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5712		if (phy->rev < 2) {
5713			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5714			    0x0002);
5715			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5716			    0x0001);
5717		} else {
5718			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5719			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5720			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5721			     BWN_BFL_EXTLNA) &&
5722			    (phy->rev >= 7)) {
5723				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5724				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725				    0x0020, 0x0001);
5726				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727				    0x0021, 0x0001);
5728				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729				    0x0022, 0x0001);
5730				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5731				    0x0023, 0x0000);
5732				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5733				    0x0000, 0x0000);
5734				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5735				    0x0003, 0x0002);
5736			}
5737		}
5738	}
5739	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5740		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5741		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5742	}
5743
5744	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5745	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5746}
5747
5748static void
5749bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5750    uint16_t value)
5751{
5752	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5753	uint16_t addr;
5754
5755	addr = table + offset;
5756	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5757	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5758		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5759		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5760	}
5761	pg->pg_ofdmtab_addr = addr;
5762	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5763}
5764
5765static void
5766bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5767    uint32_t value)
5768{
5769	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5770	uint16_t addr;
5771
5772	addr = table + offset;
5773	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5774	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5775		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5776		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5777	}
5778	pg->pg_ofdmtab_addr = addr;
5779
5780	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5781	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5782}
5783
5784static void
5785bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5786    uint16_t value)
5787{
5788
5789	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5790	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5791}
5792
5793static void
5794bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5795{
5796	struct bwn_phy *phy = &mac->mac_phy;
5797	struct bwn_softc *sc = mac->mac_sc;
5798	unsigned int i, max_loop;
5799	uint16_t value;
5800	uint32_t buffer[5] = {
5801		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5802	};
5803
5804	if (ofdm) {
5805		max_loop = 0x1e;
5806		buffer[0] = 0x000201cc;
5807	} else {
5808		max_loop = 0xfa;
5809		buffer[0] = 0x000b846e;
5810	}
5811
5812	BWN_ASSERT_LOCKED(mac->mac_sc);
5813
5814	for (i = 0; i < 5; i++)
5815		bwn_ram_write(mac, i * 4, buffer[i]);
5816
5817	BWN_WRITE_2(mac, 0x0568, 0x0000);
5818	BWN_WRITE_2(mac, 0x07c0,
5819	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5820	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5821	BWN_WRITE_2(mac, 0x050c, value);
5822	if (phy->type == BWN_PHYTYPE_LP)
5823		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5824	BWN_WRITE_2(mac, 0x0508, 0x0000);
5825	BWN_WRITE_2(mac, 0x050a, 0x0000);
5826	BWN_WRITE_2(mac, 0x054c, 0x0000);
5827	BWN_WRITE_2(mac, 0x056a, 0x0014);
5828	BWN_WRITE_2(mac, 0x0568, 0x0826);
5829	BWN_WRITE_2(mac, 0x0500, 0x0000);
5830	if (phy->type == BWN_PHYTYPE_LP)
5831		BWN_WRITE_2(mac, 0x0502, 0x0050);
5832	else
5833		BWN_WRITE_2(mac, 0x0502, 0x0030);
5834
5835	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5836		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5837	for (i = 0x00; i < max_loop; i++) {
5838		value = BWN_READ_2(mac, 0x050e);
5839		if (value & 0x0080)
5840			break;
5841		DELAY(10);
5842	}
5843	for (i = 0x00; i < 0x0a; i++) {
5844		value = BWN_READ_2(mac, 0x050e);
5845		if (value & 0x0400)
5846			break;
5847		DELAY(10);
5848	}
5849	for (i = 0x00; i < 0x19; i++) {
5850		value = BWN_READ_2(mac, 0x0690);
5851		if (!(value & 0x0100))
5852			break;
5853		DELAY(10);
5854	}
5855	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5856		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5857}
5858
5859static void
5860bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5861{
5862	uint32_t macctl;
5863
5864	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5865
5866	macctl = BWN_READ_4(mac, BWN_MACCTL);
5867	if (macctl & BWN_MACCTL_BIGENDIAN)
5868		printf("TODO: need swap\n");
5869
5870	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5871	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5872	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5873}
5874
5875static void
5876bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5877{
5878	uint16_t value;
5879
5880	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5881	    ("%s:%d: fail", __func__, __LINE__));
5882
5883	value = (uint8_t) (ctl->q);
5884	value |= ((uint8_t) (ctl->i)) << 8;
5885	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5886}
5887
5888static uint16_t
5889bwn_lo_calcfeed(struct bwn_mac *mac,
5890    uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5891{
5892	struct bwn_phy *phy = &mac->mac_phy;
5893	struct bwn_softc *sc = mac->mac_sc;
5894	uint16_t rfover;
5895	uint16_t feedthrough;
5896
5897	if (phy->gmode) {
5898		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5899		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5900
5901		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5902		    ("%s:%d: fail", __func__, __LINE__));
5903		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5904		    ("%s:%d: fail", __func__, __LINE__));
5905
5906		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5907
5908		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5909		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5910		    phy->rev > 6)
5911			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5912
5913		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5914		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915		DELAY(10);
5916		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5917		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5918		DELAY(10);
5919		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5920		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5921		DELAY(10);
5922		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5923	} else {
5924		pga |= BWN_PHY_PGACTL_UNKNOWN;
5925		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926		DELAY(10);
5927		pga |= BWN_PHY_PGACTL_LOWBANDW;
5928		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5929		DELAY(10);
5930		pga |= BWN_PHY_PGACTL_LPF;
5931		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5932	}
5933	DELAY(21);
5934	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5935
5936	return (feedthrough);
5937}
5938
5939static uint16_t
5940bwn_lo_txctl_regtable(struct bwn_mac *mac,
5941    uint16_t *value, uint16_t *pad_mix_gain)
5942{
5943	struct bwn_phy *phy = &mac->mac_phy;
5944	uint16_t reg, v, padmix;
5945
5946	if (phy->type == BWN_PHYTYPE_B) {
5947		v = 0x30;
5948		if (phy->rf_rev <= 5) {
5949			reg = 0x43;
5950			padmix = 0;
5951		} else {
5952			reg = 0x52;
5953			padmix = 5;
5954		}
5955	} else {
5956		if (phy->rev >= 2 && phy->rf_rev == 8) {
5957			reg = 0x43;
5958			v = 0x10;
5959			padmix = 2;
5960		} else {
5961			reg = 0x52;
5962			v = 0x30;
5963			padmix = 5;
5964		}
5965	}
5966	if (value)
5967		*value = v;
5968	if (pad_mix_gain)
5969		*pad_mix_gain = padmix;
5970
5971	return (reg);
5972}
5973
5974static void
5975bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5976{
5977	struct bwn_phy *phy = &mac->mac_phy;
5978	struct bwn_phy_g *pg = &phy->phy_g;
5979	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5980	uint16_t reg, mask;
5981	uint16_t trsw_rx, pga;
5982	uint16_t rf_pctl_reg;
5983
5984	static const uint8_t tx_bias_values[] = {
5985		0x09, 0x08, 0x0a, 0x01, 0x00,
5986		0x02, 0x05, 0x04, 0x06,
5987	};
5988	static const uint8_t tx_magn_values[] = {
5989		0x70, 0x40,
5990	};
5991
5992	if (!BWN_HAS_LOOPBACK(phy)) {
5993		rf_pctl_reg = 6;
5994		trsw_rx = 2;
5995		pga = 0;
5996	} else {
5997		int lb_gain;
5998
5999		trsw_rx = 0;
6000		lb_gain = pg->pg_max_lb_gain / 2;
6001		if (lb_gain > 10) {
6002			rf_pctl_reg = 0;
6003			pga = abs(10 - lb_gain) / 6;
6004			pga = MIN(MAX(pga, 0), 15);
6005		} else {
6006			int cmp_val;
6007			int tmp;
6008
6009			pga = 0;
6010			cmp_val = 0x24;
6011			if ((phy->rev >= 2) &&
6012			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6013				cmp_val = 0x3c;
6014			tmp = lb_gain;
6015			if ((10 - lb_gain) < cmp_val)
6016				tmp = (10 - lb_gain);
6017			if (tmp < 0)
6018				tmp += 6;
6019			else
6020				tmp += 3;
6021			cmp_val /= 4;
6022			tmp /= 4;
6023			if (tmp >= cmp_val)
6024				rf_pctl_reg = cmp_val;
6025			else
6026				rf_pctl_reg = tmp;
6027		}
6028	}
6029	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6030	bwn_phy_g_set_bbatt(mac, 2);
6031
6032	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6033	mask = ~mask;
6034	BWN_RF_MASK(mac, reg, mask);
6035
6036	if (BWN_HAS_TXMAG(phy)) {
6037		int i, j;
6038		int feedthrough;
6039		int min_feedth = 0xffff;
6040		uint8_t tx_magn, tx_bias;
6041
6042		for (i = 0; i < N(tx_magn_values); i++) {
6043			tx_magn = tx_magn_values[i];
6044			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6045			for (j = 0; j < N(tx_bias_values); j++) {
6046				tx_bias = tx_bias_values[j];
6047				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6048				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6049				    trsw_rx);
6050				if (feedthrough < min_feedth) {
6051					lo->tx_bias = tx_bias;
6052					lo->tx_magn = tx_magn;
6053					min_feedth = feedthrough;
6054				}
6055				if (lo->tx_bias == 0)
6056					break;
6057			}
6058			BWN_RF_WRITE(mac, 0x52,
6059					  (BWN_RF_READ(mac, 0x52)
6060					   & 0xff00) | lo->tx_bias | lo->
6061					  tx_magn);
6062		}
6063	} else {
6064		lo->tx_magn = 0;
6065		lo->tx_bias = 0;
6066		BWN_RF_MASK(mac, 0x52, 0xfff0);
6067	}
6068
6069	BWN_GETTIME(lo->txctl_measured_time);
6070}
6071
6072static void
6073bwn_lo_get_powervector(struct bwn_mac *mac)
6074{
6075	struct bwn_phy *phy = &mac->mac_phy;
6076	struct bwn_phy_g *pg = &phy->phy_g;
6077	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6078	int i;
6079	uint64_t tmp;
6080	uint64_t power_vector = 0;
6081
6082	for (i = 0; i < 8; i += 2) {
6083		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6084		power_vector |= (tmp << (i * 8));
6085		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6086	}
6087	if (power_vector)
6088		lo->power_vector = power_vector;
6089
6090	BWN_GETTIME(lo->pwr_vec_read_time);
6091}
6092
6093static void
6094bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6095    int use_trsw_rx)
6096{
6097	struct bwn_phy *phy = &mac->mac_phy;
6098	struct bwn_phy_g *pg = &phy->phy_g;
6099	uint16_t tmp;
6100
6101	if (max_rx_gain < 0)
6102		max_rx_gain = 0;
6103
6104	if (BWN_HAS_LOOPBACK(phy)) {
6105		int trsw_rx = 0;
6106		int trsw_rx_gain;
6107
6108		if (use_trsw_rx) {
6109			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6110			if (max_rx_gain >= trsw_rx_gain) {
6111				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6112				trsw_rx = 0x20;
6113			}
6114		} else
6115			trsw_rx_gain = max_rx_gain;
6116		if (trsw_rx_gain < 9) {
6117			pg->pg_lna_lod_gain = 0;
6118		} else {
6119			pg->pg_lna_lod_gain = 1;
6120			trsw_rx_gain -= 8;
6121		}
6122		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6123		pg->pg_pga_gain = trsw_rx_gain / 3;
6124		if (pg->pg_pga_gain >= 5) {
6125			pg->pg_pga_gain -= 5;
6126			pg->pg_lna_gain = 2;
6127		} else
6128			pg->pg_lna_gain = 0;
6129	} else {
6130		pg->pg_lna_gain = 0;
6131		pg->pg_trsw_rx_gain = 0x20;
6132		if (max_rx_gain >= 0x14) {
6133			pg->pg_lna_lod_gain = 1;
6134			pg->pg_pga_gain = 2;
6135		} else if (max_rx_gain >= 0x12) {
6136			pg->pg_lna_lod_gain = 1;
6137			pg->pg_pga_gain = 1;
6138		} else if (max_rx_gain >= 0xf) {
6139			pg->pg_lna_lod_gain = 1;
6140			pg->pg_pga_gain = 0;
6141		} else {
6142			pg->pg_lna_lod_gain = 0;
6143			pg->pg_pga_gain = 0;
6144		}
6145	}
6146
6147	tmp = BWN_RF_READ(mac, 0x7a);
6148	if (pg->pg_lna_lod_gain == 0)
6149		tmp &= ~0x0008;
6150	else
6151		tmp |= 0x0008;
6152	BWN_RF_WRITE(mac, 0x7a, tmp);
6153}
6154
6155static void
6156bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6157{
6158	struct bwn_phy *phy = &mac->mac_phy;
6159	struct bwn_phy_g *pg = &phy->phy_g;
6160	struct bwn_softc *sc = mac->mac_sc;
6161	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6162	struct timespec ts;
6163	uint16_t tmp;
6164
6165	if (bwn_has_hwpctl(mac)) {
6166		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6167		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6168		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6169		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6170		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6171
6172		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6173		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6174		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6175		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6176	}
6177	if (phy->type == BWN_PHYTYPE_B &&
6178	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6179		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6180		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6181	}
6182	if (phy->rev >= 2) {
6183		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6184		sav->phy_analogoverval =
6185		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6186		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6187		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6188		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6189		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6190		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6191
6192		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6193		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6194		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6195		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6196		if (phy->type == BWN_PHYTYPE_G) {
6197			if ((phy->rev >= 7) &&
6198			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6199			     BWN_BFL_EXTLNA)) {
6200				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6201			} else {
6202				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6203			}
6204		} else {
6205			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6206		}
6207		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6208	}
6209	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6210	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6211	sav->rf0 = BWN_RF_READ(mac, 0x43);
6212	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6213	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6214	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6215	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6216	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6217
6218	if (!BWN_HAS_TXMAG(phy)) {
6219		sav->rf2 = BWN_RF_READ(mac, 0x52);
6220		sav->rf2 &= 0x00f0;
6221	}
6222	if (phy->type == BWN_PHYTYPE_B) {
6223		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6224		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6225		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6226		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6227	} else {
6228		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6229			    | 0x8000);
6230	}
6231	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6232		    & 0xf000);
6233
6234	tmp =
6235	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6236	BWN_PHY_WRITE(mac, tmp, 0x007f);
6237
6238	tmp = sav->phy_syncctl;
6239	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6240	tmp = sav->rf1;
6241	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6242
6243	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6244	if (phy->type == BWN_PHYTYPE_G ||
6245	    (phy->type == BWN_PHYTYPE_B &&
6246	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6247		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6248	} else
6249		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6250	if (phy->rev >= 2)
6251		bwn_dummy_transmission(mac, 0, 1);
6252	bwn_phy_g_switch_chan(mac, 6, 0);
6253	BWN_RF_READ(mac, 0x51);
6254	if (phy->type == BWN_PHYTYPE_G)
6255		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6256
6257	nanouptime(&ts);
6258	if (time_before(lo->txctl_measured_time,
6259	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6260		bwn_lo_measure_txctl_values(mac);
6261
6262	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6263		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6264	else {
6265		if (phy->type == BWN_PHYTYPE_B)
6266			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6267		else
6268			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6269	}
6270}
6271
6272static void
6273bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6274{
6275	struct bwn_phy *phy = &mac->mac_phy;
6276	struct bwn_phy_g *pg = &phy->phy_g;
6277	uint16_t tmp;
6278
6279	if (phy->rev >= 2) {
6280		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6281		tmp = (pg->pg_pga_gain << 8);
6282		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6283		DELAY(5);
6284		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6285		DELAY(2);
6286		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6287	} else {
6288		tmp = (pg->pg_pga_gain | 0xefa0);
6289		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6290	}
6291	if (phy->type == BWN_PHYTYPE_G) {
6292		if (phy->rev >= 3)
6293			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6294		else
6295			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6296		if (phy->rev >= 2)
6297			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6298		else
6299			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6300	}
6301	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6302	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6303	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6304	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6305	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6306	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6307	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6308	if (!BWN_HAS_TXMAG(phy)) {
6309		tmp = sav->rf2;
6310		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6311	}
6312	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6313	if (phy->type == BWN_PHYTYPE_B &&
6314	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6315		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6316		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6317	}
6318	if (phy->rev >= 2) {
6319		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6320		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6321			      sav->phy_analogoverval);
6322		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6323		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6324		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6325		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6326		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6327	}
6328	if (bwn_has_hwpctl(mac)) {
6329		tmp = (sav->phy_lomask & 0xbfff);
6330		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6331		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6332		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6333		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6334		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6335	}
6336	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6337}
6338
6339static int
6340bwn_lo_probe_loctl(struct bwn_mac *mac,
6341    struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6342{
6343	struct bwn_phy *phy = &mac->mac_phy;
6344	struct bwn_phy_g *pg = &phy->phy_g;
6345	struct bwn_loctl orig, test;
6346	struct bwn_loctl prev = { -100, -100 };
6347	static const struct bwn_loctl modifiers[] = {
6348		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6349		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6350	};
6351	int begin, end, lower = 0, i;
6352	uint16_t feedth;
6353
6354	if (d->curstate == 0) {
6355		begin = 1;
6356		end = 8;
6357	} else if (d->curstate % 2 == 0) {
6358		begin = d->curstate - 1;
6359		end = d->curstate + 1;
6360	} else {
6361		begin = d->curstate - 2;
6362		end = d->curstate + 2;
6363	}
6364	if (begin < 1)
6365		begin += 8;
6366	if (end > 8)
6367		end -= 8;
6368
6369	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6370	i = begin;
6371	d->curstate = i;
6372	while (1) {
6373		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6374		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6375		test.i += modifiers[i - 1].i * d->multipler;
6376		test.q += modifiers[i - 1].q * d->multipler;
6377		if ((test.i != prev.i || test.q != prev.q) &&
6378		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6379			bwn_lo_write(mac, &test);
6380			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6381			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6382			if (feedth < d->feedth) {
6383				memcpy(probe, &test,
6384				    sizeof(struct bwn_loctl));
6385				lower = 1;
6386				d->feedth = feedth;
6387				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6388					break;
6389			}
6390		}
6391		memcpy(&prev, &test, sizeof(prev));
6392		if (i == end)
6393			break;
6394		if (i == 8)
6395			i = 1;
6396		else
6397			i++;
6398		d->curstate = i;
6399	}
6400
6401	return (lower);
6402}
6403
6404static void
6405bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6406{
6407	struct bwn_phy *phy = &mac->mac_phy;
6408	struct bwn_phy_g *pg = &phy->phy_g;
6409	struct bwn_lo_g_sm d;
6410	struct bwn_loctl probe;
6411	int lower, repeat, cnt = 0;
6412	uint16_t feedth;
6413
6414	d.nmeasure = 0;
6415	d.multipler = 1;
6416	if (BWN_HAS_LOOPBACK(phy))
6417		d.multipler = 3;
6418
6419	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6420	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6421
6422	do {
6423		bwn_lo_write(mac, &d.loctl);
6424		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6425		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6426		if (feedth < 0x258) {
6427			if (feedth >= 0x12c)
6428				*rxgain += 6;
6429			else
6430				*rxgain += 3;
6431			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6432			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6433		}
6434		d.feedth = feedth;
6435		d.curstate = 0;
6436		do {
6437			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6438			    ("%s:%d: fail", __func__, __LINE__));
6439			memcpy(&probe, &d.loctl,
6440			       sizeof(struct bwn_loctl));
6441			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6442			if (!lower)
6443				break;
6444			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6445				break;
6446			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6447			d.nmeasure++;
6448		} while (d.nmeasure < 24);
6449		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6450
6451		if (BWN_HAS_LOOPBACK(phy)) {
6452			if (d.feedth > 0x1194)
6453				*rxgain -= 6;
6454			else if (d.feedth < 0x5dc)
6455				*rxgain += 3;
6456			if (cnt == 0) {
6457				if (d.feedth <= 0x5dc) {
6458					d.multipler = 1;
6459					cnt++;
6460				} else
6461					d.multipler = 2;
6462			} else if (cnt == 2)
6463				d.multipler = 1;
6464		}
6465		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6466	} while (++cnt < repeat);
6467}
6468
6469static struct bwn_lo_calib *
6470bwn_lo_calibset(struct bwn_mac *mac,
6471    const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6472{
6473	struct bwn_phy *phy = &mac->mac_phy;
6474	struct bwn_phy_g *pg = &phy->phy_g;
6475	struct bwn_loctl loctl = { 0, 0 };
6476	struct bwn_lo_calib *cal;
6477	struct bwn_lo_g_value sval = { 0 };
6478	int rxgain;
6479	uint16_t pad, reg, value;
6480
6481	sval.old_channel = phy->chan;
6482	bwn_mac_suspend(mac);
6483	bwn_lo_save(mac, &sval);
6484
6485	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6486	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6487	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6488
6489	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6490	if (rfatt->padmix)
6491		rxgain -= pad;
6492	if (BWN_HAS_LOOPBACK(phy))
6493		rxgain += pg->pg_max_lb_gain;
6494	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6495	bwn_phy_g_set_bbatt(mac, bbatt->att);
6496	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6497
6498	bwn_lo_restore(mac, &sval);
6499	bwn_mac_enable(mac);
6500
6501	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6502	if (!cal) {
6503		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6504		return (NULL);
6505	}
6506	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6507	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6508	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6509
6510	BWN_GETTIME(cal->calib_time);
6511
6512	return (cal);
6513}
6514
6515static struct bwn_lo_calib *
6516bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6517    const struct bwn_rfatt *rfatt)
6518{
6519	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6520	struct bwn_lo_calib *c;
6521
6522	TAILQ_FOREACH(c, &lo->calib_list, list) {
6523		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6524			continue;
6525		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6526			continue;
6527		return (c);
6528	}
6529
6530	c = bwn_lo_calibset(mac, bbatt, rfatt);
6531	if (!c)
6532		return (NULL);
6533	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6534
6535	return (c);
6536}
6537
6538static void
6539bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6540{
6541	struct bwn_phy *phy = &mac->mac_phy;
6542	struct bwn_phy_g *pg = &phy->phy_g;
6543	struct bwn_softc *sc = mac->mac_sc;
6544	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6545	const struct bwn_rfatt *rfatt;
6546	const struct bwn_bbatt *bbatt;
6547	uint64_t pvector;
6548	int i;
6549	int rf_offset, bb_offset;
6550	uint8_t changed = 0;
6551
6552	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6553	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6554	    ("%s:%d: fail", __func__, __LINE__));
6555
6556	pvector = lo->power_vector;
6557	if (!update && !pvector)
6558		return;
6559
6560	bwn_mac_suspend(mac);
6561
6562	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6563		struct bwn_lo_calib *cal;
6564		int idx;
6565		uint16_t val;
6566
6567		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6568			continue;
6569		bb_offset = i / lo->rfatt.len;
6570		rf_offset = i % lo->rfatt.len;
6571		bbatt = &(lo->bbatt.array[bb_offset]);
6572		rfatt = &(lo->rfatt.array[rf_offset]);
6573
6574		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6575		if (!cal) {
6576			device_printf(sc->sc_dev, "LO: Could not "
6577			    "calibrate DC table entry\n");
6578			continue;
6579		}
6580		val = (uint8_t)(cal->ctl.q);
6581		val |= ((uint8_t)(cal->ctl.i)) << 4;
6582		free(cal, M_DEVBUF);
6583
6584		idx = i / 2;
6585		if (i % 2)
6586			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6587			    | ((val & 0x00ff) << 8);
6588		else
6589			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6590			    | (val & 0x00ff);
6591		changed = 1;
6592	}
6593	if (changed) {
6594		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6595			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6596	}
6597	bwn_mac_enable(mac);
6598}
6599
6600static void
6601bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6602{
6603
6604	if (!rf->padmix)
6605		return;
6606	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6607		rf->att = 4;
6608}
6609
6610static void
6611bwn_lo_g_adjust(struct bwn_mac *mac)
6612{
6613	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6614	struct bwn_lo_calib *cal;
6615	struct bwn_rfatt rf;
6616
6617	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6618	bwn_lo_fixup_rfatt(&rf);
6619
6620	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6621	if (!cal)
6622		return;
6623	bwn_lo_write(mac, &cal->ctl);
6624}
6625
6626static void
6627bwn_lo_g_init(struct bwn_mac *mac)
6628{
6629
6630	if (!bwn_has_hwpctl(mac))
6631		return;
6632
6633	bwn_lo_get_powervector(mac);
6634	bwn_phy_g_dc_lookup_init(mac, 1);
6635}
6636
6637static void
6638bwn_mac_suspend(struct bwn_mac *mac)
6639{
6640	struct bwn_softc *sc = mac->mac_sc;
6641	int i;
6642	uint32_t tmp;
6643
6644	KASSERT(mac->mac_suspended >= 0,
6645	    ("%s:%d: fail", __func__, __LINE__));
6646
6647	if (mac->mac_suspended == 0) {
6648		bwn_psctl(mac, BWN_PS_AWAKE);
6649		BWN_WRITE_4(mac, BWN_MACCTL,
6650			    BWN_READ_4(mac, BWN_MACCTL)
6651			    & ~BWN_MACCTL_ON);
6652		BWN_READ_4(mac, BWN_MACCTL);
6653		for (i = 35; i; i--) {
6654			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6655			if (tmp & BWN_INTR_MAC_SUSPENDED)
6656				goto out;
6657			DELAY(10);
6658		}
6659		for (i = 40; i; i--) {
6660			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6661			if (tmp & BWN_INTR_MAC_SUSPENDED)
6662				goto out;
6663			DELAY(1000);
6664		}
6665		device_printf(sc->sc_dev, "MAC suspend failed\n");
6666	}
6667out:
6668	mac->mac_suspended++;
6669}
6670
6671static void
6672bwn_mac_enable(struct bwn_mac *mac)
6673{
6674	struct bwn_softc *sc = mac->mac_sc;
6675	uint16_t state;
6676
6677	state = bwn_shm_read_2(mac, BWN_SHARED,
6678	    BWN_SHARED_UCODESTAT);
6679	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6680	    state != BWN_SHARED_UCODESTAT_SLEEP)
6681		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6682
6683	mac->mac_suspended--;
6684	KASSERT(mac->mac_suspended >= 0,
6685	    ("%s:%d: fail", __func__, __LINE__));
6686	if (mac->mac_suspended == 0) {
6687		BWN_WRITE_4(mac, BWN_MACCTL,
6688		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6689		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6690		BWN_READ_4(mac, BWN_MACCTL);
6691		BWN_READ_4(mac, BWN_INTR_REASON);
6692		bwn_psctl(mac, 0);
6693	}
6694}
6695
6696static void
6697bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6698{
6699	struct bwn_softc *sc = mac->mac_sc;
6700	int i;
6701	uint16_t ucstat;
6702
6703	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6704	    ("%s:%d: fail", __func__, __LINE__));
6705	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6706	    ("%s:%d: fail", __func__, __LINE__));
6707
6708	/* XXX forcibly awake and hwps-off */
6709
6710	BWN_WRITE_4(mac, BWN_MACCTL,
6711	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6712	    ~BWN_MACCTL_HWPS);
6713	BWN_READ_4(mac, BWN_MACCTL);
6714	if (siba_get_revid(sc->sc_dev) >= 5) {
6715		for (i = 0; i < 100; i++) {
6716			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6717			    BWN_SHARED_UCODESTAT);
6718			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6719				break;
6720			DELAY(10);
6721		}
6722	}
6723}
6724
6725static int16_t
6726bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6727{
6728
6729	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6730	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6731}
6732
6733static void
6734bwn_nrssi_threshold(struct bwn_mac *mac)
6735{
6736	struct bwn_phy *phy = &mac->mac_phy;
6737	struct bwn_phy_g *pg = &phy->phy_g;
6738	struct bwn_softc *sc = mac->mac_sc;
6739	int32_t a, b;
6740	int16_t tmp16;
6741	uint16_t tmpu16;
6742
6743	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6744
6745	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6746		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6747			a = 0x13;
6748			b = 0x12;
6749		} else {
6750			a = 0xe;
6751			b = 0x11;
6752		}
6753
6754		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6755		a += (pg->pg_nrssi[0] << 6);
6756		a += (a < 32) ? 31 : 32;
6757		a = a >> 6;
6758		a = MIN(MAX(a, -31), 31);
6759
6760		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6761		b += (pg->pg_nrssi[0] << 6);
6762		if (b < 32)
6763			b += 31;
6764		else
6765			b += 32;
6766		b = b >> 6;
6767		b = MIN(MAX(b, -31), 31);
6768
6769		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6770		tmpu16 |= ((uint32_t)b & 0x0000003f);
6771		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6772		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6773		return;
6774	}
6775
6776	tmp16 = bwn_nrssi_read(mac, 0x20);
6777	if (tmp16 >= 0x20)
6778		tmp16 -= 0x40;
6779	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6780}
6781
6782static void
6783bwn_nrssi_slope_11g(struct bwn_mac *mac)
6784{
6785#define	SAVE_RF_MAX		3
6786#define	SAVE_PHY_COMM_MAX	4
6787#define	SAVE_PHY3_MAX		8
6788	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6789		{ 0x7a, 0x52, 0x43 };
6790	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6791		{ 0x15, 0x5a, 0x59, 0x58 };
6792	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6793		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6794		0x0801, 0x0060, 0x0014, 0x0478
6795	};
6796	struct bwn_phy *phy = &mac->mac_phy;
6797	struct bwn_phy_g *pg = &phy->phy_g;
6798	int32_t i, tmp32, phy3_idx = 0;
6799	uint16_t delta, tmp;
6800	uint16_t save_rf[SAVE_RF_MAX];
6801	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6802	uint16_t save_phy3[SAVE_PHY3_MAX];
6803	uint16_t ant_div, phy0, chan_ex;
6804	int16_t nrssi0, nrssi1;
6805
6806	KASSERT(phy->type == BWN_PHYTYPE_G,
6807	    ("%s:%d: fail", __func__, __LINE__));
6808
6809	if (phy->rf_rev >= 9)
6810		return;
6811	if (phy->rf_rev == 8)
6812		bwn_nrssi_offset(mac);
6813
6814	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6815	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6816
6817	/*
6818	 * Save RF/PHY registers for later restoration
6819	 */
6820	ant_div = BWN_READ_2(mac, 0x03e2);
6821	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6822	for (i = 0; i < SAVE_RF_MAX; ++i)
6823		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6824	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6825		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6826
6827	phy0 = BWN_READ_2(mac, BWN_PHY0);
6828	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6829	if (phy->rev >= 3) {
6830		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6831			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6832		BWN_PHY_WRITE(mac, 0x002e, 0);
6833		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6834		switch (phy->rev) {
6835		case 4:
6836		case 6:
6837		case 7:
6838			BWN_PHY_SET(mac, 0x0478, 0x0100);
6839			BWN_PHY_SET(mac, 0x0801, 0x0040);
6840			break;
6841		case 3:
6842		case 5:
6843			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6844			break;
6845		}
6846		BWN_PHY_SET(mac, 0x0060, 0x0040);
6847		BWN_PHY_SET(mac, 0x0014, 0x0200);
6848	}
6849	/*
6850	 * Calculate nrssi0
6851	 */
6852	BWN_RF_SET(mac, 0x007a, 0x0070);
6853	bwn_set_all_gains(mac, 0, 8, 0);
6854	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6855	if (phy->rev >= 2) {
6856		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6857		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6858	}
6859	BWN_RF_SET(mac, 0x007a, 0x0080);
6860	DELAY(20);
6861
6862	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6863	if (nrssi0 >= 0x0020)
6864		nrssi0 -= 0x0040;
6865
6866	/*
6867	 * Calculate nrssi1
6868	 */
6869	BWN_RF_MASK(mac, 0x007a, 0x007f);
6870	if (phy->rev >= 2)
6871		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6872
6873	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6874	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6875	BWN_RF_SET(mac, 0x007a, 0x000f);
6876	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6877	if (phy->rev >= 2) {
6878		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6879		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6880	}
6881
6882	bwn_set_all_gains(mac, 3, 0, 1);
6883	if (phy->rf_rev == 8) {
6884		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6885	} else {
6886		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6887		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6888		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6889		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6890	}
6891	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6892	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6893	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6894	DELAY(20);
6895	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6896
6897	/*
6898	 * Install calculated narrow RSSI values
6899	 */
6900	if (nrssi1 >= 0x0020)
6901		nrssi1 -= 0x0040;
6902	if (nrssi0 == nrssi1)
6903		pg->pg_nrssi_slope = 0x00010000;
6904	else
6905		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6906	if (nrssi0 >= -4) {
6907		pg->pg_nrssi[0] = nrssi1;
6908		pg->pg_nrssi[1] = nrssi0;
6909	}
6910
6911	/*
6912	 * Restore saved RF/PHY registers
6913	 */
6914	if (phy->rev >= 3) {
6915		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6916			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6917			    save_phy3[phy3_idx]);
6918		}
6919	}
6920	if (phy->rev >= 2) {
6921		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6922		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6923	}
6924
6925	for (i = 0; i < SAVE_RF_MAX; ++i)
6926		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6927
6928	BWN_WRITE_2(mac, 0x03e2, ant_div);
6929	BWN_WRITE_2(mac, 0x03e6, phy0);
6930	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6931
6932	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6933		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6934
6935	bwn_spu_workaround(mac, phy->chan);
6936	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6937	bwn_set_original_gains(mac);
6938	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6939	if (phy->rev >= 3) {
6940		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6941			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6942			    save_phy3[phy3_idx]);
6943		}
6944	}
6945
6946	delta = 0x1f - pg->pg_nrssi[0];
6947	for (i = 0; i < 64; i++) {
6948		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6949		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6950		pg->pg_nrssi_lt[i] = tmp32;
6951	}
6952
6953	bwn_nrssi_threshold(mac);
6954#undef SAVE_RF_MAX
6955#undef SAVE_PHY_COMM_MAX
6956#undef SAVE_PHY3_MAX
6957}
6958
6959static void
6960bwn_nrssi_offset(struct bwn_mac *mac)
6961{
6962#define	SAVE_RF_MAX		2
6963#define	SAVE_PHY_COMM_MAX	10
6964#define	SAVE_PHY6_MAX		8
6965	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6966		{ 0x7a, 0x43 };
6967	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6968		0x0001, 0x0811, 0x0812, 0x0814,
6969		0x0815, 0x005a, 0x0059, 0x0058,
6970		0x000a, 0x0003
6971	};
6972	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6973		0x002e, 0x002f, 0x080f, 0x0810,
6974		0x0801, 0x0060, 0x0014, 0x0478
6975	};
6976	struct bwn_phy *phy = &mac->mac_phy;
6977	int i, phy6_idx = 0;
6978	uint16_t save_rf[SAVE_RF_MAX];
6979	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6980	uint16_t save_phy6[SAVE_PHY6_MAX];
6981	int16_t nrssi;
6982	uint16_t saved = 0xffff;
6983
6984	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6985		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6986	for (i = 0; i < SAVE_RF_MAX; ++i)
6987		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6988
6989	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6990	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6991	BWN_PHY_SET(mac, 0x0811, 0x000c);
6992	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6993	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6994	if (phy->rev >= 6) {
6995		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6996			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6997
6998		BWN_PHY_WRITE(mac, 0x002e, 0);
6999		BWN_PHY_WRITE(mac, 0x002f, 0);
7000		BWN_PHY_WRITE(mac, 0x080f, 0);
7001		BWN_PHY_WRITE(mac, 0x0810, 0);
7002		BWN_PHY_SET(mac, 0x0478, 0x0100);
7003		BWN_PHY_SET(mac, 0x0801, 0x0040);
7004		BWN_PHY_SET(mac, 0x0060, 0x0040);
7005		BWN_PHY_SET(mac, 0x0014, 0x0200);
7006	}
7007	BWN_RF_SET(mac, 0x007a, 0x0070);
7008	BWN_RF_SET(mac, 0x007a, 0x0080);
7009	DELAY(30);
7010
7011	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7012	if (nrssi >= 0x20)
7013		nrssi -= 0x40;
7014	if (nrssi == 31) {
7015		for (i = 7; i >= 4; i--) {
7016			BWN_RF_WRITE(mac, 0x007b, i);
7017			DELAY(20);
7018			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7019			    0x003f);
7020			if (nrssi >= 0x20)
7021				nrssi -= 0x40;
7022			if (nrssi < 31 && saved == 0xffff)
7023				saved = i;
7024		}
7025		if (saved == 0xffff)
7026			saved = 4;
7027	} else {
7028		BWN_RF_MASK(mac, 0x007a, 0x007f);
7029		if (phy->rev != 1) {
7030			BWN_PHY_SET(mac, 0x0814, 0x0001);
7031			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7032		}
7033		BWN_PHY_SET(mac, 0x0811, 0x000c);
7034		BWN_PHY_SET(mac, 0x0812, 0x000c);
7035		BWN_PHY_SET(mac, 0x0811, 0x0030);
7036		BWN_PHY_SET(mac, 0x0812, 0x0030);
7037		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7038		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7039		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7040		if (phy->rev == 0)
7041			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7042		else
7043			BWN_PHY_SET(mac, 0x000a, 0x2000);
7044		if (phy->rev != 1) {
7045			BWN_PHY_SET(mac, 0x0814, 0x0004);
7046			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7047		}
7048		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7049		BWN_RF_SET(mac, 0x007a, 0x000f);
7050		bwn_set_all_gains(mac, 3, 0, 1);
7051		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7052		DELAY(30);
7053		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7054		if (nrssi >= 0x20)
7055			nrssi -= 0x40;
7056		if (nrssi == -32) {
7057			for (i = 0; i < 4; i++) {
7058				BWN_RF_WRITE(mac, 0x007b, i);
7059				DELAY(20);
7060				nrssi = (int16_t)((BWN_PHY_READ(mac,
7061				    0x047f) >> 8) & 0x003f);
7062				if (nrssi >= 0x20)
7063					nrssi -= 0x40;
7064				if (nrssi > -31 && saved == 0xffff)
7065					saved = i;
7066			}
7067			if (saved == 0xffff)
7068				saved = 3;
7069		} else
7070			saved = 0;
7071	}
7072	BWN_RF_WRITE(mac, 0x007b, saved);
7073
7074	/*
7075	 * Restore saved RF/PHY registers
7076	 */
7077	if (phy->rev >= 6) {
7078		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7079			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7080			    save_phy6[phy6_idx]);
7081		}
7082	}
7083	if (phy->rev != 1) {
7084		for (i = 3; i < 5; i++)
7085			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7086			    save_phy_comm[i]);
7087	}
7088	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7089		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7090
7091	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7092		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7093
7094	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7095	BWN_PHY_SET(mac, 0x0429, 0x8000);
7096	bwn_set_original_gains(mac);
7097	if (phy->rev >= 6) {
7098		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7099			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7100			    save_phy6[phy6_idx]);
7101		}
7102	}
7103
7104	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7105	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7106	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7107}
7108
7109static void
7110bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7111    int16_t third)
7112{
7113	struct bwn_phy *phy = &mac->mac_phy;
7114	uint16_t i;
7115	uint16_t start = 0x08, end = 0x18;
7116	uint16_t tmp;
7117	uint16_t table;
7118
7119	if (phy->rev <= 1) {
7120		start = 0x10;
7121		end = 0x20;
7122	}
7123
7124	table = BWN_OFDMTAB_GAINX;
7125	if (phy->rev <= 1)
7126		table = BWN_OFDMTAB_GAINX_R1;
7127	for (i = 0; i < 4; i++)
7128		bwn_ofdmtab_write_2(mac, table, i, first);
7129
7130	for (i = start; i < end; i++)
7131		bwn_ofdmtab_write_2(mac, table, i, second);
7132
7133	if (third != -1) {
7134		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7135		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7136		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7137		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7138	}
7139	bwn_dummy_transmission(mac, 0, 1);
7140}
7141
7142static void
7143bwn_set_original_gains(struct bwn_mac *mac)
7144{
7145	struct bwn_phy *phy = &mac->mac_phy;
7146	uint16_t i, tmp;
7147	uint16_t table;
7148	uint16_t start = 0x0008, end = 0x0018;
7149
7150	if (phy->rev <= 1) {
7151		start = 0x0010;
7152		end = 0x0020;
7153	}
7154
7155	table = BWN_OFDMTAB_GAINX;
7156	if (phy->rev <= 1)
7157		table = BWN_OFDMTAB_GAINX_R1;
7158	for (i = 0; i < 4; i++) {
7159		tmp = (i & 0xfffc);
7160		tmp |= (i & 0x0001) << 1;
7161		tmp |= (i & 0x0002) >> 1;
7162
7163		bwn_ofdmtab_write_2(mac, table, i, tmp);
7164	}
7165
7166	for (i = start; i < end; i++)
7167		bwn_ofdmtab_write_2(mac, table, i, i - start);
7168
7169	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7170	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7171	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7172	bwn_dummy_transmission(mac, 0, 1);
7173}
7174
7175static void
7176bwn_phy_hwpctl_init(struct bwn_mac *mac)
7177{
7178	struct bwn_phy *phy = &mac->mac_phy;
7179	struct bwn_phy_g *pg = &phy->phy_g;
7180	struct bwn_rfatt old_rfatt, rfatt;
7181	struct bwn_bbatt old_bbatt, bbatt;
7182	struct bwn_softc *sc = mac->mac_sc;
7183	uint8_t old_txctl = 0;
7184
7185	KASSERT(phy->type == BWN_PHYTYPE_G,
7186	    ("%s:%d: fail", __func__, __LINE__));
7187
7188	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7189	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7190		return;
7191
7192	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7193
7194	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7195
7196	if (!phy->gmode)
7197		return;
7198	bwn_hwpctl_early_init(mac);
7199	if (pg->pg_curtssi == 0) {
7200		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7201			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7202		} else {
7203			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7204			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7205			old_txctl = pg->pg_txctl;
7206
7207			bbatt.att = 11;
7208			if (phy->rf_rev == 8) {
7209				rfatt.att = 15;
7210				rfatt.padmix = 1;
7211			} else {
7212				rfatt.att = 9;
7213				rfatt.padmix = 0;
7214			}
7215			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7216		}
7217		bwn_dummy_transmission(mac, 0, 1);
7218		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7219		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7220			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7221		else
7222			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7223			    &old_rfatt, old_txctl);
7224	}
7225	bwn_hwpctl_init_gphy(mac);
7226
7227	/* clear TSSI */
7228	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7229	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7230	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7231	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7232}
7233
7234static void
7235bwn_hwpctl_early_init(struct bwn_mac *mac)
7236{
7237	struct bwn_phy *phy = &mac->mac_phy;
7238
7239	if (!bwn_has_hwpctl(mac)) {
7240		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7241		return;
7242	}
7243
7244	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7245	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7246	BWN_PHY_SET(mac, 0x047c, 0x0002);
7247	BWN_PHY_SET(mac, 0x047a, 0xf000);
7248	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7249		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7250		BWN_PHY_SET(mac, 0x005d, 0x8000);
7251		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7252		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7253		BWN_PHY_SET(mac, 0x0036, 0x0400);
7254	} else {
7255		BWN_PHY_SET(mac, 0x0036, 0x0200);
7256		BWN_PHY_SET(mac, 0x0036, 0x0400);
7257		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7258		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7259		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7260		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7261		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7262	}
7263}
7264
7265static void
7266bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7267{
7268	struct bwn_phy *phy = &mac->mac_phy;
7269	struct bwn_phy_g *pg = &phy->phy_g;
7270	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7271	int i;
7272	uint16_t nr_written = 0, tmp, value;
7273	uint8_t rf, bb;
7274
7275	if (!bwn_has_hwpctl(mac)) {
7276		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7277		return;
7278	}
7279
7280	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7281	    (pg->pg_idletssi - pg->pg_curtssi));
7282	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7283	    (pg->pg_idletssi - pg->pg_curtssi));
7284
7285	for (i = 0; i < 32; i++)
7286		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7287	for (i = 32; i < 64; i++)
7288		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7289	for (i = 0; i < 64; i += 2) {
7290		value = (uint16_t) pg->pg_tssi2dbm[i];
7291		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7292		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7293	}
7294
7295	for (rf = 0; rf < lo->rfatt.len; rf++) {
7296		for (bb = 0; bb < lo->bbatt.len; bb++) {
7297			if (nr_written >= 0x40)
7298				return;
7299			tmp = lo->bbatt.array[bb].att;
7300			tmp <<= 8;
7301			if (phy->rf_rev == 8)
7302				tmp |= 0x50;
7303			else
7304				tmp |= 0x40;
7305			tmp |= lo->rfatt.array[rf].att;
7306			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7307			nr_written++;
7308		}
7309	}
7310
7311	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7312	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7313
7314	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7315	BWN_PHY_SET(mac, 0x0478, 0x0800);
7316	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7317	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7318
7319	bwn_phy_g_dc_lookup_init(mac, 1);
7320	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7321}
7322
7323static void
7324bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7325{
7326	struct bwn_softc *sc = mac->mac_sc;
7327
7328	if (spu != 0)
7329		bwn_spu_workaround(mac, channel);
7330
7331	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7332
7333	if (channel == 14) {
7334		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7335			bwn_hf_write(mac,
7336			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7337		else
7338			bwn_hf_write(mac,
7339			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7340		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7341		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7342		return;
7343	}
7344
7345	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7346	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7347}
7348
7349static uint16_t
7350bwn_phy_g_chan2freq(uint8_t channel)
7351{
7352	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7353
7354	KASSERT(channel >= 1 && channel <= 14,
7355	    ("%s:%d: fail", __func__, __LINE__));
7356
7357	return (bwn_phy_g_rf_channels[channel - 1]);
7358}
7359
7360static void
7361bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7362    const struct bwn_rfatt *rfatt, uint8_t txctl)
7363{
7364	struct bwn_phy *phy = &mac->mac_phy;
7365	struct bwn_phy_g *pg = &phy->phy_g;
7366	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7367	uint16_t bb, rf;
7368	uint16_t tx_bias, tx_magn;
7369
7370	bb = bbatt->att;
7371	rf = rfatt->att;
7372	tx_bias = lo->tx_bias;
7373	tx_magn = lo->tx_magn;
7374	if (tx_bias == 0xff)
7375		tx_bias = 0;
7376
7377	pg->pg_txctl = txctl;
7378	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7379	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7380	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7381	bwn_phy_g_set_bbatt(mac, bb);
7382	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7383	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7384		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7385	else {
7386		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7387		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7388	}
7389	if (BWN_HAS_TXMAG(phy))
7390		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7391	else
7392		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7393	bwn_lo_g_adjust(mac);
7394}
7395
7396static void
7397bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7398    uint16_t bbatt)
7399{
7400	struct bwn_phy *phy = &mac->mac_phy;
7401
7402	if (phy->analog == 0) {
7403		BWN_WRITE_2(mac, BWN_PHY0,
7404		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7405		return;
7406	}
7407	if (phy->analog > 1) {
7408		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7409		return;
7410	}
7411	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7412}
7413
7414static uint16_t
7415bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7416{
7417	struct bwn_phy *phy = &mac->mac_phy;
7418	struct bwn_phy_g *pg = &phy->phy_g;
7419	struct bwn_softc *sc = mac->mac_sc;
7420	int max_lb_gain;
7421	uint16_t extlna;
7422	uint16_t i;
7423
7424	if (phy->gmode == 0)
7425		return (0);
7426
7427	if (BWN_HAS_LOOPBACK(phy)) {
7428		max_lb_gain = pg->pg_max_lb_gain;
7429		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7430		if (max_lb_gain >= 0x46) {
7431			extlna = 0x3000;
7432			max_lb_gain -= 0x46;
7433		} else if (max_lb_gain >= 0x3a) {
7434			extlna = 0x1000;
7435			max_lb_gain -= 0x3a;
7436		} else if (max_lb_gain >= 0x2e) {
7437			extlna = 0x2000;
7438			max_lb_gain -= 0x2e;
7439		} else {
7440			extlna = 0;
7441			max_lb_gain -= 0x10;
7442		}
7443
7444		for (i = 0; i < 16; i++) {
7445			max_lb_gain -= (i * 6);
7446			if (max_lb_gain < 6)
7447				break;
7448		}
7449
7450		if ((phy->rev < 7) ||
7451		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7452			if (reg == BWN_PHY_RFOVER) {
7453				return (0x1b3);
7454			} else if (reg == BWN_PHY_RFOVERVAL) {
7455				extlna |= (i << 8);
7456				switch (lpd) {
7457				case BWN_LPD(0, 1, 1):
7458					return (0x0f92);
7459				case BWN_LPD(0, 0, 1):
7460				case BWN_LPD(1, 0, 1):
7461					return (0x0092 | extlna);
7462				case BWN_LPD(1, 0, 0):
7463					return (0x0093 | extlna);
7464				}
7465				KASSERT(0 == 1,
7466				    ("%s:%d: fail", __func__, __LINE__));
7467			}
7468			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7469		} else {
7470			if (reg == BWN_PHY_RFOVER)
7471				return (0x9b3);
7472			if (reg == BWN_PHY_RFOVERVAL) {
7473				if (extlna)
7474					extlna |= 0x8000;
7475				extlna |= (i << 8);
7476				switch (lpd) {
7477				case BWN_LPD(0, 1, 1):
7478					return (0x8f92);
7479				case BWN_LPD(0, 0, 1):
7480					return (0x8092 | extlna);
7481				case BWN_LPD(1, 0, 1):
7482					return (0x2092 | extlna);
7483				case BWN_LPD(1, 0, 0):
7484					return (0x2093 | extlna);
7485				}
7486				KASSERT(0 == 1,
7487				    ("%s:%d: fail", __func__, __LINE__));
7488			}
7489			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7490		}
7491		return (0);
7492	}
7493
7494	if ((phy->rev < 7) ||
7495	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7496		if (reg == BWN_PHY_RFOVER) {
7497			return (0x1b3);
7498		} else if (reg == BWN_PHY_RFOVERVAL) {
7499			switch (lpd) {
7500			case BWN_LPD(0, 1, 1):
7501				return (0x0fb2);
7502			case BWN_LPD(0, 0, 1):
7503				return (0x00b2);
7504			case BWN_LPD(1, 0, 1):
7505				return (0x30b2);
7506			case BWN_LPD(1, 0, 0):
7507				return (0x30b3);
7508			}
7509			KASSERT(0 == 1,
7510			    ("%s:%d: fail", __func__, __LINE__));
7511		}
7512		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7513	} else {
7514		if (reg == BWN_PHY_RFOVER) {
7515			return (0x9b3);
7516		} else if (reg == BWN_PHY_RFOVERVAL) {
7517			switch (lpd) {
7518			case BWN_LPD(0, 1, 1):
7519				return (0x8fb2);
7520			case BWN_LPD(0, 0, 1):
7521				return (0x80b2);
7522			case BWN_LPD(1, 0, 1):
7523				return (0x20b2);
7524			case BWN_LPD(1, 0, 0):
7525				return (0x20b3);
7526			}
7527			KASSERT(0 == 1,
7528			    ("%s:%d: fail", __func__, __LINE__));
7529		}
7530		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7531	}
7532	return (0);
7533}
7534
7535static void
7536bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7537{
7538
7539	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7540		return;
7541	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7542	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7543	DELAY(1000);
7544	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7545}
7546
7547static int
7548bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7549{
7550	struct bwn_softc *sc = mac->mac_sc;
7551	struct bwn_fw *fw = &mac->mac_fw;
7552	const uint8_t rev = siba_get_revid(sc->sc_dev);
7553	const char *filename;
7554	uint32_t high;
7555	int error;
7556
7557	/* microcode */
7558	if (rev >= 5 && rev <= 10)
7559		filename = "ucode5";
7560	else if (rev >= 11 && rev <= 12)
7561		filename = "ucode11";
7562	else if (rev == 13)
7563		filename = "ucode13";
7564	else if (rev == 14)
7565		filename = "ucode14";
7566	else if (rev >= 15)
7567		filename = "ucode15";
7568	else {
7569		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7570		bwn_release_firmware(mac);
7571		return (EOPNOTSUPP);
7572	}
7573	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7574	if (error) {
7575		bwn_release_firmware(mac);
7576		return (error);
7577	}
7578
7579	/* PCM */
7580	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7581	if (rev >= 5 && rev <= 10) {
7582		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7583		if (error == ENOENT)
7584			fw->no_pcmfile = 1;
7585		else if (error) {
7586			bwn_release_firmware(mac);
7587			return (error);
7588		}
7589	} else if (rev < 11) {
7590		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7591		return (EOPNOTSUPP);
7592	}
7593
7594	/* initvals */
7595	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7596	switch (mac->mac_phy.type) {
7597	case BWN_PHYTYPE_A:
7598		if (rev < 5 || rev > 10)
7599			goto fail1;
7600		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7601			filename = "a0g1initvals5";
7602		else
7603			filename = "a0g0initvals5";
7604		break;
7605	case BWN_PHYTYPE_G:
7606		if (rev >= 5 && rev <= 10)
7607			filename = "b0g0initvals5";
7608		else if (rev >= 13)
7609			filename = "b0g0initvals13";
7610		else
7611			goto fail1;
7612		break;
7613	case BWN_PHYTYPE_LP:
7614		if (rev == 13)
7615			filename = "lp0initvals13";
7616		else if (rev == 14)
7617			filename = "lp0initvals14";
7618		else if (rev >= 15)
7619			filename = "lp0initvals15";
7620		else
7621			goto fail1;
7622		break;
7623	case BWN_PHYTYPE_N:
7624		if (rev >= 11 && rev <= 12)
7625			filename = "n0initvals11";
7626		else
7627			goto fail1;
7628		break;
7629	default:
7630		goto fail1;
7631	}
7632	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7633	if (error) {
7634		bwn_release_firmware(mac);
7635		return (error);
7636	}
7637
7638	/* bandswitch initvals */
7639	switch (mac->mac_phy.type) {
7640	case BWN_PHYTYPE_A:
7641		if (rev >= 5 && rev <= 10) {
7642			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7643				filename = "a0g1bsinitvals5";
7644			else
7645				filename = "a0g0bsinitvals5";
7646		} else if (rev >= 11)
7647			filename = NULL;
7648		else
7649			goto fail1;
7650		break;
7651	case BWN_PHYTYPE_G:
7652		if (rev >= 5 && rev <= 10)
7653			filename = "b0g0bsinitvals5";
7654		else if (rev >= 11)
7655			filename = NULL;
7656		else
7657			goto fail1;
7658		break;
7659	case BWN_PHYTYPE_LP:
7660		if (rev == 13)
7661			filename = "lp0bsinitvals13";
7662		else if (rev == 14)
7663			filename = "lp0bsinitvals14";
7664		else if (rev >= 15)
7665			filename = "lp0bsinitvals15";
7666		else
7667			goto fail1;
7668		break;
7669	case BWN_PHYTYPE_N:
7670		if (rev >= 11 && rev <= 12)
7671			filename = "n0bsinitvals11";
7672		else
7673			goto fail1;
7674		break;
7675	default:
7676		goto fail1;
7677	}
7678	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7679	if (error) {
7680		bwn_release_firmware(mac);
7681		return (error);
7682	}
7683	return (0);
7684fail1:
7685	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7686	bwn_release_firmware(mac);
7687	return (EOPNOTSUPP);
7688}
7689
7690static int
7691bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7692    const char *name, struct bwn_fwfile *bfw)
7693{
7694	const struct bwn_fwhdr *hdr;
7695	struct bwn_softc *sc = mac->mac_sc;
7696	const struct firmware *fw;
7697	char namebuf[64];
7698
7699	if (name == NULL) {
7700		bwn_do_release_fw(bfw);
7701		return (0);
7702	}
7703	if (bfw->filename != NULL) {
7704		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7705			return (0);
7706		bwn_do_release_fw(bfw);
7707	}
7708
7709	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7710	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7711	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7712	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7713	fw = firmware_get(namebuf);
7714	if (fw == NULL) {
7715		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7716		    namebuf);
7717		return (ENOENT);
7718	}
7719	if (fw->datasize < sizeof(struct bwn_fwhdr))
7720		goto fail;
7721	hdr = (const struct bwn_fwhdr *)(fw->data);
7722	switch (hdr->type) {
7723	case BWN_FWTYPE_UCODE:
7724	case BWN_FWTYPE_PCM:
7725		if (be32toh(hdr->size) !=
7726		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7727			goto fail;
7728		/* FALLTHROUGH */
7729	case BWN_FWTYPE_IV:
7730		if (hdr->ver != 1)
7731			goto fail;
7732		break;
7733	default:
7734		goto fail;
7735	}
7736	bfw->filename = name;
7737	bfw->fw = fw;
7738	bfw->type = type;
7739	return (0);
7740fail:
7741	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7742	if (fw != NULL)
7743		firmware_put(fw, FIRMWARE_UNLOAD);
7744	return (EPROTO);
7745}
7746
7747static void
7748bwn_release_firmware(struct bwn_mac *mac)
7749{
7750
7751	bwn_do_release_fw(&mac->mac_fw.ucode);
7752	bwn_do_release_fw(&mac->mac_fw.pcm);
7753	bwn_do_release_fw(&mac->mac_fw.initvals);
7754	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7755}
7756
7757static void
7758bwn_do_release_fw(struct bwn_fwfile *bfw)
7759{
7760
7761	if (bfw->fw != NULL)
7762		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7763	bfw->fw = NULL;
7764	bfw->filename = NULL;
7765}
7766
7767static int
7768bwn_fw_loaducode(struct bwn_mac *mac)
7769{
7770#define	GETFWOFFSET(fwp, offset)	\
7771	((const uint32_t *)((const char *)fwp.fw->data + offset))
7772#define	GETFWSIZE(fwp, offset)	\
7773	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7774	struct bwn_softc *sc = mac->mac_sc;
7775	const uint32_t *data;
7776	unsigned int i;
7777	uint32_t ctl;
7778	uint16_t date, fwcaps, time;
7779	int error = 0;
7780
7781	ctl = BWN_READ_4(mac, BWN_MACCTL);
7782	ctl |= BWN_MACCTL_MCODE_JMP0;
7783	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7784	    __LINE__));
7785	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7786	for (i = 0; i < 64; i++)
7787		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7788	for (i = 0; i < 4096; i += 2)
7789		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7790
7791	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7792	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7793	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7794	     i++) {
7795		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7796		DELAY(10);
7797	}
7798
7799	if (mac->mac_fw.pcm.fw) {
7800		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7801		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7802		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7803		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7804		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7805		    sizeof(struct bwn_fwhdr)); i++) {
7806			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7807			DELAY(10);
7808		}
7809	}
7810
7811	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7812	BWN_WRITE_4(mac, BWN_MACCTL,
7813	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7814	    BWN_MACCTL_MCODE_RUN);
7815
7816	for (i = 0; i < 21; i++) {
7817		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7818			break;
7819		if (i >= 20) {
7820			device_printf(sc->sc_dev, "ucode timeout\n");
7821			error = ENXIO;
7822			goto error;
7823		}
7824		DELAY(50000);
7825	}
7826	BWN_READ_4(mac, BWN_INTR_REASON);
7827
7828	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7829	if (mac->mac_fw.rev <= 0x128) {
7830		device_printf(sc->sc_dev, "the firmware is too old\n");
7831		error = EOPNOTSUPP;
7832		goto error;
7833	}
7834	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7835	    BWN_SHARED_UCODE_PATCH);
7836	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7837	mac->mac_fw.opensource = (date == 0xffff);
7838	if (bwn_wme != 0)
7839		mac->mac_flags |= BWN_MAC_FLAG_WME;
7840	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7841
7842	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7843	if (mac->mac_fw.opensource == 0) {
7844		device_printf(sc->sc_dev,
7845		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7846		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7847		if (mac->mac_fw.no_pcmfile)
7848			device_printf(sc->sc_dev,
7849			    "no HW crypto acceleration due to pcm5\n");
7850	} else {
7851		mac->mac_fw.patch = time;
7852		fwcaps = bwn_fwcaps_read(mac);
7853		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7854			device_printf(sc->sc_dev,
7855			    "disabling HW crypto acceleration\n");
7856			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7857		}
7858		if (!(fwcaps & BWN_FWCAPS_WME)) {
7859			device_printf(sc->sc_dev, "disabling WME support\n");
7860			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7861		}
7862	}
7863
7864	if (BWN_ISOLDFMT(mac))
7865		device_printf(sc->sc_dev, "using old firmware image\n");
7866
7867	return (0);
7868
7869error:
7870	BWN_WRITE_4(mac, BWN_MACCTL,
7871	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7872	    BWN_MACCTL_MCODE_JMP0);
7873
7874	return (error);
7875#undef GETFWSIZE
7876#undef GETFWOFFSET
7877}
7878
7879/* OpenFirmware only */
7880static uint16_t
7881bwn_fwcaps_read(struct bwn_mac *mac)
7882{
7883
7884	KASSERT(mac->mac_fw.opensource == 1,
7885	    ("%s:%d: fail", __func__, __LINE__));
7886	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7887}
7888
7889static int
7890bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7891    size_t count, size_t array_size)
7892{
7893#define	GET_NEXTIV16(iv)						\
7894	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7895	    sizeof(uint16_t) + sizeof(uint16_t)))
7896#define	GET_NEXTIV32(iv)						\
7897	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7898	    sizeof(uint16_t) + sizeof(uint32_t)))
7899	struct bwn_softc *sc = mac->mac_sc;
7900	const struct bwn_fwinitvals *iv;
7901	uint16_t offset;
7902	size_t i;
7903	uint8_t bit32;
7904
7905	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7906	    ("%s:%d: fail", __func__, __LINE__));
7907	iv = ivals;
7908	for (i = 0; i < count; i++) {
7909		if (array_size < sizeof(iv->offset_size))
7910			goto fail;
7911		array_size -= sizeof(iv->offset_size);
7912		offset = be16toh(iv->offset_size);
7913		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7914		offset &= BWN_FWINITVALS_OFFSET_MASK;
7915		if (offset >= 0x1000)
7916			goto fail;
7917		if (bit32) {
7918			if (array_size < sizeof(iv->data.d32))
7919				goto fail;
7920			array_size -= sizeof(iv->data.d32);
7921			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7922			iv = GET_NEXTIV32(iv);
7923		} else {
7924
7925			if (array_size < sizeof(iv->data.d16))
7926				goto fail;
7927			array_size -= sizeof(iv->data.d16);
7928			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7929
7930			iv = GET_NEXTIV16(iv);
7931		}
7932	}
7933	if (array_size != 0)
7934		goto fail;
7935	return (0);
7936fail:
7937	device_printf(sc->sc_dev, "initvals: invalid format\n");
7938	return (EPROTO);
7939#undef GET_NEXTIV16
7940#undef GET_NEXTIV32
7941}
7942
7943static int
7944bwn_switch_channel(struct bwn_mac *mac, int chan)
7945{
7946	struct bwn_phy *phy = &(mac->mac_phy);
7947	struct bwn_softc *sc = mac->mac_sc;
7948	struct ifnet *ifp = sc->sc_ifp;
7949	struct ieee80211com *ic = ifp->if_l2com;
7950	uint16_t channelcookie, savedcookie;
7951	int error;
7952
7953	if (chan == 0xffff)
7954		chan = phy->get_default_chan(mac);
7955
7956	channelcookie = chan;
7957	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7958		channelcookie |= 0x100;
7959	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7960	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7961	error = phy->switch_channel(mac, chan);
7962	if (error)
7963		goto fail;
7964
7965	mac->mac_phy.chan = chan;
7966	DELAY(8000);
7967	return (0);
7968fail:
7969	device_printf(sc->sc_dev, "failed to switch channel\n");
7970	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7971	return (error);
7972}
7973
7974static uint16_t
7975bwn_ant2phy(int antenna)
7976{
7977
7978	switch (antenna) {
7979	case BWN_ANT0:
7980		return (BWN_TX_PHY_ANT0);
7981	case BWN_ANT1:
7982		return (BWN_TX_PHY_ANT1);
7983	case BWN_ANT2:
7984		return (BWN_TX_PHY_ANT2);
7985	case BWN_ANT3:
7986		return (BWN_TX_PHY_ANT3);
7987	case BWN_ANTAUTO:
7988		return (BWN_TX_PHY_ANT01AUTO);
7989	}
7990	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7991	return (0);
7992}
7993
7994static void
7995bwn_wme_load(struct bwn_mac *mac)
7996{
7997	struct bwn_softc *sc = mac->mac_sc;
7998	int i;
7999
8000	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8001	    ("%s:%d: fail", __func__, __LINE__));
8002
8003	bwn_mac_suspend(mac);
8004	for (i = 0; i < N(sc->sc_wmeParams); i++)
8005		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8006		    bwn_wme_shm_offsets[i]);
8007	bwn_mac_enable(mac);
8008}
8009
8010static void
8011bwn_wme_loadparams(struct bwn_mac *mac,
8012    const struct wmeParams *p, uint16_t shm_offset)
8013{
8014#define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8015	struct bwn_softc *sc = mac->mac_sc;
8016	uint16_t params[BWN_NR_WMEPARAMS];
8017	int slot, tmp;
8018	unsigned int i;
8019
8020	slot = BWN_READ_2(mac, BWN_RNG) &
8021	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8022
8023	memset(&params, 0, sizeof(params));
8024
8025	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8026	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8027	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8028
8029	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8030	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8031	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8032	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8033	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8034	params[BWN_WMEPARAM_BSLOTS] = slot;
8035	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8036
8037	for (i = 0; i < N(params); i++) {
8038		if (i == BWN_WMEPARAM_STATUS) {
8039			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8040			    shm_offset + (i * 2));
8041			tmp |= 0x100;
8042			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8043			    tmp);
8044		} else {
8045			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8046			    params[i]);
8047		}
8048	}
8049}
8050
8051static void
8052bwn_mac_write_bssid(struct bwn_mac *mac)
8053{
8054	struct bwn_softc *sc = mac->mac_sc;
8055	uint32_t tmp;
8056	int i;
8057	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8058
8059	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8060	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8061	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8062	    IEEE80211_ADDR_LEN);
8063
8064	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8065		tmp = (uint32_t) (mac_bssid[i + 0]);
8066		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8067		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8068		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8069		bwn_ram_write(mac, 0x20 + i, tmp);
8070	}
8071}
8072
8073static void
8074bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8075    const uint8_t *macaddr)
8076{
8077	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8078	uint16_t data;
8079
8080	if (!mac)
8081		macaddr = zero;
8082
8083	offset |= 0x0020;
8084	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8085
8086	data = macaddr[0];
8087	data |= macaddr[1] << 8;
8088	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089	data = macaddr[2];
8090	data |= macaddr[3] << 8;
8091	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8092	data = macaddr[4];
8093	data |= macaddr[5] << 8;
8094	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8095}
8096
8097static void
8098bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8099    const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8100{
8101	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8102	uint8_t per_sta_keys_start = 8;
8103
8104	if (BWN_SEC_NEWAPI(mac))
8105		per_sta_keys_start = 4;
8106
8107	KASSERT(index < mac->mac_max_nr_keys,
8108	    ("%s:%d: fail", __func__, __LINE__));
8109	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8110	    ("%s:%d: fail", __func__, __LINE__));
8111
8112	if (index >= per_sta_keys_start)
8113		bwn_key_macwrite(mac, index, NULL);
8114	if (key)
8115		memcpy(buf, key, key_len);
8116	bwn_key_write(mac, index, algorithm, buf);
8117	if (index >= per_sta_keys_start)
8118		bwn_key_macwrite(mac, index, mac_addr);
8119
8120	mac->mac_key[index].algorithm = algorithm;
8121}
8122
8123static void
8124bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8125{
8126	struct bwn_softc *sc = mac->mac_sc;
8127	uint32_t addrtmp[2] = { 0, 0 };
8128	uint8_t start = 8;
8129
8130	if (BWN_SEC_NEWAPI(mac))
8131		start = 4;
8132
8133	KASSERT(index >= start,
8134	    ("%s:%d: fail", __func__, __LINE__));
8135	index -= start;
8136
8137	if (addr) {
8138		addrtmp[0] = addr[0];
8139		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8140		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8141		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8142		addrtmp[1] = addr[4];
8143		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8144	}
8145
8146	if (siba_get_revid(sc->sc_dev) >= 5) {
8147		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8148		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8149	} else {
8150		if (index >= 8) {
8151			bwn_shm_write_4(mac, BWN_SHARED,
8152			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8153			bwn_shm_write_2(mac, BWN_SHARED,
8154			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8155		}
8156	}
8157}
8158
8159static void
8160bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8161    const uint8_t *key)
8162{
8163	unsigned int i;
8164	uint32_t offset;
8165	uint16_t kidx, value;
8166
8167	kidx = BWN_SEC_KEY2FW(mac, index);
8168	bwn_shm_write_2(mac, BWN_SHARED,
8169	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8170
8171	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8172	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8173		value = key[i];
8174		value |= (uint16_t)(key[i + 1]) << 8;
8175		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8176	}
8177}
8178
8179static void
8180bwn_phy_exit(struct bwn_mac *mac)
8181{
8182
8183	mac->mac_phy.rf_onoff(mac, 0);
8184	if (mac->mac_phy.exit != NULL)
8185		mac->mac_phy.exit(mac);
8186}
8187
8188static void
8189bwn_dma_free(struct bwn_mac *mac)
8190{
8191	struct bwn_dma *dma;
8192
8193	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8194		return;
8195	dma = &mac->mac_method.dma;
8196
8197	bwn_dma_ringfree(&dma->rx);
8198	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8199	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8200	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8201	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8202	bwn_dma_ringfree(&dma->mcast);
8203}
8204
8205static void
8206bwn_core_stop(struct bwn_mac *mac)
8207{
8208	struct bwn_softc *sc = mac->mac_sc;
8209
8210	BWN_ASSERT_LOCKED(sc);
8211
8212	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8213		return;
8214
8215	callout_stop(&sc->sc_rfswitch_ch);
8216	callout_stop(&sc->sc_task_ch);
8217	callout_stop(&sc->sc_watchdog_ch);
8218	sc->sc_watchdog_timer = 0;
8219	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8220	BWN_READ_4(mac, BWN_INTR_MASK);
8221	bwn_mac_suspend(mac);
8222
8223	mac->mac_status = BWN_MAC_STATUS_INITED;
8224}
8225
8226static int
8227bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8228{
8229	struct bwn_mac *up_dev = NULL;
8230	struct bwn_mac *down_dev;
8231	struct bwn_mac *mac;
8232	int err, status;
8233	uint8_t gmode;
8234
8235	BWN_ASSERT_LOCKED(sc);
8236
8237	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8238		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8239		    mac->mac_phy.supports_2ghz) {
8240			up_dev = mac;
8241			gmode = 1;
8242		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8243		    mac->mac_phy.supports_5ghz) {
8244			up_dev = mac;
8245			gmode = 0;
8246		} else {
8247			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8248			return (EINVAL);
8249		}
8250		if (up_dev != NULL)
8251			break;
8252	}
8253	if (up_dev == NULL) {
8254		device_printf(sc->sc_dev, "Could not find a device\n");
8255		return (ENODEV);
8256	}
8257	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8258		return (0);
8259
8260	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8261	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8262
8263	down_dev = sc->sc_curmac;;
8264	status = down_dev->mac_status;
8265	if (status >= BWN_MAC_STATUS_STARTED)
8266		bwn_core_stop(down_dev);
8267	if (status >= BWN_MAC_STATUS_INITED)
8268		bwn_core_exit(down_dev);
8269
8270	if (down_dev != up_dev)
8271		bwn_phy_reset(down_dev);
8272
8273	up_dev->mac_phy.gmode = gmode;
8274	if (status >= BWN_MAC_STATUS_INITED) {
8275		err = bwn_core_init(up_dev);
8276		if (err) {
8277			device_printf(sc->sc_dev,
8278			    "fatal: failed to initialize for %s-GHz\n",
8279			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8280			goto fail;
8281		}
8282	}
8283	if (status >= BWN_MAC_STATUS_STARTED)
8284		bwn_core_start(up_dev);
8285	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8286	sc->sc_curmac = up_dev;
8287
8288	return (0);
8289fail:
8290	sc->sc_curmac = NULL;
8291	return (err);
8292}
8293
8294static void
8295bwn_rf_turnon(struct bwn_mac *mac)
8296{
8297
8298	bwn_mac_suspend(mac);
8299	mac->mac_phy.rf_onoff(mac, 1);
8300	mac->mac_phy.rf_on = 1;
8301	bwn_mac_enable(mac);
8302}
8303
8304static void
8305bwn_rf_turnoff(struct bwn_mac *mac)
8306{
8307
8308	bwn_mac_suspend(mac);
8309	mac->mac_phy.rf_onoff(mac, 0);
8310	mac->mac_phy.rf_on = 0;
8311	bwn_mac_enable(mac);
8312}
8313
8314static void
8315bwn_phy_reset(struct bwn_mac *mac)
8316{
8317	struct bwn_softc *sc = mac->mac_sc;
8318
8319	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8320	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8321	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8322	DELAY(1000);
8323	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8324	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8325	    BWN_TGSLOW_PHYRESET);
8326	DELAY(1000);
8327}
8328
8329static int
8330bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8331{
8332	const struct ieee80211_txparam *tp;
8333	struct bwn_vap *bvp = BWN_VAP(vap);
8334	struct ieee80211com *ic= vap->iv_ic;
8335	struct ifnet *ifp = ic->ic_ifp;
8336	enum ieee80211_state ostate = vap->iv_state;
8337	struct bwn_softc *sc = ifp->if_softc;
8338	struct bwn_mac *mac = sc->sc_curmac;
8339	int error;
8340
8341	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8342	    ieee80211_state_name[vap->iv_state],
8343	    ieee80211_state_name[nstate]);
8344
8345	error = bvp->bv_newstate(vap, nstate, arg);
8346	if (error != 0)
8347		return (error);
8348
8349	BWN_LOCK(sc);
8350
8351	bwn_led_newstate(mac, nstate);
8352
8353	/*
8354	 * Clear the BSSID when we stop a STA
8355	 */
8356	if (vap->iv_opmode == IEEE80211_M_STA) {
8357		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8358			/*
8359			 * Clear out the BSSID.  If we reassociate to
8360			 * the same AP, this will reinialize things
8361			 * correctly...
8362			 */
8363			if (ic->ic_opmode == IEEE80211_M_STA &&
8364			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8365				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8366				bwn_set_macaddr(mac);
8367			}
8368		}
8369	}
8370
8371	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8372	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8373		/* XXX nothing to do? */
8374	} else if (nstate == IEEE80211_S_RUN) {
8375		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8376		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8377		bwn_set_opmode(mac);
8378		bwn_set_pretbtt(mac);
8379		bwn_spu_setdelay(mac, 0);
8380		bwn_set_macaddr(mac);
8381
8382		/* Initializes ratectl for a node. */
8383		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
8384		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
8385			ieee80211_ratectl_node_init(vap->iv_bss);
8386	}
8387
8388	BWN_UNLOCK(sc);
8389
8390	return (error);
8391}
8392
8393static void
8394bwn_set_pretbtt(struct bwn_mac *mac)
8395{
8396	struct bwn_softc *sc = mac->mac_sc;
8397	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8398	uint16_t pretbtt;
8399
8400	if (ic->ic_opmode == IEEE80211_M_IBSS)
8401		pretbtt = 2;
8402	else
8403		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8404	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8405	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8406}
8407
8408static int
8409bwn_intr(void *arg)
8410{
8411	struct bwn_mac *mac = arg;
8412	struct bwn_softc *sc = mac->mac_sc;
8413	uint32_t reason;
8414
8415	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8416	    (sc->sc_flags & BWN_FLAG_INVALID))
8417		return (FILTER_STRAY);
8418
8419	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8420	if (reason == 0xffffffff)	/* shared IRQ */
8421		return (FILTER_STRAY);
8422	reason &= mac->mac_intr_mask;
8423	if (reason == 0)
8424		return (FILTER_HANDLED);
8425
8426	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8427	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8428	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8429	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8430	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8431	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8432	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8433	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8434	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8435	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8436	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8437
8438	/* Disable interrupts. */
8439	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8440
8441	mac->mac_reason_intr = reason;
8442
8443	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8444	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8445
8446	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8447	return (FILTER_HANDLED);
8448}
8449
8450static void
8451bwn_intrtask(void *arg, int npending)
8452{
8453	struct bwn_mac *mac = arg;
8454	struct bwn_softc *sc = mac->mac_sc;
8455	struct ifnet *ifp = sc->sc_ifp;
8456	uint32_t merged = 0;
8457	int i, tx = 0, rx = 0;
8458
8459	BWN_LOCK(sc);
8460	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8461	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8462		BWN_UNLOCK(sc);
8463		return;
8464	}
8465
8466	for (i = 0; i < N(mac->mac_reason); i++)
8467		merged |= mac->mac_reason[i];
8468
8469	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8470		device_printf(sc->sc_dev, "MAC trans error\n");
8471
8472	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8473		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8474		mac->mac_phy.txerrors--;
8475		if (mac->mac_phy.txerrors == 0) {
8476			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8477			bwn_restart(mac, "PHY TX errors");
8478		}
8479	}
8480
8481	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8482		if (merged & BWN_DMAINTR_FATALMASK) {
8483			device_printf(sc->sc_dev,
8484			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8485			    mac->mac_reason[0], mac->mac_reason[1],
8486			    mac->mac_reason[2], mac->mac_reason[3],
8487			    mac->mac_reason[4], mac->mac_reason[5]);
8488			bwn_restart(mac, "DMA error");
8489			BWN_UNLOCK(sc);
8490			return;
8491		}
8492		if (merged & BWN_DMAINTR_NONFATALMASK) {
8493			device_printf(sc->sc_dev,
8494			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8495			    mac->mac_reason[0], mac->mac_reason[1],
8496			    mac->mac_reason[2], mac->mac_reason[3],
8497			    mac->mac_reason[4], mac->mac_reason[5]);
8498		}
8499	}
8500
8501	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8502		bwn_intr_ucode_debug(mac);
8503	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8504		bwn_intr_tbtt_indication(mac);
8505	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8506		bwn_intr_atim_end(mac);
8507	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8508		bwn_intr_beacon(mac);
8509	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8510		bwn_intr_pmq(mac);
8511	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8512		bwn_intr_noise(mac);
8513
8514	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8515		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8516			bwn_dma_rx(mac->mac_method.dma.rx);
8517			rx = 1;
8518		}
8519	} else
8520		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8521
8522	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8523	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8524	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8525	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8526	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8527
8528	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8529		bwn_intr_txeof(mac);
8530		tx = 1;
8531	}
8532
8533	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8534
8535	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8536		int evt = BWN_LED_EVENT_NONE;
8537
8538		if (tx && rx) {
8539			if (sc->sc_rx_rate > sc->sc_tx_rate)
8540				evt = BWN_LED_EVENT_RX;
8541			else
8542				evt = BWN_LED_EVENT_TX;
8543		} else if (tx) {
8544			evt = BWN_LED_EVENT_TX;
8545		} else if (rx) {
8546			evt = BWN_LED_EVENT_RX;
8547		} else if (rx == 0) {
8548			evt = BWN_LED_EVENT_POLL;
8549		}
8550
8551		if (evt != BWN_LED_EVENT_NONE)
8552			bwn_led_event(mac, evt);
8553       }
8554
8555	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8556		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8557			bwn_start_locked(ifp);
8558	}
8559
8560	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8561	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8562
8563	BWN_UNLOCK(sc);
8564}
8565
8566static void
8567bwn_restart(struct bwn_mac *mac, const char *msg)
8568{
8569	struct bwn_softc *sc = mac->mac_sc;
8570	struct ifnet *ifp = sc->sc_ifp;
8571	struct ieee80211com *ic = ifp->if_l2com;
8572
8573	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8574		return;
8575
8576	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8577	ieee80211_runtask(ic, &mac->mac_hwreset);
8578}
8579
8580static void
8581bwn_intr_ucode_debug(struct bwn_mac *mac)
8582{
8583	struct bwn_softc *sc = mac->mac_sc;
8584	uint16_t reason;
8585
8586	if (mac->mac_fw.opensource == 0)
8587		return;
8588
8589	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8590	switch (reason) {
8591	case BWN_DEBUGINTR_PANIC:
8592		bwn_handle_fwpanic(mac);
8593		break;
8594	case BWN_DEBUGINTR_DUMP_SHM:
8595		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8596		break;
8597	case BWN_DEBUGINTR_DUMP_REGS:
8598		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8599		break;
8600	case BWN_DEBUGINTR_MARKER:
8601		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8602		break;
8603	default:
8604		device_printf(sc->sc_dev,
8605		    "ucode debug unknown reason: %#x\n", reason);
8606	}
8607
8608	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8609	    BWN_DEBUGINTR_ACK);
8610}
8611
8612static void
8613bwn_intr_tbtt_indication(struct bwn_mac *mac)
8614{
8615	struct bwn_softc *sc = mac->mac_sc;
8616	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8617
8618	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8619		bwn_psctl(mac, 0);
8620	if (ic->ic_opmode == IEEE80211_M_IBSS)
8621		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8622}
8623
8624static void
8625bwn_intr_atim_end(struct bwn_mac *mac)
8626{
8627
8628	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8629		BWN_WRITE_4(mac, BWN_MACCMD,
8630		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8631		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8632	}
8633}
8634
8635static void
8636bwn_intr_beacon(struct bwn_mac *mac)
8637{
8638	struct bwn_softc *sc = mac->mac_sc;
8639	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8640	uint32_t cmd, beacon0, beacon1;
8641
8642	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8643	    ic->ic_opmode == IEEE80211_M_MBSS)
8644		return;
8645
8646	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8647
8648	cmd = BWN_READ_4(mac, BWN_MACCMD);
8649	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8650	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8651
8652	if (beacon0 && beacon1) {
8653		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8654		mac->mac_intr_mask |= BWN_INTR_BEACON;
8655		return;
8656	}
8657
8658	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8659		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8660		bwn_load_beacon0(mac);
8661		bwn_load_beacon1(mac);
8662		cmd = BWN_READ_4(mac, BWN_MACCMD);
8663		cmd |= BWN_MACCMD_BEACON0_VALID;
8664		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8665	} else {
8666		if (!beacon0) {
8667			bwn_load_beacon0(mac);
8668			cmd = BWN_READ_4(mac, BWN_MACCMD);
8669			cmd |= BWN_MACCMD_BEACON0_VALID;
8670			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8671		} else if (!beacon1) {
8672			bwn_load_beacon1(mac);
8673			cmd = BWN_READ_4(mac, BWN_MACCMD);
8674			cmd |= BWN_MACCMD_BEACON1_VALID;
8675			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8676		}
8677	}
8678}
8679
8680static void
8681bwn_intr_pmq(struct bwn_mac *mac)
8682{
8683	uint32_t tmp;
8684
8685	while (1) {
8686		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8687		if (!(tmp & 0x00000008))
8688			break;
8689	}
8690	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8691}
8692
8693static void
8694bwn_intr_noise(struct bwn_mac *mac)
8695{
8696	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8697	uint16_t tmp;
8698	uint8_t noise[4];
8699	uint8_t i, j;
8700	int32_t average;
8701
8702	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8703		return;
8704
8705	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8706	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8707	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8708	    noise[3] == 0x7f)
8709		goto new;
8710
8711	KASSERT(mac->mac_noise.noi_nsamples < 8,
8712	    ("%s:%d: fail", __func__, __LINE__));
8713	i = mac->mac_noise.noi_nsamples;
8714	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8715	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8716	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8717	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8718	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8719	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8720	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8721	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8722	mac->mac_noise.noi_nsamples++;
8723	if (mac->mac_noise.noi_nsamples == 8) {
8724		average = 0;
8725		for (i = 0; i < 8; i++) {
8726			for (j = 0; j < 4; j++)
8727				average += mac->mac_noise.noi_samples[i][j];
8728		}
8729		average = (((average / 32) * 125) + 64) / 128;
8730		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8731		if (tmp >= 8)
8732			average += 2;
8733		else
8734			average -= 25;
8735		average -= (tmp == 8) ? 72 : 48;
8736
8737		mac->mac_stats.link_noise = average;
8738		mac->mac_noise.noi_running = 0;
8739		return;
8740	}
8741new:
8742	bwn_noise_gensample(mac);
8743}
8744
8745static int
8746bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8747{
8748	struct bwn_mac *mac = prq->prq_mac;
8749	struct bwn_softc *sc = mac->mac_sc;
8750	unsigned int i;
8751
8752	BWN_ASSERT_LOCKED(sc);
8753
8754	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8755		return (0);
8756
8757	for (i = 0; i < 5000; i++) {
8758		if (bwn_pio_rxeof(prq) == 0)
8759			break;
8760	}
8761	if (i >= 5000)
8762		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8763	return ((i > 0) ? 1 : 0);
8764}
8765
8766static void
8767bwn_dma_rx(struct bwn_dma_ring *dr)
8768{
8769	int slot, curslot;
8770
8771	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8772	curslot = dr->get_curslot(dr);
8773	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8774	    ("%s:%d: fail", __func__, __LINE__));
8775
8776	slot = dr->dr_curslot;
8777	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8778		bwn_dma_rxeof(dr, &slot);
8779
8780	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8781	    BUS_DMASYNC_PREWRITE);
8782
8783	dr->set_curslot(dr, slot);
8784	dr->dr_curslot = slot;
8785}
8786
8787static void
8788bwn_intr_txeof(struct bwn_mac *mac)
8789{
8790	struct bwn_txstatus stat;
8791	uint32_t stat0, stat1;
8792	uint16_t tmp;
8793
8794	BWN_ASSERT_LOCKED(mac->mac_sc);
8795
8796	while (1) {
8797		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8798		if (!(stat0 & 0x00000001))
8799			break;
8800		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8801
8802		stat.cookie = (stat0 >> 16);
8803		stat.seq = (stat1 & 0x0000ffff);
8804		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8805		tmp = (stat0 & 0x0000ffff);
8806		stat.framecnt = ((tmp & 0xf000) >> 12);
8807		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8808		stat.sreason = ((tmp & 0x001c) >> 2);
8809		stat.pm = (tmp & 0x0080) ? 1 : 0;
8810		stat.im = (tmp & 0x0040) ? 1 : 0;
8811		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8812		stat.ack = (tmp & 0x0002) ? 1 : 0;
8813
8814		bwn_handle_txeof(mac, &stat);
8815	}
8816}
8817
8818static void
8819bwn_hwreset(void *arg, int npending)
8820{
8821	struct bwn_mac *mac = arg;
8822	struct bwn_softc *sc = mac->mac_sc;
8823	int error = 0;
8824	int prev_status;
8825
8826	BWN_LOCK(sc);
8827
8828	prev_status = mac->mac_status;
8829	if (prev_status >= BWN_MAC_STATUS_STARTED)
8830		bwn_core_stop(mac);
8831	if (prev_status >= BWN_MAC_STATUS_INITED)
8832		bwn_core_exit(mac);
8833
8834	if (prev_status >= BWN_MAC_STATUS_INITED) {
8835		error = bwn_core_init(mac);
8836		if (error)
8837			goto out;
8838	}
8839	if (prev_status >= BWN_MAC_STATUS_STARTED)
8840		bwn_core_start(mac);
8841out:
8842	if (error) {
8843		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8844		sc->sc_curmac = NULL;
8845	}
8846	BWN_UNLOCK(sc);
8847}
8848
8849static void
8850bwn_handle_fwpanic(struct bwn_mac *mac)
8851{
8852	struct bwn_softc *sc = mac->mac_sc;
8853	uint16_t reason;
8854
8855	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8856	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8857
8858	if (reason == BWN_FWPANIC_RESTART)
8859		bwn_restart(mac, "ucode panic");
8860}
8861
8862static void
8863bwn_load_beacon0(struct bwn_mac *mac)
8864{
8865
8866	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8867}
8868
8869static void
8870bwn_load_beacon1(struct bwn_mac *mac)
8871{
8872
8873	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8874}
8875
8876static uint32_t
8877bwn_jssi_read(struct bwn_mac *mac)
8878{
8879	uint32_t val = 0;
8880
8881	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8882	val <<= 16;
8883	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8884
8885	return (val);
8886}
8887
8888static void
8889bwn_noise_gensample(struct bwn_mac *mac)
8890{
8891	uint32_t jssi = 0x7f7f7f7f;
8892
8893	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8894	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8895	BWN_WRITE_4(mac, BWN_MACCMD,
8896	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8897}
8898
8899static int
8900bwn_dma_freeslot(struct bwn_dma_ring *dr)
8901{
8902	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8903
8904	return (dr->dr_numslots - dr->dr_usedslot);
8905}
8906
8907static int
8908bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8909{
8910	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8911
8912	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8913	    ("%s:%d: fail", __func__, __LINE__));
8914	if (slot == dr->dr_numslots - 1)
8915		return (0);
8916	return (slot + 1);
8917}
8918
8919static void
8920bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8921{
8922	struct bwn_mac *mac = dr->dr_mac;
8923	struct bwn_softc *sc = mac->mac_sc;
8924	struct bwn_dma *dma = &mac->mac_method.dma;
8925	struct bwn_dmadesc_generic *desc;
8926	struct bwn_dmadesc_meta *meta;
8927	struct bwn_rxhdr4 *rxhdr;
8928	struct ifnet *ifp = sc->sc_ifp;
8929	struct mbuf *m;
8930	uint32_t macstat;
8931	int32_t tmp;
8932	int cnt = 0;
8933	uint16_t len;
8934
8935	dr->getdesc(dr, *slot, &desc, &meta);
8936
8937	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8938	m = meta->mt_m;
8939
8940	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8941		ifp->if_ierrors++;
8942		return;
8943	}
8944
8945	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8946	len = le16toh(rxhdr->frame_len);
8947	if (len <= 0) {
8948		ifp->if_ierrors++;
8949		return;
8950	}
8951	if (bwn_dma_check_redzone(dr, m)) {
8952		device_printf(sc->sc_dev, "redzone error.\n");
8953		bwn_dma_set_redzone(dr, m);
8954		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8955		    BUS_DMASYNC_PREWRITE);
8956		return;
8957	}
8958	if (len > dr->dr_rx_bufsize) {
8959		tmp = len;
8960		while (1) {
8961			dr->getdesc(dr, *slot, &desc, &meta);
8962			bwn_dma_set_redzone(dr, meta->mt_m);
8963			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8964			    BUS_DMASYNC_PREWRITE);
8965			*slot = bwn_dma_nextslot(dr, *slot);
8966			cnt++;
8967			tmp -= dr->dr_rx_bufsize;
8968			if (tmp <= 0)
8969				break;
8970		}
8971		device_printf(sc->sc_dev, "too small buffer "
8972		       "(len %u buffer %u dropped %d)\n",
8973		       len, dr->dr_rx_bufsize, cnt);
8974		return;
8975	}
8976	macstat = le32toh(rxhdr->mac_status);
8977	if (macstat & BWN_RX_MAC_FCSERR) {
8978		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8979			device_printf(sc->sc_dev, "RX drop\n");
8980			return;
8981		}
8982	}
8983
8984	m->m_pkthdr.rcvif = ifp;
8985	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8986	m_adj(m, dr->dr_frameoffset);
8987
8988	bwn_rxeof(dr->dr_mac, m, rxhdr);
8989}
8990
8991static void
8992bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8993{
8994	struct bwn_dma_ring *dr;
8995	struct bwn_dmadesc_generic *desc;
8996	struct bwn_dmadesc_meta *meta;
8997	struct bwn_pio_txqueue *tq;
8998	struct bwn_pio_txpkt *tp = NULL;
8999	struct bwn_softc *sc = mac->mac_sc;
9000	struct bwn_stats *stats = &mac->mac_stats;
9001	struct ieee80211_node *ni;
9002	struct ieee80211vap *vap;
9003	int retrycnt = 0, slot;
9004
9005	BWN_ASSERT_LOCKED(mac->mac_sc);
9006
9007	if (status->im)
9008		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9009	if (status->ampdu)
9010		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9011	if (status->rtscnt) {
9012		if (status->rtscnt == 0xf)
9013			stats->rtsfail++;
9014		else
9015			stats->rts++;
9016	}
9017
9018	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9019		if (status->ack) {
9020			dr = bwn_dma_parse_cookie(mac, status,
9021			    status->cookie, &slot);
9022			if (dr == NULL) {
9023				device_printf(sc->sc_dev,
9024				    "failed to parse cookie\n");
9025				return;
9026			}
9027			while (1) {
9028				dr->getdesc(dr, slot, &desc, &meta);
9029				if (meta->mt_islast) {
9030					ni = meta->mt_ni;
9031					vap = ni->ni_vap;
9032					ieee80211_ratectl_tx_complete(vap, ni,
9033					    status->ack ?
9034					      IEEE80211_RATECTL_TX_SUCCESS :
9035					      IEEE80211_RATECTL_TX_FAILURE,
9036					    &retrycnt, 0);
9037					break;
9038				}
9039				slot = bwn_dma_nextslot(dr, slot);
9040			}
9041		}
9042		bwn_dma_handle_txeof(mac, status);
9043	} else {
9044		if (status->ack) {
9045			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9046			if (tq == NULL) {
9047				device_printf(sc->sc_dev,
9048				    "failed to parse cookie\n");
9049				return;
9050			}
9051			ni = tp->tp_ni;
9052			vap = ni->ni_vap;
9053			ieee80211_ratectl_tx_complete(vap, ni,
9054			    status->ack ?
9055			      IEEE80211_RATECTL_TX_SUCCESS :
9056			      IEEE80211_RATECTL_TX_FAILURE,
9057			    &retrycnt, 0);
9058		}
9059		bwn_pio_handle_txeof(mac, status);
9060	}
9061
9062	bwn_phy_txpower_check(mac, 0);
9063}
9064
9065static uint8_t
9066bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9067{
9068	struct bwn_mac *mac = prq->prq_mac;
9069	struct bwn_softc *sc = mac->mac_sc;
9070	struct bwn_rxhdr4 rxhdr;
9071	struct ifnet *ifp = sc->sc_ifp;
9072	struct mbuf *m;
9073	uint32_t ctl32, macstat, v32;
9074	unsigned int i, padding;
9075	uint16_t ctl16, len, totlen, v16;
9076	unsigned char *mp;
9077	char *data;
9078
9079	memset(&rxhdr, 0, sizeof(rxhdr));
9080
9081	if (prq->prq_rev >= 8) {
9082		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9083		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9084			return (0);
9085		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9086		    BWN_PIO8_RXCTL_FRAMEREADY);
9087		for (i = 0; i < 10; i++) {
9088			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9089			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9090				goto ready;
9091			DELAY(10);
9092		}
9093	} else {
9094		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9095		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9096			return (0);
9097		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9098		    BWN_PIO_RXCTL_FRAMEREADY);
9099		for (i = 0; i < 10; i++) {
9100			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9101			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9102				goto ready;
9103			DELAY(10);
9104		}
9105	}
9106	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9107	return (1);
9108ready:
9109	if (prq->prq_rev >= 8)
9110		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9111		    prq->prq_base + BWN_PIO8_RXDATA);
9112	else
9113		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9114		    prq->prq_base + BWN_PIO_RXDATA);
9115	len = le16toh(rxhdr.frame_len);
9116	if (len > 0x700) {
9117		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9118		goto error;
9119	}
9120	if (len == 0) {
9121		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9122		goto error;
9123	}
9124
9125	macstat = le32toh(rxhdr.mac_status);
9126	if (macstat & BWN_RX_MAC_FCSERR) {
9127		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9128			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9129			goto error;
9130		}
9131	}
9132
9133	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9134	totlen = len + padding;
9135	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9136	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9137	if (m == NULL) {
9138		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9139		goto error;
9140	}
9141	mp = mtod(m, unsigned char *);
9142	if (prq->prq_rev >= 8) {
9143		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9144		    prq->prq_base + BWN_PIO8_RXDATA);
9145		if (totlen & 3) {
9146			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9147			data = &(mp[totlen - 1]);
9148			switch (totlen & 3) {
9149			case 3:
9150				*data = (v32 >> 16);
9151				data--;
9152			case 2:
9153				*data = (v32 >> 8);
9154				data--;
9155			case 1:
9156				*data = v32;
9157			}
9158		}
9159	} else {
9160		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9161		    prq->prq_base + BWN_PIO_RXDATA);
9162		if (totlen & 1) {
9163			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9164			mp[totlen - 1] = v16;
9165		}
9166	}
9167
9168	m->m_pkthdr.rcvif = ifp;
9169	m->m_len = m->m_pkthdr.len = totlen;
9170
9171	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9172
9173	return (1);
9174error:
9175	if (prq->prq_rev >= 8)
9176		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9177		    BWN_PIO8_RXCTL_DATAREADY);
9178	else
9179		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9180	return (1);
9181}
9182
9183static int
9184bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9185    struct bwn_dmadesc_meta *meta, int init)
9186{
9187	struct bwn_mac *mac = dr->dr_mac;
9188	struct bwn_dma *dma = &mac->mac_method.dma;
9189	struct bwn_rxhdr4 *hdr;
9190	bus_dmamap_t map;
9191	bus_addr_t paddr;
9192	struct mbuf *m;
9193	int error;
9194
9195	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9196	if (m == NULL) {
9197		error = ENOBUFS;
9198
9199		/*
9200		 * If the NIC is up and running, we need to:
9201		 * - Clear RX buffer's header.
9202		 * - Restore RX descriptor settings.
9203		 */
9204		if (init)
9205			return (error);
9206		else
9207			goto back;
9208	}
9209	m->m_len = m->m_pkthdr.len = MCLBYTES;
9210
9211	bwn_dma_set_redzone(dr, m);
9212
9213	/*
9214	 * Try to load RX buf into temporary DMA map
9215	 */
9216	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9217	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9218	if (error) {
9219		m_freem(m);
9220
9221		/*
9222		 * See the comment above
9223		 */
9224		if (init)
9225			return (error);
9226		else
9227			goto back;
9228	}
9229
9230	if (!init)
9231		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9232	meta->mt_m = m;
9233	meta->mt_paddr = paddr;
9234
9235	/*
9236	 * Swap RX buf's DMA map with the loaded temporary one
9237	 */
9238	map = meta->mt_dmap;
9239	meta->mt_dmap = dr->dr_spare_dmap;
9240	dr->dr_spare_dmap = map;
9241
9242back:
9243	/*
9244	 * Clear RX buf header
9245	 */
9246	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9247	bzero(hdr, sizeof(*hdr));
9248	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9249	    BUS_DMASYNC_PREWRITE);
9250
9251	/*
9252	 * Setup RX buf descriptor
9253	 */
9254	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9255	    sizeof(*hdr), 0, 0, 0);
9256	return (error);
9257}
9258
9259static void
9260bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9261		 bus_size_t mapsz __unused, int error)
9262{
9263
9264	if (!error) {
9265		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9266		*((bus_addr_t *)arg) = seg->ds_addr;
9267	}
9268}
9269
9270static int
9271bwn_hwrate2ieeerate(int rate)
9272{
9273
9274	switch (rate) {
9275	case BWN_CCK_RATE_1MB:
9276		return (2);
9277	case BWN_CCK_RATE_2MB:
9278		return (4);
9279	case BWN_CCK_RATE_5MB:
9280		return (11);
9281	case BWN_CCK_RATE_11MB:
9282		return (22);
9283	case BWN_OFDM_RATE_6MB:
9284		return (12);
9285	case BWN_OFDM_RATE_9MB:
9286		return (18);
9287	case BWN_OFDM_RATE_12MB:
9288		return (24);
9289	case BWN_OFDM_RATE_18MB:
9290		return (36);
9291	case BWN_OFDM_RATE_24MB:
9292		return (48);
9293	case BWN_OFDM_RATE_36MB:
9294		return (72);
9295	case BWN_OFDM_RATE_48MB:
9296		return (96);
9297	case BWN_OFDM_RATE_54MB:
9298		return (108);
9299	default:
9300		printf("Ooops\n");
9301		return (0);
9302	}
9303}
9304
9305static void
9306bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9307{
9308	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9309	struct bwn_plcp6 *plcp;
9310	struct bwn_softc *sc = mac->mac_sc;
9311	struct ieee80211_frame_min *wh;
9312	struct ieee80211_node *ni;
9313	struct ifnet *ifp = sc->sc_ifp;
9314	struct ieee80211com *ic = ifp->if_l2com;
9315	uint32_t macstat;
9316	int padding, rate, rssi = 0, noise = 0, type;
9317	uint16_t phytype, phystat0, phystat3, chanstat;
9318	unsigned char *mp = mtod(m, unsigned char *);
9319	static int rx_mac_dec_rpt = 0;
9320
9321	BWN_ASSERT_LOCKED(sc);
9322
9323	phystat0 = le16toh(rxhdr->phy_status0);
9324	phystat3 = le16toh(rxhdr->phy_status3);
9325	macstat = le32toh(rxhdr->mac_status);
9326	chanstat = le16toh(rxhdr->channel);
9327	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9328
9329	if (macstat & BWN_RX_MAC_FCSERR)
9330		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9331	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9332		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9333	if (macstat & BWN_RX_MAC_DECERR)
9334		goto drop;
9335
9336	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9337	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9338		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9339		    m->m_pkthdr.len);
9340		goto drop;
9341	}
9342	plcp = (struct bwn_plcp6 *)(mp + padding);
9343	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9344	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9345		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9346		    m->m_pkthdr.len);
9347		goto drop;
9348	}
9349	wh = mtod(m, struct ieee80211_frame_min *);
9350
9351	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9352		device_printf(sc->sc_dev,
9353		    "RX decryption attempted (old %d keyidx %#x)\n",
9354		    BWN_ISOLDFMT(mac),
9355		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9356
9357	/* XXX calculating RSSI & noise & antenna */
9358
9359	if (phystat0 & BWN_RX_PHYST0_OFDM)
9360		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9361		    phytype == BWN_PHYTYPE_A);
9362	else
9363		rate = bwn_plcp_get_cckrate(mac, plcp);
9364	if (rate == -1) {
9365		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9366			goto drop;
9367	}
9368	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9369
9370	/* RX radio tap */
9371	if (ieee80211_radiotap_active(ic))
9372		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9373	m_adj(m, -IEEE80211_CRC_LEN);
9374
9375	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9376	noise = mac->mac_stats.link_noise;
9377
9378	ifp->if_ipackets++;
9379
9380	BWN_UNLOCK(sc);
9381
9382	ni = ieee80211_find_rxnode(ic, wh);
9383	if (ni != NULL) {
9384		type = ieee80211_input(ni, m, rssi, noise);
9385		ieee80211_free_node(ni);
9386	} else
9387		type = ieee80211_input_all(ic, m, rssi, noise);
9388
9389	BWN_LOCK(sc);
9390	return;
9391drop:
9392	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9393}
9394
9395static void
9396bwn_dma_handle_txeof(struct bwn_mac *mac,
9397    const struct bwn_txstatus *status)
9398{
9399	struct bwn_dma *dma = &mac->mac_method.dma;
9400	struct bwn_dma_ring *dr;
9401	struct bwn_dmadesc_generic *desc;
9402	struct bwn_dmadesc_meta *meta;
9403	struct bwn_softc *sc = mac->mac_sc;
9404	struct ieee80211_node *ni;
9405	struct ifnet *ifp = sc->sc_ifp;
9406	struct mbuf *m;
9407	int slot;
9408
9409	BWN_ASSERT_LOCKED(sc);
9410
9411	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9412	if (dr == NULL) {
9413		device_printf(sc->sc_dev, "failed to parse cookie\n");
9414		return;
9415	}
9416	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9417
9418	while (1) {
9419		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9420		    ("%s:%d: fail", __func__, __LINE__));
9421		dr->getdesc(dr, slot, &desc, &meta);
9422
9423		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9424			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9425		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9426			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9427
9428		if (meta->mt_islast) {
9429			KASSERT(meta->mt_m != NULL,
9430			    ("%s:%d: fail", __func__, __LINE__));
9431
9432			ni = meta->mt_ni;
9433			m = meta->mt_m;
9434			if (ni != NULL) {
9435				/*
9436				 * Do any tx complete callback. Note this must
9437				 * be done before releasing the node reference.
9438				 */
9439				if (m->m_flags & M_TXCB)
9440					ieee80211_process_callback(ni, m, 0);
9441				ieee80211_free_node(ni);
9442				meta->mt_ni = NULL;
9443			}
9444			m_freem(m);
9445			meta->mt_m = NULL;
9446		} else {
9447			KASSERT(meta->mt_m == NULL,
9448			    ("%s:%d: fail", __func__, __LINE__));
9449		}
9450
9451		dr->dr_usedslot--;
9452		if (meta->mt_islast) {
9453			ifp->if_opackets++;
9454			break;
9455		}
9456		slot = bwn_dma_nextslot(dr, slot);
9457	}
9458	sc->sc_watchdog_timer = 0;
9459	if (dr->dr_stop) {
9460		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9461		    ("%s:%d: fail", __func__, __LINE__));
9462		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9463		dr->dr_stop = 0;
9464	}
9465}
9466
9467static void
9468bwn_pio_handle_txeof(struct bwn_mac *mac,
9469    const struct bwn_txstatus *status)
9470{
9471	struct bwn_pio_txqueue *tq;
9472	struct bwn_pio_txpkt *tp = NULL;
9473	struct bwn_softc *sc = mac->mac_sc;
9474	struct ifnet *ifp = sc->sc_ifp;
9475
9476	BWN_ASSERT_LOCKED(sc);
9477
9478	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9479	if (tq == NULL)
9480		return;
9481
9482	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9483	tq->tq_free++;
9484
9485	if (tp->tp_ni != NULL) {
9486		/*
9487		 * Do any tx complete callback.  Note this must
9488		 * be done before releasing the node reference.
9489		 */
9490		if (tp->tp_m->m_flags & M_TXCB)
9491			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9492		ieee80211_free_node(tp->tp_ni);
9493		tp->tp_ni = NULL;
9494	}
9495	m_freem(tp->tp_m);
9496	tp->tp_m = NULL;
9497	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9498
9499	ifp->if_opackets++;
9500
9501	sc->sc_watchdog_timer = 0;
9502	if (tq->tq_stop) {
9503		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9504		tq->tq_stop = 0;
9505	}
9506}
9507
9508static void
9509bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9510{
9511	struct bwn_softc *sc = mac->mac_sc;
9512	struct bwn_phy *phy = &mac->mac_phy;
9513	struct ifnet *ifp = sc->sc_ifp;
9514	struct ieee80211com *ic = ifp->if_l2com;
9515	unsigned long now;
9516	int result;
9517
9518	BWN_GETTIME(now);
9519
9520	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9521		return;
9522	phy->nexttime = now + 2 * 1000;
9523
9524	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9525	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9526		return;
9527
9528	if (phy->recalc_txpwr != NULL) {
9529		result = phy->recalc_txpwr(mac,
9530		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9531		if (result == BWN_TXPWR_RES_DONE)
9532			return;
9533		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9534		    ("%s: fail", __func__));
9535		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9536
9537		ieee80211_runtask(ic, &mac->mac_txpower);
9538	}
9539}
9540
9541static uint16_t
9542bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9543{
9544
9545	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9546}
9547
9548static uint32_t
9549bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9550{
9551
9552	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9553}
9554
9555static void
9556bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9557{
9558
9559	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9560}
9561
9562static void
9563bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9564{
9565
9566	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9567}
9568
9569static int
9570bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9571{
9572
9573	switch (rate) {
9574	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9575	case 12:
9576		return (BWN_OFDM_RATE_6MB);
9577	case 18:
9578		return (BWN_OFDM_RATE_9MB);
9579	case 24:
9580		return (BWN_OFDM_RATE_12MB);
9581	case 36:
9582		return (BWN_OFDM_RATE_18MB);
9583	case 48:
9584		return (BWN_OFDM_RATE_24MB);
9585	case 72:
9586		return (BWN_OFDM_RATE_36MB);
9587	case 96:
9588		return (BWN_OFDM_RATE_48MB);
9589	case 108:
9590		return (BWN_OFDM_RATE_54MB);
9591	/* CCK rates (NB: not IEEE std, device-specific) */
9592	case 2:
9593		return (BWN_CCK_RATE_1MB);
9594	case 4:
9595		return (BWN_CCK_RATE_2MB);
9596	case 11:
9597		return (BWN_CCK_RATE_5MB);
9598	case 22:
9599		return (BWN_CCK_RATE_11MB);
9600	}
9601
9602	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9603	return (BWN_CCK_RATE_1MB);
9604}
9605
9606static int
9607bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9608    struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9609{
9610	const struct bwn_phy *phy = &mac->mac_phy;
9611	struct bwn_softc *sc = mac->mac_sc;
9612	struct ieee80211_frame *wh;
9613	struct ieee80211_frame *protwh;
9614	struct ieee80211_frame_cts *cts;
9615	struct ieee80211_frame_rts *rts;
9616	const struct ieee80211_txparam *tp;
9617	struct ieee80211vap *vap = ni->ni_vap;
9618	struct ifnet *ifp = sc->sc_ifp;
9619	struct ieee80211com *ic = ifp->if_l2com;
9620	struct mbuf *mprot;
9621	unsigned int len;
9622	uint32_t macctl = 0;
9623	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9624	uint16_t phyctl = 0;
9625	uint8_t rate, rate_fb;
9626
9627	wh = mtod(m, struct ieee80211_frame *);
9628	memset(txhdr, 0, sizeof(*txhdr));
9629
9630	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9631	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9632	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9633
9634	/*
9635	 * Find TX rate
9636	 */
9637	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9638	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9639		rate = rate_fb = tp->mgmtrate;
9640	else if (ismcast)
9641		rate = rate_fb = tp->mcastrate;
9642	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9643		rate = rate_fb = tp->ucastrate;
9644	else {
9645		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9646		rate = ni->ni_txrate;
9647
9648		if (rix > 0)
9649			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9650			    IEEE80211_RATE_VAL;
9651		else
9652			rate_fb = rate;
9653	}
9654
9655	sc->sc_tx_rate = rate;
9656
9657	rate = bwn_ieeerate2hwrate(sc, rate);
9658	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9659
9660	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9661	    bwn_plcp_getcck(rate);
9662	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9663	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9664
9665	if ((rate_fb == rate) ||
9666	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9667	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9668		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9669	else
9670		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9671		    m->m_pkthdr.len, rate, isshort);
9672
9673	/* XXX TX encryption */
9674	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9675	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9676	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9677	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9678	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9679	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9680
9681	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9682	    BWN_TX_EFT_FB_CCK;
9683	txhdr->chan = phy->chan;
9684	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9685	    BWN_TX_PHY_ENC_CCK;
9686	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9687	     rate == BWN_CCK_RATE_11MB))
9688		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9689
9690	/* XXX TX antenna selection */
9691
9692	switch (bwn_antenna_sanitize(mac, 0)) {
9693	case 0:
9694		phyctl |= BWN_TX_PHY_ANT01AUTO;
9695		break;
9696	case 1:
9697		phyctl |= BWN_TX_PHY_ANT0;
9698		break;
9699	case 2:
9700		phyctl |= BWN_TX_PHY_ANT1;
9701		break;
9702	case 3:
9703		phyctl |= BWN_TX_PHY_ANT2;
9704		break;
9705	case 4:
9706		phyctl |= BWN_TX_PHY_ANT3;
9707		break;
9708	default:
9709		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9710	}
9711
9712	if (!ismcast)
9713		macctl |= BWN_TX_MAC_ACK;
9714
9715	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9716	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9717	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9718		macctl |= BWN_TX_MAC_LONGFRAME;
9719
9720	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9721		/* XXX RTS rate is always 1MB??? */
9722		rts_rate = BWN_CCK_RATE_1MB;
9723		rts_rate_fb = bwn_get_fbrate(rts_rate);
9724
9725		protdur = ieee80211_compute_duration(ic->ic_rt,
9726		    m->m_pkthdr.len, rate, isshort) +
9727		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9728
9729		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9730			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9731			    (txhdr->body.old.rts_frame) :
9732			    (txhdr->body.new.rts_frame));
9733			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9734			    protdur);
9735			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9736			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9737			    mprot->m_pkthdr.len);
9738			m_freem(mprot);
9739			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9740			len = sizeof(struct ieee80211_frame_cts);
9741		} else {
9742			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9743			    (txhdr->body.old.rts_frame) :
9744			    (txhdr->body.new.rts_frame));
9745			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9746			    isshort);
9747			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9748			    wh->i_addr2, protdur);
9749			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9750			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9751			    mprot->m_pkthdr.len);
9752			m_freem(mprot);
9753			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9754			len = sizeof(struct ieee80211_frame_rts);
9755		}
9756		len += IEEE80211_CRC_LEN;
9757		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9758		    &txhdr->body.old.rts_plcp :
9759		    &txhdr->body.new.rts_plcp), len, rts_rate);
9760		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9761		    rts_rate_fb);
9762
9763		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9764		    (&txhdr->body.old.rts_frame) :
9765		    (&txhdr->body.new.rts_frame));
9766		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9767
9768		if (BWN_ISOFDMRATE(rts_rate)) {
9769			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9770			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9771		} else {
9772			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9773			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9774		}
9775		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9776		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9777	}
9778
9779	if (BWN_ISOLDFMT(mac))
9780		txhdr->body.old.cookie = htole16(cookie);
9781	else
9782		txhdr->body.new.cookie = htole16(cookie);
9783
9784	txhdr->macctl = htole32(macctl);
9785	txhdr->phyctl = htole16(phyctl);
9786
9787	/*
9788	 * TX radio tap
9789	 */
9790	if (ieee80211_radiotap_active_vap(vap)) {
9791		sc->sc_tx_th.wt_flags = 0;
9792		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9793			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9794		if (isshort &&
9795		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9796		     rate == BWN_CCK_RATE_11MB))
9797			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9798		sc->sc_tx_th.wt_rate = rate;
9799
9800		ieee80211_radiotap_tx(vap, m);
9801	}
9802
9803	return (0);
9804}
9805
9806static void
9807bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9808    const uint8_t rate)
9809{
9810	uint32_t d, plen;
9811	uint8_t *raw = plcp->o.raw;
9812
9813	if (BWN_ISOFDMRATE(rate)) {
9814		d = bwn_plcp_getofdm(rate);
9815		KASSERT(!(octets & 0xf000),
9816		    ("%s:%d: fail", __func__, __LINE__));
9817		d |= (octets << 5);
9818		plcp->o.data = htole32(d);
9819	} else {
9820		plen = octets * 16 / rate;
9821		if ((octets * 16 % rate) > 0) {
9822			plen++;
9823			if ((rate == BWN_CCK_RATE_11MB)
9824			    && ((octets * 8 % 11) < 4)) {
9825				raw[1] = 0x84;
9826			} else
9827				raw[1] = 0x04;
9828		} else
9829			raw[1] = 0x04;
9830		plcp->o.data |= htole32(plen << 16);
9831		raw[0] = bwn_plcp_getcck(rate);
9832	}
9833}
9834
9835static uint8_t
9836bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9837{
9838	struct bwn_softc *sc = mac->mac_sc;
9839	uint8_t mask;
9840
9841	if (n == 0)
9842		return (0);
9843	if (mac->mac_phy.gmode)
9844		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9845	else
9846		mask = siba_sprom_get_ant_a(sc->sc_dev);
9847	if (!(mask & (1 << (n - 1))))
9848		return (0);
9849	return (n);
9850}
9851
9852static uint8_t
9853bwn_get_fbrate(uint8_t bitrate)
9854{
9855	switch (bitrate) {
9856	case BWN_CCK_RATE_1MB:
9857		return (BWN_CCK_RATE_1MB);
9858	case BWN_CCK_RATE_2MB:
9859		return (BWN_CCK_RATE_1MB);
9860	case BWN_CCK_RATE_5MB:
9861		return (BWN_CCK_RATE_2MB);
9862	case BWN_CCK_RATE_11MB:
9863		return (BWN_CCK_RATE_5MB);
9864	case BWN_OFDM_RATE_6MB:
9865		return (BWN_CCK_RATE_5MB);
9866	case BWN_OFDM_RATE_9MB:
9867		return (BWN_OFDM_RATE_6MB);
9868	case BWN_OFDM_RATE_12MB:
9869		return (BWN_OFDM_RATE_9MB);
9870	case BWN_OFDM_RATE_18MB:
9871		return (BWN_OFDM_RATE_12MB);
9872	case BWN_OFDM_RATE_24MB:
9873		return (BWN_OFDM_RATE_18MB);
9874	case BWN_OFDM_RATE_36MB:
9875		return (BWN_OFDM_RATE_24MB);
9876	case BWN_OFDM_RATE_48MB:
9877		return (BWN_OFDM_RATE_36MB);
9878	case BWN_OFDM_RATE_54MB:
9879		return (BWN_OFDM_RATE_48MB);
9880	}
9881	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9882	return (0);
9883}
9884
9885static uint32_t
9886bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9887    uint32_t ctl, const void *_data, int len)
9888{
9889	struct bwn_softc *sc = mac->mac_sc;
9890	uint32_t value = 0;
9891	const uint8_t *data = _data;
9892
9893	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9894	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9895	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9896
9897	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9898	    tq->tq_base + BWN_PIO8_TXDATA);
9899	if (len & 3) {
9900		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9901		    BWN_PIO8_TXCTL_24_31);
9902		data = &(data[len - 1]);
9903		switch (len & 3) {
9904		case 3:
9905			ctl |= BWN_PIO8_TXCTL_16_23;
9906			value |= (uint32_t)(*data) << 16;
9907			data--;
9908		case 2:
9909			ctl |= BWN_PIO8_TXCTL_8_15;
9910			value |= (uint32_t)(*data) << 8;
9911			data--;
9912		case 1:
9913			value |= (uint32_t)(*data);
9914		}
9915		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9916		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9917	}
9918
9919	return (ctl);
9920}
9921
9922static void
9923bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9924    uint16_t offset, uint32_t value)
9925{
9926
9927	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9928}
9929
9930static uint16_t
9931bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9932    uint16_t ctl, const void *_data, int len)
9933{
9934	struct bwn_softc *sc = mac->mac_sc;
9935	const uint8_t *data = _data;
9936
9937	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9938	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9939
9940	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9941	    tq->tq_base + BWN_PIO_TXDATA);
9942	if (len & 1) {
9943		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9944		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9945		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9946	}
9947
9948	return (ctl);
9949}
9950
9951static uint16_t
9952bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9953    uint16_t ctl, struct mbuf *m0)
9954{
9955	int i, j = 0;
9956	uint16_t data = 0;
9957	const uint8_t *buf;
9958	struct mbuf *m = m0;
9959
9960	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9961	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9962
9963	for (; m != NULL; m = m->m_next) {
9964		buf = mtod(m, const uint8_t *);
9965		for (i = 0; i < m->m_len; i++) {
9966			if (!((j++) % 2))
9967				data |= buf[i];
9968			else {
9969				data |= (buf[i] << 8);
9970				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9971				data = 0;
9972			}
9973		}
9974	}
9975	if (m0->m_pkthdr.len % 2) {
9976		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9977		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9978		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9979	}
9980
9981	return (ctl);
9982}
9983
9984static void
9985bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9986{
9987
9988	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9989		return;
9990	BWN_WRITE_2(mac, 0x684, 510 + time);
9991	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9992}
9993
9994static struct bwn_dma_ring *
9995bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9996{
9997
9998	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9999		return (mac->mac_method.dma.wme[WME_AC_BE]);
10000
10001	switch (prio) {
10002	case 3:
10003		return (mac->mac_method.dma.wme[WME_AC_VO]);
10004	case 2:
10005		return (mac->mac_method.dma.wme[WME_AC_VI]);
10006	case 0:
10007		return (mac->mac_method.dma.wme[WME_AC_BE]);
10008	case 1:
10009		return (mac->mac_method.dma.wme[WME_AC_BK]);
10010	}
10011	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10012	return (NULL);
10013}
10014
10015static int
10016bwn_dma_getslot(struct bwn_dma_ring *dr)
10017{
10018	int slot;
10019
10020	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10021
10022	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10023	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10024	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10025
10026	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10027	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10028	dr->dr_curslot = slot;
10029	dr->dr_usedslot++;
10030
10031	return (slot);
10032}
10033
10034static int
10035bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10036{
10037	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10038	unsigned int a, b, c, d;
10039	unsigned int avg;
10040	uint32_t tmp;
10041
10042	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10043	a = tmp & 0xff;
10044	b = (tmp >> 8) & 0xff;
10045	c = (tmp >> 16) & 0xff;
10046	d = (tmp >> 24) & 0xff;
10047	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10048	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10049		return (ENOENT);
10050	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10051	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10052	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10053
10054	if (ofdm) {
10055		a = (a + 32) & 0x3f;
10056		b = (b + 32) & 0x3f;
10057		c = (c + 32) & 0x3f;
10058		d = (d + 32) & 0x3f;
10059	}
10060
10061	avg = (a + b + c + d + 2) / 4;
10062	if (ofdm) {
10063		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10064		    & BWN_HF_4DB_CCK_POWERBOOST)
10065			avg = (avg >= 13) ? (avg - 13) : 0;
10066	}
10067	return (avg);
10068}
10069
10070static void
10071bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10072{
10073	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10074	int rfatt = *rfattp;
10075	int bbatt = *bbattp;
10076
10077	while (1) {
10078		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10079			break;
10080		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10081			break;
10082		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10083			break;
10084		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10085			break;
10086		if (bbatt > lo->bbatt.max) {
10087			bbatt -= 4;
10088			rfatt += 1;
10089			continue;
10090		}
10091		if (bbatt < lo->bbatt.min) {
10092			bbatt += 4;
10093			rfatt -= 1;
10094			continue;
10095		}
10096		if (rfatt > lo->rfatt.max) {
10097			rfatt -= 1;
10098			bbatt += 4;
10099			continue;
10100		}
10101		if (rfatt < lo->rfatt.min) {
10102			rfatt += 1;
10103			bbatt -= 4;
10104			continue;
10105		}
10106		break;
10107	}
10108
10109	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10110	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10111}
10112
10113static void
10114bwn_phy_lock(struct bwn_mac *mac)
10115{
10116	struct bwn_softc *sc = mac->mac_sc;
10117	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10118
10119	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10120	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10121
10122	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10123		bwn_psctl(mac, BWN_PS_AWAKE);
10124}
10125
10126static void
10127bwn_phy_unlock(struct bwn_mac *mac)
10128{
10129	struct bwn_softc *sc = mac->mac_sc;
10130	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10131
10132	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10133	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10134
10135	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10136		bwn_psctl(mac, 0);
10137}
10138
10139static void
10140bwn_rf_lock(struct bwn_mac *mac)
10141{
10142
10143	BWN_WRITE_4(mac, BWN_MACCTL,
10144	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10145	BWN_READ_4(mac, BWN_MACCTL);
10146	DELAY(10);
10147}
10148
10149static void
10150bwn_rf_unlock(struct bwn_mac *mac)
10151{
10152
10153	BWN_READ_2(mac, BWN_PHYVER);
10154	BWN_WRITE_4(mac, BWN_MACCTL,
10155	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10156}
10157
10158static struct bwn_pio_txqueue *
10159bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10160    struct bwn_pio_txpkt **pack)
10161{
10162	struct bwn_pio *pio = &mac->mac_method.pio;
10163	struct bwn_pio_txqueue *tq = NULL;
10164	unsigned int index;
10165
10166	switch (cookie & 0xf000) {
10167	case 0x1000:
10168		tq = &pio->wme[WME_AC_BK];
10169		break;
10170	case 0x2000:
10171		tq = &pio->wme[WME_AC_BE];
10172		break;
10173	case 0x3000:
10174		tq = &pio->wme[WME_AC_VI];
10175		break;
10176	case 0x4000:
10177		tq = &pio->wme[WME_AC_VO];
10178		break;
10179	case 0x5000:
10180		tq = &pio->mcast;
10181		break;
10182	}
10183	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10184	if (tq == NULL)
10185		return (NULL);
10186	index = (cookie & 0x0fff);
10187	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10188	if (index >= N(tq->tq_pkts))
10189		return (NULL);
10190	*pack = &tq->tq_pkts[index];
10191	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10192	return (tq);
10193}
10194
10195static void
10196bwn_txpwr(void *arg, int npending)
10197{
10198	struct bwn_mac *mac = arg;
10199	struct bwn_softc *sc = mac->mac_sc;
10200
10201	BWN_LOCK(sc);
10202	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10203	    mac->mac_phy.set_txpwr != NULL)
10204		mac->mac_phy.set_txpwr(mac);
10205	BWN_UNLOCK(sc);
10206}
10207
10208static void
10209bwn_task_15s(struct bwn_mac *mac)
10210{
10211	uint16_t reg;
10212
10213	if (mac->mac_fw.opensource) {
10214		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10215		if (reg) {
10216			bwn_restart(mac, "fw watchdog");
10217			return;
10218		}
10219		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10220	}
10221	if (mac->mac_phy.task_15s)
10222		mac->mac_phy.task_15s(mac);
10223
10224	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10225}
10226
10227static void
10228bwn_task_30s(struct bwn_mac *mac)
10229{
10230
10231	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10232		return;
10233	mac->mac_noise.noi_running = 1;
10234	mac->mac_noise.noi_nsamples = 0;
10235
10236	bwn_noise_gensample(mac);
10237}
10238
10239static void
10240bwn_task_60s(struct bwn_mac *mac)
10241{
10242
10243	if (mac->mac_phy.task_60s)
10244		mac->mac_phy.task_60s(mac);
10245	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10246}
10247
10248static void
10249bwn_tasks(void *arg)
10250{
10251	struct bwn_mac *mac = arg;
10252	struct bwn_softc *sc = mac->mac_sc;
10253
10254	BWN_ASSERT_LOCKED(sc);
10255	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10256		return;
10257
10258	if (mac->mac_task_state % 4 == 0)
10259		bwn_task_60s(mac);
10260	if (mac->mac_task_state % 2 == 0)
10261		bwn_task_30s(mac);
10262	bwn_task_15s(mac);
10263
10264	mac->mac_task_state++;
10265	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10266}
10267
10268static int
10269bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10270{
10271	struct bwn_softc *sc = mac->mac_sc;
10272
10273	KASSERT(a == 0, ("not support APHY\n"));
10274
10275	switch (plcp->o.raw[0] & 0xf) {
10276	case 0xb:
10277		return (BWN_OFDM_RATE_6MB);
10278	case 0xf:
10279		return (BWN_OFDM_RATE_9MB);
10280	case 0xa:
10281		return (BWN_OFDM_RATE_12MB);
10282	case 0xe:
10283		return (BWN_OFDM_RATE_18MB);
10284	case 0x9:
10285		return (BWN_OFDM_RATE_24MB);
10286	case 0xd:
10287		return (BWN_OFDM_RATE_36MB);
10288	case 0x8:
10289		return (BWN_OFDM_RATE_48MB);
10290	case 0xc:
10291		return (BWN_OFDM_RATE_54MB);
10292	}
10293	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10294	    plcp->o.raw[0] & 0xf);
10295	return (-1);
10296}
10297
10298static int
10299bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10300{
10301	struct bwn_softc *sc = mac->mac_sc;
10302
10303	switch (plcp->o.raw[0]) {
10304	case 0x0a:
10305		return (BWN_CCK_RATE_1MB);
10306	case 0x14:
10307		return (BWN_CCK_RATE_2MB);
10308	case 0x37:
10309		return (BWN_CCK_RATE_5MB);
10310	case 0x6e:
10311		return (BWN_CCK_RATE_11MB);
10312	}
10313	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10314	return (-1);
10315}
10316
10317static void
10318bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10319    const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10320    int rssi, int noise)
10321{
10322	struct bwn_softc *sc = mac->mac_sc;
10323	const struct ieee80211_frame_min *wh;
10324	uint64_t tsf;
10325	uint16_t low_mactime_now;
10326
10327	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10328		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10329
10330	wh = mtod(m, const struct ieee80211_frame_min *);
10331	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10332		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10333
10334	bwn_tsf_read(mac, &tsf);
10335	low_mactime_now = tsf;
10336	tsf = tsf & ~0xffffULL;
10337	tsf += le16toh(rxhdr->mac_time);
10338	if (low_mactime_now < le16toh(rxhdr->mac_time))
10339		tsf -= 0x10000;
10340
10341	sc->sc_rx_th.wr_tsf = tsf;
10342	sc->sc_rx_th.wr_rate = rate;
10343	sc->sc_rx_th.wr_antsignal = rssi;
10344	sc->sc_rx_th.wr_antnoise = noise;
10345}
10346
10347static void
10348bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10349{
10350	uint32_t low, high;
10351
10352	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10353	    ("%s:%d: fail", __func__, __LINE__));
10354
10355	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10356	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10357	*tsf = high;
10358	*tsf <<= 32;
10359	*tsf |= low;
10360}
10361
10362static int
10363bwn_dma_attach(struct bwn_mac *mac)
10364{
10365	struct bwn_dma *dma = &mac->mac_method.dma;
10366	struct bwn_softc *sc = mac->mac_sc;
10367	bus_addr_t lowaddr = 0;
10368	int error;
10369
10370	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10371		return (0);
10372
10373	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10374
10375	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10376
10377	dma->dmatype = bwn_dma_gettype(mac);
10378	if (dma->dmatype == BWN_DMA_30BIT)
10379		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10380	else if (dma->dmatype == BWN_DMA_32BIT)
10381		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10382	else
10383		lowaddr = BUS_SPACE_MAXADDR;
10384
10385	/*
10386	 * Create top level DMA tag
10387	 */
10388	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10389			       BWN_ALIGN, 0,		/* alignment, bounds */
10390			       lowaddr,			/* lowaddr */
10391			       BUS_SPACE_MAXADDR,	/* highaddr */
10392			       NULL, NULL,		/* filter, filterarg */
10393			       MAXBSIZE,		/* maxsize */
10394			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10395			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10396			       0,			/* flags */
10397			       NULL, NULL,		/* lockfunc, lockarg */
10398			       &dma->parent_dtag);
10399	if (error) {
10400		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10401		return (error);
10402	}
10403
10404	/*
10405	 * Create TX/RX mbuf DMA tag
10406	 */
10407	error = bus_dma_tag_create(dma->parent_dtag,
10408				1,
10409				0,
10410				BUS_SPACE_MAXADDR,
10411				BUS_SPACE_MAXADDR,
10412				NULL, NULL,
10413				MCLBYTES,
10414				1,
10415				BUS_SPACE_MAXSIZE_32BIT,
10416				0,
10417				NULL, NULL,
10418				&dma->rxbuf_dtag);
10419	if (error) {
10420		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10421		goto fail0;
10422	}
10423	error = bus_dma_tag_create(dma->parent_dtag,
10424				1,
10425				0,
10426				BUS_SPACE_MAXADDR,
10427				BUS_SPACE_MAXADDR,
10428				NULL, NULL,
10429				MCLBYTES,
10430				1,
10431				BUS_SPACE_MAXSIZE_32BIT,
10432				0,
10433				NULL, NULL,
10434				&dma->txbuf_dtag);
10435	if (error) {
10436		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10437		goto fail1;
10438	}
10439
10440	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10441	if (!dma->wme[WME_AC_BK])
10442		goto fail2;
10443
10444	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10445	if (!dma->wme[WME_AC_BE])
10446		goto fail3;
10447
10448	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10449	if (!dma->wme[WME_AC_VI])
10450		goto fail4;
10451
10452	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10453	if (!dma->wme[WME_AC_VO])
10454		goto fail5;
10455
10456	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10457	if (!dma->mcast)
10458		goto fail6;
10459	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10460	if (!dma->rx)
10461		goto fail7;
10462
10463	return (error);
10464
10465fail7:	bwn_dma_ringfree(&dma->mcast);
10466fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10467fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10468fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10469fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10470fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10471fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10472fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10473	return (error);
10474}
10475
10476static struct bwn_dma_ring *
10477bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10478    uint16_t cookie, int *slot)
10479{
10480	struct bwn_dma *dma = &mac->mac_method.dma;
10481	struct bwn_dma_ring *dr;
10482	struct bwn_softc *sc = mac->mac_sc;
10483
10484	BWN_ASSERT_LOCKED(mac->mac_sc);
10485
10486	switch (cookie & 0xf000) {
10487	case 0x1000:
10488		dr = dma->wme[WME_AC_BK];
10489		break;
10490	case 0x2000:
10491		dr = dma->wme[WME_AC_BE];
10492		break;
10493	case 0x3000:
10494		dr = dma->wme[WME_AC_VI];
10495		break;
10496	case 0x4000:
10497		dr = dma->wme[WME_AC_VO];
10498		break;
10499	case 0x5000:
10500		dr = dma->mcast;
10501		break;
10502	default:
10503		dr = NULL;
10504		KASSERT(0 == 1,
10505		    ("invalid cookie value %d", cookie & 0xf000));
10506	}
10507	*slot = (cookie & 0x0fff);
10508	if (*slot < 0 || *slot >= dr->dr_numslots) {
10509		/*
10510		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10511		 * that it occurs events which have same H/W sequence numbers.
10512		 * When it's occurred just prints a WARNING msgs and ignores.
10513		 */
10514		KASSERT(status->seq == dma->lastseq,
10515		    ("%s:%d: fail", __func__, __LINE__));
10516		device_printf(sc->sc_dev,
10517		    "out of slot ranges (0 < %d < %d)\n", *slot,
10518		    dr->dr_numslots);
10519		return (NULL);
10520	}
10521	dma->lastseq = status->seq;
10522	return (dr);
10523}
10524
10525static void
10526bwn_dma_stop(struct bwn_mac *mac)
10527{
10528	struct bwn_dma *dma;
10529
10530	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10531		return;
10532	dma = &mac->mac_method.dma;
10533
10534	bwn_dma_ringstop(&dma->rx);
10535	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10536	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10537	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10538	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10539	bwn_dma_ringstop(&dma->mcast);
10540}
10541
10542static void
10543bwn_dma_ringstop(struct bwn_dma_ring **dr)
10544{
10545
10546	if (dr == NULL)
10547		return;
10548
10549	bwn_dma_cleanup(*dr);
10550}
10551
10552static void
10553bwn_pio_stop(struct bwn_mac *mac)
10554{
10555	struct bwn_pio *pio;
10556
10557	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10558		return;
10559	pio = &mac->mac_method.pio;
10560
10561	bwn_destroy_queue_tx(&pio->mcast);
10562	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10563	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10564	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10565	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10566}
10567
10568static void
10569bwn_led_attach(struct bwn_mac *mac)
10570{
10571	struct bwn_softc *sc = mac->mac_sc;
10572	const uint8_t *led_act = NULL;
10573	uint16_t val[BWN_LED_MAX];
10574	int i;
10575
10576	sc->sc_led_idle = (2350 * hz) / 1000;
10577	sc->sc_led_blink = 1;
10578
10579	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10580		if (siba_get_pci_subvendor(sc->sc_dev) ==
10581		    bwn_vendor_led_act[i].vid) {
10582			led_act = bwn_vendor_led_act[i].led_act;
10583			break;
10584		}
10585	}
10586	if (led_act == NULL)
10587		led_act = bwn_default_led_act;
10588
10589	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10590	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10591	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10592	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10593
10594	for (i = 0; i < BWN_LED_MAX; ++i) {
10595		struct bwn_led *led = &sc->sc_leds[i];
10596
10597		if (val[i] == 0xff) {
10598			led->led_act = led_act[i];
10599		} else {
10600			if (val[i] & BWN_LED_ACT_LOW)
10601				led->led_flags |= BWN_LED_F_ACTLOW;
10602			led->led_act = val[i] & BWN_LED_ACT_MASK;
10603		}
10604		led->led_mask = (1 << i);
10605
10606		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10607		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10608		    led->led_act == BWN_LED_ACT_BLINK) {
10609			led->led_flags |= BWN_LED_F_BLINK;
10610			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10611				led->led_flags |= BWN_LED_F_POLLABLE;
10612			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10613				led->led_flags |= BWN_LED_F_SLOW;
10614
10615			if (sc->sc_blink_led == NULL) {
10616				sc->sc_blink_led = led;
10617				if (led->led_flags & BWN_LED_F_SLOW)
10618					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10619			}
10620		}
10621
10622		DPRINTF(sc, BWN_DEBUG_LED,
10623		    "%dth led, act %d, lowact %d\n", i,
10624		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10625	}
10626	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10627}
10628
10629static __inline uint16_t
10630bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10631{
10632
10633	if (led->led_flags & BWN_LED_F_ACTLOW)
10634		on = !on;
10635	if (on)
10636		val |= led->led_mask;
10637	else
10638		val &= ~led->led_mask;
10639	return val;
10640}
10641
10642static void
10643bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10644{
10645	struct bwn_softc *sc = mac->mac_sc;
10646	struct ifnet *ifp = sc->sc_ifp;
10647	struct ieee80211com *ic = ifp->if_l2com;
10648	uint16_t val;
10649	int i;
10650
10651	if (nstate == IEEE80211_S_INIT) {
10652		callout_stop(&sc->sc_led_blink_ch);
10653		sc->sc_led_blinking = 0;
10654	}
10655
10656	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10657		return;
10658
10659	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10660	for (i = 0; i < BWN_LED_MAX; ++i) {
10661		struct bwn_led *led = &sc->sc_leds[i];
10662		int on;
10663
10664		if (led->led_act == BWN_LED_ACT_UNKN ||
10665		    led->led_act == BWN_LED_ACT_NULL)
10666			continue;
10667
10668		if ((led->led_flags & BWN_LED_F_BLINK) &&
10669		    nstate != IEEE80211_S_INIT)
10670			continue;
10671
10672		switch (led->led_act) {
10673		case BWN_LED_ACT_ON:    /* Always on */
10674			on = 1;
10675			break;
10676		case BWN_LED_ACT_OFF:   /* Always off */
10677		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10678			on = 0;
10679			break;
10680		default:
10681			on = 1;
10682			switch (nstate) {
10683			case IEEE80211_S_INIT:
10684				on = 0;
10685				break;
10686			case IEEE80211_S_RUN:
10687				if (led->led_act == BWN_LED_ACT_11G &&
10688				    ic->ic_curmode != IEEE80211_MODE_11G)
10689					on = 0;
10690				break;
10691			default:
10692				if (led->led_act == BWN_LED_ACT_ASSOC)
10693					on = 0;
10694				break;
10695			}
10696			break;
10697		}
10698
10699		val = bwn_led_onoff(led, val, on);
10700	}
10701	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10702}
10703
10704static void
10705bwn_led_event(struct bwn_mac *mac, int event)
10706{
10707	struct bwn_softc *sc = mac->mac_sc;
10708	struct bwn_led *led = sc->sc_blink_led;
10709	int rate;
10710
10711	if (event == BWN_LED_EVENT_POLL) {
10712		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10713			return;
10714		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10715			return;
10716	}
10717
10718	sc->sc_led_ticks = ticks;
10719	if (sc->sc_led_blinking)
10720		return;
10721
10722	switch (event) {
10723	case BWN_LED_EVENT_RX:
10724		rate = sc->sc_rx_rate;
10725		break;
10726	case BWN_LED_EVENT_TX:
10727		rate = sc->sc_tx_rate;
10728		break;
10729	case BWN_LED_EVENT_POLL:
10730		rate = 0;
10731		break;
10732	default:
10733		panic("unknown LED event %d\n", event);
10734		break;
10735	}
10736	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10737	    bwn_led_duration[rate].off_dur);
10738}
10739
10740static void
10741bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10742{
10743	struct bwn_softc *sc = mac->mac_sc;
10744	struct bwn_led *led = sc->sc_blink_led;
10745	uint16_t val;
10746
10747	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10748	val = bwn_led_onoff(led, val, 1);
10749	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10750
10751	if (led->led_flags & BWN_LED_F_SLOW) {
10752		BWN_LED_SLOWDOWN(on_dur);
10753		BWN_LED_SLOWDOWN(off_dur);
10754	}
10755
10756	sc->sc_led_blinking = 1;
10757	sc->sc_led_blink_offdur = off_dur;
10758
10759	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10760}
10761
10762static void
10763bwn_led_blink_next(void *arg)
10764{
10765	struct bwn_mac *mac = arg;
10766	struct bwn_softc *sc = mac->mac_sc;
10767	uint16_t val;
10768
10769	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10770	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10771	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10772
10773	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10774	    bwn_led_blink_end, mac);
10775}
10776
10777static void
10778bwn_led_blink_end(void *arg)
10779{
10780	struct bwn_mac *mac = arg;
10781	struct bwn_softc *sc = mac->mac_sc;
10782
10783	sc->sc_led_blinking = 0;
10784}
10785
10786static int
10787bwn_suspend(device_t dev)
10788{
10789	struct bwn_softc *sc = device_get_softc(dev);
10790
10791	bwn_stop(sc, 1);
10792	return (0);
10793}
10794
10795static int
10796bwn_resume(device_t dev)
10797{
10798	struct bwn_softc *sc = device_get_softc(dev);
10799	struct ifnet *ifp = sc->sc_ifp;
10800
10801	if (ifp->if_flags & IFF_UP)
10802		bwn_init(sc);
10803	return (0);
10804}
10805
10806static void
10807bwn_rfswitch(void *arg)
10808{
10809	struct bwn_softc *sc = arg;
10810	struct bwn_mac *mac = sc->sc_curmac;
10811	int cur = 0, prev = 0;
10812
10813	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10814	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10815
10816	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10817		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10818			& BWN_RF_HWENABLED_HI_MASK))
10819			cur = 1;
10820	} else {
10821		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10822		    & BWN_RF_HWENABLED_LO_MASK)
10823			cur = 1;
10824	}
10825
10826	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10827		prev = 1;
10828
10829	if (cur != prev) {
10830		if (cur)
10831			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10832		else
10833			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10834
10835		device_printf(sc->sc_dev,
10836		    "status of RF switch is changed to %s\n",
10837		    cur ? "ON" : "OFF");
10838		if (cur != mac->mac_phy.rf_on) {
10839			if (cur)
10840				bwn_rf_turnon(mac);
10841			else
10842				bwn_rf_turnoff(mac);
10843		}
10844	}
10845
10846	callout_schedule(&sc->sc_rfswitch_ch, hz);
10847}
10848
10849static void
10850bwn_phy_lp_init_pre(struct bwn_mac *mac)
10851{
10852	struct bwn_phy *phy = &mac->mac_phy;
10853	struct bwn_phy_lp *plp = &phy->phy_lp;
10854
10855	plp->plp_antenna = BWN_ANT_DEFAULT;
10856}
10857
10858static int
10859bwn_phy_lp_init(struct bwn_mac *mac)
10860{
10861	static const struct bwn_stxtable tables[] = {
10862		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10863		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10864		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10865		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10866		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10867		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10868		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10869		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10870		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10871		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10872		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10873		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10874		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10875		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10876		{ 2, 11, 0x40, 0, 0x0f }
10877	};
10878	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10879	struct bwn_softc *sc = mac->mac_sc;
10880	const struct bwn_stxtable *st;
10881	struct ifnet *ifp = sc->sc_ifp;
10882	struct ieee80211com *ic = ifp->if_l2com;
10883	int i, error;
10884	uint16_t tmp;
10885
10886	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10887	bwn_phy_lp_bbinit(mac);
10888
10889	/* initialize RF */
10890	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10891	DELAY(1);
10892	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10893	DELAY(1);
10894
10895	if (mac->mac_phy.rf_ver == 0x2062)
10896		bwn_phy_lp_b2062_init(mac);
10897	else {
10898		bwn_phy_lp_b2063_init(mac);
10899
10900		/* synchronize stx table. */
10901		for (i = 0; i < N(tables); i++) {
10902			st = &tables[i];
10903			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10904			tmp >>= st->st_rfshift;
10905			tmp <<= st->st_physhift;
10906			BWN_PHY_SETMASK(mac,
10907			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10908			    ~(st->st_mask << st->st_physhift), tmp);
10909		}
10910
10911		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10912		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10913	}
10914
10915	/* calibrate RC */
10916	if (mac->mac_phy.rev >= 2)
10917		bwn_phy_lp_rxcal_r2(mac);
10918	else if (!plp->plp_rccap) {
10919		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10920			bwn_phy_lp_rccal_r12(mac);
10921	} else
10922		bwn_phy_lp_set_rccap(mac);
10923
10924	error = bwn_phy_lp_switch_channel(mac, 7);
10925	if (error)
10926		device_printf(sc->sc_dev,
10927		    "failed to change channel 7 (%d)\n", error);
10928	bwn_phy_lp_txpctl_init(mac);
10929	bwn_phy_lp_calib(mac);
10930	return (0);
10931}
10932
10933static uint16_t
10934bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10935{
10936
10937	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10938	return (BWN_READ_2(mac, BWN_PHYDATA));
10939}
10940
10941static void
10942bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10943{
10944
10945	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10946	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10947}
10948
10949static void
10950bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10951    uint16_t set)
10952{
10953
10954	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10955	BWN_WRITE_2(mac, BWN_PHYDATA,
10956	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10957}
10958
10959static uint16_t
10960bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10961{
10962
10963	KASSERT(reg != 1, ("unaccessible register %d", reg));
10964	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10965		reg |= 0x100;
10966	if (mac->mac_phy.rev >= 2)
10967		reg |= 0x200;
10968	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10969	return BWN_READ_2(mac, BWN_RFDATALO);
10970}
10971
10972static void
10973bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10974{
10975
10976	KASSERT(reg != 1, ("unaccessible register %d", reg));
10977	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10978	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10979}
10980
10981static void
10982bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10983{
10984
10985	if (on) {
10986		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10987		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10988		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10989		return;
10990	}
10991
10992	if (mac->mac_phy.rev >= 2) {
10993		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10994		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10995		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10996		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10997		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10998		return;
10999	}
11000
11001	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11002	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11003	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11004	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11005}
11006
11007static int
11008bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11009{
11010	struct bwn_phy *phy = &mac->mac_phy;
11011	struct bwn_phy_lp *plp = &phy->phy_lp;
11012	int error;
11013
11014	if (phy->rf_ver == 0x2063) {
11015		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11016		if (error)
11017			return (error);
11018	} else {
11019		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11020		if (error)
11021			return (error);
11022		bwn_phy_lp_set_anafilter(mac, chan);
11023		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11024	}
11025
11026	plp->plp_chan = chan;
11027	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11028	return (0);
11029}
11030
11031static uint32_t
11032bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11033{
11034	struct bwn_softc *sc = mac->mac_sc;
11035	struct ifnet *ifp = sc->sc_ifp;
11036	struct ieee80211com *ic = ifp->if_l2com;
11037
11038	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11039}
11040
11041static void
11042bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11043{
11044	struct bwn_phy *phy = &mac->mac_phy;
11045	struct bwn_phy_lp *plp = &phy->phy_lp;
11046
11047	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11048		return;
11049
11050	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11051	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11052	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11053	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11054	plp->plp_antenna = antenna;
11055}
11056
11057static void
11058bwn_phy_lp_task_60s(struct bwn_mac *mac)
11059{
11060
11061	bwn_phy_lp_calib(mac);
11062}
11063
11064static void
11065bwn_phy_lp_readsprom(struct bwn_mac *mac)
11066{
11067	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11068	struct bwn_softc *sc = mac->mac_sc;
11069	struct ifnet *ifp = sc->sc_ifp;
11070	struct ieee80211com *ic = ifp->if_l2com;
11071
11072	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11073		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11074		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11075		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11076		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11077		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11078		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11079		return;
11080	}
11081
11082	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11083	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11084	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11085	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11086	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11087	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11088	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11089	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11090}
11091
11092static void
11093bwn_phy_lp_bbinit(struct bwn_mac *mac)
11094{
11095
11096	bwn_phy_lp_tblinit(mac);
11097	if (mac->mac_phy.rev >= 2)
11098		bwn_phy_lp_bbinit_r2(mac);
11099	else
11100		bwn_phy_lp_bbinit_r01(mac);
11101}
11102
11103static void
11104bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11105{
11106	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11107	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11108	struct bwn_softc *sc = mac->mac_sc;
11109	struct ifnet *ifp = sc->sc_ifp;
11110	struct ieee80211com *ic = ifp->if_l2com;
11111
11112	bwn_phy_lp_set_txgain(mac,
11113	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11114	bwn_phy_lp_set_bbmult(mac, 150);
11115}
11116
11117static void
11118bwn_phy_lp_calib(struct bwn_mac *mac)
11119{
11120	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11121	struct bwn_softc *sc = mac->mac_sc;
11122	struct ifnet *ifp = sc->sc_ifp;
11123	struct ieee80211com *ic = ifp->if_l2com;
11124	const struct bwn_rxcompco *rc = NULL;
11125	struct bwn_txgain ogain;
11126	int i, omode, oafeovr, orf, obbmult;
11127	uint8_t mode, fc = 0;
11128
11129	if (plp->plp_chanfullcal != plp->plp_chan) {
11130		plp->plp_chanfullcal = plp->plp_chan;
11131		fc = 1;
11132	}
11133
11134	bwn_mac_suspend(mac);
11135
11136	/* BlueTooth Coexistance Override */
11137	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11138	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11139
11140	if (mac->mac_phy.rev >= 2)
11141		bwn_phy_lp_digflt_save(mac);
11142	bwn_phy_lp_get_txpctlmode(mac);
11143	mode = plp->plp_txpctlmode;
11144	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11145	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11146		bwn_phy_lp_bugfix(mac);
11147	if (mac->mac_phy.rev >= 2 && fc == 1) {
11148		bwn_phy_lp_get_txpctlmode(mac);
11149		omode = plp->plp_txpctlmode;
11150		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11151		if (oafeovr)
11152			ogain = bwn_phy_lp_get_txgain(mac);
11153		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11154		obbmult = bwn_phy_lp_get_bbmult(mac);
11155		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11156		if (oafeovr)
11157			bwn_phy_lp_set_txgain(mac, &ogain);
11158		bwn_phy_lp_set_bbmult(mac, obbmult);
11159		bwn_phy_lp_set_txpctlmode(mac, omode);
11160		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11161	}
11162	bwn_phy_lp_set_txpctlmode(mac, mode);
11163	if (mac->mac_phy.rev >= 2)
11164		bwn_phy_lp_digflt_restore(mac);
11165
11166	/* do RX IQ Calculation; assumes that noise is true. */
11167	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11168		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11169			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11170				rc = &bwn_rxcompco_5354[i];
11171		}
11172	} else if (mac->mac_phy.rev >= 2)
11173		rc = &bwn_rxcompco_r2;
11174	else {
11175		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11176			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11177				rc = &bwn_rxcompco_r12[i];
11178		}
11179	}
11180	if (rc == NULL)
11181		goto fail;
11182
11183	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11184	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11185
11186	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11187
11188	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11189		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11190		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11191	} else {
11192		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11193		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11194	}
11195
11196	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11197	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11198	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11199	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11200	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11201	bwn_phy_lp_set_deaf(mac, 0);
11202	/* XXX no checking return value? */
11203	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11204	bwn_phy_lp_clear_deaf(mac, 0);
11205	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11206	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11207	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11208
11209	/* disable RX GAIN override. */
11210	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11211	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11212	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11213	if (mac->mac_phy.rev >= 2) {
11214		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11215		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11216			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11217			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11218		}
11219	} else {
11220		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11221	}
11222
11223	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11224	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11225fail:
11226	bwn_mac_enable(mac);
11227}
11228
11229static void
11230bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11231{
11232
11233	if (on) {
11234		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11235		return;
11236	}
11237
11238	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11239	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11240}
11241
11242static int
11243bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11244{
11245	static const struct bwn_b206x_chan *bc = NULL;
11246	struct bwn_softc *sc = mac->mac_sc;
11247	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11248	    tmp[6];
11249	uint16_t old, scale, tmp16;
11250	int i, div;
11251
11252	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11253		if (bwn_b2063_chantable[i].bc_chan == chan) {
11254			bc = &bwn_b2063_chantable[i];
11255			break;
11256		}
11257	}
11258	if (bc == NULL)
11259		return (EINVAL);
11260
11261	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11262	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11263	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11264	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11265	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11266	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11267	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11268	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11269	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11270	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11271	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11272	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11273
11274	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11275	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11276
11277	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11278	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11279	freqref = freqxtal * 3;
11280	div = (freqxtal <= 26000000 ? 1 : 2);
11281	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11282	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11283		999999) / 1000000) + 1;
11284
11285	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11286	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11287	    0xfff8, timeout >> 2);
11288	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11289	    0xff9f,timeout << 5);
11290	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11291
11292	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11293	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11294	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11295
11296	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11297	    (timeoutref + 1)) - 1;
11298	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11299	    0xf0, count >> 8);
11300	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11301
11302	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11303	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11304	while (tmp[1] >= freqref) {
11305		tmp[0]++;
11306		tmp[1] -= freqref;
11307	}
11308	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11309	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11310	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11311	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11312	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11313
11314	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11315	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11316	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11317	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11318
11319	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11320	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11321
11322	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11323		scale = 1;
11324		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11325	} else {
11326		scale = 0;
11327		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11328	}
11329	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11330	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11331
11332	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11333	    (scale + 1);
11334	if (tmp[5] > 150)
11335		tmp[5] = 0;
11336
11337	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11338	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11339
11340	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11341	if (freqxtal > 26000000)
11342		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11343	else
11344		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11345
11346	if (val[0] == 45)
11347		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11348	else
11349		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11350
11351	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11352	DELAY(1);
11353	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11354
11355	/* VCO Calibration */
11356	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11357	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11358	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11359	DELAY(1);
11360	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11361	DELAY(1);
11362	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11363	DELAY(1);
11364	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11365	DELAY(300);
11366	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11367
11368	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11369	return (0);
11370}
11371
11372static int
11373bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11374{
11375	struct bwn_softc *sc = mac->mac_sc;
11376	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11377	const struct bwn_b206x_chan *bc = NULL;
11378	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11379	uint32_t tmp[9];
11380	int i;
11381
11382	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11383		if (bwn_b2062_chantable[i].bc_chan == chan) {
11384			bc = &bwn_b2062_chantable[i];
11385			break;
11386		}
11387	}
11388
11389	if (bc == NULL)
11390		return (EINVAL);
11391
11392	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11393	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11394	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11395	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11396	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11397	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11398	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11399	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11400	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11401	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11402
11403	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11404	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11405	bwn_phy_lp_b2062_reset_pllbias(mac);
11406	tmp[0] = freqxtal / 1000;
11407	tmp[1] = plp->plp_div * 1000;
11408	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11409	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11410		tmp[2] *= 2;
11411	tmp[3] = 48 * tmp[0];
11412	tmp[5] = tmp[2] / tmp[3];
11413	tmp[6] = tmp[2] % tmp[3];
11414	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11415	tmp[4] = tmp[6] * 0x100;
11416	tmp[5] = tmp[4] / tmp[3];
11417	tmp[6] = tmp[4] % tmp[3];
11418	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11419	tmp[4] = tmp[6] * 0x100;
11420	tmp[5] = tmp[4] / tmp[3];
11421	tmp[6] = tmp[4] % tmp[3];
11422	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11423	tmp[4] = tmp[6] * 0x100;
11424	tmp[5] = tmp[4] / tmp[3];
11425	tmp[6] = tmp[4] % tmp[3];
11426	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11427	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11428	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11429	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11430	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11431	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11432
11433	bwn_phy_lp_b2062_vco_calib(mac);
11434	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11435		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11436		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11437		bwn_phy_lp_b2062_reset_pllbias(mac);
11438		bwn_phy_lp_b2062_vco_calib(mac);
11439		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11440			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11441			return (EIO);
11442		}
11443	}
11444	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11445	return (0);
11446}
11447
11448static void
11449bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11450{
11451	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11452	uint16_t tmp = (channel == 14);
11453
11454	if (mac->mac_phy.rev < 2) {
11455		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11456		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11457			bwn_phy_lp_set_rccap(mac);
11458		return;
11459	}
11460
11461	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11462}
11463
11464static void
11465bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11466{
11467	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11468	struct bwn_softc *sc = mac->mac_sc;
11469	struct ifnet *ifp = sc->sc_ifp;
11470	struct ieee80211com *ic = ifp->if_l2com;
11471	uint16_t iso, tmp[3];
11472
11473	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11474
11475	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11476		iso = plp->plp_txisoband_m;
11477	else if (freq <= 5320)
11478		iso = plp->plp_txisoband_l;
11479	else if (freq <= 5700)
11480		iso = plp->plp_txisoband_m;
11481	else
11482		iso = plp->plp_txisoband_h;
11483
11484	tmp[0] = ((iso - 26) / 12) << 12;
11485	tmp[1] = tmp[0] + 0x1000;
11486	tmp[2] = tmp[0] + 0x2000;
11487
11488	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11489	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11490}
11491
11492static void
11493bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11494{
11495	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11496	int i;
11497	static const uint16_t addr[] = {
11498		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11499		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11500		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11501		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11502		BWN_PHY_OFDM(0xcf),
11503	};
11504	static const uint16_t val[] = {
11505		0xde5e, 0xe832, 0xe331, 0x4d26,
11506		0x0026, 0x1420, 0x0020, 0xfe08,
11507		0x0008,
11508	};
11509
11510	for (i = 0; i < N(addr); i++) {
11511		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11512		BWN_PHY_WRITE(mac, addr[i], val[i]);
11513	}
11514}
11515
11516static void
11517bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11518{
11519	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11520	struct bwn_softc *sc = mac->mac_sc;
11521	uint16_t ctl;
11522
11523	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11524	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11525	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11526		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11527		break;
11528	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11529		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11530		break;
11531	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11532		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11533		break;
11534	default:
11535		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11536		device_printf(sc->sc_dev, "unknown command mode\n");
11537		break;
11538	}
11539}
11540
11541static void
11542bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11543{
11544	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11545	uint16_t ctl;
11546	uint8_t old;
11547
11548	bwn_phy_lp_get_txpctlmode(mac);
11549	old = plp->plp_txpctlmode;
11550	if (old == mode)
11551		return;
11552	plp->plp_txpctlmode = mode;
11553
11554	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11555		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11556		    plp->plp_tssiidx);
11557		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11558		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11559
11560		/* disable TX GAIN override */
11561		if (mac->mac_phy.rev < 2)
11562			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11563		else {
11564			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11565			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11566		}
11567		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11568
11569		plp->plp_txpwridx = -1;
11570	}
11571	if (mac->mac_phy.rev >= 2) {
11572		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11573			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11574		else
11575			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11576	}
11577
11578	/* writes TX Power Control mode */
11579	switch (plp->plp_txpctlmode) {
11580	case BWN_PHYLP_TXPCTL_OFF:
11581		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11582		break;
11583	case BWN_PHYLP_TXPCTL_ON_HW:
11584		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11585		break;
11586	case BWN_PHYLP_TXPCTL_ON_SW:
11587		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11588		break;
11589	default:
11590		ctl = 0;
11591		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11592	}
11593	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11594	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11595}
11596
11597static void
11598bwn_phy_lp_bugfix(struct bwn_mac *mac)
11599{
11600	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11601	struct bwn_softc *sc = mac->mac_sc;
11602	const unsigned int size = 256;
11603	struct bwn_txgain tg;
11604	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11605	uint16_t tssinpt, tssiidx, value[2];
11606	uint8_t mode;
11607	int8_t txpwridx;
11608
11609	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11610	    M_NOWAIT | M_ZERO);
11611	if (tabs == NULL) {
11612		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11613		return;
11614	}
11615
11616	bwn_phy_lp_get_txpctlmode(mac);
11617	mode = plp->plp_txpctlmode;
11618	txpwridx = plp->plp_txpwridx;
11619	tssinpt = plp->plp_tssinpt;
11620	tssiidx = plp->plp_tssiidx;
11621
11622	bwn_tab_read_multi(mac,
11623	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11624	    BWN_TAB_4(7, 0x140), size, tabs);
11625
11626	bwn_phy_lp_tblinit(mac);
11627	bwn_phy_lp_bbinit(mac);
11628	bwn_phy_lp_txpctl_init(mac);
11629	bwn_phy_lp_rf_onoff(mac, 1);
11630	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11631
11632	bwn_tab_write_multi(mac,
11633	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11634	    BWN_TAB_4(7, 0x140), size, tabs);
11635
11636	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11637	plp->plp_tssinpt = tssinpt;
11638	plp->plp_tssiidx = tssiidx;
11639	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11640	if (txpwridx != -1) {
11641		/* set TX power by index */
11642		plp->plp_txpwridx = txpwridx;
11643		bwn_phy_lp_get_txpctlmode(mac);
11644		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11645			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11646		if (mac->mac_phy.rev >= 2) {
11647			rxcomp = bwn_tab_read(mac,
11648			    BWN_TAB_4(7, txpwridx + 320));
11649			txgain = bwn_tab_read(mac,
11650			    BWN_TAB_4(7, txpwridx + 192));
11651			tg.tg_pad = (txgain >> 16) & 0xff;
11652			tg.tg_gm = txgain & 0xff;
11653			tg.tg_pga = (txgain >> 8) & 0xff;
11654			tg.tg_dac = (rxcomp >> 28) & 0xff;
11655			bwn_phy_lp_set_txgain(mac, &tg);
11656		} else {
11657			rxcomp = bwn_tab_read(mac,
11658			    BWN_TAB_4(10, txpwridx + 320));
11659			txgain = bwn_tab_read(mac,
11660			    BWN_TAB_4(10, txpwridx + 192));
11661			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11662			    0xf800, (txgain >> 4) & 0x7fff);
11663			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11664			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11665		}
11666		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11667
11668		/* set TX IQCC */
11669		value[0] = (rxcomp >> 10) & 0x3ff;
11670		value[1] = rxcomp & 0x3ff;
11671		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11672
11673		coeff = bwn_tab_read(mac,
11674		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11675		    BWN_TAB_4(10, txpwridx + 448));
11676		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11677		if (mac->mac_phy.rev >= 2) {
11678			rfpwr = bwn_tab_read(mac,
11679			    BWN_TAB_4(7, txpwridx + 576));
11680			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11681			    rfpwr & 0xffff);
11682		}
11683		bwn_phy_lp_set_txgain_override(mac);
11684	}
11685	if (plp->plp_rccap)
11686		bwn_phy_lp_set_rccap(mac);
11687	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11688	bwn_phy_lp_set_txpctlmode(mac, mode);
11689	free(tabs, M_DEVBUF);
11690}
11691
11692static void
11693bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11694{
11695	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11696	int i;
11697	static const uint16_t addr[] = {
11698		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11699		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11700		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11701		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11702		BWN_PHY_OFDM(0xcf),
11703	};
11704
11705	for (i = 0; i < N(addr); i++)
11706		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11707}
11708
11709static void
11710bwn_phy_lp_tblinit(struct bwn_mac *mac)
11711{
11712	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11713
11714	if (mac->mac_phy.rev < 2) {
11715		bwn_phy_lp_tblinit_r01(mac);
11716		bwn_phy_lp_tblinit_txgain(mac);
11717		bwn_phy_lp_set_gaintbl(mac, freq);
11718		return;
11719	}
11720
11721	bwn_phy_lp_tblinit_r2(mac);
11722	bwn_phy_lp_tblinit_txgain(mac);
11723}
11724
11725struct bwn_wpair {
11726	uint16_t		reg;
11727	uint16_t		value;
11728};
11729
11730struct bwn_smpair {
11731	uint16_t		offset;
11732	uint16_t		mask;
11733	uint16_t		set;
11734};
11735
11736static void
11737bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11738{
11739	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11740	struct bwn_softc *sc = mac->mac_sc;
11741	struct ifnet *ifp = sc->sc_ifp;
11742	struct ieee80211com *ic = ifp->if_l2com;
11743	static const struct bwn_wpair v1[] = {
11744		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11745		{ BWN_PHY_AFE_CTL, 0x8800 },
11746		{ BWN_PHY_AFE_CTL_OVR, 0 },
11747		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11748		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11749		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11750		{ BWN_PHY_OFDM(0xf9), 0 },
11751		{ BWN_PHY_TR_LOOKUP_1, 0 }
11752	};
11753	static const struct bwn_smpair v2[] = {
11754		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11755		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11756		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11757		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11758		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11759	};
11760	static const struct bwn_smpair v3[] = {
11761		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11762		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11763		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11764		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11765		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11766		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11767		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11768		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11769		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11770		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11771
11772	};
11773	int i;
11774
11775	for (i = 0; i < N(v1); i++)
11776		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11777	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11778	for (i = 0; i < N(v2); i++)
11779		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11780
11781	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11782	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11783	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11784	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11785		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11786		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11787	} else {
11788		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11789	}
11790	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11791	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11792	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11793	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11794	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11795	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11796	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11797	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11798	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11799	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11800	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11801	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11802	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11803		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11804		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11805	} else {
11806		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11807		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11808	}
11809	for (i = 0; i < N(v3); i++)
11810		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11811	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11812	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11813		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11814		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11815	}
11816
11817	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11818		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11819		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11820		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11821		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11822		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11823		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11824	} else
11825		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11826
11827	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11828	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11829	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11830	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11831	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11832	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11833	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11834	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11835	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11836
11837	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11838	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11839		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11840		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11841		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11842	}
11843
11844	bwn_phy_lp_digflt_save(mac);
11845}
11846
11847static void
11848bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11849{
11850	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11851	struct bwn_softc *sc = mac->mac_sc;
11852	struct ifnet *ifp = sc->sc_ifp;
11853	struct ieee80211com *ic = ifp->if_l2com;
11854	static const struct bwn_smpair v1[] = {
11855		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11856		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11857		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11858		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11859		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11860		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11861		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11862	};
11863	static const struct bwn_smpair v2[] = {
11864		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11865		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11866		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11867		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11868		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11869		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11870		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11871		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11872		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11873		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11874		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11875		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11876		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11877		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11878		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11879		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11880	};
11881	static const struct bwn_smpair v3[] = {
11882		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11883		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11884		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11885		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11886		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11887		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11888		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11889		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11890	};
11891	static const struct bwn_smpair v4[] = {
11892		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11893		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11894		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11895		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11896		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11897		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11898		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11899		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11900	};
11901	static const struct bwn_smpair v5[] = {
11902		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11903		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11904		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11905		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11906		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11907		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11908		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11909		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11910	};
11911	int i;
11912	uint16_t tmp, tmp2;
11913
11914	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11915	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11916	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11917	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11918	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11919	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11920	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11921	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11922	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11923	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11924	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11925	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11926	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11927	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11928	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11929	for (i = 0; i < N(v1); i++)
11930		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11931	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11932	    0xff00, plp->plp_rxpwroffset);
11933	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11934	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11935	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11936		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11937		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11938		if (mac->mac_phy.rev == 0)
11939			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11940			    0xffcf, 0x0010);
11941		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11942	} else {
11943		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11944		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11945		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11946	}
11947	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11948	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11949	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11950		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11951	else
11952		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11953	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11954	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11955	    0xfff9, (plp->plp_bxarch << 1));
11956	if (mac->mac_phy.rev == 1 &&
11957	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11958		for (i = 0; i < N(v2); i++)
11959			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11960			    v2[i].set);
11961	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11962	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11963	    ((mac->mac_phy.rev == 0) &&
11964	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11965		for (i = 0; i < N(v3); i++)
11966			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11967			    v3[i].set);
11968	} else if (mac->mac_phy.rev == 1 ||
11969		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11970		for (i = 0; i < N(v4); i++)
11971			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11972			    v4[i].set);
11973	} else {
11974		for (i = 0; i < N(v5); i++)
11975			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11976			    v5[i].set);
11977	}
11978	if (mac->mac_phy.rev == 1 &&
11979	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11980		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11981		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11982		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11983		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11984	}
11985	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11986	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11987	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11988		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11989		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11990		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11991		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11992	}
11993	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11994		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11995		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11996		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11997		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11998		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11999		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12000		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12001		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12002	} else {
12003		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12004		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12005	}
12006	if (mac->mac_phy.rev == 1) {
12007		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12008		tmp2 = (tmp & 0x03e0) >> 5;
12009		tmp2 |= tmp2 << 5;
12010		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12011		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12012		tmp2 = (tmp & 0x1f00) >> 8;
12013		tmp2 |= tmp2 << 5;
12014		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12015		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12016		tmp2 = tmp & 0x00ff;
12017		tmp2 |= tmp << 8;
12018		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12019	}
12020}
12021
12022struct bwn_b2062_freq {
12023	uint16_t		freq;
12024	uint8_t			value[6];
12025};
12026
12027static void
12028bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12029{
12030#define	CALC_CTL7(freq, div)						\
12031	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12032#define	CALC_CTL18(freq, div)						\
12033	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12034#define	CALC_CTL19(freq, div)						\
12035	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12036	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12037	struct bwn_softc *sc = mac->mac_sc;
12038	struct ifnet *ifp = sc->sc_ifp;
12039	struct ieee80211com *ic = ifp->if_l2com;
12040	static const struct bwn_b2062_freq freqdata_tab[] = {
12041		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12042		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12043		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12044		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12045		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12046		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12047	};
12048	static const struct bwn_wpair v1[] = {
12049		{ BWN_B2062_N_TXCTL3, 0 },
12050		{ BWN_B2062_N_TXCTL4, 0 },
12051		{ BWN_B2062_N_TXCTL5, 0 },
12052		{ BWN_B2062_N_TXCTL6, 0 },
12053		{ BWN_B2062_N_PDNCTL0, 0x40 },
12054		{ BWN_B2062_N_PDNCTL0, 0 },
12055		{ BWN_B2062_N_CALIB_TS, 0x10 },
12056		{ BWN_B2062_N_CALIB_TS, 0 }
12057	};
12058	const struct bwn_b2062_freq *f = NULL;
12059	uint32_t xtalfreq, ref;
12060	unsigned int i;
12061
12062	bwn_phy_lp_b2062_tblinit(mac);
12063
12064	for (i = 0; i < N(v1); i++)
12065		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12066	if (mac->mac_phy.rev > 0)
12067		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12068		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12069	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12070		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12071	else
12072		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12073
12074	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12075	    ("%s:%d: fail", __func__, __LINE__));
12076	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12077	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12078
12079	if (xtalfreq <= 30000000) {
12080		plp->plp_div = 1;
12081		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12082	} else {
12083		plp->plp_div = 2;
12084		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12085	}
12086
12087	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12088	    CALC_CTL7(xtalfreq, plp->plp_div));
12089	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12090	    CALC_CTL18(xtalfreq, plp->plp_div));
12091	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12092	    CALC_CTL19(xtalfreq, plp->plp_div));
12093
12094	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12095	ref &= 0xffff;
12096	for (i = 0; i < N(freqdata_tab); i++) {
12097		if (ref < freqdata_tab[i].freq) {
12098			f = &freqdata_tab[i];
12099			break;
12100		}
12101	}
12102	if (f == NULL)
12103		f = &freqdata_tab[N(freqdata_tab) - 1];
12104	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12105	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12106	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12107	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12108	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12109	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12110#undef CALC_CTL7
12111#undef CALC_CTL18
12112#undef CALC_CTL19
12113}
12114
12115static void
12116bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12117{
12118
12119	bwn_phy_lp_b2063_tblinit(mac);
12120	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12121	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12122	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12123	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12124	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12125	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12126	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12127	if (mac->mac_phy.rev == 2) {
12128		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12129		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12130		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12131	} else {
12132		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12133		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12134	}
12135}
12136
12137static void
12138bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12139{
12140	struct bwn_softc *sc = mac->mac_sc;
12141	static const struct bwn_wpair v1[] = {
12142		{ BWN_B2063_RX_BB_SP8, 0x0 },
12143		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12144		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12145		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12146		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12147		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12148		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12149		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12150	};
12151	static const struct bwn_wpair v2[] = {
12152		{ BWN_B2063_TX_BB_SP3, 0x0 },
12153		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12154		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12155		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12156		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12157	};
12158	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12159	int i;
12160	uint8_t tmp;
12161
12162	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12163
12164	for (i = 0; i < 2; i++)
12165		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12166	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12167	for (i = 2; i < N(v1); i++)
12168		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12169	for (i = 0; i < 10000; i++) {
12170		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12171			break;
12172		DELAY(1000);
12173	}
12174
12175	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12176		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12177
12178	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12179
12180	for (i = 0; i < N(v2); i++)
12181		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12182	if (freqxtal == 24000000) {
12183		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12184		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12185	} else {
12186		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12187		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12188	}
12189	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12190	for (i = 0; i < 10000; i++) {
12191		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12192			break;
12193		DELAY(1000);
12194	}
12195	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12196		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12197	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12198}
12199
12200static void
12201bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12202{
12203	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12204	struct bwn_softc *sc = mac->mac_sc;
12205	struct bwn_phy_lp_iq_est ie;
12206	struct bwn_txgain tx_gains;
12207	static const uint32_t pwrtbl[21] = {
12208		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12209		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12210		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12211		0x0004c, 0x0002c, 0x0001a,
12212	};
12213	uint32_t npwr, ipwr, sqpwr, tmp;
12214	int loopback, i, j, sum, error;
12215	uint16_t save[7];
12216	uint8_t txo, bbmult, txpctlmode;
12217
12218	error = bwn_phy_lp_switch_channel(mac, 7);
12219	if (error)
12220		device_printf(sc->sc_dev,
12221		    "failed to change channel to 7 (%d)\n", error);
12222	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12223	bbmult = bwn_phy_lp_get_bbmult(mac);
12224	if (txo)
12225		tx_gains = bwn_phy_lp_get_txgain(mac);
12226
12227	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12228	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12229	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12230	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12231	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12232	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12233	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12234
12235	bwn_phy_lp_get_txpctlmode(mac);
12236	txpctlmode = plp->plp_txpctlmode;
12237	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12238
12239	/* disable CRS */
12240	bwn_phy_lp_set_deaf(mac, 1);
12241	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12242	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12243	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12244	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12245	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12246	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12247	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12248	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12249	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12250	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12251	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12252	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12253	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12254	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12255	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12256	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12257	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12258	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12259	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12260	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12261	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12262	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12263	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12264	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12265
12266	loopback = bwn_phy_lp_loopback(mac);
12267	if (loopback == -1)
12268		goto done;
12269	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12270	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12271	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12272	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12273	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12274
12275	tmp = 0;
12276	memset(&ie, 0, sizeof(ie));
12277	for (i = 128; i <= 159; i++) {
12278		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12279		sum = 0;
12280		for (j = 5; j <= 25; j++) {
12281			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12282			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12283				goto done;
12284			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12285			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12286			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12287			    12);
12288			sum += ((ipwr - npwr) * (ipwr - npwr));
12289			if ((i == 128) || (sum < tmp)) {
12290				plp->plp_rccap = i;
12291				tmp = sum;
12292			}
12293		}
12294	}
12295	bwn_phy_lp_ddfs_turnoff(mac);
12296done:
12297	/* restore CRS */
12298	bwn_phy_lp_clear_deaf(mac, 1);
12299	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12300	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12301
12302	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12303	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12304	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12305	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12306	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12307	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12308	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12309
12310	bwn_phy_lp_set_bbmult(mac, bbmult);
12311	if (txo)
12312		bwn_phy_lp_set_txgain(mac, &tx_gains);
12313	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12314	if (plp->plp_rccap)
12315		bwn_phy_lp_set_rccap(mac);
12316}
12317
12318static void
12319bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12320{
12321	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12322	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12323
12324	if (mac->mac_phy.rev == 1)
12325		rc_cap = MIN(rc_cap + 5, 15);
12326
12327	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12328	    MAX(plp->plp_rccap - 4, 0x80));
12329	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12330	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12331	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12332}
12333
12334static uint32_t
12335bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12336{
12337	uint32_t i, q, r;
12338
12339	if (div == 0)
12340		return (0);
12341
12342	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12343		q <<= 1;
12344		if (r << 1 >= div) {
12345			q++;
12346			r = (r << 1) - div;
12347		}
12348	}
12349	if (r << 1 >= div)
12350		q++;
12351	return (q);
12352}
12353
12354static void
12355bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12356{
12357	struct bwn_softc *sc = mac->mac_sc;
12358
12359	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12360	DELAY(20);
12361	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12362		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12363		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12364	} else {
12365		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12366	}
12367	DELAY(5);
12368}
12369
12370static void
12371bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12372{
12373
12374	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12375	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12376	DELAY(200);
12377}
12378
12379static void
12380bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12381{
12382#define	FLAG_A	0x01
12383#define	FLAG_G	0x02
12384	struct bwn_softc *sc = mac->mac_sc;
12385	struct ifnet *ifp = sc->sc_ifp;
12386	struct ieee80211com *ic = ifp->if_l2com;
12387	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12388		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12389		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12390		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12391		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12392		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12393		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12394		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12395		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12396		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12397		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12398		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12399		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12400		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12401		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12402		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12403		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12404		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12405		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12406		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12407		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12408		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12409		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12410		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12411		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12412		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12413		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12414		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12415		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12416		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12417		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12418		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12419		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12420		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12421		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12422		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12423		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12424		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12425		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12426		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12427		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12428		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12429		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12430		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12431		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12432		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12433		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12434		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12435	};
12436	const struct bwn_b206x_rfinit_entry *br;
12437	unsigned int i;
12438
12439	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12440		br = &bwn_b2062_init_tab[i];
12441		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12442			if (br->br_flags & FLAG_G)
12443				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12444		} else {
12445			if (br->br_flags & FLAG_A)
12446				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12447		}
12448	}
12449#undef FLAG_A
12450#undef FLAG_B
12451}
12452
12453static void
12454bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12455{
12456#define	FLAG_A	0x01
12457#define	FLAG_G	0x02
12458	struct bwn_softc *sc = mac->mac_sc;
12459	struct ifnet *ifp = sc->sc_ifp;
12460	struct ieee80211com *ic = ifp->if_l2com;
12461	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12462		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12463		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12464		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12465		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12466		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12467		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12468		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12469		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12470		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12471		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12472		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12473		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12474		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12475		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12476		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12477		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12478		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12479		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12480		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12481		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12482		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12483		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12484		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12485		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12486		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12487		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12488		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12489		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12490		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12491		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12492		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12493		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12494		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12495		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12496		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12497		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12498		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12499		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12500		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12501		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12502		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12503		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12504	};
12505	const struct bwn_b206x_rfinit_entry *br;
12506	unsigned int i;
12507
12508	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12509		br = &bwn_b2063_init_tab[i];
12510		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12511			if (br->br_flags & FLAG_G)
12512				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12513		} else {
12514			if (br->br_flags & FLAG_A)
12515				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12516		}
12517	}
12518#undef FLAG_A
12519#undef FLAG_B
12520}
12521
12522static void
12523bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12524    int count, void *_data)
12525{
12526	unsigned int i;
12527	uint32_t offset, type;
12528	uint8_t *data = _data;
12529
12530	type = BWN_TAB_GETTYPE(typenoffset);
12531	offset = BWN_TAB_GETOFFSET(typenoffset);
12532	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12533
12534	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12535
12536	for (i = 0; i < count; i++) {
12537		switch (type) {
12538		case BWN_TAB_8BIT:
12539			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12540			data++;
12541			break;
12542		case BWN_TAB_16BIT:
12543			*((uint16_t *)data) = BWN_PHY_READ(mac,
12544			    BWN_PHY_TABLEDATALO);
12545			data += 2;
12546			break;
12547		case BWN_TAB_32BIT:
12548			*((uint32_t *)data) = BWN_PHY_READ(mac,
12549			    BWN_PHY_TABLEDATAHI);
12550			*((uint32_t *)data) <<= 16;
12551			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12552			    BWN_PHY_TABLEDATALO);
12553			data += 4;
12554			break;
12555		default:
12556			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12557		}
12558	}
12559}
12560
12561static void
12562bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12563    int count, const void *_data)
12564{
12565	uint32_t offset, type, value;
12566	const uint8_t *data = _data;
12567	unsigned int i;
12568
12569	type = BWN_TAB_GETTYPE(typenoffset);
12570	offset = BWN_TAB_GETOFFSET(typenoffset);
12571	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12572
12573	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12574
12575	for (i = 0; i < count; i++) {
12576		switch (type) {
12577		case BWN_TAB_8BIT:
12578			value = *data;
12579			data++;
12580			KASSERT(!(value & ~0xff),
12581			    ("%s:%d: fail", __func__, __LINE__));
12582			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12583			break;
12584		case BWN_TAB_16BIT:
12585			value = *((const uint16_t *)data);
12586			data += 2;
12587			KASSERT(!(value & ~0xffff),
12588			    ("%s:%d: fail", __func__, __LINE__));
12589			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12590			break;
12591		case BWN_TAB_32BIT:
12592			value = *((const uint32_t *)data);
12593			data += 4;
12594			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12595			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12596			break;
12597		default:
12598			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12599		}
12600	}
12601}
12602
12603static struct bwn_txgain
12604bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12605{
12606	struct bwn_txgain tg;
12607	uint16_t tmp;
12608
12609	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12610	if (mac->mac_phy.rev < 2) {
12611		tmp = BWN_PHY_READ(mac,
12612		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12613		tg.tg_gm = tmp & 0x0007;
12614		tg.tg_pga = (tmp & 0x0078) >> 3;
12615		tg.tg_pad = (tmp & 0x780) >> 7;
12616		return (tg);
12617	}
12618
12619	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12620	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12621	tg.tg_gm = tmp & 0xff;
12622	tg.tg_pga = (tmp >> 8) & 0xff;
12623	return (tg);
12624}
12625
12626static uint8_t
12627bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12628{
12629
12630	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12631}
12632
12633static void
12634bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12635{
12636	uint16_t pa;
12637
12638	if (mac->mac_phy.rev < 2) {
12639		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12640		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12641		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12642		bwn_phy_lp_set_txgain_override(mac);
12643		return;
12644	}
12645
12646	pa = bwn_phy_lp_get_pa_gain(mac);
12647	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12648	    (tg->tg_pga << 8) | tg->tg_gm);
12649	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12650	    tg->tg_pad | (pa << 6));
12651	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12652	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12653	    tg->tg_pad | (pa << 8));
12654	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12655	bwn_phy_lp_set_txgain_override(mac);
12656}
12657
12658static void
12659bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12660{
12661
12662	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12663}
12664
12665static void
12666bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12667{
12668	uint16_t trsw = (tx << 1) | rx;
12669
12670	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12671	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12672}
12673
12674static void
12675bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12676{
12677	struct bwn_softc *sc = mac->mac_sc;
12678	struct ifnet *ifp = sc->sc_ifp;
12679	struct ieee80211com *ic = ifp->if_l2com;
12680	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12681
12682	if (mac->mac_phy.rev < 2) {
12683		trsw = gain & 0x1;
12684		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12685		ext_lna = (gain & 2) >> 1;
12686
12687		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12688		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12689		    0xfbff, ext_lna << 10);
12690		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12691		    0xf7ff, ext_lna << 11);
12692		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12693	} else {
12694		low_gain = gain & 0xffff;
12695		high_gain = (gain >> 16) & 0xf;
12696		ext_lna = (gain >> 21) & 0x1;
12697		trsw = ~(gain >> 20) & 0x1;
12698
12699		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12700		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12701		    0xfdff, ext_lna << 9);
12702		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12703		    0xfbff, ext_lna << 10);
12704		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12705		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12706		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12707			tmp = (gain >> 2) & 0x3;
12708			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12709			    0xe7ff, tmp<<11);
12710			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12711			    tmp << 3);
12712		}
12713	}
12714
12715	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12716	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12717	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12718	if (mac->mac_phy.rev >= 2) {
12719		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12720		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12721			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12722			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12723		}
12724		return;
12725	}
12726	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12727}
12728
12729static void
12730bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12731{
12732	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12733
12734	if (user)
12735		plp->plp_crsusr_off = 1;
12736	else
12737		plp->plp_crssys_off = 1;
12738
12739	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12740}
12741
12742static void
12743bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12744{
12745	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12746	struct bwn_softc *sc = mac->mac_sc;
12747	struct ifnet *ifp = sc->sc_ifp;
12748	struct ieee80211com *ic = ifp->if_l2com;
12749
12750	if (user)
12751		plp->plp_crsusr_off = 0;
12752	else
12753		plp->plp_crssys_off = 0;
12754
12755	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12756		return;
12757
12758	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12759		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12760	else
12761		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12762}
12763
12764static unsigned int
12765bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12766{
12767	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12768	static uint8_t sqrt_table[256] = {
12769		10, 14, 17, 20, 22, 24, 26, 28,
12770		30, 31, 33, 34, 36, 37, 38, 40,
12771		41, 42, 43, 44, 45, 46, 47, 48,
12772		50, 50, 51, 52, 53, 54, 55, 56,
12773		57, 58, 59, 60, 60, 61, 62, 63,
12774		64, 64, 65, 66, 67, 67, 68, 69,
12775		70, 70, 71, 72, 72, 73, 74, 74,
12776		75, 76, 76, 77, 78, 78, 79, 80,
12777		80, 81, 81, 82, 83, 83, 84, 84,
12778		85, 86, 86, 87, 87, 88, 88, 89,
12779		90, 90, 91, 91, 92, 92, 93, 93,
12780		94, 94, 95, 95, 96, 96, 97, 97,
12781		98, 98, 99, 100, 100, 100, 101, 101,
12782		102, 102, 103, 103, 104, 104, 105, 105,
12783		106, 106, 107, 107, 108, 108, 109, 109,
12784		110, 110, 110, 111, 111, 112, 112, 113,
12785		113, 114, 114, 114, 115, 115, 116, 116,
12786		117, 117, 117, 118, 118, 119, 119, 120,
12787		120, 120, 121, 121, 122, 122, 122, 123,
12788		123, 124, 124, 124, 125, 125, 126, 126,
12789		126, 127, 127, 128, 128, 128, 129, 129,
12790		130, 130, 130, 131, 131, 131, 132, 132,
12791		133, 133, 133, 134, 134, 134, 135, 135,
12792		136, 136, 136, 137, 137, 137, 138, 138,
12793		138, 139, 139, 140, 140, 140, 141, 141,
12794		141, 142, 142, 142, 143, 143, 143, 144,
12795		144, 144, 145, 145, 145, 146, 146, 146,
12796		147, 147, 147, 148, 148, 148, 149, 149,
12797		150, 150, 150, 150, 151, 151, 151, 152,
12798		152, 152, 153, 153, 153, 154, 154, 154,
12799		155, 155, 155, 156, 156, 156, 157, 157,
12800		157, 158, 158, 158, 159, 159, 159, 160
12801	};
12802
12803	if (x == 0)
12804		return (0);
12805	if (x >= 256) {
12806		unsigned int tmp;
12807
12808		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12809			/* do nothing */ ;
12810		return (tmp);
12811	}
12812	return (sqrt_table[x - 1] / 10);
12813}
12814
12815static int
12816bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12817{
12818#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12819	int _t;								\
12820	_t = _x - 20;							\
12821	if (_t >= 0) {							\
12822		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12823	} else {							\
12824		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12825	}								\
12826} while (0)
12827#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12828	int _t;								\
12829	_t = _x - 11;							\
12830	if (_t >= 0)							\
12831		_v = (_y << (31 - _x)) / (_z >> _t);			\
12832	else								\
12833		_v = (_y << (31 - _x)) / (_z << -_t);			\
12834} while (0)
12835	struct bwn_phy_lp_iq_est ie;
12836	uint16_t v0, v1;
12837	int tmp[2], ret;
12838
12839	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12840	v0 = v1 >> 8;
12841	v1 |= 0xff;
12842
12843	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12844	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12845
12846	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12847	if (ret == 0)
12848		goto done;
12849
12850	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12851		ret = 0;
12852		goto done;
12853	}
12854
12855	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12856	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12857
12858	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12859	v0 = tmp[0] >> 3;
12860	v1 = tmp[1] >> 4;
12861done:
12862	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12863	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12864	return ret;
12865#undef CALC_COEFF
12866#undef CALC_COEFF2
12867}
12868
12869static void
12870bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12871{
12872	static const uint16_t noisescale[] = {
12873		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12874		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12875		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12876		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12877		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12878	};
12879	static const uint16_t crsgainnft[] = {
12880		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12881		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12882		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12883		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12884		0x013d,
12885	};
12886	static const uint16_t filterctl[] = {
12887		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12888		0xff53, 0x0127,
12889	};
12890	static const uint32_t psctl[] = {
12891		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12892		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12893		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12894		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12895		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12896		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12897		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12898		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12899	};
12900	static const uint16_t ofdmcckgain_r0[] = {
12901		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12902		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12903		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12904		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12905		0x755d,
12906	};
12907	static const uint16_t ofdmcckgain_r1[] = {
12908		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12909		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12910		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12911		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12912		0x755d,
12913	};
12914	static const uint16_t gaindelta[] = {
12915		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12916		0x0000,
12917	};
12918	static const uint32_t txpwrctl[] = {
12919		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12920		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12921		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12922		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12923		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12924		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12925		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12926		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12927		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12928		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12929		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12930		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12931		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12932		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12950		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12951		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12952		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12953		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12954		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12955		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12956		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12957		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12958		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12959		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12960		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12961		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12962		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12963		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12964		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12965		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12966		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12967		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12968		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12969		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12970		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12971		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12972		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12973		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12974		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12975		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12976		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12977		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12978		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12979		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12980		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12981		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12982		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12983		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12984		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12985		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12986		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12987		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12988		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12989		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12990		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12991		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12992		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12993		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12994		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12995		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12996		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12997		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12998		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12999		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13000		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13001		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13002		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13003		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13004		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13005		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13006		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13007		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13008		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13009		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13010		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13011		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13012		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13013		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13014		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13015		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13016		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13017		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13018		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13019		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13020		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13021		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13022		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13023		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13024		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13025		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13026		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13027		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13028		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13029		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13030		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13031		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13032		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13033		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13034		0x00000702,
13035	};
13036
13037	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13038
13039	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13040	    bwn_tab_sigsq_tbl);
13041	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13042	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13043	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13044	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13045	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13046	    bwn_tab_pllfrac_tbl);
13047	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13048	    bwn_tabl_iqlocal_tbl);
13049	if (mac->mac_phy.rev == 0) {
13050		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13051		    ofdmcckgain_r0);
13052		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13053		    ofdmcckgain_r0);
13054	} else {
13055		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13056		    ofdmcckgain_r1);
13057		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13058		    ofdmcckgain_r1);
13059	}
13060	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13061	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13062}
13063
13064static void
13065bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13066{
13067	struct bwn_softc *sc = mac->mac_sc;
13068	int i;
13069	static const uint16_t noisescale[] = {
13070		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13071		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13072		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13073		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13074		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13075		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13076		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13077	};
13078	static const uint32_t filterctl[] = {
13079		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13080		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13081	};
13082	static const uint32_t psctl[] = {
13083		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13084		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13085		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13086		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13087	};
13088	static const uint32_t gainidx[] = {
13089		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13090		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13091		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13092		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13093		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13094		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13095		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13096		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13097		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13098		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13099		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13100		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13101		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13102		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13103		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13104		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13105		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13106		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13107		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13108		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13109		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13110		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13111		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13112		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13113		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13114		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13115		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13116		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13117		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13118		0x0000001a, 0x64ca55ad, 0x0000001a
13119	};
13120	static const uint16_t auxgainidx[] = {
13121		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13122		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13123		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13124		0x0004, 0x0016
13125	};
13126	static const uint16_t swctl[] = {
13127		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13128		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13129		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13130		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13131		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13132		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13133		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13134		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13135	};
13136	static const uint8_t hf[] = {
13137		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13138		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13139	};
13140	static const uint32_t gainval[] = {
13141		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13142		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13143		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13144		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13145		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13146		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13147		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13148		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13149		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13150		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13151		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13152		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13153		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13154		0x000000f1, 0x00000000, 0x00000000
13155	};
13156	static const uint16_t gain[] = {
13157		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13158		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13159		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13160		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13161		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13162		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13163		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13164		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13165		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13166		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13167		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13168		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13169	};
13170	static const uint32_t papdeps[] = {
13171		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13172		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13173		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13174		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13175		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13176		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13177		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13178		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13179		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13180		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13181		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13182		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13183		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13184	};
13185	static const uint32_t papdmult[] = {
13186		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13187		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13188		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13189		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13190		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13191		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13192		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13193		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13194		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13195		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13196		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13197		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13198		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13199	};
13200	static const uint32_t gainidx_a0[] = {
13201		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13202		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13203		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13204		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13205		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13206		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13207		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13208		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13209		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13210		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13211		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13212		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13213		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13214	};
13215	static const uint16_t auxgainidx_a0[] = {
13216		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13217		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13218		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13219		0x0002, 0x0014
13220	};
13221	static const uint32_t gainval_a0[] = {
13222		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13223		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13224		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13225		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13226		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13227		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13228		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13229		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13231		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13232		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13233		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13234		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13235		0x000000f7, 0x00000000, 0x00000000
13236	};
13237	static const uint16_t gain_a0[] = {
13238		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13239		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13240		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13241		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13242		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13243		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13244		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13245		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13246		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13250	};
13251
13252	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13253
13254	for (i = 0; i < 704; i++)
13255		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13256
13257	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13258	    bwn_tab_sigsq_tbl);
13259	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13260	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13261	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13262	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13263	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13264	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13265	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13266	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13267	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13268	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13269	    bwn_tab_pllfrac_tbl);
13270	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13271	    bwn_tabl_iqlocal_tbl);
13272	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13273	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13274
13275	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13276	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13277		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13278		    gainidx_a0);
13279		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13280		    auxgainidx_a0);
13281		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13282		    gainval_a0);
13283		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13284	}
13285}
13286
13287static void
13288bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13289{
13290	struct bwn_softc *sc = mac->mac_sc;
13291	struct ifnet *ifp = sc->sc_ifp;
13292	struct ieee80211com *ic = ifp->if_l2com;
13293	static struct bwn_txgain_entry txgain_r2[] = {
13294		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13295		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13296		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13297		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13298		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13299		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13300		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13301		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13302		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13303		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13304		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13305		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13306		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13307		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13308		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13309		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13310		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13311		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13312		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13313		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13314		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13315		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13316		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13317		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13318		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13319		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13320		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13321		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13322		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13323		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13324		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13325		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13326		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13327		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13328		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13329		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13330		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13331		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13332		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13333		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13334		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13335		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13336		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13337		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13338		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13339		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13340		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13341		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13342		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13343		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13344		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13345		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13346		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13347		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13348		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13349		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13350		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13351		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13352		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13353		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13354		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13355		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13356		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13357		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13358	};
13359	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13360		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13361		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13362		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13363		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13364		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13365		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13366		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13367		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13368		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13369		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13370		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13371		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13372		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13373		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13374		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13375		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13376		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13377		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13378		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13379		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13380		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13381		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13382		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13383		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13384		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13385		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13386		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13387		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13388		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13389		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13390		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13391		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13392		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13393		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13394		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13395		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13396		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13397		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13398		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13399		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13400		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13401		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13402		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13403		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13404		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13405		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13406		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13407		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13408		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13409		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13410		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13411		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13412		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13413		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13414		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13415		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13416		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13417		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13418		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13419		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13420		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13421		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13422		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13423		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13424	};
13425	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13426		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13427		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13428		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13429		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13430		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13431		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13432		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13433		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13434		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13435		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13436		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13437		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13438		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13439		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13440		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13441		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13442		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13443		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13444		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13445		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13446		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13447		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13448		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13449		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13450		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13451		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13452		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13453		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13454		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13455		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13456		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13457		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13458		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13459		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13460		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13461		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13462		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13463		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13464		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13465		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13466		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13467		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13468		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13469		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13470		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13471		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13472		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13473		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13474		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13475		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13476		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13477		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13478		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13479		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13480		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13481		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13482		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13483		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13484		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13485		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13486		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13487		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13488		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13489		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13490	};
13491	static struct bwn_txgain_entry txgain_r0[] = {
13492		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13493		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13494		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13495		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13496		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13497		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13498		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13499		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13500		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13501		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13502		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13503		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13504		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13505		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13506		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13507		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13508		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13509		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13510		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13511		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13512		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13513		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13514		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13515		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13516		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13517		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13518		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13519		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13520		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13521		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13522		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13523		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13524		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13525		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13526		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13527		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13528		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13529		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13530		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13531		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13532		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13533		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13534		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13535		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13536		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13537		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13538		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13539		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13540		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13541		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13542		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13543		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13544		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13545		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13546		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13547		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13548		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13549		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13550		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13551		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13552		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13553		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13554		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13555		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13556	};
13557	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13558		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13559		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13560		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13561		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13562		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13563		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13564		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13565		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13566		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13567		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13568		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13569		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13570		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13571		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13572		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13573		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13574		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13575		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13576		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13577		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13578		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13579		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13580		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13581		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13582		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13583		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13584		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13585		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13586		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13587		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13588		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13589		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13590		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13591		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13592		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13593		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13594		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13595		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13596		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13597		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13598		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13599		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13600		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13601		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13602		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13603		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13604		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13605		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13606		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13607		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13608		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13609		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13610		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13611		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13612		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13613		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13614		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13615		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13616		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13617		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13618		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13619		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13620		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13621		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13622	};
13623	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13624		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13625		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13626		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13627		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13628		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13629		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13630		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13631		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13632		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13633		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13634		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13635		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13636		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13637		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13638		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13639		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13640		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13641		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13642		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13643		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13644		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13645		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13646		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13647		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13648		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13649		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13650		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13651		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13652		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13653		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13654		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13655		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13656		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13657		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13658		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13659		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13660		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13661		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13662		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13663		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13664		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13665		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13666		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13667		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13668		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13669		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13670		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13671		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13672		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13673		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13674		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13675		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13676		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13677		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13678		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13679		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13680		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13681		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13682		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13683		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13684		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13685		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13686		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13687		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13688	};
13689	static struct bwn_txgain_entry txgain_r1[] = {
13690		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13691		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13692		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13693		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13694		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13695		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13696		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13697		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13698		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13699		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13700		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13701		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13702		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13703		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13704		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13705		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13706		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13707		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13708		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13709		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13710		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13711		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13712		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13713		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13714		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13715		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13716		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13717		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13718		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13719		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13720		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13721		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13722		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13723		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13724		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13725		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13726		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13727		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13728		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13729		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13730		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13731		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13732		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13733		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13734		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13735		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13736		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13737		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13738		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13739		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13740		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13741		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13742		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13743		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13744		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13745		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13746		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13747		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13748		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13749		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13750		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13751		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13752		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13753		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13754		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13755		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13756		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13757		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13758		{ 7, 11, 6, 0, 71 }
13759	};
13760	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13761		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13762		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13763		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13764		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13765		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13766		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13767		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13768		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13769		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13770		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13771		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13772		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13773		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13774		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13775		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13776		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13777		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13778		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13779		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13780		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13781		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13782		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13783		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13784		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13785		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13786		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13787		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13788		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13789		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13790		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13791		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13792		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13793		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13794		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13795		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13796		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13797		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13798		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13799		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13800		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13801		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13802		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13803		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13804		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13805		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13806		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13807		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13808		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13809		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13810		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13811		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13812		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13813		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13814		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13815		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13816		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13817		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13818		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13819		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13820		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13821		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13822		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13823		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13824		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13825	};
13826	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13827		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13828		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13829		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13830		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13831		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13832		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13833		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13834		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13835		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13836		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13837		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13838		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13839		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13840		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13841		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13842		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13843		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13844		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13845		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13846		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13847		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13848		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13849		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13850		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13851		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13852		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13853		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13854		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13855		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13856		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13857		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13858		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13859		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13860		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13861		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13862		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13863		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13864		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13865		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13866		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13867		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13868		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13869		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13870		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13871		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13872		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13873		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13874		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13875		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13876		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13877		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13878		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13879		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13880		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13881		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13882		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13883		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13884		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13885		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13886		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13887		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13888		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13889		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13890		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13891	};
13892
13893	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13894		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13895			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13896		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13897			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13898			    txgain_2ghz_r2);
13899		else
13900			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13901			    txgain_5ghz_r2);
13902		return;
13903	}
13904
13905	if (mac->mac_phy.rev == 0) {
13906		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13907		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13908			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13909		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13910			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13911			    txgain_2ghz_r0);
13912		else
13913			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13914			    txgain_5ghz_r0);
13915		return;
13916	}
13917
13918	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13919	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13920		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13921	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13922		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13923	else
13924		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13925}
13926
13927static void
13928bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13929{
13930	uint32_t offset, type;
13931
13932	type = BWN_TAB_GETTYPE(typeoffset);
13933	offset = BWN_TAB_GETOFFSET(typeoffset);
13934	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13935
13936	switch (type) {
13937	case BWN_TAB_8BIT:
13938		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13939		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13940		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13941		break;
13942	case BWN_TAB_16BIT:
13943		KASSERT(!(value & ~0xffff),
13944		    ("%s:%d: fail", __func__, __LINE__));
13945		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13946		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13947		break;
13948	case BWN_TAB_32BIT:
13949		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13950		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13951		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13952		break;
13953	default:
13954		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13955	}
13956}
13957
13958static int
13959bwn_phy_lp_loopback(struct bwn_mac *mac)
13960{
13961	struct bwn_phy_lp_iq_est ie;
13962	int i, index = -1;
13963	uint32_t tmp;
13964
13965	memset(&ie, 0, sizeof(ie));
13966
13967	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13968	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13969	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13970	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13971	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13972	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13973	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13974	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13975	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13976	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13977	for (i = 0; i < 32; i++) {
13978		bwn_phy_lp_set_rxgain_idx(mac, i);
13979		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13980		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13981			continue;
13982		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13983		if ((tmp > 4000) && (tmp < 10000)) {
13984			index = i;
13985			break;
13986		}
13987	}
13988	bwn_phy_lp_ddfs_turnoff(mac);
13989	return (index);
13990}
13991
13992static void
13993bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13994{
13995
13996	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13997}
13998
13999static void
14000bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14001    int incr1, int incr2, int scale_idx)
14002{
14003
14004	bwn_phy_lp_ddfs_turnoff(mac);
14005	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14006	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14007	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14008	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14009	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14010	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14011	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14012	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14013	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14014	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14015}
14016
14017static uint8_t
14018bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14019    struct bwn_phy_lp_iq_est *ie)
14020{
14021	int i;
14022
14023	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14024	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14025	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14026	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14027	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14028
14029	for (i = 0; i < 500; i++) {
14030		if (!(BWN_PHY_READ(mac,
14031		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14032			break;
14033		DELAY(1000);
14034	}
14035	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14036		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14037		return 0;
14038	}
14039
14040	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14041	ie->ie_iqprod <<= 16;
14042	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14043	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14044	ie->ie_ipwr <<= 16;
14045	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14046	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14047	ie->ie_qpwr <<= 16;
14048	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14049
14050	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14051	return 1;
14052}
14053
14054static uint32_t
14055bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14056{
14057	uint32_t offset, type, value;
14058
14059	type = BWN_TAB_GETTYPE(typeoffset);
14060	offset = BWN_TAB_GETOFFSET(typeoffset);
14061	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14062
14063	switch (type) {
14064	case BWN_TAB_8BIT:
14065		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14066		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14067		break;
14068	case BWN_TAB_16BIT:
14069		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14070		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14071		break;
14072	case BWN_TAB_32BIT:
14073		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14074		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14075		value <<= 16;
14076		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14077		break;
14078	default:
14079		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14080		value = 0;
14081	}
14082
14083	return (value);
14084}
14085
14086static void
14087bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14088{
14089
14090	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14091	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14092}
14093
14094static void
14095bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14096{
14097	uint16_t ctl;
14098
14099	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14100	ctl |= dac << 7;
14101	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14102}
14103
14104static void
14105bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14106{
14107
14108	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14109	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14110}
14111
14112static void
14113bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14114{
14115
14116	if (mac->mac_phy.rev < 2)
14117		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14118	else {
14119		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14120		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14121	}
14122	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14123}
14124
14125static uint16_t
14126bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14127{
14128
14129	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14130}
14131
14132static uint8_t
14133bwn_nbits(int32_t val)
14134{
14135	uint32_t tmp;
14136	uint8_t nbits = 0;
14137
14138	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14139		nbits++;
14140	return (nbits);
14141}
14142
14143static void
14144bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14145    struct bwn_txgain_entry *table)
14146{
14147	int i;
14148
14149	for (i = offset; i < count; i++)
14150		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14151}
14152
14153static void
14154bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14155    struct bwn_txgain_entry data)
14156{
14157
14158	if (mac->mac_phy.rev >= 2)
14159		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14160	else
14161		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14162}
14163
14164static void
14165bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14166    struct bwn_txgain_entry te)
14167{
14168	struct bwn_softc *sc = mac->mac_sc;
14169	struct ifnet *ifp = sc->sc_ifp;
14170	struct ieee80211com *ic = ifp->if_l2com;
14171	uint32_t tmp;
14172
14173	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14174
14175	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14176	if (mac->mac_phy.rev >= 3) {
14177		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14178		    (0x10 << 24) : (0x70 << 24));
14179	} else {
14180		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14181		    (0x14 << 24) : (0x7f << 24));
14182	}
14183	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14184	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14185	    te.te_bbmult << 20 | te.te_dac << 28);
14186}
14187
14188static void
14189bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14190    struct bwn_txgain_entry te)
14191{
14192
14193	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14194
14195	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14196	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14197	    te.te_dac);
14198	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14199}
14200
14201static void
14202bwn_sysctl_node(struct bwn_softc *sc)
14203{
14204	device_t dev = sc->sc_dev;
14205	struct bwn_mac *mac;
14206	struct bwn_stats *stats;
14207
14208	/* XXX assume that count of MAC is only 1. */
14209
14210	if ((mac = sc->sc_curmac) == NULL)
14211		return;
14212	stats = &mac->mac_stats;
14213
14214	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14215	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14216	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14217	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14218	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14219	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14220	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14221	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14222	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14223
14224#ifdef BWN_DEBUG
14225	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14226	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14227	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14228#endif
14229}
14230
14231static device_method_t bwn_methods[] = {
14232	/* Device interface */
14233	DEVMETHOD(device_probe,		bwn_probe),
14234	DEVMETHOD(device_attach,	bwn_attach),
14235	DEVMETHOD(device_detach,	bwn_detach),
14236	DEVMETHOD(device_suspend,	bwn_suspend),
14237	DEVMETHOD(device_resume,	bwn_resume),
14238	KOBJMETHOD_END
14239};
14240static driver_t bwn_driver = {
14241	"bwn",
14242	bwn_methods,
14243	sizeof(struct bwn_softc)
14244};
14245static devclass_t bwn_devclass;
14246DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14247MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14248MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14249MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14250MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14251