xref: /freebsd/sys/dev/bwn/if_bwn.c (revision b2db760808f74bb53c232900091c9da801ebbfcc)
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$");
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 
76 SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77 
78 /*
79  * Tunable & sysctl variables.
80  */
81 
82 #ifdef BWN_DEBUG
83 static	int bwn_debug = 0;
84 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85     "Broadcom debugging printfs");
86 TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87 enum {
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 
116 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118     "uses Bad Frames Preemption");
119 static int	bwn_bluetooth = 1;
120 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121     "turns on Bluetooth Coexistence");
122 static int	bwn_hwpctl = 0;
123 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124     "uses H/W power control");
125 static int	bwn_msi_disable = 0;		/* MSI disabled  */
126 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127 static int	bwn_usedma = 1;
128 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129     "uses DMA");
130 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131 static int	bwn_wme = 1;
132 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133     "uses WME support");
134 
135 static int	bwn_attach_pre(struct bwn_softc *);
136 static int	bwn_attach_post(struct bwn_softc *);
137 static void	bwn_sprom_bugfixes(device_t);
138 static void	bwn_init(void *);
139 static int	bwn_init_locked(struct bwn_softc *);
140 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141 static void	bwn_start(struct ifnet *);
142 static int	bwn_attach_core(struct bwn_mac *);
143 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144 static int	bwn_phy_getinfo(struct bwn_mac *, int);
145 static int	bwn_chiptest(struct bwn_mac *);
146 static int	bwn_setup_channels(struct bwn_mac *, int, int);
147 static int	bwn_phy_g_attach(struct bwn_mac *);
148 static void	bwn_phy_g_detach(struct bwn_mac *);
149 static void	bwn_phy_g_init_pre(struct bwn_mac *);
150 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151 static int	bwn_phy_g_init(struct bwn_mac *);
152 static void	bwn_phy_g_exit(struct bwn_mac *);
153 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155 		    uint16_t);
156 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158 		    uint16_t);
159 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164 static int	bwn_phy_g_im(struct bwn_mac *, int);
165 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167 static void	bwn_phy_g_task_15s(struct bwn_mac *);
168 static void	bwn_phy_g_task_60s(struct bwn_mac *);
169 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173 		    uint16_t);
174 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176 		    uint32_t);
177 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178 		    uint16_t);
179 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180 		    const struct bwn_channelinfo *, int);
181 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182 		    const struct ieee80211_bpf_params *);
183 static void	bwn_updateslot(struct ifnet *);
184 static void	bwn_update_promisc(struct ifnet *);
185 static void	bwn_wme_init(struct bwn_mac *);
186 static int	bwn_wme_update(struct ieee80211com *);
187 static void	bwn_wme_clear(struct bwn_softc *);
188 static void	bwn_wme_load(struct bwn_mac *);
189 static void	bwn_wme_loadparams(struct bwn_mac *,
190 		    const struct wmeParams *, uint16_t);
191 static void	bwn_scan_start(struct ieee80211com *);
192 static void	bwn_scan_end(struct ieee80211com *);
193 static void	bwn_set_channel(struct ieee80211com *);
194 static 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]);
198 static void	bwn_vap_delete(struct ieee80211vap *);
199 static void	bwn_stop(struct bwn_softc *, int);
200 static void	bwn_stop_locked(struct bwn_softc *, int);
201 static int	bwn_core_init(struct bwn_mac *);
202 static void	bwn_core_start(struct bwn_mac *);
203 static void	bwn_core_exit(struct bwn_mac *);
204 static void	bwn_bt_disable(struct bwn_mac *);
205 static int	bwn_chip_init(struct bwn_mac *);
206 static uint64_t	bwn_hf_read(struct bwn_mac *);
207 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
208 static void	bwn_set_txretry(struct bwn_mac *, int, int);
209 static void	bwn_rate_init(struct bwn_mac *);
210 static void	bwn_set_phytxctl(struct bwn_mac *);
211 static void	bwn_spu_setdelay(struct bwn_mac *, int);
212 static void	bwn_bt_enable(struct bwn_mac *);
213 static void	bwn_set_macaddr(struct bwn_mac *);
214 static void	bwn_crypt_init(struct bwn_mac *);
215 static void	bwn_chip_exit(struct bwn_mac *);
216 static int	bwn_fw_fillinfo(struct bwn_mac *);
217 static int	bwn_fw_loaducode(struct bwn_mac *);
218 static int	bwn_gpio_init(struct bwn_mac *);
219 static int	bwn_fw_loadinitvals(struct bwn_mac *);
220 static int	bwn_phy_init(struct bwn_mac *);
221 static void	bwn_set_txantenna(struct bwn_mac *, int);
222 static void	bwn_set_opmode(struct bwn_mac *);
223 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
224 static uint8_t	bwn_plcp_getcck(const uint8_t);
225 static uint8_t	bwn_plcp_getofdm(const uint8_t);
226 static void	bwn_pio_init(struct bwn_mac *);
227 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
228 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
229 		    int);
230 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
231 		    struct bwn_pio_rxqueue *, int);
232 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
233 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
234 		    uint16_t);
235 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
236 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
237 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
238 static void	bwn_pio_handle_txeof(struct bwn_mac *,
239 		    const struct bwn_txstatus *);
240 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
241 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
242 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
243 		    uint16_t);
244 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
245 		    uint32_t);
246 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
247 		    struct mbuf *);
248 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
249 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
250 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
251 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
252 		    uint16_t, uint32_t);
253 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
254 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
255 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
256 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
257 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
258 		    uint16_t, struct bwn_pio_txpkt **);
259 static void	bwn_dma_init(struct bwn_mac *);
260 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
261 static int	bwn_dma_mask2type(uint64_t);
262 static uint64_t	bwn_dma_mask(struct bwn_mac *);
263 static uint16_t	bwn_dma_base(int, int);
264 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
265 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
266 		    int, struct bwn_dmadesc_generic **,
267 		    struct bwn_dmadesc_meta **);
268 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
269 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
270 		    int, int);
271 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
272 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
273 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
274 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
275 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
276 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
277 		    int, struct bwn_dmadesc_generic **,
278 		    struct bwn_dmadesc_meta **);
279 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
280 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
281 		    int, int);
282 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
283 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
284 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
285 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
286 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
287 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
288 static void	bwn_dma_setup(struct bwn_dma_ring *);
289 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
290 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
291 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
292 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
293 static void	bwn_dma_rx(struct bwn_dma_ring *);
294 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
295 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
296 		    struct bwn_dmadesc_meta *);
297 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
298 static int	bwn_dma_gettype(struct bwn_mac *);
299 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
300 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
301 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
302 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
303 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
304 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
305 		    int);
306 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
307 		    bus_size_t, int);
308 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
309 static void	bwn_dma_handle_txeof(struct bwn_mac *,
310 		    const struct bwn_txstatus *);
311 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
312 		    struct mbuf *);
313 static int	bwn_dma_getslot(struct bwn_dma_ring *);
314 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
315 		    uint8_t);
316 static int	bwn_dma_attach(struct bwn_mac *);
317 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
318 		    int, int, int);
319 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
320 		    const struct bwn_txstatus *, uint16_t, int *);
321 static void	bwn_dma_free(struct bwn_mac *);
322 static void	bwn_phy_g_init_sub(struct bwn_mac *);
323 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
324 static void	bwn_phy_init_b5(struct bwn_mac *);
325 static void	bwn_phy_init_b6(struct bwn_mac *);
326 static void	bwn_phy_init_a(struct bwn_mac *);
327 static void	bwn_loopback_calcgain(struct bwn_mac *);
328 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
329 static void	bwn_lo_g_init(struct bwn_mac *);
330 static void	bwn_lo_g_adjust(struct bwn_mac *);
331 static void	bwn_lo_get_powervector(struct bwn_mac *);
332 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
333 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
334 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
335 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
336 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
337 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
338 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
339 		    uint8_t);
340 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
341 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
342 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
343 static void	bwn_wa_init(struct bwn_mac *);
344 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
345 		    uint16_t);
346 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
347 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
348 		    uint32_t);
349 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
350 		    uint16_t);
351 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
352 static void	bwn_mac_suspend(struct bwn_mac *);
353 static void	bwn_mac_enable(struct bwn_mac *);
354 static void	bwn_psctl(struct bwn_mac *, uint32_t);
355 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
356 static void	bwn_nrssi_offset(struct bwn_mac *);
357 static void	bwn_nrssi_threshold(struct bwn_mac *);
358 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
359 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
360 		    int16_t);
361 static void	bwn_set_original_gains(struct bwn_mac *);
362 static void	bwn_hwpctl_early_init(struct bwn_mac *);
363 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
364 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
365 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
366 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
367 		    const char *, struct bwn_fwfile *);
368 static void	bwn_release_firmware(struct bwn_mac *);
369 static void	bwn_do_release_fw(struct bwn_fwfile *);
370 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
371 static int	bwn_fwinitvals_write(struct bwn_mac *,
372 		    const struct bwn_fwinitvals *, size_t, size_t);
373 static int	bwn_switch_channel(struct bwn_mac *, int);
374 static uint16_t	bwn_ant2phy(int);
375 static void	bwn_mac_write_bssid(struct bwn_mac *);
376 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
377 		    const uint8_t *);
378 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
379 		    const uint8_t *, size_t, const uint8_t *);
380 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
381 		    const uint8_t *);
382 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
383 		    const uint8_t *);
384 static void	bwn_phy_exit(struct bwn_mac *);
385 static void	bwn_core_stop(struct bwn_mac *);
386 static int	bwn_switch_band(struct bwn_softc *,
387 		    struct ieee80211_channel *);
388 static void	bwn_phy_reset(struct bwn_mac *);
389 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
390 static void	bwn_set_pretbtt(struct bwn_mac *);
391 static int	bwn_intr(void *);
392 static void	bwn_intrtask(void *, int);
393 static void	bwn_restart(struct bwn_mac *, const char *);
394 static void	bwn_intr_ucode_debug(struct bwn_mac *);
395 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
396 static void	bwn_intr_atim_end(struct bwn_mac *);
397 static void	bwn_intr_beacon(struct bwn_mac *);
398 static void	bwn_intr_pmq(struct bwn_mac *);
399 static void	bwn_intr_noise(struct bwn_mac *);
400 static void	bwn_intr_txeof(struct bwn_mac *);
401 static void	bwn_hwreset(void *, int);
402 static void	bwn_handle_fwpanic(struct bwn_mac *);
403 static void	bwn_load_beacon0(struct bwn_mac *);
404 static void	bwn_load_beacon1(struct bwn_mac *);
405 static uint32_t	bwn_jssi_read(struct bwn_mac *);
406 static void	bwn_noise_gensample(struct bwn_mac *);
407 static void	bwn_handle_txeof(struct bwn_mac *,
408 		    const struct bwn_txstatus *);
409 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
410 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
411 static void	bwn_start_locked(struct ifnet *);
412 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
413 		    struct mbuf *);
414 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
415 static int	bwn_set_txhdr(struct bwn_mac *,
416 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
417 		    uint16_t);
418 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
419 		    const uint8_t);
420 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
421 static uint8_t	bwn_get_fbrate(uint8_t);
422 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
423 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
424 static void	bwn_phy_lock(struct bwn_mac *);
425 static void	bwn_phy_unlock(struct bwn_mac *);
426 static void	bwn_rf_lock(struct bwn_mac *);
427 static void	bwn_rf_unlock(struct bwn_mac *);
428 static void	bwn_txpwr(void *, int);
429 static void	bwn_tasks(void *);
430 static void	bwn_task_15s(struct bwn_mac *);
431 static void	bwn_task_30s(struct bwn_mac *);
432 static void	bwn_task_60s(struct bwn_mac *);
433 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
434 		    uint8_t);
435 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
436 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
437 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
438 		    int, int);
439 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
440 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
441 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
442 static void	bwn_watchdog(void *);
443 static void	bwn_dma_stop(struct bwn_mac *);
444 static void	bwn_pio_stop(struct bwn_mac *);
445 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
446 static void	bwn_led_attach(struct bwn_mac *);
447 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
448 static void	bwn_led_event(struct bwn_mac *, int);
449 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
450 static void	bwn_led_blink_next(void *);
451 static void	bwn_led_blink_end(void *);
452 static void	bwn_rfswitch(void *);
453 static void	bwn_rf_turnon(struct bwn_mac *);
454 static void	bwn_rf_turnoff(struct bwn_mac *);
455 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
456 static int	bwn_phy_lp_init(struct bwn_mac *);
457 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
458 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
459 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
460 		    uint16_t);
461 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
462 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
463 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
464 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
465 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
466 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
467 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
468 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
469 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
470 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
471 static void	bwn_phy_lp_calib(struct bwn_mac *);
472 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
473 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
474 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
475 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
476 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
477 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
478 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
479 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
480 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
481 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
482 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
483 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
484 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
485 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
486 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
487 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
488 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
489 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
490 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
491 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
492 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
493 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
494 		    const void *);
495 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
496 static struct bwn_txgain
497 		bwn_phy_lp_get_txgain(struct bwn_mac *);
498 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
499 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
500 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
501 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
502 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
503 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
504 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
505 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
506 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
507 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
508 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
509 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
510 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
511 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
512 static int	bwn_phy_lp_loopback(struct bwn_mac *);
513 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
514 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
515 		    int);
516 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
517 		    struct bwn_phy_lp_iq_est *);
518 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
519 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
520 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
521 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
522 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
523 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
524 static uint8_t	bwn_nbits(int32_t);
525 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
526 		    struct bwn_txgain_entry *);
527 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
528 		    struct bwn_txgain_entry);
529 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
530 		    struct bwn_txgain_entry);
531 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
532 		    struct bwn_txgain_entry);
533 static void	bwn_sysctl_node(struct bwn_softc *);
534 
535 static struct resource_spec bwn_res_spec_legacy[] = {
536 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
537 	{ -1,			0,		0 }
538 };
539 
540 static struct resource_spec bwn_res_spec_msi[] = {
541 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
542 	{ -1,			0,		0 }
543 };
544 
545 static 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 
555 static 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 
573 static 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 
615 static 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 
651 static 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 
705 static 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 
730 static 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 */
785 static 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 */
793 static 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 
809 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
810 
811 static 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 
820 static 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 
825 static 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 
840 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
841 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
842 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
843 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
844 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
845 const 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 
853 static 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 
861 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
862 	{ BWN_VENDOR_LED_ACT_DEFAULT };
863 
864 #undef VENDOR_LED_ACT
865 
866 static 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 
885 static 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 
892 static 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 
904 static int
905 bwn_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 
919 static int
920 bwn_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);
1033 fail1:
1034 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1035 		pci_release_msi(dev);
1036 fail0:
1037 	free(mac, M_DEVBUF);
1038 	return (error);
1039 }
1040 
1041 static int
1042 bwn_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 
1052 static int
1053 bwn_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 		| IEEE80211_C_RATECTL		/* use ratectl */
1074 		;
1075 
1076 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1077 
1078 	/* call MI attach routine. */
1079 	ieee80211_ifattach(ic,
1080 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1082 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1083 
1084 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1085 
1086 	/* override default methods */
1087 	ic->ic_raw_xmit = bwn_raw_xmit;
1088 	ic->ic_updateslot = bwn_updateslot;
1089 	ic->ic_update_promisc = bwn_update_promisc;
1090 	ic->ic_wme.wme_update = bwn_wme_update;
1091 
1092 	ic->ic_scan_start = bwn_scan_start;
1093 	ic->ic_scan_end = bwn_scan_end;
1094 	ic->ic_set_channel = bwn_set_channel;
1095 
1096 	ic->ic_vap_create = bwn_vap_create;
1097 	ic->ic_vap_delete = bwn_vap_delete;
1098 
1099 	ieee80211_radiotap_attach(ic,
1100 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101 	    BWN_TX_RADIOTAP_PRESENT,
1102 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103 	    BWN_RX_RADIOTAP_PRESENT);
1104 
1105 	bwn_sysctl_node(sc);
1106 
1107 	if (bootverbose)
1108 		ieee80211_announce(ic);
1109 	return (0);
1110 }
1111 
1112 static void
1113 bwn_phy_detach(struct bwn_mac *mac)
1114 {
1115 
1116 	if (mac->mac_phy.detach != NULL)
1117 		mac->mac_phy.detach(mac);
1118 }
1119 
1120 static int
1121 bwn_detach(device_t dev)
1122 {
1123 	struct bwn_softc *sc = device_get_softc(dev);
1124 	struct bwn_mac *mac = sc->sc_curmac;
1125 	struct ifnet *ifp = sc->sc_ifp;
1126 	struct ieee80211com *ic = ifp->if_l2com;
1127 	int i;
1128 
1129 	sc->sc_flags |= BWN_FLAG_INVALID;
1130 
1131 	if (device_is_attached(sc->sc_dev)) {
1132 		bwn_stop(sc, 1);
1133 		bwn_dma_free(mac);
1134 		callout_drain(&sc->sc_led_blink_ch);
1135 		callout_drain(&sc->sc_rfswitch_ch);
1136 		callout_drain(&sc->sc_task_ch);
1137 		callout_drain(&sc->sc_watchdog_ch);
1138 		bwn_phy_detach(mac);
1139 		if (ifp != NULL) {
1140 			ieee80211_draintask(ic, &mac->mac_hwreset);
1141 			ieee80211_draintask(ic, &mac->mac_txpower);
1142 			ieee80211_ifdetach(ic);
1143 			if_free(ifp);
1144 		}
1145 	}
1146 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147 	taskqueue_free(sc->sc_tq);
1148 
1149 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150 		if (mac->mac_intrhand[i] != NULL) {
1151 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1152 			    mac->mac_intrhand[i]);
1153 			mac->mac_intrhand[i] = NULL;
1154 		}
1155 	}
1156 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157 	if (mac->mac_msi != 0)
1158 		pci_release_msi(dev);
1159 
1160 	BWN_LOCK_DESTROY(sc);
1161 	return (0);
1162 }
1163 
1164 static int
1165 bwn_attach_pre(struct bwn_softc *sc)
1166 {
1167 	struct ifnet *ifp;
1168 	int error = 0;
1169 
1170 	BWN_LOCK_INIT(sc);
1171 	TAILQ_INIT(&sc->sc_maclist);
1172 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175 
1176 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177 		taskqueue_thread_enqueue, &sc->sc_tq);
1178 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179 		"%s taskq", device_get_nameunit(sc->sc_dev));
1180 
1181 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182 	if (ifp == NULL) {
1183 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1184 		error = ENOSPC;
1185 		goto fail;
1186 	}
1187 
1188 	/* set these up early for if_printf use */
1189 	if_initname(ifp, device_get_name(sc->sc_dev),
1190 	    device_get_unit(sc->sc_dev));
1191 
1192 	ifp->if_softc = sc;
1193 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194 	ifp->if_init = bwn_init;
1195 	ifp->if_ioctl = bwn_ioctl;
1196 	ifp->if_start = bwn_start;
1197 	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198 	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199 	IFQ_SET_READY(&ifp->if_snd);
1200 
1201 	return (0);
1202 
1203 fail:	BWN_LOCK_DESTROY(sc);
1204 	return (error);
1205 }
1206 
1207 static void
1208 bwn_sprom_bugfixes(device_t dev)
1209 {
1210 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1211 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1212 	 (siba_get_pci_device(dev) == _device) &&			\
1213 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1214 	 (siba_get_pci_subdevice(dev) == _subdevice))
1215 
1216 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217 	    siba_get_pci_subdevice(dev) == 0x4e &&
1218 	    siba_get_pci_revid(dev) > 0x40)
1219 		siba_sprom_set_bf_lo(dev,
1220 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223 		siba_sprom_set_bf_lo(dev,
1224 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233 			siba_sprom_set_bf_lo(dev,
1234 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235 	}
1236 #undef	BWN_ISDEV
1237 }
1238 
1239 static int
1240 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241 {
1242 #define	IS_RUNNING(ifp) \
1243 	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244 	struct bwn_softc *sc = ifp->if_softc;
1245 	struct ieee80211com *ic = ifp->if_l2com;
1246 	struct ifreq *ifr = (struct ifreq *)data;
1247 	int error = 0, startall;
1248 
1249 	switch (cmd) {
1250 	case SIOCSIFFLAGS:
1251 		startall = 0;
1252 		if (IS_RUNNING(ifp)) {
1253 			bwn_update_promisc(ifp);
1254 		} else if (ifp->if_flags & IFF_UP) {
1255 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256 				bwn_init(sc);
1257 				startall = 1;
1258 			}
1259 		} else
1260 			bwn_stop(sc, 1);
1261 		if (startall)
1262 			ieee80211_start_all(ic);
1263 		break;
1264 	case SIOCGIFMEDIA:
1265 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266 		break;
1267 	case SIOCGIFADDR:
1268 		error = ether_ioctl(ifp, cmd, data);
1269 		break;
1270 	default:
1271 		error = EINVAL;
1272 		break;
1273 	}
1274 	return (error);
1275 }
1276 
1277 static void
1278 bwn_start(struct ifnet *ifp)
1279 {
1280 	struct bwn_softc *sc = ifp->if_softc;
1281 
1282 	BWN_LOCK(sc);
1283 	bwn_start_locked(ifp);
1284 	BWN_UNLOCK(sc);
1285 }
1286 
1287 static void
1288 bwn_start_locked(struct ifnet *ifp)
1289 {
1290 	struct bwn_softc *sc = ifp->if_softc;
1291 	struct bwn_mac *mac = sc->sc_curmac;
1292 	struct ieee80211_frame *wh;
1293 	struct ieee80211_node *ni;
1294 	struct ieee80211_key *k;
1295 	struct mbuf *m;
1296 
1297 	BWN_ASSERT_LOCKED(sc);
1298 
1299 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1301 		return;
1302 
1303 	for (;;) {
1304 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1305 		if (m == NULL)
1306 			break;
1307 
1308 		if (bwn_tx_isfull(sc, m))
1309 			break;
1310 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311 		if (ni == NULL) {
1312 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313 			m_freem(m);
1314 			ifp->if_oerrors++;
1315 			continue;
1316 		}
1317 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318 		wh = mtod(m, struct ieee80211_frame *);
1319 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320 			k = ieee80211_crypto_encap(ni, m);
1321 			if (k == NULL) {
1322 				ieee80211_free_node(ni);
1323 				m_freem(m);
1324 				ifp->if_oerrors++;
1325 				continue;
1326 			}
1327 		}
1328 		wh = NULL;	/* Catch any invalid use */
1329 
1330 		if (bwn_tx_start(sc, ni, m) != 0) {
1331 			if (ni != NULL)
1332 				ieee80211_free_node(ni);
1333 			ifp->if_oerrors++;
1334 			continue;
1335 		}
1336 
1337 		sc->sc_watchdog_timer = 5;
1338 	}
1339 }
1340 
1341 static int
1342 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343 {
1344 	struct bwn_dma_ring *dr;
1345 	struct bwn_mac *mac = sc->sc_curmac;
1346 	struct bwn_pio_txqueue *tq;
1347 	struct ifnet *ifp = sc->sc_ifp;
1348 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349 
1350 	BWN_ASSERT_LOCKED(sc);
1351 
1352 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354 		if (dr->dr_stop == 1 ||
1355 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356 			dr->dr_stop = 1;
1357 			goto full;
1358 		}
1359 	} else {
1360 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362 		    pktlen > (tq->tq_size - tq->tq_used)) {
1363 			tq->tq_stop = 1;
1364 			goto full;
1365 		}
1366 	}
1367 	return (0);
1368 full:
1369 	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371 	return (1);
1372 }
1373 
1374 static int
1375 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376 {
1377 	struct bwn_mac *mac = sc->sc_curmac;
1378 	int error;
1379 
1380 	BWN_ASSERT_LOCKED(sc);
1381 
1382 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383 		m_freem(m);
1384 		return (ENXIO);
1385 	}
1386 
1387 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389 	if (error) {
1390 		m_freem(m);
1391 		return (error);
1392 	}
1393 	return (0);
1394 }
1395 
1396 static int
1397 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398 {
1399 	struct bwn_pio_txpkt *tp;
1400 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401 	struct bwn_softc *sc = mac->mac_sc;
1402 	struct bwn_txhdr txhdr;
1403 	struct mbuf *m_new;
1404 	uint32_t ctl32;
1405 	int error;
1406 	uint16_t ctl16;
1407 
1408 	BWN_ASSERT_LOCKED(sc);
1409 
1410 	/* XXX TODO send packets after DTIM */
1411 
1412 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1414 	tp->tp_ni = ni;
1415 	tp->tp_m = m;
1416 
1417 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418 	if (error) {
1419 		device_printf(sc->sc_dev, "tx fail\n");
1420 		return (error);
1421 	}
1422 
1423 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425 	tq->tq_free--;
1426 
1427 	if (siba_get_revid(sc->sc_dev) >= 8) {
1428 		/*
1429 		 * XXX please removes m_defrag(9)
1430 		 */
1431 		m_new = m_defrag(m, M_DONTWAIT);
1432 		if (m_new == NULL) {
1433 			device_printf(sc->sc_dev,
1434 			    "%s: can't defrag TX buffer\n",
1435 			    __func__);
1436 			return (ENOBUFS);
1437 		}
1438 		if (m_new->m_next != NULL)
1439 			device_printf(sc->sc_dev,
1440 			    "TODO: fragmented packets for PIO\n");
1441 		tp->tp_m = m_new;
1442 
1443 		/* send HEADER */
1444 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1445 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448 		/* send BODY */
1449 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1451 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1453 	} else {
1454 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1455 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460 		    ctl16 | BWN_PIO_TXCTL_EOF);
1461 	}
1462 
1463 	return (0);
1464 }
1465 
1466 static struct bwn_pio_txqueue *
1467 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468 {
1469 
1470 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472 
1473 	switch (prio) {
1474 	case 0:
1475 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476 	case 1:
1477 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478 	case 2:
1479 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480 	case 3:
1481 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482 	}
1483 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484 	return (NULL);
1485 }
1486 
1487 static int
1488 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489 {
1490 #define	BWN_GET_TXHDRCACHE(slot)					\
1491 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492 	struct bwn_dma *dma = &mac->mac_method.dma;
1493 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494 	struct bwn_dmadesc_generic *desc;
1495 	struct bwn_dmadesc_meta *mt;
1496 	struct bwn_softc *sc = mac->mac_sc;
1497 	struct ifnet *ifp = sc->sc_ifp;
1498 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500 
1501 	BWN_ASSERT_LOCKED(sc);
1502 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503 
1504 	/* XXX send after DTIM */
1505 
1506 	slot = bwn_dma_getslot(dr);
1507 	dr->getdesc(dr, slot, &desc, &mt);
1508 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509 	    ("%s:%d: fail", __func__, __LINE__));
1510 
1511 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513 	    BWN_DMA_COOKIE(dr, slot));
1514 	if (error)
1515 		goto fail;
1516 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1519 	if (error) {
1520 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521 		    __func__, error);
1522 		goto fail;
1523 	}
1524 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525 	    BUS_DMASYNC_PREWRITE);
1526 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528 	    BUS_DMASYNC_PREWRITE);
1529 
1530 	slot = bwn_dma_getslot(dr);
1531 	dr->getdesc(dr, slot, &desc, &mt);
1532 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534 	mt->mt_m = m;
1535 	mt->mt_ni = ni;
1536 
1537 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539 	if (error && error != EFBIG) {
1540 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541 		    __func__, error);
1542 		goto fail;
1543 	}
1544 	if (error) {    /* error == EFBIG */
1545 		struct mbuf *m_new;
1546 
1547 		m_new = m_defrag(m, M_DONTWAIT);
1548 		if (m_new == NULL) {
1549 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1550 			    __func__);
1551 			error = ENOBUFS;
1552 			goto fail;
1553 		} else {
1554 			m = m_new;
1555 		}
1556 
1557 		mt->mt_m = m;
1558 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560 		if (error) {
1561 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562 			    __func__, error);
1563 			goto fail;
1564 		}
1565 	}
1566 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569 	    BUS_DMASYNC_PREWRITE);
1570 
1571 	/* XXX send after DTIM */
1572 
1573 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574 	return (0);
1575 fail:
1576 	dr->dr_curslot = backup[0];
1577 	dr->dr_usedslot = backup[1];
1578 	return (error);
1579 #undef BWN_GET_TXHDRCACHE
1580 }
1581 
1582 static void
1583 bwn_watchdog(void *arg)
1584 {
1585 	struct bwn_softc *sc = arg;
1586 	struct ifnet *ifp = sc->sc_ifp;
1587 
1588 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589 		if_printf(ifp, "device timeout\n");
1590 		ifp->if_oerrors++;
1591 	}
1592 	callout_schedule(&sc->sc_watchdog_ch, hz);
1593 }
1594 
1595 static int
1596 bwn_attach_core(struct bwn_mac *mac)
1597 {
1598 	struct bwn_softc *sc = mac->mac_sc;
1599 	int error, have_bg = 0, have_a = 0;
1600 	uint32_t high;
1601 
1602 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604 
1605 	siba_powerup(sc->sc_dev, 0);
1606 
1607 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608 	bwn_reset_core(mac,
1609 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610 	error = bwn_phy_getinfo(mac, high);
1611 	if (error)
1612 		goto fail;
1613 
1614 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619 		have_a = have_bg = 0;
1620 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621 			have_a = 1;
1622 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1624 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1625 			have_bg = 1;
1626 		else
1627 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628 			    mac->mac_phy.type));
1629 	}
1630 	/* XXX turns off PHY A because it's not supported */
1631 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1633 		have_a = 0;
1634 		have_bg = 1;
1635 	}
1636 
1637 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638 		mac->mac_phy.attach = bwn_phy_g_attach;
1639 		mac->mac_phy.detach = bwn_phy_g_detach;
1640 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642 		mac->mac_phy.init = bwn_phy_g_init;
1643 		mac->mac_phy.exit = bwn_phy_g_exit;
1644 		mac->mac_phy.phy_read = bwn_phy_g_read;
1645 		mac->mac_phy.phy_write = bwn_phy_g_write;
1646 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654 		mac->mac_phy.set_im = bwn_phy_g_im;
1655 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661 		mac->mac_phy.init = bwn_phy_lp_init;
1662 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1663 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1664 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673 	} else {
1674 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675 		    mac->mac_phy.type);
1676 		error = ENXIO;
1677 		goto fail;
1678 	}
1679 
1680 	mac->mac_phy.gmode = have_bg;
1681 	if (mac->mac_phy.attach != NULL) {
1682 		error = mac->mac_phy.attach(mac);
1683 		if (error) {
1684 			device_printf(sc->sc_dev, "failed\n");
1685 			goto fail;
1686 		}
1687 	}
1688 
1689 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690 
1691 	error = bwn_chiptest(mac);
1692 	if (error)
1693 		goto fail;
1694 	error = bwn_setup_channels(mac, have_bg, have_a);
1695 	if (error) {
1696 		device_printf(sc->sc_dev, "failed to setup channels\n");
1697 		goto fail;
1698 	}
1699 
1700 	if (sc->sc_curmac == NULL)
1701 		sc->sc_curmac = mac;
1702 
1703 	error = bwn_dma_attach(mac);
1704 	if (error != 0) {
1705 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706 		goto fail;
1707 	}
1708 
1709 	mac->mac_phy.switch_analog(mac, 0);
1710 
1711 	siba_dev_down(sc->sc_dev, 0);
1712 fail:
1713 	siba_powerdown(sc->sc_dev);
1714 	return (error);
1715 }
1716 
1717 static void
1718 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719 {
1720 	struct bwn_softc *sc = mac->mac_sc;
1721 	uint32_t low, ctl;
1722 
1723 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724 
1725 	siba_dev_up(sc->sc_dev, flags);
1726 	DELAY(2000);
1727 
1728 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729 	    ~BWN_TGSLOW_PHYRESET;
1730 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732 	DELAY(1000);
1733 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735 	DELAY(1000);
1736 
1737 	if (mac->mac_phy.switch_analog != NULL)
1738 		mac->mac_phy.switch_analog(mac, 1);
1739 
1740 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741 	if (flags & BWN_TGSLOW_SUPPORT_G)
1742 		ctl |= BWN_MACCTL_GMODE;
1743 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744 }
1745 
1746 static int
1747 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748 {
1749 	struct bwn_phy *phy = &mac->mac_phy;
1750 	struct bwn_softc *sc = mac->mac_sc;
1751 	uint32_t tmp;
1752 
1753 	/* PHY */
1754 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1755 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756 	phy->rf_on = 1;
1757 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1760 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766 		goto unsupphy;
1767 
1768 	/* RADIO */
1769 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770 		if (siba_get_chiprev(sc->sc_dev) == 0)
1771 			tmp = 0x3205017f;
1772 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1773 			tmp = 0x4205017f;
1774 		else
1775 			tmp = 0x5205017f;
1776 	} else {
1777 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781 	}
1782 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784 	phy->rf_manuf = (tmp & 0x00000fff);
1785 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1786 		goto unsupradio;
1787 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791 	    (phy->type == BWN_PHYTYPE_N &&
1792 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793 	    (phy->type == BWN_PHYTYPE_LP &&
1794 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795 		goto unsupradio;
1796 
1797 	return (0);
1798 unsupphy:
1799 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800 	    "analog %#x)\n",
1801 	    phy->type, phy->rev, phy->analog);
1802 	return (ENXIO);
1803 unsupradio:
1804 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805 	    "rev %#x)\n",
1806 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807 	return (ENXIO);
1808 }
1809 
1810 static int
1811 bwn_chiptest(struct bwn_mac *mac)
1812 {
1813 #define	TESTVAL0	0x55aaaa55
1814 #define	TESTVAL1	0xaa5555aa
1815 	struct bwn_softc *sc = mac->mac_sc;
1816 	uint32_t v, backup;
1817 
1818 	BWN_LOCK(sc);
1819 
1820 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821 
1822 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824 		goto error;
1825 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827 		goto error;
1828 
1829 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830 
1831 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1833 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836 			goto error;
1837 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838 			goto error;
1839 	}
1840 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841 
1842 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844 		goto error;
1845 
1846 	BWN_UNLOCK(sc);
1847 	return (0);
1848 error:
1849 	BWN_UNLOCK(sc);
1850 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851 	return (ENODEV);
1852 }
1853 
1854 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856 
1857 static int
1858 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859 {
1860 	struct bwn_softc *sc = mac->mac_sc;
1861 	struct ifnet *ifp = sc->sc_ifp;
1862 	struct ieee80211com *ic = ifp->if_l2com;
1863 
1864 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865 	ic->ic_nchans = 0;
1866 
1867 	if (have_bg)
1868 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871 		if (have_a)
1872 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873 			    &ic->ic_nchans, &bwn_chantable_n,
1874 			    IEEE80211_CHAN_HTA);
1875 	} else {
1876 		if (have_a)
1877 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878 			    &ic->ic_nchans, &bwn_chantable_a,
1879 			    IEEE80211_CHAN_A);
1880 	}
1881 
1882 	mac->mac_phy.supports_2ghz = have_bg;
1883 	mac->mac_phy.supports_5ghz = have_a;
1884 
1885 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1886 }
1887 
1888 static uint32_t
1889 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890 {
1891 	uint32_t ret;
1892 
1893 	BWN_ASSERT_LOCKED(mac->mac_sc);
1894 
1895 	if (way == BWN_SHARED) {
1896 		KASSERT((offset & 0x0001) == 0,
1897 		    ("%s:%d warn", __func__, __LINE__));
1898 		if (offset & 0x0003) {
1899 			bwn_shm_ctlword(mac, way, offset >> 2);
1900 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901 			ret <<= 16;
1902 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904 			goto out;
1905 		}
1906 		offset >>= 2;
1907 	}
1908 	bwn_shm_ctlword(mac, way, offset);
1909 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910 out:
1911 	return (ret);
1912 }
1913 
1914 static uint16_t
1915 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916 {
1917 	uint16_t ret;
1918 
1919 	BWN_ASSERT_LOCKED(mac->mac_sc);
1920 
1921 	if (way == BWN_SHARED) {
1922 		KASSERT((offset & 0x0001) == 0,
1923 		    ("%s:%d warn", __func__, __LINE__));
1924 		if (offset & 0x0003) {
1925 			bwn_shm_ctlword(mac, way, offset >> 2);
1926 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927 			goto out;
1928 		}
1929 		offset >>= 2;
1930 	}
1931 	bwn_shm_ctlword(mac, way, offset);
1932 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933 out:
1934 
1935 	return (ret);
1936 }
1937 
1938 static void
1939 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940     uint16_t offset)
1941 {
1942 	uint32_t control;
1943 
1944 	control = way;
1945 	control <<= 16;
1946 	control |= offset;
1947 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948 }
1949 
1950 static void
1951 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952     uint32_t value)
1953 {
1954 	BWN_ASSERT_LOCKED(mac->mac_sc);
1955 
1956 	if (way == BWN_SHARED) {
1957 		KASSERT((offset & 0x0001) == 0,
1958 		    ("%s:%d warn", __func__, __LINE__));
1959 		if (offset & 0x0003) {
1960 			bwn_shm_ctlword(mac, way, offset >> 2);
1961 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962 				    (value >> 16) & 0xffff);
1963 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965 			return;
1966 		}
1967 		offset >>= 2;
1968 	}
1969 	bwn_shm_ctlword(mac, way, offset);
1970 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971 }
1972 
1973 static void
1974 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975     uint16_t value)
1976 {
1977 	BWN_ASSERT_LOCKED(mac->mac_sc);
1978 
1979 	if (way == BWN_SHARED) {
1980 		KASSERT((offset & 0x0001) == 0,
1981 		    ("%s:%d warn", __func__, __LINE__));
1982 		if (offset & 0x0003) {
1983 			bwn_shm_ctlword(mac, way, offset >> 2);
1984 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985 			return;
1986 		}
1987 		offset >>= 2;
1988 	}
1989 	bwn_shm_ctlword(mac, way, offset);
1990 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991 }
1992 
1993 static void
1994 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995     int txpow)
1996 {
1997 
1998 	c->ic_freq = freq;
1999 	c->ic_flags = flags;
2000 	c->ic_ieee = ieee;
2001 	c->ic_minpower = 0;
2002 	c->ic_maxpower = 2 * txpow;
2003 	c->ic_maxregpower = txpow;
2004 }
2005 
2006 static void
2007 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008     const struct bwn_channelinfo *ci, int flags)
2009 {
2010 	struct ieee80211_channel *c;
2011 	int i;
2012 
2013 	c = &chans[*nchans];
2014 
2015 	for (i = 0; i < ci->nchannels; i++) {
2016 		const struct bwn_channel *hc;
2017 
2018 		hc = &ci->channels[i];
2019 		if (*nchans >= maxchans)
2020 			break;
2021 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022 		c++, (*nchans)++;
2023 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024 			/* g channel have a separate b-only entry */
2025 			if (*nchans >= maxchans)
2026 				break;
2027 			c[0] = c[-1];
2028 			c[-1].ic_flags = IEEE80211_CHAN_B;
2029 			c++, (*nchans)++;
2030 		}
2031 		if (flags == IEEE80211_CHAN_HTG) {
2032 			/* HT g channel have a separate g-only entry */
2033 			if (*nchans >= maxchans)
2034 				break;
2035 			c[-1].ic_flags = IEEE80211_CHAN_G;
2036 			c[0] = c[-1];
2037 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2039 			c++, (*nchans)++;
2040 		}
2041 		if (flags == IEEE80211_CHAN_HTA) {
2042 			/* HT a channel have a separate a-only entry */
2043 			if (*nchans >= maxchans)
2044 				break;
2045 			c[-1].ic_flags = IEEE80211_CHAN_A;
2046 			c[0] = c[-1];
2047 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2049 			c++, (*nchans)++;
2050 		}
2051 	}
2052 }
2053 
2054 static int
2055 bwn_phy_g_attach(struct bwn_mac *mac)
2056 {
2057 	struct bwn_softc *sc = mac->mac_sc;
2058 	struct bwn_phy *phy = &mac->mac_phy;
2059 	struct bwn_phy_g *pg = &phy->phy_g;
2060 	unsigned int i;
2061 	int16_t pab0, pab1, pab2;
2062 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063 	int8_t bg;
2064 
2065 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069 
2070 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071 		device_printf(sc->sc_dev, "not supported anymore\n");
2072 
2073 	pg->pg_flags = 0;
2074 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075 	    pab2 == -1) {
2076 		pg->pg_idletssi = 52;
2077 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078 		return (0);
2079 	}
2080 
2081 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083 	if (pg->pg_tssi2dbm == NULL) {
2084 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085 		return (ENOMEM);
2086 	}
2087 	for (i = 0; i < 64; i++) {
2088 		int32_t m1, m2, f, q, delta;
2089 		int8_t j = 0;
2090 
2091 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093 		f = 256;
2094 
2095 		do {
2096 			if (j > 15) {
2097 				device_printf(sc->sc_dev,
2098 				    "failed to generate tssi2dBm\n");
2099 				free(pg->pg_tssi2dbm, M_DEVBUF);
2100 				return (ENOMEM);
2101 			}
2102 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103 			    f, 2048);
2104 			delta = abs(q - f);
2105 			f = q;
2106 			j++;
2107 		} while (delta >= 2);
2108 
2109 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110 		    128);
2111 	}
2112 
2113 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114 	return (0);
2115 }
2116 
2117 static void
2118 bwn_phy_g_detach(struct bwn_mac *mac)
2119 {
2120 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121 
2122 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123 		free(pg->pg_tssi2dbm, M_DEVBUF);
2124 		pg->pg_tssi2dbm = NULL;
2125 	}
2126 	pg->pg_flags = 0;
2127 }
2128 
2129 static void
2130 bwn_phy_g_init_pre(struct bwn_mac *mac)
2131 {
2132 	struct bwn_phy *phy = &mac->mac_phy;
2133 	struct bwn_phy_g *pg = &phy->phy_g;
2134 	void *tssi2dbm;
2135 	int idletssi;
2136 	unsigned int i;
2137 
2138 	tssi2dbm = pg->pg_tssi2dbm;
2139 	idletssi = pg->pg_idletssi;
2140 
2141 	memset(pg, 0, sizeof(*pg));
2142 
2143 	pg->pg_tssi2dbm = tssi2dbm;
2144 	pg->pg_idletssi = idletssi;
2145 
2146 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147 
2148 	for (i = 0; i < N(pg->pg_nrssi); i++)
2149 		pg->pg_nrssi[i] = -1000;
2150 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151 		pg->pg_nrssi_lt[i] = i;
2152 	pg->pg_lofcal = 0xffff;
2153 	pg->pg_initval = 0xffff;
2154 	pg->pg_immode = BWN_IMMODE_NONE;
2155 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156 	pg->pg_avgtssi = 0xff;
2157 
2158 	pg->pg_loctl.tx_bias = 0xff;
2159 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2160 }
2161 
2162 static int
2163 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164 {
2165 	struct bwn_phy *phy = &mac->mac_phy;
2166 	struct bwn_phy_g *pg = &phy->phy_g;
2167 	struct bwn_softc *sc = mac->mac_sc;
2168 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169 	static const struct bwn_rfatt rfatt0[] = {
2170 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2171 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172 		{ 3, 1 }, { 4, 1 }
2173 	};
2174 	static const struct bwn_rfatt rfatt1[] = {
2175 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176 		{ 14, 1 }
2177 	};
2178 	static const struct bwn_rfatt rfatt2[] = {
2179 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180 		{ 9, 1 }
2181 	};
2182 	static const struct bwn_bbatt bbatt_0[] = {
2183 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184 	};
2185 
2186 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187 
2188 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189 		pg->pg_bbatt.att = 0;
2190 	else
2191 		pg->pg_bbatt.att = 2;
2192 
2193 	/* prepare Radio Attenuation */
2194 	pg->pg_rfatt.padmix = 0;
2195 
2196 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199 			pg->pg_rfatt.att = 2;
2200 			goto done;
2201 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202 			pg->pg_rfatt.att = 3;
2203 			goto done;
2204 		}
2205 	}
2206 
2207 	if (phy->type == BWN_PHYTYPE_A) {
2208 		pg->pg_rfatt.att = 0x60;
2209 		goto done;
2210 	}
2211 
2212 	switch (phy->rf_ver) {
2213 	case 0x2050:
2214 		switch (phy->rf_rev) {
2215 		case 0:
2216 			pg->pg_rfatt.att = 5;
2217 			goto done;
2218 		case 1:
2219 			if (phy->type == BWN_PHYTYPE_G) {
2220 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2221 				    SIBA_BOARDVENDOR_BCM &&
2222 				    siba_get_pci_subdevice(sc->sc_dev) ==
2223 				    SIBA_BOARD_BCM4309G &&
2224 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2225 					pg->pg_rfatt.att = 3;
2226 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227 				    SIBA_BOARDVENDOR_BCM &&
2228 				    siba_get_pci_subdevice(sc->sc_dev) ==
2229 				    SIBA_BOARD_BU4306)
2230 					pg->pg_rfatt.att = 3;
2231 				else
2232 					pg->pg_rfatt.att = 1;
2233 			} else {
2234 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2235 				    SIBA_BOARDVENDOR_BCM &&
2236 				    siba_get_pci_subdevice(sc->sc_dev) ==
2237 				    SIBA_BOARD_BCM4309G &&
2238 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2239 					pg->pg_rfatt.att = 7;
2240 				else
2241 					pg->pg_rfatt.att = 6;
2242 			}
2243 			goto done;
2244 		case 2:
2245 			if (phy->type == BWN_PHYTYPE_G) {
2246 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2247 				    SIBA_BOARDVENDOR_BCM &&
2248 				    siba_get_pci_subdevice(sc->sc_dev) ==
2249 				    SIBA_BOARD_BCM4309G &&
2250 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2251 					pg->pg_rfatt.att = 3;
2252 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253 				    SIBA_BOARDVENDOR_BCM &&
2254 				    siba_get_pci_subdevice(sc->sc_dev) ==
2255 				    SIBA_BOARD_BU4306)
2256 					pg->pg_rfatt.att = 5;
2257 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258 					pg->pg_rfatt.att = 4;
2259 				else
2260 					pg->pg_rfatt.att = 3;
2261 			} else
2262 				pg->pg_rfatt.att = 6;
2263 			goto done;
2264 		case 3:
2265 			pg->pg_rfatt.att = 5;
2266 			goto done;
2267 		case 4:
2268 		case 5:
2269 			pg->pg_rfatt.att = 1;
2270 			goto done;
2271 		case 6:
2272 		case 7:
2273 			pg->pg_rfatt.att = 5;
2274 			goto done;
2275 		case 8:
2276 			pg->pg_rfatt.att = 0xa;
2277 			pg->pg_rfatt.padmix = 1;
2278 			goto done;
2279 		case 9:
2280 		default:
2281 			pg->pg_rfatt.att = 5;
2282 			goto done;
2283 		}
2284 		break;
2285 	case 0x2053:
2286 		switch (phy->rf_rev) {
2287 		case 1:
2288 			pg->pg_rfatt.att = 6;
2289 			goto done;
2290 		}
2291 		break;
2292 	}
2293 	pg->pg_rfatt.att = 5;
2294 done:
2295 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296 
2297 	if (!bwn_has_hwpctl(mac)) {
2298 		lo->rfatt.array = rfatt0;
2299 		lo->rfatt.len = N(rfatt0);
2300 		lo->rfatt.min = 0;
2301 		lo->rfatt.max = 9;
2302 		goto genbbatt;
2303 	}
2304 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305 		lo->rfatt.array = rfatt1;
2306 		lo->rfatt.len = N(rfatt1);
2307 		lo->rfatt.min = 0;
2308 		lo->rfatt.max = 14;
2309 		goto genbbatt;
2310 	}
2311 	lo->rfatt.array = rfatt2;
2312 	lo->rfatt.len = N(rfatt2);
2313 	lo->rfatt.min = 0;
2314 	lo->rfatt.max = 9;
2315 genbbatt:
2316 	lo->bbatt.array = bbatt_0;
2317 	lo->bbatt.len = N(bbatt_0);
2318 	lo->bbatt.min = 0;
2319 	lo->bbatt.max = 8;
2320 
2321 	BWN_READ_4(mac, BWN_MACCTL);
2322 	if (phy->rev == 1) {
2323 		phy->gmode = 0;
2324 		bwn_reset_core(mac, 0);
2325 		bwn_phy_g_init_sub(mac);
2326 		phy->gmode = 1;
2327 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328 	}
2329 	return (0);
2330 }
2331 
2332 static uint16_t
2333 bwn_phy_g_txctl(struct bwn_mac *mac)
2334 {
2335 	struct bwn_phy *phy = &mac->mac_phy;
2336 
2337 	if (phy->rf_ver != 0x2050)
2338 		return (0);
2339 	if (phy->rf_rev == 1)
2340 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341 	if (phy->rf_rev < 6)
2342 		return (BWN_TXCTL_PA2DB);
2343 	if (phy->rf_rev == 8)
2344 		return (BWN_TXCTL_TXMIX);
2345 	return (0);
2346 }
2347 
2348 static int
2349 bwn_phy_g_init(struct bwn_mac *mac)
2350 {
2351 
2352 	bwn_phy_g_init_sub(mac);
2353 	return (0);
2354 }
2355 
2356 static void
2357 bwn_phy_g_exit(struct bwn_mac *mac)
2358 {
2359 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360 	struct bwn_lo_calib *cal, *tmp;
2361 
2362 	if (lo == NULL)
2363 		return;
2364 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2366 		free(cal, M_DEVBUF);
2367 	}
2368 }
2369 
2370 static uint16_t
2371 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372 {
2373 
2374 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375 	return (BWN_READ_2(mac, BWN_PHYDATA));
2376 }
2377 
2378 static void
2379 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380 {
2381 
2382 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384 }
2385 
2386 static uint16_t
2387 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388 {
2389 
2390 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392 	return (BWN_READ_2(mac, BWN_RFDATALO));
2393 }
2394 
2395 static void
2396 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397 {
2398 
2399 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402 }
2403 
2404 static int
2405 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406 {
2407 
2408 	return (mac->mac_phy.rev >= 6);
2409 }
2410 
2411 static void
2412 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413 {
2414 	struct bwn_phy *phy = &mac->mac_phy;
2415 	struct bwn_phy_g *pg = &phy->phy_g;
2416 	unsigned int channel;
2417 	uint16_t rfover, rfoverval;
2418 
2419 	if (on) {
2420 		if (phy->rf_on)
2421 			return;
2422 
2423 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428 			    pg->pg_radioctx_over);
2429 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430 			    pg->pg_radioctx_overval);
2431 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432 		}
2433 		channel = phy->chan;
2434 		bwn_phy_g_switch_chan(mac, 6, 1);
2435 		bwn_phy_g_switch_chan(mac, channel, 0);
2436 		return;
2437 	}
2438 
2439 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441 	pg->pg_radioctx_over = rfover;
2442 	pg->pg_radioctx_overval = rfoverval;
2443 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446 }
2447 
2448 static int
2449 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450 {
2451 
2452 	if ((newchan < 1) || (newchan > 14))
2453 		return (EINVAL);
2454 	bwn_phy_g_switch_chan(mac, newchan, 0);
2455 
2456 	return (0);
2457 }
2458 
2459 static uint32_t
2460 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461 {
2462 
2463 	return (1);
2464 }
2465 
2466 static void
2467 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468 {
2469 	struct bwn_phy *phy = &mac->mac_phy;
2470 	uint64_t hf;
2471 	int autodiv = 0;
2472 	uint16_t tmp;
2473 
2474 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475 		autodiv = 1;
2476 
2477 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478 	bwn_hf_write(mac, hf);
2479 
2480 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2483 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484 
2485 	if (autodiv) {
2486 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487 		if (antenna == BWN_ANTAUTO1)
2488 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489 		else
2490 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492 	}
2493 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494 	if (autodiv)
2495 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496 	else
2497 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499 	if (phy->rev >= 2) {
2500 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504 		    0x15);
2505 		if (phy->rev == 2)
2506 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507 		else
2508 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510 			    8);
2511 	}
2512 	if (phy->rev >= 6)
2513 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514 
2515 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516 	bwn_hf_write(mac, hf);
2517 }
2518 
2519 static int
2520 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521 {
2522 	struct bwn_phy *phy = &mac->mac_phy;
2523 	struct bwn_phy_g *pg = &phy->phy_g;
2524 
2525 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527 
2528 	if (phy->rev == 0 || !phy->gmode)
2529 		return (ENODEV);
2530 
2531 	pg->pg_aci_wlan_automatic = 0;
2532 	return (0);
2533 }
2534 
2535 static int
2536 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537 {
2538 	struct bwn_phy *phy = &mac->mac_phy;
2539 	struct bwn_phy_g *pg = &phy->phy_g;
2540 	struct bwn_softc *sc = mac->mac_sc;
2541 	unsigned int tssi;
2542 	int cck, ofdm;
2543 	int power;
2544 	int rfatt, bbatt;
2545 	unsigned int max;
2546 
2547 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548 
2549 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551 	if (cck < 0 && ofdm < 0) {
2552 		if (ignore_tssi == 0)
2553 			return (BWN_TXPWR_RES_DONE);
2554 		cck = 0;
2555 		ofdm = 0;
2556 	}
2557 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558 	if (pg->pg_avgtssi != 0xff)
2559 		tssi = (tssi + pg->pg_avgtssi) / 2;
2560 	pg->pg_avgtssi = tssi;
2561 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562 
2563 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565 		max -= 3;
2566 	if (max >= 120) {
2567 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568 		max = 80;
2569 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570 	}
2571 
2572 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574 	     tssi, 0x00), 0x3f)]);
2575 	if (power == 0)
2576 		return (BWN_TXPWR_RES_DONE);
2577 
2578 	rfatt = -((power + 7) / 8);
2579 	bbatt = (-(power / 2)) - (4 * rfatt);
2580 	if ((rfatt == 0) && (bbatt == 0))
2581 		return (BWN_TXPWR_RES_DONE);
2582 	pg->pg_bbatt_delta = bbatt;
2583 	pg->pg_rfatt_delta = rfatt;
2584 	return (BWN_TXPWR_RES_NEED_ADJUST);
2585 }
2586 
2587 static void
2588 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589 {
2590 	struct bwn_phy *phy = &mac->mac_phy;
2591 	struct bwn_phy_g *pg = &phy->phy_g;
2592 	struct bwn_softc *sc = mac->mac_sc;
2593 	int rfatt, bbatt;
2594 	uint8_t txctl;
2595 
2596 	bwn_mac_suspend(mac);
2597 
2598 	BWN_ASSERT_LOCKED(sc);
2599 
2600 	bbatt = pg->pg_bbatt.att;
2601 	bbatt += pg->pg_bbatt_delta;
2602 	rfatt = pg->pg_rfatt.att;
2603 	rfatt += pg->pg_rfatt_delta;
2604 
2605 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606 	txctl = pg->pg_txctl;
2607 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608 		if (rfatt <= 1) {
2609 			if (txctl == 0) {
2610 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611 				rfatt += 2;
2612 				bbatt += 2;
2613 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614 			    BWN_BFL_PACTRL) {
2615 				bbatt += 4 * (rfatt - 2);
2616 				rfatt = 2;
2617 			}
2618 		} else if (rfatt > 4 && txctl) {
2619 			txctl = 0;
2620 			if (bbatt < 3) {
2621 				rfatt -= 3;
2622 				bbatt += 2;
2623 			} else {
2624 				rfatt -= 2;
2625 				bbatt -= 2;
2626 			}
2627 		}
2628 	}
2629 	pg->pg_txctl = txctl;
2630 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631 	pg->pg_rfatt.att = rfatt;
2632 	pg->pg_bbatt.att = bbatt;
2633 
2634 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635 
2636 	bwn_phy_lock(mac);
2637 	bwn_rf_lock(mac);
2638 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639 	    pg->pg_txctl);
2640 	bwn_rf_unlock(mac);
2641 	bwn_phy_unlock(mac);
2642 
2643 	bwn_mac_enable(mac);
2644 }
2645 
2646 static void
2647 bwn_phy_g_task_15s(struct bwn_mac *mac)
2648 {
2649 	struct bwn_phy *phy = &mac->mac_phy;
2650 	struct bwn_phy_g *pg = &phy->phy_g;
2651 	struct bwn_softc *sc = mac->mac_sc;
2652 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653 	unsigned long expire, now;
2654 	struct bwn_lo_calib *cal, *tmp;
2655 	uint8_t expired = 0;
2656 
2657 	bwn_mac_suspend(mac);
2658 
2659 	if (lo == NULL)
2660 		goto fail;
2661 
2662 	BWN_GETTIME(now);
2663 	if (bwn_has_hwpctl(mac)) {
2664 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2665 		if (time_before(lo->pwr_vec_read_time, expire)) {
2666 			bwn_lo_get_powervector(mac);
2667 			bwn_phy_g_dc_lookup_init(mac, 0);
2668 		}
2669 		goto fail;
2670 	}
2671 
2672 	expire = now - BWN_LO_CALIB_EXPIRE;
2673 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674 		if (!time_before(cal->calib_time, expire))
2675 			continue;
2676 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679 			expired = 1;
2680 		}
2681 
2682 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684 		    cal->ctl.i, cal->ctl.q);
2685 
2686 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2687 		free(cal, M_DEVBUF);
2688 	}
2689 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691 		    &pg->pg_rfatt);
2692 		if (cal == NULL) {
2693 			device_printf(sc->sc_dev,
2694 			    "failed to recalibrate LO\n");
2695 			goto fail;
2696 		}
2697 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698 		bwn_lo_write(mac, &cal->ctl);
2699 	}
2700 
2701 fail:
2702 	bwn_mac_enable(mac);
2703 }
2704 
2705 static void
2706 bwn_phy_g_task_60s(struct bwn_mac *mac)
2707 {
2708 	struct bwn_phy *phy = &mac->mac_phy;
2709 	struct bwn_softc *sc = mac->mac_sc;
2710 	uint8_t old = phy->chan;
2711 
2712 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713 		return;
2714 
2715 	bwn_mac_suspend(mac);
2716 	bwn_nrssi_slope_11g(mac);
2717 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719 		bwn_switch_channel(mac, old);
2720 	}
2721 	bwn_mac_enable(mac);
2722 }
2723 
2724 static void
2725 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726 {
2727 
2728 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729 }
2730 
2731 static int
2732 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733 	const struct ieee80211_bpf_params *params)
2734 {
2735 	struct ieee80211com *ic = ni->ni_ic;
2736 	struct ifnet *ifp = ic->ic_ifp;
2737 	struct bwn_softc *sc = ifp->if_softc;
2738 	struct bwn_mac *mac = sc->sc_curmac;
2739 
2740 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742 		ieee80211_free_node(ni);
2743 		m_freem(m);
2744 		return (ENETDOWN);
2745 	}
2746 
2747 	BWN_LOCK(sc);
2748 	if (bwn_tx_isfull(sc, m)) {
2749 		ieee80211_free_node(ni);
2750 		m_freem(m);
2751 		ifp->if_oerrors++;
2752 		BWN_UNLOCK(sc);
2753 		return (ENOBUFS);
2754 	}
2755 
2756 	if (bwn_tx_start(sc, ni, m) != 0) {
2757 		if (ni != NULL)
2758 			ieee80211_free_node(ni);
2759 		ifp->if_oerrors++;
2760 	}
2761 	sc->sc_watchdog_timer = 5;
2762 	BWN_UNLOCK(sc);
2763 	return (0);
2764 }
2765 
2766 /*
2767  * Callback from the 802.11 layer to update the slot time
2768  * based on the current setting.  We use it to notify the
2769  * firmware of ERP changes and the f/w takes care of things
2770  * like slot time and preamble.
2771  */
2772 static void
2773 bwn_updateslot(struct ifnet *ifp)
2774 {
2775 	struct bwn_softc *sc = ifp->if_softc;
2776 	struct ieee80211com *ic = ifp->if_l2com;
2777 	struct bwn_mac *mac;
2778 
2779 	BWN_LOCK(sc);
2780 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781 		mac = (struct bwn_mac *)sc->sc_curmac;
2782 		bwn_set_slot_time(mac,
2783 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784 	}
2785 	BWN_UNLOCK(sc);
2786 }
2787 
2788 /*
2789  * Callback from the 802.11 layer after a promiscuous mode change.
2790  * Note this interface does not check the operating mode as this
2791  * is an internal callback and we are expected to honor the current
2792  * state (e.g. this is used for setting the interface in promiscuous
2793  * mode when operating in hostap mode to do ACS).
2794  */
2795 static void
2796 bwn_update_promisc(struct ifnet *ifp)
2797 {
2798 	struct bwn_softc *sc = ifp->if_softc;
2799 	struct bwn_mac *mac = sc->sc_curmac;
2800 
2801 	BWN_LOCK(sc);
2802 	mac = sc->sc_curmac;
2803 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804 		if (ifp->if_flags & IFF_PROMISC)
2805 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2806 		else
2807 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808 		bwn_set_opmode(mac);
2809 	}
2810 	BWN_UNLOCK(sc);
2811 }
2812 
2813 /*
2814  * Callback from the 802.11 layer to update WME parameters.
2815  */
2816 static int
2817 bwn_wme_update(struct ieee80211com *ic)
2818 {
2819 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820 	struct bwn_mac *mac = sc->sc_curmac;
2821 	struct wmeParams *wmep;
2822 	int i;
2823 
2824 	BWN_LOCK(sc);
2825 	mac = sc->sc_curmac;
2826 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827 		bwn_mac_suspend(mac);
2828 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831 		}
2832 		bwn_mac_enable(mac);
2833 	}
2834 	BWN_UNLOCK(sc);
2835 	return (0);
2836 }
2837 
2838 static void
2839 bwn_scan_start(struct ieee80211com *ic)
2840 {
2841 	struct ifnet *ifp = ic->ic_ifp;
2842 	struct bwn_softc *sc = ifp->if_softc;
2843 	struct bwn_mac *mac;
2844 
2845 	BWN_LOCK(sc);
2846 	mac = sc->sc_curmac;
2847 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849 		bwn_set_opmode(mac);
2850 		/* disable CFP update during scan */
2851 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852 	}
2853 	BWN_UNLOCK(sc);
2854 }
2855 
2856 static void
2857 bwn_scan_end(struct ieee80211com *ic)
2858 {
2859 	struct ifnet *ifp = ic->ic_ifp;
2860 	struct bwn_softc *sc = ifp->if_softc;
2861 	struct bwn_mac *mac;
2862 
2863 	BWN_LOCK(sc);
2864 	mac = sc->sc_curmac;
2865 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867 		bwn_set_opmode(mac);
2868 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869 	}
2870 	BWN_UNLOCK(sc);
2871 }
2872 
2873 static void
2874 bwn_set_channel(struct ieee80211com *ic)
2875 {
2876 	struct ifnet *ifp = ic->ic_ifp;
2877 	struct bwn_softc *sc = ifp->if_softc;
2878 	struct bwn_mac *mac = sc->sc_curmac;
2879 	struct bwn_phy *phy = &mac->mac_phy;
2880 	int chan, error;
2881 
2882 	BWN_LOCK(sc);
2883 
2884 	error = bwn_switch_band(sc, ic->ic_curchan);
2885 	if (error)
2886 		goto fail;;
2887 	bwn_mac_suspend(mac);
2888 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890 	if (chan != phy->chan)
2891 		bwn_switch_channel(mac, chan);
2892 
2893 	/* TX power level */
2894 	if (ic->ic_curchan->ic_maxpower != 0 &&
2895 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2896 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898 		    BWN_TXPWR_IGNORE_TSSI);
2899 	}
2900 
2901 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902 	if (phy->set_antenna)
2903 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904 
2905 	if (sc->sc_rf_enabled != phy->rf_on) {
2906 		if (sc->sc_rf_enabled) {
2907 			bwn_rf_turnon(mac);
2908 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909 				device_printf(sc->sc_dev,
2910 				    "please turns on the RF switch\n");
2911 		} else
2912 			bwn_rf_turnoff(mac);
2913 	}
2914 
2915 	bwn_mac_enable(mac);
2916 
2917 fail:
2918 	/*
2919 	 * Setup radio tap channel freq and flags
2920 	 */
2921 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922 		htole16(ic->ic_curchan->ic_freq);
2923 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2925 
2926 	BWN_UNLOCK(sc);
2927 }
2928 
2929 static struct ieee80211vap *
2930 bwn_vap_create(struct ieee80211com *ic,
2931 	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2932 	const uint8_t bssid[IEEE80211_ADDR_LEN],
2933 	const uint8_t mac0[IEEE80211_ADDR_LEN])
2934 {
2935 	struct ifnet *ifp = ic->ic_ifp;
2936 	struct bwn_softc *sc = ifp->if_softc;
2937 	struct ieee80211vap *vap;
2938 	struct bwn_vap *bvp;
2939 	uint8_t mac[IEEE80211_ADDR_LEN];
2940 
2941 	IEEE80211_ADDR_COPY(mac, mac0);
2942 	switch (opmode) {
2943 	case IEEE80211_M_HOSTAP:
2944 	case IEEE80211_M_MBSS:
2945 	case IEEE80211_M_STA:
2946 	case IEEE80211_M_WDS:
2947 	case IEEE80211_M_MONITOR:
2948 	case IEEE80211_M_IBSS:
2949 	case IEEE80211_M_AHDEMO:
2950 		break;
2951 	default:
2952 		return (NULL);
2953 	}
2954 
2955 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956 
2957 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958 	    M_80211_VAP, M_NOWAIT | M_ZERO);
2959 	if (bvp == NULL) {
2960 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961 		return (NULL);
2962 	}
2963 	vap = &bvp->bv_vap;
2964 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966 	/* override with driver methods */
2967 	bvp->bv_newstate = vap->iv_newstate;
2968 	vap->iv_newstate = bwn_newstate;
2969 
2970 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2971 	vap->iv_max_aid = BWN_STAID_MAX;
2972 
2973 	ieee80211_ratectl_init(vap);
2974 
2975 	/* complete setup */
2976 	ieee80211_vap_attach(vap, ieee80211_media_change,
2977 	    ieee80211_media_status);
2978 	return (vap);
2979 }
2980 
2981 static void
2982 bwn_vap_delete(struct ieee80211vap *vap)
2983 {
2984 	struct bwn_vap *bvp = BWN_VAP(vap);
2985 
2986 	ieee80211_ratectl_deinit(vap);
2987 	ieee80211_vap_detach(vap);
2988 	free(bvp, M_80211_VAP);
2989 }
2990 
2991 static void
2992 bwn_init(void *arg)
2993 {
2994 	struct bwn_softc *sc = arg;
2995 	struct ifnet *ifp = sc->sc_ifp;
2996 	struct ieee80211com *ic = ifp->if_l2com;
2997 	int error = 0;
2998 
2999 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000 		__func__, ifp->if_flags);
3001 
3002 	BWN_LOCK(sc);
3003 	error = bwn_init_locked(sc);
3004 	BWN_UNLOCK(sc);
3005 
3006 	if (error == 0)
3007 		ieee80211_start_all(ic);	/* start all vap's */
3008 }
3009 
3010 static int
3011 bwn_init_locked(struct bwn_softc *sc)
3012 {
3013 	struct bwn_mac *mac;
3014 	struct ifnet *ifp = sc->sc_ifp;
3015 	int error;
3016 
3017 	BWN_ASSERT_LOCKED(sc);
3018 
3019 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021 	sc->sc_filters = 0;
3022 	bwn_wme_clear(sc);
3023 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024 	sc->sc_rf_enabled = 1;
3025 
3026 	mac = sc->sc_curmac;
3027 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028 		error = bwn_core_init(mac);
3029 		if (error != 0)
3030 			return (error);
3031 	}
3032 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033 		bwn_core_start(mac);
3034 
3035 	bwn_set_opmode(mac);
3036 	bwn_set_pretbtt(mac);
3037 	bwn_spu_setdelay(mac, 0);
3038 	bwn_set_macaddr(mac);
3039 
3040 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043 
3044 	return (0);
3045 }
3046 
3047 static void
3048 bwn_stop(struct bwn_softc *sc, int statechg)
3049 {
3050 
3051 	BWN_LOCK(sc);
3052 	bwn_stop_locked(sc, statechg);
3053 	BWN_UNLOCK(sc);
3054 }
3055 
3056 static void
3057 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058 {
3059 	struct bwn_mac *mac = sc->sc_curmac;
3060 	struct ifnet *ifp = sc->sc_ifp;
3061 
3062 	BWN_ASSERT_LOCKED(sc);
3063 
3064 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065 		/* XXX FIXME opmode not based on VAP */
3066 		bwn_set_opmode(mac);
3067 		bwn_set_macaddr(mac);
3068 	}
3069 
3070 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071 		bwn_core_stop(mac);
3072 
3073 	callout_stop(&sc->sc_led_blink_ch);
3074 	sc->sc_led_blinking = 0;
3075 
3076 	bwn_core_exit(mac);
3077 	sc->sc_rf_enabled = 0;
3078 
3079 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080 }
3081 
3082 static void
3083 bwn_wme_clear(struct bwn_softc *sc)
3084 {
3085 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3086 	struct wmeParams *p;
3087 	unsigned int i;
3088 
3089 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090 	    ("%s:%d: fail", __func__, __LINE__));
3091 
3092 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093 		p = &(sc->sc_wmeParams[i]);
3094 
3095 		switch (bwn_wme_shm_offsets[i]) {
3096 		case BWN_WME_VOICE:
3097 			p->wmep_txopLimit = 0;
3098 			p->wmep_aifsn = 2;
3099 			/* XXX FIXME: log2(cwmin) */
3100 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102 			break;
3103 		case BWN_WME_VIDEO:
3104 			p->wmep_txopLimit = 0;
3105 			p->wmep_aifsn = 2;
3106 			/* XXX FIXME: log2(cwmin) */
3107 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109 			break;
3110 		case BWN_WME_BESTEFFORT:
3111 			p->wmep_txopLimit = 0;
3112 			p->wmep_aifsn = 3;
3113 			/* XXX FIXME: log2(cwmin) */
3114 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116 			break;
3117 		case BWN_WME_BACKGROUND:
3118 			p->wmep_txopLimit = 0;
3119 			p->wmep_aifsn = 7;
3120 			/* XXX FIXME: log2(cwmin) */
3121 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123 			break;
3124 		default:
3125 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126 		}
3127 	}
3128 }
3129 
3130 static int
3131 bwn_core_init(struct bwn_mac *mac)
3132 {
3133 	struct bwn_softc *sc = mac->mac_sc;
3134 	uint64_t hf;
3135 	int error;
3136 
3137 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138 	    ("%s:%d: fail", __func__, __LINE__));
3139 
3140 	siba_powerup(sc->sc_dev, 0);
3141 	if (!siba_dev_isup(sc->sc_dev))
3142 		bwn_reset_core(mac,
3143 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144 
3145 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148 	BWN_GETTIME(mac->mac_phy.nexttime);
3149 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151 	mac->mac_stats.link_noise = -95;
3152 	mac->mac_reason_intr = 0;
3153 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155 #ifdef BWN_DEBUG
3156 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3157 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158 #endif
3159 	mac->mac_suspended = 1;
3160 	mac->mac_task_state = 0;
3161 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162 
3163 	mac->mac_phy.init_pre(mac);
3164 
3165 	siba_pcicore_intr(sc->sc_dev);
3166 
3167 	siba_fix_imcfglobug(sc->sc_dev);
3168 	bwn_bt_disable(mac);
3169 	if (mac->mac_phy.prepare_hw) {
3170 		error = mac->mac_phy.prepare_hw(mac);
3171 		if (error)
3172 			goto fail0;
3173 	}
3174 	error = bwn_chip_init(mac);
3175 	if (error)
3176 		goto fail0;
3177 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178 	    siba_get_revid(sc->sc_dev));
3179 	hf = bwn_hf_read(mac);
3180 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184 		if (mac->mac_phy.rev == 1)
3185 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186 	}
3187 	if (mac->mac_phy.rf_ver == 0x2050) {
3188 		if (mac->mac_phy.rf_rev < 6)
3189 			hf |= BWN_HF_FORCE_VCO_RECALC;
3190 		if (mac->mac_phy.rf_rev == 6)
3191 			hf |= BWN_HF_4318_TSSI;
3192 	}
3193 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199 	bwn_hf_write(mac, hf);
3200 
3201 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205 
3206 	bwn_rate_init(mac);
3207 	bwn_set_phytxctl(mac);
3208 
3209 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212 
3213 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214 		bwn_pio_init(mac);
3215 	else
3216 		bwn_dma_init(mac);
3217 	if (error)
3218 		goto fail1;
3219 	bwn_wme_init(mac);
3220 	bwn_spu_setdelay(mac, 1);
3221 	bwn_bt_enable(mac);
3222 
3223 	siba_powerup(sc->sc_dev,
3224 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3225 	bwn_set_macaddr(mac);
3226 	bwn_crypt_init(mac);
3227 
3228 	/* XXX LED initializatin */
3229 
3230 	mac->mac_status = BWN_MAC_STATUS_INITED;
3231 
3232 	return (error);
3233 
3234 fail1:
3235 	bwn_chip_exit(mac);
3236 fail0:
3237 	siba_powerdown(sc->sc_dev);
3238 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3239 	    ("%s:%d: fail", __func__, __LINE__));
3240 	return (error);
3241 }
3242 
3243 static void
3244 bwn_core_start(struct bwn_mac *mac)
3245 {
3246 	struct bwn_softc *sc = mac->mac_sc;
3247 	uint32_t tmp;
3248 
3249 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3250 	    ("%s:%d: fail", __func__, __LINE__));
3251 
3252 	if (siba_get_revid(sc->sc_dev) < 5)
3253 		return;
3254 
3255 	while (1) {
3256 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3257 		if (!(tmp & 0x00000001))
3258 			break;
3259 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3260 	}
3261 
3262 	bwn_mac_enable(mac);
3263 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3264 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3265 
3266 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3267 }
3268 
3269 static void
3270 bwn_core_exit(struct bwn_mac *mac)
3271 {
3272 	struct bwn_softc *sc = mac->mac_sc;
3273 	uint32_t macctl;
3274 
3275 	BWN_ASSERT_LOCKED(mac->mac_sc);
3276 
3277 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3278 	    ("%s:%d: fail", __func__, __LINE__));
3279 
3280 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3281 		return;
3282 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3283 
3284 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3285 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3286 	macctl |= BWN_MACCTL_MCODE_JMP0;
3287 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3288 
3289 	bwn_dma_stop(mac);
3290 	bwn_pio_stop(mac);
3291 	bwn_chip_exit(mac);
3292 	mac->mac_phy.switch_analog(mac, 0);
3293 	siba_dev_down(sc->sc_dev, 0);
3294 	siba_powerdown(sc->sc_dev);
3295 }
3296 
3297 static void
3298 bwn_bt_disable(struct bwn_mac *mac)
3299 {
3300 	struct bwn_softc *sc = mac->mac_sc;
3301 
3302 	(void)sc;
3303 	/* XXX do nothing yet */
3304 }
3305 
3306 static int
3307 bwn_chip_init(struct bwn_mac *mac)
3308 {
3309 	struct bwn_softc *sc = mac->mac_sc;
3310 	struct bwn_phy *phy = &mac->mac_phy;
3311 	uint32_t macctl;
3312 	int error;
3313 
3314 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3315 	if (phy->gmode)
3316 		macctl |= BWN_MACCTL_GMODE;
3317 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3318 
3319 	error = bwn_fw_fillinfo(mac);
3320 	if (error)
3321 		return (error);
3322 	error = bwn_fw_loaducode(mac);
3323 	if (error)
3324 		return (error);
3325 
3326 	error = bwn_gpio_init(mac);
3327 	if (error)
3328 		return (error);
3329 
3330 	error = bwn_fw_loadinitvals(mac);
3331 	if (error) {
3332 		siba_gpio_set(sc->sc_dev, 0);
3333 		return (error);
3334 	}
3335 	phy->switch_analog(mac, 1);
3336 	error = bwn_phy_init(mac);
3337 	if (error) {
3338 		siba_gpio_set(sc->sc_dev, 0);
3339 		return (error);
3340 	}
3341 	if (phy->set_im)
3342 		phy->set_im(mac, BWN_IMMODE_NONE);
3343 	if (phy->set_antenna)
3344 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3345 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3346 
3347 	if (phy->type == BWN_PHYTYPE_B)
3348 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3349 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3350 	if (siba_get_revid(sc->sc_dev) < 5)
3351 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3352 
3353 	BWN_WRITE_4(mac, BWN_MACCTL,
3354 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3355 	BWN_WRITE_4(mac, BWN_MACCTL,
3356 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3357 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3358 
3359 	bwn_set_opmode(mac);
3360 	if (siba_get_revid(sc->sc_dev) < 3) {
3361 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3362 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3363 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3364 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3365 	} else {
3366 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3367 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3368 	}
3369 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3370 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3371 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3372 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3373 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3374 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3375 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3376 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3377 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3378 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3379 	return (error);
3380 }
3381 
3382 /* read hostflags */
3383 static uint64_t
3384 bwn_hf_read(struct bwn_mac *mac)
3385 {
3386 	uint64_t ret;
3387 
3388 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3389 	ret <<= 16;
3390 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3391 	ret <<= 16;
3392 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3393 	return (ret);
3394 }
3395 
3396 static void
3397 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3398 {
3399 
3400 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3401 	    (value & 0x00000000ffffull));
3402 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3403 	    (value & 0x0000ffff0000ull) >> 16);
3404 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3405 	    (value & 0xffff00000000ULL) >> 32);
3406 }
3407 
3408 static void
3409 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3410 {
3411 
3412 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3413 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3414 }
3415 
3416 static void
3417 bwn_rate_init(struct bwn_mac *mac)
3418 {
3419 
3420 	switch (mac->mac_phy.type) {
3421 	case BWN_PHYTYPE_A:
3422 	case BWN_PHYTYPE_G:
3423 	case BWN_PHYTYPE_LP:
3424 	case BWN_PHYTYPE_N:
3425 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3426 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3427 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3428 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3429 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3430 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3431 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3432 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3433 			break;
3434 		/* FALLTHROUGH */
3435 	case BWN_PHYTYPE_B:
3436 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3437 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3438 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3439 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3440 		break;
3441 	default:
3442 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3443 	}
3444 }
3445 
3446 static void
3447 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3448 {
3449 	uint16_t offset;
3450 
3451 	if (ofdm) {
3452 		offset = 0x480;
3453 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3454 	} else {
3455 		offset = 0x4c0;
3456 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3457 	}
3458 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3459 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3460 }
3461 
3462 static uint8_t
3463 bwn_plcp_getcck(const uint8_t bitrate)
3464 {
3465 
3466 	switch (bitrate) {
3467 	case BWN_CCK_RATE_1MB:
3468 		return (0x0a);
3469 	case BWN_CCK_RATE_2MB:
3470 		return (0x14);
3471 	case BWN_CCK_RATE_5MB:
3472 		return (0x37);
3473 	case BWN_CCK_RATE_11MB:
3474 		return (0x6e);
3475 	}
3476 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3477 	return (0);
3478 }
3479 
3480 static uint8_t
3481 bwn_plcp_getofdm(const uint8_t bitrate)
3482 {
3483 
3484 	switch (bitrate) {
3485 	case BWN_OFDM_RATE_6MB:
3486 		return (0xb);
3487 	case BWN_OFDM_RATE_9MB:
3488 		return (0xf);
3489 	case BWN_OFDM_RATE_12MB:
3490 		return (0xa);
3491 	case BWN_OFDM_RATE_18MB:
3492 		return (0xe);
3493 	case BWN_OFDM_RATE_24MB:
3494 		return (0x9);
3495 	case BWN_OFDM_RATE_36MB:
3496 		return (0xd);
3497 	case BWN_OFDM_RATE_48MB:
3498 		return (0x8);
3499 	case BWN_OFDM_RATE_54MB:
3500 		return (0xc);
3501 	}
3502 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3503 	return (0);
3504 }
3505 
3506 static void
3507 bwn_set_phytxctl(struct bwn_mac *mac)
3508 {
3509 	uint16_t ctl;
3510 
3511 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3512 	    BWN_TX_PHY_TXPWR);
3513 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3514 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3515 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3516 }
3517 
3518 static void
3519 bwn_pio_init(struct bwn_mac *mac)
3520 {
3521 	struct bwn_pio *pio = &mac->mac_method.pio;
3522 
3523 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3524 	    & ~BWN_MACCTL_BIGENDIAN);
3525 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3526 
3527 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3528 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3529 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3530 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3531 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3532 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3533 }
3534 
3535 static void
3536 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3537     int index)
3538 {
3539 	struct bwn_pio_txpkt *tp;
3540 	struct bwn_softc *sc = mac->mac_sc;
3541 	unsigned int i;
3542 
3543 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3544 	tq->tq_index = index;
3545 
3546 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3547 	if (siba_get_revid(sc->sc_dev) >= 8)
3548 		tq->tq_size = 1920;
3549 	else {
3550 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3551 		tq->tq_size -= 80;
3552 	}
3553 
3554 	TAILQ_INIT(&tq->tq_pktlist);
3555 	for (i = 0; i < N(tq->tq_pkts); i++) {
3556 		tp = &(tq->tq_pkts[i]);
3557 		tp->tp_index = i;
3558 		tp->tp_queue = tq;
3559 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3560 	}
3561 }
3562 
3563 static uint16_t
3564 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3565 {
3566 	struct bwn_softc *sc = mac->mac_sc;
3567 	static const uint16_t bases[] = {
3568 		BWN_PIO_BASE0,
3569 		BWN_PIO_BASE1,
3570 		BWN_PIO_BASE2,
3571 		BWN_PIO_BASE3,
3572 		BWN_PIO_BASE4,
3573 		BWN_PIO_BASE5,
3574 		BWN_PIO_BASE6,
3575 		BWN_PIO_BASE7,
3576 	};
3577 	static const uint16_t bases_rev11[] = {
3578 		BWN_PIO11_BASE0,
3579 		BWN_PIO11_BASE1,
3580 		BWN_PIO11_BASE2,
3581 		BWN_PIO11_BASE3,
3582 		BWN_PIO11_BASE4,
3583 		BWN_PIO11_BASE5,
3584 	};
3585 
3586 	if (siba_get_revid(sc->sc_dev) >= 11) {
3587 		if (index >= N(bases_rev11))
3588 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589 		return (bases_rev11[index]);
3590 	}
3591 	if (index >= N(bases))
3592 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3593 	return (bases[index]);
3594 }
3595 
3596 static void
3597 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3598     int index)
3599 {
3600 	struct bwn_softc *sc = mac->mac_sc;
3601 
3602 	prq->prq_mac = mac;
3603 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3604 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3605 	bwn_dma_rxdirectfifo(mac, index, 1);
3606 }
3607 
3608 static void
3609 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3610 {
3611 	if (tq == NULL)
3612 		return;
3613 	bwn_pio_cancel_tx_packets(tq);
3614 }
3615 
3616 static void
3617 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3618 {
3619 
3620 	bwn_destroy_pioqueue_tx(pio);
3621 }
3622 
3623 static uint16_t
3624 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3625     uint16_t offset)
3626 {
3627 
3628 	return (BWN_READ_2(mac, tq->tq_base + offset));
3629 }
3630 
3631 static void
3632 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3633 {
3634 	uint32_t ctl;
3635 	int type;
3636 	uint16_t base;
3637 
3638 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3639 	base = bwn_dma_base(type, idx);
3640 	if (type == BWN_DMA_64BIT) {
3641 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3642 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3643 		if (enable)
3644 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3645 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3646 	} else {
3647 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3648 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3649 		if (enable)
3650 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3651 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3652 	}
3653 }
3654 
3655 static uint64_t
3656 bwn_dma_mask(struct bwn_mac *mac)
3657 {
3658 	uint32_t tmp;
3659 	uint16_t base;
3660 
3661 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3662 	if (tmp & SIBA_TGSHIGH_DMA64)
3663 		return (BWN_DMA_BIT_MASK(64));
3664 	base = bwn_dma_base(0, 0);
3665 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3666 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3667 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3668 		return (BWN_DMA_BIT_MASK(32));
3669 
3670 	return (BWN_DMA_BIT_MASK(30));
3671 }
3672 
3673 static int
3674 bwn_dma_mask2type(uint64_t dmamask)
3675 {
3676 
3677 	if (dmamask == BWN_DMA_BIT_MASK(30))
3678 		return (BWN_DMA_30BIT);
3679 	if (dmamask == BWN_DMA_BIT_MASK(32))
3680 		return (BWN_DMA_32BIT);
3681 	if (dmamask == BWN_DMA_BIT_MASK(64))
3682 		return (BWN_DMA_64BIT);
3683 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3684 	return (BWN_DMA_30BIT);
3685 }
3686 
3687 static void
3688 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3689 {
3690 	struct bwn_pio_txpkt *tp;
3691 	unsigned int i;
3692 
3693 	for (i = 0; i < N(tq->tq_pkts); i++) {
3694 		tp = &(tq->tq_pkts[i]);
3695 		if (tp->tp_m) {
3696 			m_freem(tp->tp_m);
3697 			tp->tp_m = NULL;
3698 		}
3699 	}
3700 }
3701 
3702 static uint16_t
3703 bwn_dma_base(int type, int controller_idx)
3704 {
3705 	static const uint16_t map64[] = {
3706 		BWN_DMA64_BASE0,
3707 		BWN_DMA64_BASE1,
3708 		BWN_DMA64_BASE2,
3709 		BWN_DMA64_BASE3,
3710 		BWN_DMA64_BASE4,
3711 		BWN_DMA64_BASE5,
3712 	};
3713 	static const uint16_t map32[] = {
3714 		BWN_DMA32_BASE0,
3715 		BWN_DMA32_BASE1,
3716 		BWN_DMA32_BASE2,
3717 		BWN_DMA32_BASE3,
3718 		BWN_DMA32_BASE4,
3719 		BWN_DMA32_BASE5,
3720 	};
3721 
3722 	if (type == BWN_DMA_64BIT) {
3723 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3724 		    ("%s:%d: fail", __func__, __LINE__));
3725 		return (map64[controller_idx]);
3726 	}
3727 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3728 	    ("%s:%d: fail", __func__, __LINE__));
3729 	return (map32[controller_idx]);
3730 }
3731 
3732 static void
3733 bwn_dma_init(struct bwn_mac *mac)
3734 {
3735 	struct bwn_dma *dma = &mac->mac_method.dma;
3736 
3737 	/* setup TX DMA channels. */
3738 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3739 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3740 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3741 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3742 	bwn_dma_setup(dma->mcast);
3743 	/* setup RX DMA channel. */
3744 	bwn_dma_setup(dma->rx);
3745 }
3746 
3747 static struct bwn_dma_ring *
3748 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3749     int for_tx, int type)
3750 {
3751 	struct bwn_dma *dma = &mac->mac_method.dma;
3752 	struct bwn_dma_ring *dr;
3753 	struct bwn_dmadesc_generic *desc;
3754 	struct bwn_dmadesc_meta *mt;
3755 	struct bwn_softc *sc = mac->mac_sc;
3756 	int error, i;
3757 
3758 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3759 	if (dr == NULL)
3760 		goto out;
3761 	dr->dr_numslots = BWN_RXRING_SLOTS;
3762 	if (for_tx)
3763 		dr->dr_numslots = BWN_TXRING_SLOTS;
3764 
3765 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3766 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3767 	if (dr->dr_meta == NULL)
3768 		goto fail0;
3769 
3770 	dr->dr_type = type;
3771 	dr->dr_mac = mac;
3772 	dr->dr_base = bwn_dma_base(type, controller_index);
3773 	dr->dr_index = controller_index;
3774 	if (type == BWN_DMA_64BIT) {
3775 		dr->getdesc = bwn_dma_64_getdesc;
3776 		dr->setdesc = bwn_dma_64_setdesc;
3777 		dr->start_transfer = bwn_dma_64_start_transfer;
3778 		dr->suspend = bwn_dma_64_suspend;
3779 		dr->resume = bwn_dma_64_resume;
3780 		dr->get_curslot = bwn_dma_64_get_curslot;
3781 		dr->set_curslot = bwn_dma_64_set_curslot;
3782 	} else {
3783 		dr->getdesc = bwn_dma_32_getdesc;
3784 		dr->setdesc = bwn_dma_32_setdesc;
3785 		dr->start_transfer = bwn_dma_32_start_transfer;
3786 		dr->suspend = bwn_dma_32_suspend;
3787 		dr->resume = bwn_dma_32_resume;
3788 		dr->get_curslot = bwn_dma_32_get_curslot;
3789 		dr->set_curslot = bwn_dma_32_set_curslot;
3790 	}
3791 	if (for_tx) {
3792 		dr->dr_tx = 1;
3793 		dr->dr_curslot = -1;
3794 	} else {
3795 		if (dr->dr_index == 0) {
3796 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3797 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3798 		} else
3799 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3800 	}
3801 
3802 	error = bwn_dma_allocringmemory(dr);
3803 	if (error)
3804 		goto fail2;
3805 
3806 	if (for_tx) {
3807 		/*
3808 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3809 		 * BWN_TX_SLOTS_PER_FRAME
3810 		 */
3811 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3812 		    ("%s:%d: fail", __func__, __LINE__));
3813 
3814 		dr->dr_txhdr_cache =
3815 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3816 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3817 		KASSERT(dr->dr_txhdr_cache != NULL,
3818 		    ("%s:%d: fail", __func__, __LINE__));
3819 
3820 		/*
3821 		 * Create TX ring DMA stuffs
3822 		 */
3823 		error = bus_dma_tag_create(dma->parent_dtag,
3824 				    BWN_ALIGN, 0,
3825 				    BUS_SPACE_MAXADDR,
3826 				    BUS_SPACE_MAXADDR,
3827 				    NULL, NULL,
3828 				    BWN_HDRSIZE(mac),
3829 				    1,
3830 				    BUS_SPACE_MAXSIZE_32BIT,
3831 				    0,
3832 				    NULL, NULL,
3833 				    &dr->dr_txring_dtag);
3834 		if (error) {
3835 			device_printf(sc->sc_dev,
3836 			    "can't create TX ring DMA tag: TODO frees\n");
3837 			goto fail1;
3838 		}
3839 
3840 		for (i = 0; i < dr->dr_numslots; i += 2) {
3841 			dr->getdesc(dr, i, &desc, &mt);
3842 
3843 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3844 			mt->mt_m = NULL;
3845 			mt->mt_ni = NULL;
3846 			mt->mt_islast = 0;
3847 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3848 			    &mt->mt_dmap);
3849 			if (error) {
3850 				device_printf(sc->sc_dev,
3851 				     "can't create RX buf DMA map\n");
3852 				goto fail1;
3853 			}
3854 
3855 			dr->getdesc(dr, i + 1, &desc, &mt);
3856 
3857 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3858 			mt->mt_m = NULL;
3859 			mt->mt_ni = NULL;
3860 			mt->mt_islast = 1;
3861 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3862 			    &mt->mt_dmap);
3863 			if (error) {
3864 				device_printf(sc->sc_dev,
3865 				     "can't create RX buf DMA map\n");
3866 				goto fail1;
3867 			}
3868 		}
3869 	} else {
3870 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3871 		    &dr->dr_spare_dmap);
3872 		if (error) {
3873 			device_printf(sc->sc_dev,
3874 			    "can't create RX buf DMA map\n");
3875 			goto out;		/* XXX wrong! */
3876 		}
3877 
3878 		for (i = 0; i < dr->dr_numslots; i++) {
3879 			dr->getdesc(dr, i, &desc, &mt);
3880 
3881 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3882 			    &mt->mt_dmap);
3883 			if (error) {
3884 				device_printf(sc->sc_dev,
3885 				    "can't create RX buf DMA map\n");
3886 				goto out;	/* XXX wrong! */
3887 			}
3888 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3889 			if (error) {
3890 				device_printf(sc->sc_dev,
3891 				    "failed to allocate RX buf\n");
3892 				goto out;	/* XXX wrong! */
3893 			}
3894 		}
3895 
3896 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3897 		    BUS_DMASYNC_PREWRITE);
3898 
3899 		dr->dr_usedslot = dr->dr_numslots;
3900 	}
3901 
3902       out:
3903 	return (dr);
3904 
3905 fail2:
3906 	free(dr->dr_txhdr_cache, M_DEVBUF);
3907 fail1:
3908 	free(dr->dr_meta, M_DEVBUF);
3909 fail0:
3910 	free(dr, M_DEVBUF);
3911 	return (NULL);
3912 }
3913 
3914 static void
3915 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3916 {
3917 
3918 	if (dr == NULL)
3919 		return;
3920 
3921 	bwn_dma_free_descbufs(*dr);
3922 	bwn_dma_free_ringmemory(*dr);
3923 
3924 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3925 	free((*dr)->dr_meta, M_DEVBUF);
3926 	free(*dr, M_DEVBUF);
3927 
3928 	*dr = NULL;
3929 }
3930 
3931 static void
3932 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3933     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3934 {
3935 	struct bwn_dmadesc32 *desc;
3936 
3937 	*meta = &(dr->dr_meta[slot]);
3938 	desc = dr->dr_ring_descbase;
3939 	desc = &(desc[slot]);
3940 
3941 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3942 }
3943 
3944 static void
3945 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3946     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3947     int start, int end, int irq)
3948 {
3949 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3950 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3951 	uint32_t addr, addrext, ctl;
3952 	int slot;
3953 
3954 	slot = (int)(&(desc->dma.dma32) - descbase);
3955 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3956 	    ("%s:%d: fail", __func__, __LINE__));
3957 
3958 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3959 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3960 	addr |= siba_dma_translation(sc->sc_dev);
3961 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3962 	if (slot == dr->dr_numslots - 1)
3963 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3964 	if (start)
3965 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3966 	if (end)
3967 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3968 	if (irq)
3969 		ctl |= BWN_DMA32_DCTL_IRQ;
3970 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3971 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3972 
3973 	desc->dma.dma32.control = htole32(ctl);
3974 	desc->dma.dma32.address = htole32(addr);
3975 }
3976 
3977 static void
3978 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3979 {
3980 
3981 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3982 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3983 }
3984 
3985 static void
3986 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3987 {
3988 
3989 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3990 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3991 }
3992 
3993 static void
3994 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3995 {
3996 
3997 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3998 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3999 }
4000 
4001 static int
4002 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4003 {
4004 	uint32_t val;
4005 
4006 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4007 	val &= BWN_DMA32_RXDPTR;
4008 
4009 	return (val / sizeof(struct bwn_dmadesc32));
4010 }
4011 
4012 static void
4013 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4014 {
4015 
4016 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4017 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4018 }
4019 
4020 static void
4021 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4022     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4023 {
4024 	struct bwn_dmadesc64 *desc;
4025 
4026 	*meta = &(dr->dr_meta[slot]);
4027 	desc = dr->dr_ring_descbase;
4028 	desc = &(desc[slot]);
4029 
4030 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4031 }
4032 
4033 static void
4034 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4035     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4036     int start, int end, int irq)
4037 {
4038 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4039 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4040 	int slot;
4041 	uint32_t ctl0 = 0, ctl1 = 0;
4042 	uint32_t addrlo, addrhi;
4043 	uint32_t addrext;
4044 
4045 	slot = (int)(&(desc->dma.dma64) - descbase);
4046 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4047 	    ("%s:%d: fail", __func__, __LINE__));
4048 
4049 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4050 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4051 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4052 	    30;
4053 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4054 	if (slot == dr->dr_numslots - 1)
4055 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4056 	if (start)
4057 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4058 	if (end)
4059 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4060 	if (irq)
4061 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4062 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4063 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4064 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4065 
4066 	desc->dma.dma64.control0 = htole32(ctl0);
4067 	desc->dma.dma64.control1 = htole32(ctl1);
4068 	desc->dma.dma64.address_low = htole32(addrlo);
4069 	desc->dma.dma64.address_high = htole32(addrhi);
4070 }
4071 
4072 static void
4073 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4074 {
4075 
4076 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4077 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4078 }
4079 
4080 static void
4081 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4082 {
4083 
4084 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4085 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4086 }
4087 
4088 static void
4089 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4090 {
4091 
4092 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4093 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4094 }
4095 
4096 static int
4097 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4098 {
4099 	uint32_t val;
4100 
4101 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4102 	val &= BWN_DMA64_RXSTATDPTR;
4103 
4104 	return (val / sizeof(struct bwn_dmadesc64));
4105 }
4106 
4107 static void
4108 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4109 {
4110 
4111 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4112 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4113 }
4114 
4115 static int
4116 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4117 {
4118 	struct bwn_mac *mac = dr->dr_mac;
4119 	struct bwn_dma *dma = &mac->mac_method.dma;
4120 	struct bwn_softc *sc = mac->mac_sc;
4121 	int error;
4122 
4123 	error = bus_dma_tag_create(dma->parent_dtag,
4124 			    BWN_ALIGN, 0,
4125 			    BUS_SPACE_MAXADDR,
4126 			    BUS_SPACE_MAXADDR,
4127 			    NULL, NULL,
4128 			    BWN_DMA_RINGMEMSIZE,
4129 			    1,
4130 			    BUS_SPACE_MAXSIZE_32BIT,
4131 			    0,
4132 			    NULL, NULL,
4133 			    &dr->dr_ring_dtag);
4134 	if (error) {
4135 		device_printf(sc->sc_dev,
4136 		    "can't create TX ring DMA tag: TODO frees\n");
4137 		return (-1);
4138 	}
4139 
4140 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4141 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4142 	    &dr->dr_ring_dmap);
4143 	if (error) {
4144 		device_printf(sc->sc_dev,
4145 		    "can't allocate DMA mem: TODO frees\n");
4146 		return (-1);
4147 	}
4148 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4149 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4150 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4151 	if (error) {
4152 		device_printf(sc->sc_dev,
4153 		    "can't load DMA mem: TODO free\n");
4154 		return (-1);
4155 	}
4156 
4157 	return (0);
4158 }
4159 
4160 static void
4161 bwn_dma_setup(struct bwn_dma_ring *dr)
4162 {
4163 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4164 	uint64_t ring64;
4165 	uint32_t addrext, ring32, value;
4166 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4167 
4168 	if (dr->dr_tx) {
4169 		dr->dr_curslot = -1;
4170 
4171 		if (dr->dr_type == BWN_DMA_64BIT) {
4172 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4173 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4174 			    >> 30;
4175 			value = BWN_DMA64_TXENABLE;
4176 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4177 			    & BWN_DMA64_TXADDREXT_MASK;
4178 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4179 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4180 			    (ring64 & 0xffffffff));
4181 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4182 			    ((ring64 >> 32) &
4183 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4184 		} else {
4185 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4186 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4187 			value = BWN_DMA32_TXENABLE;
4188 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4189 			    & BWN_DMA32_TXADDREXT_MASK;
4190 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4191 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4192 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4193 		}
4194 		return;
4195 	}
4196 
4197 	/*
4198 	 * set for RX
4199 	 */
4200 	dr->dr_usedslot = dr->dr_numslots;
4201 
4202 	if (dr->dr_type == BWN_DMA_64BIT) {
4203 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4204 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4205 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4206 		value |= BWN_DMA64_RXENABLE;
4207 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4208 		    & BWN_DMA64_RXADDREXT_MASK;
4209 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4210 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4211 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4212 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4213 		    | (trans << 1));
4214 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4215 		    sizeof(struct bwn_dmadesc64));
4216 	} else {
4217 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4218 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4219 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4220 		value |= BWN_DMA32_RXENABLE;
4221 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4222 		    & BWN_DMA32_RXADDREXT_MASK;
4223 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4224 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4225 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4226 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4227 		    sizeof(struct bwn_dmadesc32));
4228 	}
4229 }
4230 
4231 static void
4232 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4233 {
4234 
4235 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4236 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4237 	    dr->dr_ring_dmap);
4238 }
4239 
4240 static void
4241 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4242 {
4243 
4244 	if (dr->dr_tx) {
4245 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4246 		if (dr->dr_type == BWN_DMA_64BIT) {
4247 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4248 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4249 		} else
4250 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4251 	} else {
4252 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4253 		if (dr->dr_type == BWN_DMA_64BIT) {
4254 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4255 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4256 		} else
4257 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4258 	}
4259 }
4260 
4261 static void
4262 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4263 {
4264 	struct bwn_dmadesc_generic *desc;
4265 	struct bwn_dmadesc_meta *meta;
4266 	struct bwn_mac *mac = dr->dr_mac;
4267 	struct bwn_dma *dma = &mac->mac_method.dma;
4268 	struct bwn_softc *sc = mac->mac_sc;
4269 	int i;
4270 
4271 	if (!dr->dr_usedslot)
4272 		return;
4273 	for (i = 0; i < dr->dr_numslots; i++) {
4274 		dr->getdesc(dr, i, &desc, &meta);
4275 
4276 		if (meta->mt_m == NULL) {
4277 			if (!dr->dr_tx)
4278 				device_printf(sc->sc_dev, "%s: not TX?\n",
4279 				    __func__);
4280 			continue;
4281 		}
4282 		if (dr->dr_tx) {
4283 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4284 				bus_dmamap_unload(dr->dr_txring_dtag,
4285 				    meta->mt_dmap);
4286 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4287 				bus_dmamap_unload(dma->txbuf_dtag,
4288 				    meta->mt_dmap);
4289 		} else
4290 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4291 		bwn_dma_free_descbuf(dr, meta);
4292 	}
4293 }
4294 
4295 static int
4296 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4297     int type)
4298 {
4299 	struct bwn_softc *sc = mac->mac_sc;
4300 	uint32_t value;
4301 	int i;
4302 	uint16_t offset;
4303 
4304 	for (i = 0; i < 10; i++) {
4305 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4306 		    BWN_DMA32_TXSTATUS;
4307 		value = BWN_READ_4(mac, base + offset);
4308 		if (type == BWN_DMA_64BIT) {
4309 			value &= BWN_DMA64_TXSTAT;
4310 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4311 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4312 			    value == BWN_DMA64_TXSTAT_STOPPED)
4313 				break;
4314 		} else {
4315 			value &= BWN_DMA32_TXSTATE;
4316 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4317 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4318 			    value == BWN_DMA32_TXSTAT_STOPPED)
4319 				break;
4320 		}
4321 		DELAY(1000);
4322 	}
4323 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4324 	BWN_WRITE_4(mac, base + offset, 0);
4325 	for (i = 0; i < 10; i++) {
4326 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4327 						   BWN_DMA32_TXSTATUS;
4328 		value = BWN_READ_4(mac, base + offset);
4329 		if (type == BWN_DMA_64BIT) {
4330 			value &= BWN_DMA64_TXSTAT;
4331 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4332 				i = -1;
4333 				break;
4334 			}
4335 		} else {
4336 			value &= BWN_DMA32_TXSTATE;
4337 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4338 				i = -1;
4339 				break;
4340 			}
4341 		}
4342 		DELAY(1000);
4343 	}
4344 	if (i != -1) {
4345 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4346 		return (ENODEV);
4347 	}
4348 	DELAY(1000);
4349 
4350 	return (0);
4351 }
4352 
4353 static int
4354 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4355     int type)
4356 {
4357 	struct bwn_softc *sc = mac->mac_sc;
4358 	uint32_t value;
4359 	int i;
4360 	uint16_t offset;
4361 
4362 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4363 	BWN_WRITE_4(mac, base + offset, 0);
4364 	for (i = 0; i < 10; i++) {
4365 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4366 		    BWN_DMA32_RXSTATUS;
4367 		value = BWN_READ_4(mac, base + offset);
4368 		if (type == BWN_DMA_64BIT) {
4369 			value &= BWN_DMA64_RXSTAT;
4370 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4371 				i = -1;
4372 				break;
4373 			}
4374 		} else {
4375 			value &= BWN_DMA32_RXSTATE;
4376 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4377 				i = -1;
4378 				break;
4379 			}
4380 		}
4381 		DELAY(1000);
4382 	}
4383 	if (i != -1) {
4384 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4385 		return (ENODEV);
4386 	}
4387 
4388 	return (0);
4389 }
4390 
4391 static void
4392 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4393     struct bwn_dmadesc_meta *meta)
4394 {
4395 
4396 	if (meta->mt_m != NULL) {
4397 		m_freem(meta->mt_m);
4398 		meta->mt_m = NULL;
4399 	}
4400 	if (meta->mt_ni != NULL) {
4401 		ieee80211_free_node(meta->mt_ni);
4402 		meta->mt_ni = NULL;
4403 	}
4404 }
4405 
4406 static void
4407 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4408 {
4409 	struct bwn_rxhdr4 *rxhdr;
4410 	unsigned char *frame;
4411 
4412 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4413 	rxhdr->frame_len = 0;
4414 
4415 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4416 	    sizeof(struct bwn_plcp6) + 2,
4417 	    ("%s:%d: fail", __func__, __LINE__));
4418 	frame = mtod(m, char *) + dr->dr_frameoffset;
4419 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4420 }
4421 
4422 static uint8_t
4423 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4424 {
4425 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4426 
4427 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4428 	    == 0xff);
4429 }
4430 
4431 static void
4432 bwn_wme_init(struct bwn_mac *mac)
4433 {
4434 
4435 	bwn_wme_load(mac);
4436 
4437 	/* enable WME support. */
4438 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4439 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4440 	    BWN_IFSCTL_USE_EDCF);
4441 }
4442 
4443 static void
4444 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4445 {
4446 	struct bwn_softc *sc = mac->mac_sc;
4447 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4448 	uint16_t delay;	/* microsec */
4449 
4450 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4451 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4452 		delay = 500;
4453 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4454 		delay = max(delay, (uint16_t)2400);
4455 
4456 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4457 }
4458 
4459 static void
4460 bwn_bt_enable(struct bwn_mac *mac)
4461 {
4462 	struct bwn_softc *sc = mac->mac_sc;
4463 	uint64_t hf;
4464 
4465 	if (bwn_bluetooth == 0)
4466 		return;
4467 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4468 		return;
4469 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4470 		return;
4471 
4472 	hf = bwn_hf_read(mac);
4473 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4474 		hf |= BWN_HF_BT_COEXISTALT;
4475 	else
4476 		hf |= BWN_HF_BT_COEXIST;
4477 	bwn_hf_write(mac, hf);
4478 }
4479 
4480 static void
4481 bwn_set_macaddr(struct bwn_mac *mac)
4482 {
4483 
4484 	bwn_mac_write_bssid(mac);
4485 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4486 }
4487 
4488 static void
4489 bwn_clear_keys(struct bwn_mac *mac)
4490 {
4491 	int i;
4492 
4493 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4494 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4495 		    ("%s:%d: fail", __func__, __LINE__));
4496 
4497 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4498 		    NULL, BWN_SEC_KEYSIZE, NULL);
4499 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4500 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4501 			    NULL, BWN_SEC_KEYSIZE, NULL);
4502 		}
4503 		mac->mac_key[i].keyconf = NULL;
4504 	}
4505 }
4506 
4507 static void
4508 bwn_crypt_init(struct bwn_mac *mac)
4509 {
4510 	struct bwn_softc *sc = mac->mac_sc;
4511 
4512 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4513 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4514 	    ("%s:%d: fail", __func__, __LINE__));
4515 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4516 	mac->mac_ktp *= 2;
4517 	if (siba_get_revid(sc->sc_dev) >= 5)
4518 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4519 	bwn_clear_keys(mac);
4520 }
4521 
4522 static void
4523 bwn_chip_exit(struct bwn_mac *mac)
4524 {
4525 	struct bwn_softc *sc = mac->mac_sc;
4526 
4527 	bwn_phy_exit(mac);
4528 	siba_gpio_set(sc->sc_dev, 0);
4529 }
4530 
4531 static int
4532 bwn_fw_fillinfo(struct bwn_mac *mac)
4533 {
4534 	int error;
4535 
4536 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4537 	if (error == 0)
4538 		return (0);
4539 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4540 	if (error == 0)
4541 		return (0);
4542 	return (error);
4543 }
4544 
4545 static int
4546 bwn_gpio_init(struct bwn_mac *mac)
4547 {
4548 	struct bwn_softc *sc = mac->mac_sc;
4549 	uint32_t mask = 0x1f, set = 0xf, value;
4550 
4551 	BWN_WRITE_4(mac, BWN_MACCTL,
4552 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4553 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4554 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4555 
4556 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4557 		mask |= 0x0060;
4558 		set |= 0x0060;
4559 	}
4560 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4561 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4562 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4563 		mask |= 0x0200;
4564 		set |= 0x0200;
4565 	}
4566 	if (siba_get_revid(sc->sc_dev) >= 2)
4567 		mask |= 0x0010;
4568 
4569 	value = siba_gpio_get(sc->sc_dev);
4570 	if (value == -1)
4571 		return (0);
4572 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4573 
4574 	return (0);
4575 }
4576 
4577 static int
4578 bwn_fw_loadinitvals(struct bwn_mac *mac)
4579 {
4580 #define	GETFWOFFSET(fwp, offset)				\
4581 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4582 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4583 	const struct bwn_fwhdr *hdr;
4584 	struct bwn_fw *fw = &mac->mac_fw;
4585 	int error;
4586 
4587 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4588 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4589 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4590 	if (error)
4591 		return (error);
4592 	if (fw->initvals_band.fw) {
4593 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4594 		error = bwn_fwinitvals_write(mac,
4595 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4596 		    be32toh(hdr->size),
4597 		    fw->initvals_band.fw->datasize - hdr_len);
4598 	}
4599 	return (error);
4600 #undef GETFWOFFSET
4601 }
4602 
4603 static int
4604 bwn_phy_init(struct bwn_mac *mac)
4605 {
4606 	struct bwn_softc *sc = mac->mac_sc;
4607 	int error;
4608 
4609 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4610 	mac->mac_phy.rf_onoff(mac, 1);
4611 	error = mac->mac_phy.init(mac);
4612 	if (error) {
4613 		device_printf(sc->sc_dev, "PHY init failed\n");
4614 		goto fail0;
4615 	}
4616 	error = bwn_switch_channel(mac,
4617 	    mac->mac_phy.get_default_chan(mac));
4618 	if (error) {
4619 		device_printf(sc->sc_dev,
4620 		    "failed to switch default channel\n");
4621 		goto fail1;
4622 	}
4623 	return (0);
4624 fail1:
4625 	if (mac->mac_phy.exit)
4626 		mac->mac_phy.exit(mac);
4627 fail0:
4628 	mac->mac_phy.rf_onoff(mac, 0);
4629 
4630 	return (error);
4631 }
4632 
4633 static void
4634 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4635 {
4636 	uint16_t ant;
4637 	uint16_t tmp;
4638 
4639 	ant = bwn_ant2phy(antenna);
4640 
4641 	/* For ACK/CTS */
4642 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4643 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4645 	/* For Probe Resposes */
4646 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4647 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4648 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4649 }
4650 
4651 static void
4652 bwn_set_opmode(struct bwn_mac *mac)
4653 {
4654 	struct bwn_softc *sc = mac->mac_sc;
4655 	struct ifnet *ifp = sc->sc_ifp;
4656 	struct ieee80211com *ic = ifp->if_l2com;
4657 	uint32_t ctl;
4658 	uint16_t cfp_pretbtt;
4659 
4660 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4661 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4662 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4663 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4664 	ctl |= BWN_MACCTL_STA;
4665 
4666 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4667 	    ic->ic_opmode == IEEE80211_M_MBSS)
4668 		ctl |= BWN_MACCTL_HOSTAP;
4669 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4670 		ctl &= ~BWN_MACCTL_STA;
4671 	ctl |= sc->sc_filters;
4672 
4673 	if (siba_get_revid(sc->sc_dev) <= 4)
4674 		ctl |= BWN_MACCTL_PROMISC;
4675 
4676 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4677 
4678 	cfp_pretbtt = 2;
4679 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4680 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4681 		    siba_get_chiprev(sc->sc_dev) == 3)
4682 			cfp_pretbtt = 100;
4683 		else
4684 			cfp_pretbtt = 50;
4685 	}
4686 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4687 }
4688 
4689 static int
4690 bwn_dma_gettype(struct bwn_mac *mac)
4691 {
4692 	uint32_t tmp;
4693 	uint16_t base;
4694 
4695 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4696 	if (tmp & SIBA_TGSHIGH_DMA64)
4697 		return (BWN_DMA_64BIT);
4698 	base = bwn_dma_base(0, 0);
4699 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4700 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4701 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4702 		return (BWN_DMA_32BIT);
4703 
4704 	return (BWN_DMA_30BIT);
4705 }
4706 
4707 static void
4708 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4709 {
4710 	if (!error) {
4711 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4712 		*((bus_addr_t *)arg) = seg->ds_addr;
4713 	}
4714 }
4715 
4716 static void
4717 bwn_phy_g_init_sub(struct bwn_mac *mac)
4718 {
4719 	struct bwn_phy *phy = &mac->mac_phy;
4720 	struct bwn_phy_g *pg = &phy->phy_g;
4721 	struct bwn_softc *sc = mac->mac_sc;
4722 	uint16_t i, tmp;
4723 
4724 	if (phy->rev == 1)
4725 		bwn_phy_init_b5(mac);
4726 	else
4727 		bwn_phy_init_b6(mac);
4728 
4729 	if (phy->rev >= 2 || phy->gmode)
4730 		bwn_phy_init_a(mac);
4731 
4732 	if (phy->rev >= 2) {
4733 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4734 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4735 	}
4736 	if (phy->rev == 2) {
4737 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4738 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739 	}
4740 	if (phy->rev > 5) {
4741 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4742 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4743 	}
4744 	if (phy->gmode || phy->rev >= 2) {
4745 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4746 		tmp &= BWN_PHYVER_VERSION;
4747 		if (tmp == 3 || tmp == 5) {
4748 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4749 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4750 		}
4751 		if (tmp == 5) {
4752 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4753 			    0x1f00);
4754 		}
4755 	}
4756 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4757 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4758 	if (phy->rf_rev == 8) {
4759 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4760 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4761 	}
4762 	if (BWN_HAS_LOOPBACK(phy))
4763 		bwn_loopback_calcgain(mac);
4764 
4765 	if (phy->rf_rev != 8) {
4766 		if (pg->pg_initval == 0xffff)
4767 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4768 		else
4769 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4770 	}
4771 	bwn_lo_g_init(mac);
4772 	if (BWN_HAS_TXMAG(phy)) {
4773 		BWN_RF_WRITE(mac, 0x52,
4774 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4775 		    | pg->pg_loctl.tx_bias |
4776 		    pg->pg_loctl.tx_magn);
4777 	} else {
4778 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4779 	}
4780 	if (phy->rev >= 6) {
4781 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4782 		    (pg->pg_loctl.tx_bias << 12));
4783 	}
4784 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4785 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4786 	else
4787 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4788 	if (phy->rev < 2)
4789 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4790 	else
4791 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4792 	if (phy->gmode || phy->rev >= 2) {
4793 		bwn_lo_g_adjust(mac);
4794 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4795 	}
4796 
4797 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4798 		for (i = 0; i < 64; i++) {
4799 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4800 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4801 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4802 			    -32), 31));
4803 		}
4804 		bwn_nrssi_threshold(mac);
4805 	} else if (phy->gmode || phy->rev >= 2) {
4806 		if (pg->pg_nrssi[0] == -1000) {
4807 			KASSERT(pg->pg_nrssi[1] == -1000,
4808 			    ("%s:%d: fail", __func__, __LINE__));
4809 			bwn_nrssi_slope_11g(mac);
4810 		} else
4811 			bwn_nrssi_threshold(mac);
4812 	}
4813 	if (phy->rf_rev == 8)
4814 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4815 	bwn_phy_hwpctl_init(mac);
4816 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4817 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4818 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4819 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4820 	}
4821 }
4822 
4823 static uint8_t
4824 bwn_has_hwpctl(struct bwn_mac *mac)
4825 {
4826 
4827 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4828 		return (0);
4829 	return (mac->mac_phy.use_hwpctl(mac));
4830 }
4831 
4832 static void
4833 bwn_phy_init_b5(struct bwn_mac *mac)
4834 {
4835 	struct bwn_phy *phy = &mac->mac_phy;
4836 	struct bwn_phy_g *pg = &phy->phy_g;
4837 	struct bwn_softc *sc = mac->mac_sc;
4838 	uint16_t offset, value;
4839 	uint8_t old_channel;
4840 
4841 	if (phy->analog == 1)
4842 		BWN_RF_SET(mac, 0x007a, 0x0050);
4843 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4844 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4845 		value = 0x2120;
4846 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4847 			BWN_PHY_WRITE(mac, offset, value);
4848 			value += 0x202;
4849 		}
4850 	}
4851 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4852 	if (phy->rf_ver == 0x2050)
4853 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4854 
4855 	if (phy->gmode || phy->rev >= 2) {
4856 		if (phy->rf_ver == 0x2050) {
4857 			BWN_RF_SET(mac, 0x007a, 0x0020);
4858 			BWN_RF_SET(mac, 0x0051, 0x0004);
4859 		}
4860 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4861 
4862 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4863 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4864 
4865 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4866 
4867 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4868 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4869 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4870 	}
4871 
4872 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4873 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4874 
4875 	if (phy->analog == 1) {
4876 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4877 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4878 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4879 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4880 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4881 	} else
4882 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4883 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4884 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4885 
4886 	if (phy->analog == 1)
4887 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4888 	else
4889 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4890 
4891 	if (phy->analog == 0)
4892 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4893 
4894 	old_channel = phy->chan;
4895 	bwn_phy_g_switch_chan(mac, 7, 0);
4896 
4897 	if (phy->rf_ver != 0x2050) {
4898 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4899 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4900 	}
4901 
4902 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4904 
4905 	if (phy->rf_ver == 0x2050) {
4906 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4907 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4908 	}
4909 
4910 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4911 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4912 	BWN_RF_SET(mac, 0x007a, 0x0007);
4913 
4914 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4915 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4916 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4917 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4918 
4919 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4920 	    pg->pg_txctl);
4921 
4922 	if (phy->rf_ver == 0x2050)
4923 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4924 
4925 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4926 }
4927 
4928 static void
4929 bwn_loopback_calcgain(struct bwn_mac *mac)
4930 {
4931 	struct bwn_phy *phy = &mac->mac_phy;
4932 	struct bwn_phy_g *pg = &phy->phy_g;
4933 	struct bwn_softc *sc = mac->mac_sc;
4934 	uint16_t backup_phy[16] = { 0 };
4935 	uint16_t backup_radio[3];
4936 	uint16_t backup_bband;
4937 	uint16_t i, j, loop_i_max;
4938 	uint16_t trsw_rx;
4939 	uint16_t loop1_outer_done, loop1_inner_done;
4940 
4941 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4942 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4943 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4944 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4945 	if (phy->rev != 1) {
4946 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4947 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4948 	}
4949 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4950 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4951 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4952 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4953 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4954 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4955 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4956 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4957 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4958 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4959 	backup_bband = pg->pg_bbatt.att;
4960 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4961 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4962 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4963 
4964 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4965 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4966 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4967 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4968 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4969 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4970 	if (phy->rev != 1) {
4971 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4972 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4973 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4974 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4975 	}
4976 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4977 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4978 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4979 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4980 
4981 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4982 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4983 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4984 
4985 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4986 	if (phy->rev != 1) {
4987 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4988 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4989 	}
4990 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4991 
4992 	if (phy->rf_rev == 8)
4993 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4994 	else {
4995 		BWN_RF_WRITE(mac, 0x52, 0);
4996 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4997 	}
4998 	bwn_phy_g_set_bbatt(mac, 11);
4999 
5000 	if (phy->rev >= 3)
5001 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5002 	else
5003 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5004 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5005 
5006 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5007 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5008 
5009 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5010 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5011 
5012 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5013 		if (phy->rev >= 7) {
5014 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5015 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5016 		}
5017 	}
5018 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5019 
5020 	j = 0;
5021 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5022 	for (i = 0; i < loop_i_max; i++) {
5023 		for (j = 0; j < 16; j++) {
5024 			BWN_RF_WRITE(mac, 0x43, i);
5025 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5026 			    (j << 8));
5027 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5028 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5029 			DELAY(20);
5030 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5031 				goto done0;
5032 		}
5033 	}
5034 done0:
5035 	loop1_outer_done = i;
5036 	loop1_inner_done = j;
5037 	if (j >= 8) {
5038 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5039 		trsw_rx = 0x1b;
5040 		for (j = j - 8; j < 16; j++) {
5041 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5042 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5043 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5044 			DELAY(20);
5045 			trsw_rx -= 3;
5046 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5047 				goto done1;
5048 		}
5049 	} else
5050 		trsw_rx = 0x18;
5051 done1:
5052 
5053 	if (phy->rev != 1) {
5054 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5055 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5056 	}
5057 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5058 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5059 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5060 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5061 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5062 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5063 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5064 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5065 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5066 
5067 	bwn_phy_g_set_bbatt(mac, backup_bband);
5068 
5069 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5070 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5071 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5072 
5073 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5074 	DELAY(10);
5075 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5076 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5077 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5078 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5079 
5080 	pg->pg_max_lb_gain =
5081 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5082 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5083 }
5084 
5085 static uint16_t
5086 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5087 {
5088 	struct bwn_phy *phy = &mac->mac_phy;
5089 	uint32_t tmp1 = 0, tmp2 = 0;
5090 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5091 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5092 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5093 	static const uint8_t rcc_table[] = {
5094 		0x02, 0x03, 0x01, 0x0f,
5095 		0x06, 0x07, 0x05, 0x0f,
5096 		0x0a, 0x0b, 0x09, 0x0f,
5097 		0x0e, 0x0f, 0x0d, 0x0f,
5098 	};
5099 
5100 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5101 	    rfoverval = rfover = cck3 = 0;
5102 	radio0 = BWN_RF_READ(mac, 0x43);
5103 	radio1 = BWN_RF_READ(mac, 0x51);
5104 	radio2 = BWN_RF_READ(mac, 0x52);
5105 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5106 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5107 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5108 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5109 
5110 	if (phy->type == BWN_PHYTYPE_B) {
5111 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5112 		reg0 = BWN_READ_2(mac, 0x3ec);
5113 
5114 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5115 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5116 	} else if (phy->gmode || phy->rev >= 2) {
5117 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5118 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5119 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5120 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5121 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5122 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5123 
5124 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5125 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5126 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5127 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5128 		if (BWN_HAS_LOOPBACK(phy)) {
5129 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5130 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5131 			if (phy->rev >= 3)
5132 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5133 			else
5134 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5135 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5136 		}
5137 
5138 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5139 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5140 			BWN_LPD(0, 1, 1)));
5141 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5142 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5143 	}
5144 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5145 
5146 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5147 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5148 	reg1 = BWN_READ_2(mac, 0x3e6);
5149 	reg2 = BWN_READ_2(mac, 0x3f4);
5150 
5151 	if (phy->analog == 0)
5152 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5153 	else {
5154 		if (phy->analog >= 2)
5155 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5156 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5157 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5158 	}
5159 
5160 	reg = BWN_RF_READ(mac, 0x60);
5161 	index = (reg & 0x001e) >> 1;
5162 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5163 
5164 	if (phy->type == BWN_PHYTYPE_B)
5165 		BWN_RF_WRITE(mac, 0x78, 0x26);
5166 	if (phy->gmode || phy->rev >= 2) {
5167 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5168 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5169 			BWN_LPD(0, 1, 1)));
5170 	}
5171 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5172 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5173 	if (phy->gmode || phy->rev >= 2) {
5174 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5175 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5176 			BWN_LPD(0, 0, 1)));
5177 	}
5178 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5179 	BWN_RF_SET(mac, 0x51, 0x0004);
5180 	if (phy->rf_rev == 8)
5181 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5182 	else {
5183 		BWN_RF_WRITE(mac, 0x52, 0);
5184 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5185 	}
5186 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5187 
5188 	for (i = 0; i < 16; i++) {
5189 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5190 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5191 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5192 		if (phy->gmode || phy->rev >= 2) {
5193 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5194 			    bwn_rf_2050_rfoverval(mac,
5195 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5196 		}
5197 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5198 		DELAY(10);
5199 		if (phy->gmode || phy->rev >= 2) {
5200 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5201 			    bwn_rf_2050_rfoverval(mac,
5202 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5203 		}
5204 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5205 		DELAY(10);
5206 		if (phy->gmode || phy->rev >= 2) {
5207 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5208 			    bwn_rf_2050_rfoverval(mac,
5209 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5210 		}
5211 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5212 		DELAY(20);
5213 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5214 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5215 		if (phy->gmode || phy->rev >= 2) {
5216 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5217 			    bwn_rf_2050_rfoverval(mac,
5218 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5219 		}
5220 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5221 	}
5222 	DELAY(10);
5223 
5224 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5225 	tmp1++;
5226 	tmp1 >>= 9;
5227 
5228 	for (i = 0; i < 16; i++) {
5229 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5230 		BWN_RF_WRITE(mac, 0x78, radio78);
5231 		DELAY(10);
5232 		for (j = 0; j < 16; j++) {
5233 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5234 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5235 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5236 			if (phy->gmode || phy->rev >= 2) {
5237 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238 				    bwn_rf_2050_rfoverval(mac,
5239 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5240 			}
5241 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5242 			DELAY(10);
5243 			if (phy->gmode || phy->rev >= 2) {
5244 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245 				    bwn_rf_2050_rfoverval(mac,
5246 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5247 			}
5248 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5249 			DELAY(10);
5250 			if (phy->gmode || phy->rev >= 2) {
5251 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5252 				    bwn_rf_2050_rfoverval(mac,
5253 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5254 			}
5255 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5256 			DELAY(10);
5257 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5258 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5259 			if (phy->gmode || phy->rev >= 2) {
5260 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5261 				    bwn_rf_2050_rfoverval(mac,
5262 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5263 			}
5264 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5265 		}
5266 		tmp2++;
5267 		tmp2 >>= 8;
5268 		if (tmp1 < tmp2)
5269 			break;
5270 	}
5271 
5272 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5273 	BWN_RF_WRITE(mac, 0x51, radio1);
5274 	BWN_RF_WRITE(mac, 0x52, radio2);
5275 	BWN_RF_WRITE(mac, 0x43, radio0);
5276 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5277 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5278 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5279 	BWN_WRITE_2(mac, 0x3e6, reg1);
5280 	if (phy->analog != 0)
5281 		BWN_WRITE_2(mac, 0x3f4, reg2);
5282 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5283 	bwn_spu_workaround(mac, phy->chan);
5284 	if (phy->type == BWN_PHYTYPE_B) {
5285 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5286 		BWN_WRITE_2(mac, 0x3ec, reg0);
5287 	} else if (phy->gmode) {
5288 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5289 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5290 			    & 0x7fff);
5291 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5292 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5293 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5294 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5295 			      analogoverval);
5296 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5297 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5298 		if (BWN_HAS_LOOPBACK(phy)) {
5299 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5300 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5301 		}
5302 	}
5303 
5304 	return ((i > 15) ? radio78 : rcc);
5305 }
5306 
5307 static void
5308 bwn_phy_init_b6(struct bwn_mac *mac)
5309 {
5310 	struct bwn_phy *phy = &mac->mac_phy;
5311 	struct bwn_phy_g *pg = &phy->phy_g;
5312 	struct bwn_softc *sc = mac->mac_sc;
5313 	uint16_t offset, val;
5314 	uint8_t old_channel;
5315 
5316 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5317 	    ("%s:%d: fail", __func__, __LINE__));
5318 
5319 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5320 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5321 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5322 		BWN_RF_WRITE(mac, 0x51, 0x37);
5323 		BWN_RF_WRITE(mac, 0x52, 0x70);
5324 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5325 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5326 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5327 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5328 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5329 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5330 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5331 		bwn_hf_write(mac,
5332 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5333 	}
5334 	if (phy->rf_rev == 8) {
5335 		BWN_RF_WRITE(mac, 0x51, 0);
5336 		BWN_RF_WRITE(mac, 0x52, 0x40);
5337 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5338 		BWN_RF_WRITE(mac, 0x54, 0x98);
5339 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5340 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5341 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5342 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5343 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5344 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5345 		} else {
5346 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5347 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5348 		}
5349 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5350 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5351 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5352 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5353 	}
5354 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5355 		BWN_PHY_WRITE(mac, offset, val);
5356 		val -= 0x0202;
5357 	}
5358 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5359 		BWN_PHY_WRITE(mac, offset, val);
5360 		val -= 0x0202;
5361 	}
5362 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5363 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5364 		val += 0x0202;
5365 	}
5366 	if (phy->type == BWN_PHYTYPE_G) {
5367 		BWN_RF_SET(mac, 0x007a, 0x0020);
5368 		BWN_RF_SET(mac, 0x0051, 0x0004);
5369 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5370 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5371 		BWN_PHY_WRITE(mac, 0x5b, 0);
5372 		BWN_PHY_WRITE(mac, 0x5c, 0);
5373 	}
5374 
5375 	old_channel = phy->chan;
5376 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5377 
5378 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5379 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5380 	DELAY(40);
5381 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5382 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5383 		BWN_RF_WRITE(mac, 0x50, 0x20);
5384 	}
5385 	if (phy->rf_rev <= 2) {
5386 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5387 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5388 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5389 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5390 	}
5391 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5392 
5393 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5394 
5395 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5396 	if (phy->rf_rev >= 6)
5397 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5398 	else
5399 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5400 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5401 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5402 	    pg->pg_txctl);
5403 	if (phy->rf_rev <= 5)
5404 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5405 	if (phy->rf_rev <= 2)
5406 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5407 
5408 	if (phy->analog == 4) {
5409 		BWN_WRITE_2(mac, 0x3e4, 9);
5410 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5411 	} else
5412 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5413 	if (phy->type == BWN_PHYTYPE_B)
5414 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5415 	else if (phy->type == BWN_PHYTYPE_G)
5416 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5417 }
5418 
5419 static void
5420 bwn_phy_init_a(struct bwn_mac *mac)
5421 {
5422 	struct bwn_phy *phy = &mac->mac_phy;
5423 	struct bwn_softc *sc = mac->mac_sc;
5424 
5425 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5426 	    ("%s:%d: fail", __func__, __LINE__));
5427 
5428 	if (phy->rev >= 6) {
5429 		if (phy->type == BWN_PHYTYPE_A)
5430 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5431 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5432 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5433 		else
5434 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5435 	}
5436 
5437 	bwn_wa_init(mac);
5438 
5439 	if (phy->type == BWN_PHYTYPE_G &&
5440 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5441 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5442 }
5443 
5444 static void
5445 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5446 {
5447 	int i;
5448 
5449 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5450 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5451 }
5452 
5453 static void
5454 bwn_wa_agc(struct bwn_mac *mac)
5455 {
5456 	struct bwn_phy *phy = &mac->mac_phy;
5457 
5458 	if (phy->rev == 1) {
5459 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5460 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5461 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5462 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5463 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5464 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5465 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5466 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5467 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5468 	} else {
5469 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5470 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5471 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5472 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5473 	}
5474 
5475 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5476 	    0x5700);
5477 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5478 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5479 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5480 	BWN_RF_SET(mac, 0x7a, 0x0008);
5481 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5482 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5483 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5484 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5485 	if (phy->rev == 1)
5486 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5487 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5488 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5489 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5490 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5491 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5492 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5493 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5494 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5495 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5496 	if (phy->rev == 1) {
5497 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5498 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5499 	} else {
5500 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5501 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5502 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5503 		if (phy->rev >= 6) {
5504 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5505 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5506 			    (uint16_t)~0xf000, 0x3000);
5507 		}
5508 	}
5509 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5510 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5511 	if (phy->rev == 1) {
5512 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5513 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5514 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5515 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5516 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5517 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5518 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5519 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5520 	} else {
5521 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5522 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5523 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5524 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5525 	}
5526 	if (phy->rev >= 6) {
5527 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5528 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5529 	}
5530 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5531 }
5532 
5533 static void
5534 bwn_wa_grev1(struct bwn_mac *mac)
5535 {
5536 	struct bwn_phy *phy = &mac->mac_phy;
5537 	int i;
5538 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5539 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5540 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5541 
5542 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5543 
5544 	/* init CRSTHRES and ANTDWELL */
5545 	if (phy->rev == 1) {
5546 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5547 	} else if (phy->rev == 2) {
5548 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5549 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5550 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5551 	} else {
5552 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5553 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5554 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5555 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5556 	}
5557 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5558 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5559 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5560 
5561 	/* XXX support PHY-A??? */
5562 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5563 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5564 		    bwn_tab_finefreqg[i]);
5565 
5566 	/* XXX support PHY-A??? */
5567 	if (phy->rev == 1)
5568 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5569 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570 			    bwn_tab_noise_g1[i]);
5571 	else
5572 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5573 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5574 			    bwn_tab_noise_g2[i]);
5575 
5576 
5577 	for (i = 0; i < N(bwn_tab_rotor); i++)
5578 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5579 		    bwn_tab_rotor[i]);
5580 
5581 	/* XXX support PHY-A??? */
5582 	if (phy->rev >= 6) {
5583 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5584 		    BWN_PHY_ENCORE_EN)
5585 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5586 		else
5587 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5588 	} else
5589 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5590 
5591 	for (i = 0; i < N(bwn_tab_retard); i++)
5592 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5593 		    bwn_tab_retard[i]);
5594 
5595 	if (phy->rev == 1) {
5596 		for (i = 0; i < 16; i++)
5597 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5598 			    i, 0x0020);
5599 	} else {
5600 		for (i = 0; i < 32; i++)
5601 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5602 	}
5603 
5604 	bwn_wa_agc(mac);
5605 }
5606 
5607 static void
5608 bwn_wa_grev26789(struct bwn_mac *mac)
5609 {
5610 	struct bwn_phy *phy = &mac->mac_phy;
5611 	int i;
5612 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5613 	uint16_t ofdmrev;
5614 
5615 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5616 
5617 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5618 
5619 	/* init CRSTHRES and ANTDWELL */
5620 	if (phy->rev == 1)
5621 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5622 	else if (phy->rev == 2) {
5623 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5624 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5625 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5626 	} else {
5627 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5628 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5629 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5630 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5631 	}
5632 
5633 	for (i = 0; i < 64; i++)
5634 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5635 
5636 	/* XXX support PHY-A??? */
5637 	if (phy->rev == 1)
5638 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5639 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640 			    bwn_tab_noise_g1[i]);
5641 	else
5642 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5643 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5644 			    bwn_tab_noise_g2[i]);
5645 
5646 	/* XXX support PHY-A??? */
5647 	if (phy->rev >= 6) {
5648 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5649 		    BWN_PHY_ENCORE_EN)
5650 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5651 		else
5652 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5653 	} else
5654 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5655 
5656 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5657 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5658 		    bwn_tab_sigmasqr2[i]);
5659 
5660 	if (phy->rev == 1) {
5661 		for (i = 0; i < 16; i++)
5662 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5663 			    0x0020);
5664 	} else {
5665 		for (i = 0; i < 32; i++)
5666 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5667 	}
5668 
5669 	bwn_wa_agc(mac);
5670 
5671 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5672 	if (ofdmrev > 2) {
5673 		if (phy->type == BWN_PHYTYPE_A)
5674 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5675 		else
5676 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5677 	} else {
5678 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5679 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5680 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5681 	}
5682 
5683 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5684 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5685 }
5686 
5687 static void
5688 bwn_wa_init(struct bwn_mac *mac)
5689 {
5690 	struct bwn_phy *phy = &mac->mac_phy;
5691 	struct bwn_softc *sc = mac->mac_sc;
5692 
5693 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5694 
5695 	switch (phy->rev) {
5696 	case 1:
5697 		bwn_wa_grev1(mac);
5698 		break;
5699 	case 2:
5700 	case 6:
5701 	case 7:
5702 	case 8:
5703 	case 9:
5704 		bwn_wa_grev26789(mac);
5705 		break;
5706 	default:
5707 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5708 	}
5709 
5710 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5711 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5712 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5713 		if (phy->rev < 2) {
5714 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5715 			    0x0002);
5716 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5717 			    0x0001);
5718 		} else {
5719 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5720 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5721 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5722 			     BWN_BFL_EXTLNA) &&
5723 			    (phy->rev >= 7)) {
5724 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5725 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726 				    0x0020, 0x0001);
5727 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728 				    0x0021, 0x0001);
5729 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730 				    0x0022, 0x0001);
5731 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732 				    0x0023, 0x0000);
5733 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5734 				    0x0000, 0x0000);
5735 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5736 				    0x0003, 0x0002);
5737 			}
5738 		}
5739 	}
5740 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5741 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5742 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5743 	}
5744 
5745 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5746 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5747 }
5748 
5749 static void
5750 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5751     uint16_t value)
5752 {
5753 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5754 	uint16_t addr;
5755 
5756 	addr = table + offset;
5757 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5758 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5759 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5760 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5761 	}
5762 	pg->pg_ofdmtab_addr = addr;
5763 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5764 }
5765 
5766 static void
5767 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5768     uint32_t value)
5769 {
5770 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5771 	uint16_t addr;
5772 
5773 	addr = table + offset;
5774 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5775 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5776 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5777 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5778 	}
5779 	pg->pg_ofdmtab_addr = addr;
5780 
5781 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5782 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5783 }
5784 
5785 static void
5786 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5787     uint16_t value)
5788 {
5789 
5790 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5791 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5792 }
5793 
5794 static void
5795 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5796 {
5797 	struct bwn_phy *phy = &mac->mac_phy;
5798 	struct bwn_softc *sc = mac->mac_sc;
5799 	unsigned int i, max_loop;
5800 	uint16_t value;
5801 	uint32_t buffer[5] = {
5802 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5803 	};
5804 
5805 	if (ofdm) {
5806 		max_loop = 0x1e;
5807 		buffer[0] = 0x000201cc;
5808 	} else {
5809 		max_loop = 0xfa;
5810 		buffer[0] = 0x000b846e;
5811 	}
5812 
5813 	BWN_ASSERT_LOCKED(mac->mac_sc);
5814 
5815 	for (i = 0; i < 5; i++)
5816 		bwn_ram_write(mac, i * 4, buffer[i]);
5817 
5818 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5819 	BWN_WRITE_2(mac, 0x07c0,
5820 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5821 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5822 	BWN_WRITE_2(mac, 0x050c, value);
5823 	if (phy->type == BWN_PHYTYPE_LP)
5824 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5825 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5826 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5827 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5828 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5829 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5830 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5831 	if (phy->type == BWN_PHYTYPE_LP)
5832 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5833 	else
5834 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5835 
5836 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5837 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5838 	for (i = 0x00; i < max_loop; i++) {
5839 		value = BWN_READ_2(mac, 0x050e);
5840 		if (value & 0x0080)
5841 			break;
5842 		DELAY(10);
5843 	}
5844 	for (i = 0x00; i < 0x0a; i++) {
5845 		value = BWN_READ_2(mac, 0x050e);
5846 		if (value & 0x0400)
5847 			break;
5848 		DELAY(10);
5849 	}
5850 	for (i = 0x00; i < 0x19; i++) {
5851 		value = BWN_READ_2(mac, 0x0690);
5852 		if (!(value & 0x0100))
5853 			break;
5854 		DELAY(10);
5855 	}
5856 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5857 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5858 }
5859 
5860 static void
5861 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5862 {
5863 	uint32_t macctl;
5864 
5865 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5866 
5867 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5868 	if (macctl & BWN_MACCTL_BIGENDIAN)
5869 		printf("TODO: need swap\n");
5870 
5871 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5872 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5873 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5874 }
5875 
5876 static void
5877 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5878 {
5879 	uint16_t value;
5880 
5881 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5882 	    ("%s:%d: fail", __func__, __LINE__));
5883 
5884 	value = (uint8_t) (ctl->q);
5885 	value |= ((uint8_t) (ctl->i)) << 8;
5886 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5887 }
5888 
5889 static uint16_t
5890 bwn_lo_calcfeed(struct bwn_mac *mac,
5891     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5892 {
5893 	struct bwn_phy *phy = &mac->mac_phy;
5894 	struct bwn_softc *sc = mac->mac_sc;
5895 	uint16_t rfover;
5896 	uint16_t feedthrough;
5897 
5898 	if (phy->gmode) {
5899 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5900 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5901 
5902 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5903 		    ("%s:%d: fail", __func__, __LINE__));
5904 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5905 		    ("%s:%d: fail", __func__, __LINE__));
5906 
5907 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5908 
5909 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5910 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5911 		    phy->rev > 6)
5912 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5913 
5914 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5915 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5916 		DELAY(10);
5917 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5918 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5919 		DELAY(10);
5920 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5921 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5922 		DELAY(10);
5923 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5924 	} else {
5925 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5926 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5927 		DELAY(10);
5928 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5929 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5930 		DELAY(10);
5931 		pga |= BWN_PHY_PGACTL_LPF;
5932 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5933 	}
5934 	DELAY(21);
5935 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5936 
5937 	return (feedthrough);
5938 }
5939 
5940 static uint16_t
5941 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5942     uint16_t *value, uint16_t *pad_mix_gain)
5943 {
5944 	struct bwn_phy *phy = &mac->mac_phy;
5945 	uint16_t reg, v, padmix;
5946 
5947 	if (phy->type == BWN_PHYTYPE_B) {
5948 		v = 0x30;
5949 		if (phy->rf_rev <= 5) {
5950 			reg = 0x43;
5951 			padmix = 0;
5952 		} else {
5953 			reg = 0x52;
5954 			padmix = 5;
5955 		}
5956 	} else {
5957 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5958 			reg = 0x43;
5959 			v = 0x10;
5960 			padmix = 2;
5961 		} else {
5962 			reg = 0x52;
5963 			v = 0x30;
5964 			padmix = 5;
5965 		}
5966 	}
5967 	if (value)
5968 		*value = v;
5969 	if (pad_mix_gain)
5970 		*pad_mix_gain = padmix;
5971 
5972 	return (reg);
5973 }
5974 
5975 static void
5976 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5977 {
5978 	struct bwn_phy *phy = &mac->mac_phy;
5979 	struct bwn_phy_g *pg = &phy->phy_g;
5980 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5981 	uint16_t reg, mask;
5982 	uint16_t trsw_rx, pga;
5983 	uint16_t rf_pctl_reg;
5984 
5985 	static const uint8_t tx_bias_values[] = {
5986 		0x09, 0x08, 0x0a, 0x01, 0x00,
5987 		0x02, 0x05, 0x04, 0x06,
5988 	};
5989 	static const uint8_t tx_magn_values[] = {
5990 		0x70, 0x40,
5991 	};
5992 
5993 	if (!BWN_HAS_LOOPBACK(phy)) {
5994 		rf_pctl_reg = 6;
5995 		trsw_rx = 2;
5996 		pga = 0;
5997 	} else {
5998 		int lb_gain;
5999 
6000 		trsw_rx = 0;
6001 		lb_gain = pg->pg_max_lb_gain / 2;
6002 		if (lb_gain > 10) {
6003 			rf_pctl_reg = 0;
6004 			pga = abs(10 - lb_gain) / 6;
6005 			pga = MIN(MAX(pga, 0), 15);
6006 		} else {
6007 			int cmp_val;
6008 			int tmp;
6009 
6010 			pga = 0;
6011 			cmp_val = 0x24;
6012 			if ((phy->rev >= 2) &&
6013 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6014 				cmp_val = 0x3c;
6015 			tmp = lb_gain;
6016 			if ((10 - lb_gain) < cmp_val)
6017 				tmp = (10 - lb_gain);
6018 			if (tmp < 0)
6019 				tmp += 6;
6020 			else
6021 				tmp += 3;
6022 			cmp_val /= 4;
6023 			tmp /= 4;
6024 			if (tmp >= cmp_val)
6025 				rf_pctl_reg = cmp_val;
6026 			else
6027 				rf_pctl_reg = tmp;
6028 		}
6029 	}
6030 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6031 	bwn_phy_g_set_bbatt(mac, 2);
6032 
6033 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6034 	mask = ~mask;
6035 	BWN_RF_MASK(mac, reg, mask);
6036 
6037 	if (BWN_HAS_TXMAG(phy)) {
6038 		int i, j;
6039 		int feedthrough;
6040 		int min_feedth = 0xffff;
6041 		uint8_t tx_magn, tx_bias;
6042 
6043 		for (i = 0; i < N(tx_magn_values); i++) {
6044 			tx_magn = tx_magn_values[i];
6045 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6046 			for (j = 0; j < N(tx_bias_values); j++) {
6047 				tx_bias = tx_bias_values[j];
6048 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6049 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6050 				    trsw_rx);
6051 				if (feedthrough < min_feedth) {
6052 					lo->tx_bias = tx_bias;
6053 					lo->tx_magn = tx_magn;
6054 					min_feedth = feedthrough;
6055 				}
6056 				if (lo->tx_bias == 0)
6057 					break;
6058 			}
6059 			BWN_RF_WRITE(mac, 0x52,
6060 					  (BWN_RF_READ(mac, 0x52)
6061 					   & 0xff00) | lo->tx_bias | lo->
6062 					  tx_magn);
6063 		}
6064 	} else {
6065 		lo->tx_magn = 0;
6066 		lo->tx_bias = 0;
6067 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6068 	}
6069 
6070 	BWN_GETTIME(lo->txctl_measured_time);
6071 }
6072 
6073 static void
6074 bwn_lo_get_powervector(struct bwn_mac *mac)
6075 {
6076 	struct bwn_phy *phy = &mac->mac_phy;
6077 	struct bwn_phy_g *pg = &phy->phy_g;
6078 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6079 	int i;
6080 	uint64_t tmp;
6081 	uint64_t power_vector = 0;
6082 
6083 	for (i = 0; i < 8; i += 2) {
6084 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6085 		power_vector |= (tmp << (i * 8));
6086 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6087 	}
6088 	if (power_vector)
6089 		lo->power_vector = power_vector;
6090 
6091 	BWN_GETTIME(lo->pwr_vec_read_time);
6092 }
6093 
6094 static void
6095 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6096     int use_trsw_rx)
6097 {
6098 	struct bwn_phy *phy = &mac->mac_phy;
6099 	struct bwn_phy_g *pg = &phy->phy_g;
6100 	uint16_t tmp;
6101 
6102 	if (max_rx_gain < 0)
6103 		max_rx_gain = 0;
6104 
6105 	if (BWN_HAS_LOOPBACK(phy)) {
6106 		int trsw_rx = 0;
6107 		int trsw_rx_gain;
6108 
6109 		if (use_trsw_rx) {
6110 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6111 			if (max_rx_gain >= trsw_rx_gain) {
6112 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6113 				trsw_rx = 0x20;
6114 			}
6115 		} else
6116 			trsw_rx_gain = max_rx_gain;
6117 		if (trsw_rx_gain < 9) {
6118 			pg->pg_lna_lod_gain = 0;
6119 		} else {
6120 			pg->pg_lna_lod_gain = 1;
6121 			trsw_rx_gain -= 8;
6122 		}
6123 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6124 		pg->pg_pga_gain = trsw_rx_gain / 3;
6125 		if (pg->pg_pga_gain >= 5) {
6126 			pg->pg_pga_gain -= 5;
6127 			pg->pg_lna_gain = 2;
6128 		} else
6129 			pg->pg_lna_gain = 0;
6130 	} else {
6131 		pg->pg_lna_gain = 0;
6132 		pg->pg_trsw_rx_gain = 0x20;
6133 		if (max_rx_gain >= 0x14) {
6134 			pg->pg_lna_lod_gain = 1;
6135 			pg->pg_pga_gain = 2;
6136 		} else if (max_rx_gain >= 0x12) {
6137 			pg->pg_lna_lod_gain = 1;
6138 			pg->pg_pga_gain = 1;
6139 		} else if (max_rx_gain >= 0xf) {
6140 			pg->pg_lna_lod_gain = 1;
6141 			pg->pg_pga_gain = 0;
6142 		} else {
6143 			pg->pg_lna_lod_gain = 0;
6144 			pg->pg_pga_gain = 0;
6145 		}
6146 	}
6147 
6148 	tmp = BWN_RF_READ(mac, 0x7a);
6149 	if (pg->pg_lna_lod_gain == 0)
6150 		tmp &= ~0x0008;
6151 	else
6152 		tmp |= 0x0008;
6153 	BWN_RF_WRITE(mac, 0x7a, tmp);
6154 }
6155 
6156 static void
6157 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6158 {
6159 	struct bwn_phy *phy = &mac->mac_phy;
6160 	struct bwn_phy_g *pg = &phy->phy_g;
6161 	struct bwn_softc *sc = mac->mac_sc;
6162 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6163 	struct timespec ts;
6164 	uint16_t tmp;
6165 
6166 	if (bwn_has_hwpctl(mac)) {
6167 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6168 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6169 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6170 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6171 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6172 
6173 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6174 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6175 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6176 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6177 	}
6178 	if (phy->type == BWN_PHYTYPE_B &&
6179 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6180 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6181 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6182 	}
6183 	if (phy->rev >= 2) {
6184 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6185 		sav->phy_analogoverval =
6186 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6187 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6188 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6189 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6190 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6191 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6192 
6193 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6194 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6195 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6196 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6197 		if (phy->type == BWN_PHYTYPE_G) {
6198 			if ((phy->rev >= 7) &&
6199 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6200 			     BWN_BFL_EXTLNA)) {
6201 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6202 			} else {
6203 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6204 			}
6205 		} else {
6206 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6207 		}
6208 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6209 	}
6210 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6211 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6212 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6213 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6214 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6215 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6216 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6217 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6218 
6219 	if (!BWN_HAS_TXMAG(phy)) {
6220 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6221 		sav->rf2 &= 0x00f0;
6222 	}
6223 	if (phy->type == BWN_PHYTYPE_B) {
6224 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6225 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6226 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6227 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6228 	} else {
6229 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6230 			    | 0x8000);
6231 	}
6232 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6233 		    & 0xf000);
6234 
6235 	tmp =
6236 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6237 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6238 
6239 	tmp = sav->phy_syncctl;
6240 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6241 	tmp = sav->rf1;
6242 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6243 
6244 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6245 	if (phy->type == BWN_PHYTYPE_G ||
6246 	    (phy->type == BWN_PHYTYPE_B &&
6247 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6248 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6249 	} else
6250 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6251 	if (phy->rev >= 2)
6252 		bwn_dummy_transmission(mac, 0, 1);
6253 	bwn_phy_g_switch_chan(mac, 6, 0);
6254 	BWN_RF_READ(mac, 0x51);
6255 	if (phy->type == BWN_PHYTYPE_G)
6256 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6257 
6258 	nanouptime(&ts);
6259 	if (time_before(lo->txctl_measured_time,
6260 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6261 		bwn_lo_measure_txctl_values(mac);
6262 
6263 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6264 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6265 	else {
6266 		if (phy->type == BWN_PHYTYPE_B)
6267 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6268 		else
6269 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6270 	}
6271 }
6272 
6273 static void
6274 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6275 {
6276 	struct bwn_phy *phy = &mac->mac_phy;
6277 	struct bwn_phy_g *pg = &phy->phy_g;
6278 	uint16_t tmp;
6279 
6280 	if (phy->rev >= 2) {
6281 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6282 		tmp = (pg->pg_pga_gain << 8);
6283 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6284 		DELAY(5);
6285 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6286 		DELAY(2);
6287 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6288 	} else {
6289 		tmp = (pg->pg_pga_gain | 0xefa0);
6290 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6291 	}
6292 	if (phy->type == BWN_PHYTYPE_G) {
6293 		if (phy->rev >= 3)
6294 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6295 		else
6296 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6297 		if (phy->rev >= 2)
6298 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6299 		else
6300 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6301 	}
6302 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6303 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6304 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6305 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6306 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6307 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6308 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6309 	if (!BWN_HAS_TXMAG(phy)) {
6310 		tmp = sav->rf2;
6311 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6312 	}
6313 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6314 	if (phy->type == BWN_PHYTYPE_B &&
6315 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6316 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6317 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6318 	}
6319 	if (phy->rev >= 2) {
6320 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6321 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6322 			      sav->phy_analogoverval);
6323 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6324 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6325 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6326 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6327 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6328 	}
6329 	if (bwn_has_hwpctl(mac)) {
6330 		tmp = (sav->phy_lomask & 0xbfff);
6331 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6332 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6333 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6334 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6335 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6336 	}
6337 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6338 }
6339 
6340 static int
6341 bwn_lo_probe_loctl(struct bwn_mac *mac,
6342     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6343 {
6344 	struct bwn_phy *phy = &mac->mac_phy;
6345 	struct bwn_phy_g *pg = &phy->phy_g;
6346 	struct bwn_loctl orig, test;
6347 	struct bwn_loctl prev = { -100, -100 };
6348 	static const struct bwn_loctl modifiers[] = {
6349 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6350 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6351 	};
6352 	int begin, end, lower = 0, i;
6353 	uint16_t feedth;
6354 
6355 	if (d->curstate == 0) {
6356 		begin = 1;
6357 		end = 8;
6358 	} else if (d->curstate % 2 == 0) {
6359 		begin = d->curstate - 1;
6360 		end = d->curstate + 1;
6361 	} else {
6362 		begin = d->curstate - 2;
6363 		end = d->curstate + 2;
6364 	}
6365 	if (begin < 1)
6366 		begin += 8;
6367 	if (end > 8)
6368 		end -= 8;
6369 
6370 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6371 	i = begin;
6372 	d->curstate = i;
6373 	while (1) {
6374 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6375 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6376 		test.i += modifiers[i - 1].i * d->multipler;
6377 		test.q += modifiers[i - 1].q * d->multipler;
6378 		if ((test.i != prev.i || test.q != prev.q) &&
6379 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6380 			bwn_lo_write(mac, &test);
6381 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6382 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6383 			if (feedth < d->feedth) {
6384 				memcpy(probe, &test,
6385 				    sizeof(struct bwn_loctl));
6386 				lower = 1;
6387 				d->feedth = feedth;
6388 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6389 					break;
6390 			}
6391 		}
6392 		memcpy(&prev, &test, sizeof(prev));
6393 		if (i == end)
6394 			break;
6395 		if (i == 8)
6396 			i = 1;
6397 		else
6398 			i++;
6399 		d->curstate = i;
6400 	}
6401 
6402 	return (lower);
6403 }
6404 
6405 static void
6406 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6407 {
6408 	struct bwn_phy *phy = &mac->mac_phy;
6409 	struct bwn_phy_g *pg = &phy->phy_g;
6410 	struct bwn_lo_g_sm d;
6411 	struct bwn_loctl probe;
6412 	int lower, repeat, cnt = 0;
6413 	uint16_t feedth;
6414 
6415 	d.nmeasure = 0;
6416 	d.multipler = 1;
6417 	if (BWN_HAS_LOOPBACK(phy))
6418 		d.multipler = 3;
6419 
6420 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6421 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6422 
6423 	do {
6424 		bwn_lo_write(mac, &d.loctl);
6425 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6426 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6427 		if (feedth < 0x258) {
6428 			if (feedth >= 0x12c)
6429 				*rxgain += 6;
6430 			else
6431 				*rxgain += 3;
6432 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6433 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6434 		}
6435 		d.feedth = feedth;
6436 		d.curstate = 0;
6437 		do {
6438 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6439 			    ("%s:%d: fail", __func__, __LINE__));
6440 			memcpy(&probe, &d.loctl,
6441 			       sizeof(struct bwn_loctl));
6442 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6443 			if (!lower)
6444 				break;
6445 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6446 				break;
6447 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6448 			d.nmeasure++;
6449 		} while (d.nmeasure < 24);
6450 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6451 
6452 		if (BWN_HAS_LOOPBACK(phy)) {
6453 			if (d.feedth > 0x1194)
6454 				*rxgain -= 6;
6455 			else if (d.feedth < 0x5dc)
6456 				*rxgain += 3;
6457 			if (cnt == 0) {
6458 				if (d.feedth <= 0x5dc) {
6459 					d.multipler = 1;
6460 					cnt++;
6461 				} else
6462 					d.multipler = 2;
6463 			} else if (cnt == 2)
6464 				d.multipler = 1;
6465 		}
6466 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6467 	} while (++cnt < repeat);
6468 }
6469 
6470 static struct bwn_lo_calib *
6471 bwn_lo_calibset(struct bwn_mac *mac,
6472     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6473 {
6474 	struct bwn_phy *phy = &mac->mac_phy;
6475 	struct bwn_phy_g *pg = &phy->phy_g;
6476 	struct bwn_loctl loctl = { 0, 0 };
6477 	struct bwn_lo_calib *cal;
6478 	struct bwn_lo_g_value sval = { 0 };
6479 	int rxgain;
6480 	uint16_t pad, reg, value;
6481 
6482 	sval.old_channel = phy->chan;
6483 	bwn_mac_suspend(mac);
6484 	bwn_lo_save(mac, &sval);
6485 
6486 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6487 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6488 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6489 
6490 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6491 	if (rfatt->padmix)
6492 		rxgain -= pad;
6493 	if (BWN_HAS_LOOPBACK(phy))
6494 		rxgain += pg->pg_max_lb_gain;
6495 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6496 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6497 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6498 
6499 	bwn_lo_restore(mac, &sval);
6500 	bwn_mac_enable(mac);
6501 
6502 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6503 	if (!cal) {
6504 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6505 		return (NULL);
6506 	}
6507 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6508 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6509 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6510 
6511 	BWN_GETTIME(cal->calib_time);
6512 
6513 	return (cal);
6514 }
6515 
6516 static struct bwn_lo_calib *
6517 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6518     const struct bwn_rfatt *rfatt)
6519 {
6520 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6521 	struct bwn_lo_calib *c;
6522 
6523 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6524 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6525 			continue;
6526 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6527 			continue;
6528 		return (c);
6529 	}
6530 
6531 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6532 	if (!c)
6533 		return (NULL);
6534 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6535 
6536 	return (c);
6537 }
6538 
6539 static void
6540 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6541 {
6542 	struct bwn_phy *phy = &mac->mac_phy;
6543 	struct bwn_phy_g *pg = &phy->phy_g;
6544 	struct bwn_softc *sc = mac->mac_sc;
6545 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6546 	const struct bwn_rfatt *rfatt;
6547 	const struct bwn_bbatt *bbatt;
6548 	uint64_t pvector;
6549 	int i;
6550 	int rf_offset, bb_offset;
6551 	uint8_t changed = 0;
6552 
6553 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6554 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6555 	    ("%s:%d: fail", __func__, __LINE__));
6556 
6557 	pvector = lo->power_vector;
6558 	if (!update && !pvector)
6559 		return;
6560 
6561 	bwn_mac_suspend(mac);
6562 
6563 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6564 		struct bwn_lo_calib *cal;
6565 		int idx;
6566 		uint16_t val;
6567 
6568 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6569 			continue;
6570 		bb_offset = i / lo->rfatt.len;
6571 		rf_offset = i % lo->rfatt.len;
6572 		bbatt = &(lo->bbatt.array[bb_offset]);
6573 		rfatt = &(lo->rfatt.array[rf_offset]);
6574 
6575 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6576 		if (!cal) {
6577 			device_printf(sc->sc_dev, "LO: Could not "
6578 			    "calibrate DC table entry\n");
6579 			continue;
6580 		}
6581 		val = (uint8_t)(cal->ctl.q);
6582 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6583 		free(cal, M_DEVBUF);
6584 
6585 		idx = i / 2;
6586 		if (i % 2)
6587 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6588 			    | ((val & 0x00ff) << 8);
6589 		else
6590 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6591 			    | (val & 0x00ff);
6592 		changed = 1;
6593 	}
6594 	if (changed) {
6595 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6596 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6597 	}
6598 	bwn_mac_enable(mac);
6599 }
6600 
6601 static void
6602 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6603 {
6604 
6605 	if (!rf->padmix)
6606 		return;
6607 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6608 		rf->att = 4;
6609 }
6610 
6611 static void
6612 bwn_lo_g_adjust(struct bwn_mac *mac)
6613 {
6614 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6615 	struct bwn_lo_calib *cal;
6616 	struct bwn_rfatt rf;
6617 
6618 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6619 	bwn_lo_fixup_rfatt(&rf);
6620 
6621 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6622 	if (!cal)
6623 		return;
6624 	bwn_lo_write(mac, &cal->ctl);
6625 }
6626 
6627 static void
6628 bwn_lo_g_init(struct bwn_mac *mac)
6629 {
6630 
6631 	if (!bwn_has_hwpctl(mac))
6632 		return;
6633 
6634 	bwn_lo_get_powervector(mac);
6635 	bwn_phy_g_dc_lookup_init(mac, 1);
6636 }
6637 
6638 static void
6639 bwn_mac_suspend(struct bwn_mac *mac)
6640 {
6641 	struct bwn_softc *sc = mac->mac_sc;
6642 	int i;
6643 	uint32_t tmp;
6644 
6645 	KASSERT(mac->mac_suspended >= 0,
6646 	    ("%s:%d: fail", __func__, __LINE__));
6647 
6648 	if (mac->mac_suspended == 0) {
6649 		bwn_psctl(mac, BWN_PS_AWAKE);
6650 		BWN_WRITE_4(mac, BWN_MACCTL,
6651 			    BWN_READ_4(mac, BWN_MACCTL)
6652 			    & ~BWN_MACCTL_ON);
6653 		BWN_READ_4(mac, BWN_MACCTL);
6654 		for (i = 35; i; i--) {
6655 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6656 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6657 				goto out;
6658 			DELAY(10);
6659 		}
6660 		for (i = 40; i; i--) {
6661 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6662 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6663 				goto out;
6664 			DELAY(1000);
6665 		}
6666 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6667 	}
6668 out:
6669 	mac->mac_suspended++;
6670 }
6671 
6672 static void
6673 bwn_mac_enable(struct bwn_mac *mac)
6674 {
6675 	struct bwn_softc *sc = mac->mac_sc;
6676 	uint16_t state;
6677 
6678 	state = bwn_shm_read_2(mac, BWN_SHARED,
6679 	    BWN_SHARED_UCODESTAT);
6680 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6681 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6682 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6683 
6684 	mac->mac_suspended--;
6685 	KASSERT(mac->mac_suspended >= 0,
6686 	    ("%s:%d: fail", __func__, __LINE__));
6687 	if (mac->mac_suspended == 0) {
6688 		BWN_WRITE_4(mac, BWN_MACCTL,
6689 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6690 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6691 		BWN_READ_4(mac, BWN_MACCTL);
6692 		BWN_READ_4(mac, BWN_INTR_REASON);
6693 		bwn_psctl(mac, 0);
6694 	}
6695 }
6696 
6697 static void
6698 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6699 {
6700 	struct bwn_softc *sc = mac->mac_sc;
6701 	int i;
6702 	uint16_t ucstat;
6703 
6704 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6705 	    ("%s:%d: fail", __func__, __LINE__));
6706 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6707 	    ("%s:%d: fail", __func__, __LINE__));
6708 
6709 	/* XXX forcibly awake and hwps-off */
6710 
6711 	BWN_WRITE_4(mac, BWN_MACCTL,
6712 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6713 	    ~BWN_MACCTL_HWPS);
6714 	BWN_READ_4(mac, BWN_MACCTL);
6715 	if (siba_get_revid(sc->sc_dev) >= 5) {
6716 		for (i = 0; i < 100; i++) {
6717 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6718 			    BWN_SHARED_UCODESTAT);
6719 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6720 				break;
6721 			DELAY(10);
6722 		}
6723 	}
6724 }
6725 
6726 static int16_t
6727 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6728 {
6729 
6730 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6731 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6732 }
6733 
6734 static void
6735 bwn_nrssi_threshold(struct bwn_mac *mac)
6736 {
6737 	struct bwn_phy *phy = &mac->mac_phy;
6738 	struct bwn_phy_g *pg = &phy->phy_g;
6739 	struct bwn_softc *sc = mac->mac_sc;
6740 	int32_t a, b;
6741 	int16_t tmp16;
6742 	uint16_t tmpu16;
6743 
6744 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6745 
6746 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6747 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6748 			a = 0x13;
6749 			b = 0x12;
6750 		} else {
6751 			a = 0xe;
6752 			b = 0x11;
6753 		}
6754 
6755 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6756 		a += (pg->pg_nrssi[0] << 6);
6757 		a += (a < 32) ? 31 : 32;
6758 		a = a >> 6;
6759 		a = MIN(MAX(a, -31), 31);
6760 
6761 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6762 		b += (pg->pg_nrssi[0] << 6);
6763 		if (b < 32)
6764 			b += 31;
6765 		else
6766 			b += 32;
6767 		b = b >> 6;
6768 		b = MIN(MAX(b, -31), 31);
6769 
6770 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6771 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6772 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6773 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6774 		return;
6775 	}
6776 
6777 	tmp16 = bwn_nrssi_read(mac, 0x20);
6778 	if (tmp16 >= 0x20)
6779 		tmp16 -= 0x40;
6780 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6781 }
6782 
6783 static void
6784 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6785 {
6786 #define	SAVE_RF_MAX		3
6787 #define	SAVE_PHY_COMM_MAX	4
6788 #define	SAVE_PHY3_MAX		8
6789 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6790 		{ 0x7a, 0x52, 0x43 };
6791 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6792 		{ 0x15, 0x5a, 0x59, 0x58 };
6793 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6794 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6795 		0x0801, 0x0060, 0x0014, 0x0478
6796 	};
6797 	struct bwn_phy *phy = &mac->mac_phy;
6798 	struct bwn_phy_g *pg = &phy->phy_g;
6799 	int32_t i, tmp32, phy3_idx = 0;
6800 	uint16_t delta, tmp;
6801 	uint16_t save_rf[SAVE_RF_MAX];
6802 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6803 	uint16_t save_phy3[SAVE_PHY3_MAX];
6804 	uint16_t ant_div, phy0, chan_ex;
6805 	int16_t nrssi0, nrssi1;
6806 
6807 	KASSERT(phy->type == BWN_PHYTYPE_G,
6808 	    ("%s:%d: fail", __func__, __LINE__));
6809 
6810 	if (phy->rf_rev >= 9)
6811 		return;
6812 	if (phy->rf_rev == 8)
6813 		bwn_nrssi_offset(mac);
6814 
6815 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6816 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6817 
6818 	/*
6819 	 * Save RF/PHY registers for later restoration
6820 	 */
6821 	ant_div = BWN_READ_2(mac, 0x03e2);
6822 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6823 	for (i = 0; i < SAVE_RF_MAX; ++i)
6824 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6825 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6826 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6827 
6828 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6829 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6830 	if (phy->rev >= 3) {
6831 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6832 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6833 		BWN_PHY_WRITE(mac, 0x002e, 0);
6834 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6835 		switch (phy->rev) {
6836 		case 4:
6837 		case 6:
6838 		case 7:
6839 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6840 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6841 			break;
6842 		case 3:
6843 		case 5:
6844 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6845 			break;
6846 		}
6847 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6848 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6849 	}
6850 	/*
6851 	 * Calculate nrssi0
6852 	 */
6853 	BWN_RF_SET(mac, 0x007a, 0x0070);
6854 	bwn_set_all_gains(mac, 0, 8, 0);
6855 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6856 	if (phy->rev >= 2) {
6857 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6858 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6859 	}
6860 	BWN_RF_SET(mac, 0x007a, 0x0080);
6861 	DELAY(20);
6862 
6863 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6864 	if (nrssi0 >= 0x0020)
6865 		nrssi0 -= 0x0040;
6866 
6867 	/*
6868 	 * Calculate nrssi1
6869 	 */
6870 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6871 	if (phy->rev >= 2)
6872 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6873 
6874 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6875 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6876 	BWN_RF_SET(mac, 0x007a, 0x000f);
6877 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6878 	if (phy->rev >= 2) {
6879 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6880 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6881 	}
6882 
6883 	bwn_set_all_gains(mac, 3, 0, 1);
6884 	if (phy->rf_rev == 8) {
6885 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6886 	} else {
6887 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6888 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6889 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6890 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6891 	}
6892 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6893 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6894 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6895 	DELAY(20);
6896 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6897 
6898 	/*
6899 	 * Install calculated narrow RSSI values
6900 	 */
6901 	if (nrssi1 >= 0x0020)
6902 		nrssi1 -= 0x0040;
6903 	if (nrssi0 == nrssi1)
6904 		pg->pg_nrssi_slope = 0x00010000;
6905 	else
6906 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6907 	if (nrssi0 >= -4) {
6908 		pg->pg_nrssi[0] = nrssi1;
6909 		pg->pg_nrssi[1] = nrssi0;
6910 	}
6911 
6912 	/*
6913 	 * Restore saved RF/PHY registers
6914 	 */
6915 	if (phy->rev >= 3) {
6916 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6917 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6918 			    save_phy3[phy3_idx]);
6919 		}
6920 	}
6921 	if (phy->rev >= 2) {
6922 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6923 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6924 	}
6925 
6926 	for (i = 0; i < SAVE_RF_MAX; ++i)
6927 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6928 
6929 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6930 	BWN_WRITE_2(mac, 0x03e6, phy0);
6931 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6932 
6933 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6934 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6935 
6936 	bwn_spu_workaround(mac, phy->chan);
6937 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6938 	bwn_set_original_gains(mac);
6939 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6940 	if (phy->rev >= 3) {
6941 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6942 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6943 			    save_phy3[phy3_idx]);
6944 		}
6945 	}
6946 
6947 	delta = 0x1f - pg->pg_nrssi[0];
6948 	for (i = 0; i < 64; i++) {
6949 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6950 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6951 		pg->pg_nrssi_lt[i] = tmp32;
6952 	}
6953 
6954 	bwn_nrssi_threshold(mac);
6955 #undef SAVE_RF_MAX
6956 #undef SAVE_PHY_COMM_MAX
6957 #undef SAVE_PHY3_MAX
6958 }
6959 
6960 static void
6961 bwn_nrssi_offset(struct bwn_mac *mac)
6962 {
6963 #define	SAVE_RF_MAX		2
6964 #define	SAVE_PHY_COMM_MAX	10
6965 #define	SAVE_PHY6_MAX		8
6966 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6967 		{ 0x7a, 0x43 };
6968 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6969 		0x0001, 0x0811, 0x0812, 0x0814,
6970 		0x0815, 0x005a, 0x0059, 0x0058,
6971 		0x000a, 0x0003
6972 	};
6973 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6974 		0x002e, 0x002f, 0x080f, 0x0810,
6975 		0x0801, 0x0060, 0x0014, 0x0478
6976 	};
6977 	struct bwn_phy *phy = &mac->mac_phy;
6978 	int i, phy6_idx = 0;
6979 	uint16_t save_rf[SAVE_RF_MAX];
6980 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6981 	uint16_t save_phy6[SAVE_PHY6_MAX];
6982 	int16_t nrssi;
6983 	uint16_t saved = 0xffff;
6984 
6985 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6986 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6987 	for (i = 0; i < SAVE_RF_MAX; ++i)
6988 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6989 
6990 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6991 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6992 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6993 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6994 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6995 	if (phy->rev >= 6) {
6996 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6997 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6998 
6999 		BWN_PHY_WRITE(mac, 0x002e, 0);
7000 		BWN_PHY_WRITE(mac, 0x002f, 0);
7001 		BWN_PHY_WRITE(mac, 0x080f, 0);
7002 		BWN_PHY_WRITE(mac, 0x0810, 0);
7003 		BWN_PHY_SET(mac, 0x0478, 0x0100);
7004 		BWN_PHY_SET(mac, 0x0801, 0x0040);
7005 		BWN_PHY_SET(mac, 0x0060, 0x0040);
7006 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7007 	}
7008 	BWN_RF_SET(mac, 0x007a, 0x0070);
7009 	BWN_RF_SET(mac, 0x007a, 0x0080);
7010 	DELAY(30);
7011 
7012 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7013 	if (nrssi >= 0x20)
7014 		nrssi -= 0x40;
7015 	if (nrssi == 31) {
7016 		for (i = 7; i >= 4; i--) {
7017 			BWN_RF_WRITE(mac, 0x007b, i);
7018 			DELAY(20);
7019 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7020 			    0x003f);
7021 			if (nrssi >= 0x20)
7022 				nrssi -= 0x40;
7023 			if (nrssi < 31 && saved == 0xffff)
7024 				saved = i;
7025 		}
7026 		if (saved == 0xffff)
7027 			saved = 4;
7028 	} else {
7029 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7030 		if (phy->rev != 1) {
7031 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7032 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7033 		}
7034 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7035 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7036 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7037 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7038 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7039 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7040 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7041 		if (phy->rev == 0)
7042 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7043 		else
7044 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7045 		if (phy->rev != 1) {
7046 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7047 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7048 		}
7049 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7050 		BWN_RF_SET(mac, 0x007a, 0x000f);
7051 		bwn_set_all_gains(mac, 3, 0, 1);
7052 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7053 		DELAY(30);
7054 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7055 		if (nrssi >= 0x20)
7056 			nrssi -= 0x40;
7057 		if (nrssi == -32) {
7058 			for (i = 0; i < 4; i++) {
7059 				BWN_RF_WRITE(mac, 0x007b, i);
7060 				DELAY(20);
7061 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7062 				    0x047f) >> 8) & 0x003f);
7063 				if (nrssi >= 0x20)
7064 					nrssi -= 0x40;
7065 				if (nrssi > -31 && saved == 0xffff)
7066 					saved = i;
7067 			}
7068 			if (saved == 0xffff)
7069 				saved = 3;
7070 		} else
7071 			saved = 0;
7072 	}
7073 	BWN_RF_WRITE(mac, 0x007b, saved);
7074 
7075 	/*
7076 	 * Restore saved RF/PHY registers
7077 	 */
7078 	if (phy->rev >= 6) {
7079 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7080 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7081 			    save_phy6[phy6_idx]);
7082 		}
7083 	}
7084 	if (phy->rev != 1) {
7085 		for (i = 3; i < 5; i++)
7086 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7087 			    save_phy_comm[i]);
7088 	}
7089 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7090 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7091 
7092 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7093 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7094 
7095 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7096 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7097 	bwn_set_original_gains(mac);
7098 	if (phy->rev >= 6) {
7099 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7100 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7101 			    save_phy6[phy6_idx]);
7102 		}
7103 	}
7104 
7105 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7106 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7107 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7108 }
7109 
7110 static void
7111 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7112     int16_t third)
7113 {
7114 	struct bwn_phy *phy = &mac->mac_phy;
7115 	uint16_t i;
7116 	uint16_t start = 0x08, end = 0x18;
7117 	uint16_t tmp;
7118 	uint16_t table;
7119 
7120 	if (phy->rev <= 1) {
7121 		start = 0x10;
7122 		end = 0x20;
7123 	}
7124 
7125 	table = BWN_OFDMTAB_GAINX;
7126 	if (phy->rev <= 1)
7127 		table = BWN_OFDMTAB_GAINX_R1;
7128 	for (i = 0; i < 4; i++)
7129 		bwn_ofdmtab_write_2(mac, table, i, first);
7130 
7131 	for (i = start; i < end; i++)
7132 		bwn_ofdmtab_write_2(mac, table, i, second);
7133 
7134 	if (third != -1) {
7135 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7136 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7137 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7138 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7139 	}
7140 	bwn_dummy_transmission(mac, 0, 1);
7141 }
7142 
7143 static void
7144 bwn_set_original_gains(struct bwn_mac *mac)
7145 {
7146 	struct bwn_phy *phy = &mac->mac_phy;
7147 	uint16_t i, tmp;
7148 	uint16_t table;
7149 	uint16_t start = 0x0008, end = 0x0018;
7150 
7151 	if (phy->rev <= 1) {
7152 		start = 0x0010;
7153 		end = 0x0020;
7154 	}
7155 
7156 	table = BWN_OFDMTAB_GAINX;
7157 	if (phy->rev <= 1)
7158 		table = BWN_OFDMTAB_GAINX_R1;
7159 	for (i = 0; i < 4; i++) {
7160 		tmp = (i & 0xfffc);
7161 		tmp |= (i & 0x0001) << 1;
7162 		tmp |= (i & 0x0002) >> 1;
7163 
7164 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7165 	}
7166 
7167 	for (i = start; i < end; i++)
7168 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7169 
7170 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7171 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7172 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7173 	bwn_dummy_transmission(mac, 0, 1);
7174 }
7175 
7176 static void
7177 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7178 {
7179 	struct bwn_phy *phy = &mac->mac_phy;
7180 	struct bwn_phy_g *pg = &phy->phy_g;
7181 	struct bwn_rfatt old_rfatt, rfatt;
7182 	struct bwn_bbatt old_bbatt, bbatt;
7183 	struct bwn_softc *sc = mac->mac_sc;
7184 	uint8_t old_txctl = 0;
7185 
7186 	KASSERT(phy->type == BWN_PHYTYPE_G,
7187 	    ("%s:%d: fail", __func__, __LINE__));
7188 
7189 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7190 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7191 		return;
7192 
7193 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7194 
7195 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7196 
7197 	if (!phy->gmode)
7198 		return;
7199 	bwn_hwpctl_early_init(mac);
7200 	if (pg->pg_curtssi == 0) {
7201 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7202 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7203 		} else {
7204 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7205 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7206 			old_txctl = pg->pg_txctl;
7207 
7208 			bbatt.att = 11;
7209 			if (phy->rf_rev == 8) {
7210 				rfatt.att = 15;
7211 				rfatt.padmix = 1;
7212 			} else {
7213 				rfatt.att = 9;
7214 				rfatt.padmix = 0;
7215 			}
7216 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7217 		}
7218 		bwn_dummy_transmission(mac, 0, 1);
7219 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7220 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7221 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7222 		else
7223 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7224 			    &old_rfatt, old_txctl);
7225 	}
7226 	bwn_hwpctl_init_gphy(mac);
7227 
7228 	/* clear TSSI */
7229 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7230 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7231 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7232 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7233 }
7234 
7235 static void
7236 bwn_hwpctl_early_init(struct bwn_mac *mac)
7237 {
7238 	struct bwn_phy *phy = &mac->mac_phy;
7239 
7240 	if (!bwn_has_hwpctl(mac)) {
7241 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7242 		return;
7243 	}
7244 
7245 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7246 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7247 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7248 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7249 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7250 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7251 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7252 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7253 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7254 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7255 	} else {
7256 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7257 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7258 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7259 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7260 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7261 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7262 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7263 	}
7264 }
7265 
7266 static void
7267 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7268 {
7269 	struct bwn_phy *phy = &mac->mac_phy;
7270 	struct bwn_phy_g *pg = &phy->phy_g;
7271 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7272 	int i;
7273 	uint16_t nr_written = 0, tmp, value;
7274 	uint8_t rf, bb;
7275 
7276 	if (!bwn_has_hwpctl(mac)) {
7277 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7278 		return;
7279 	}
7280 
7281 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7282 	    (pg->pg_idletssi - pg->pg_curtssi));
7283 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7284 	    (pg->pg_idletssi - pg->pg_curtssi));
7285 
7286 	for (i = 0; i < 32; i++)
7287 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7288 	for (i = 32; i < 64; i++)
7289 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7290 	for (i = 0; i < 64; i += 2) {
7291 		value = (uint16_t) pg->pg_tssi2dbm[i];
7292 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7293 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7294 	}
7295 
7296 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7297 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7298 			if (nr_written >= 0x40)
7299 				return;
7300 			tmp = lo->bbatt.array[bb].att;
7301 			tmp <<= 8;
7302 			if (phy->rf_rev == 8)
7303 				tmp |= 0x50;
7304 			else
7305 				tmp |= 0x40;
7306 			tmp |= lo->rfatt.array[rf].att;
7307 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7308 			nr_written++;
7309 		}
7310 	}
7311 
7312 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7313 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7314 
7315 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7316 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7317 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7318 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7319 
7320 	bwn_phy_g_dc_lookup_init(mac, 1);
7321 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7322 }
7323 
7324 static void
7325 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7326 {
7327 	struct bwn_softc *sc = mac->mac_sc;
7328 
7329 	if (spu != 0)
7330 		bwn_spu_workaround(mac, channel);
7331 
7332 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7333 
7334 	if (channel == 14) {
7335 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7336 			bwn_hf_write(mac,
7337 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7338 		else
7339 			bwn_hf_write(mac,
7340 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7341 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7342 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7343 		return;
7344 	}
7345 
7346 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7347 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7348 }
7349 
7350 static uint16_t
7351 bwn_phy_g_chan2freq(uint8_t channel)
7352 {
7353 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7354 
7355 	KASSERT(channel >= 1 && channel <= 14,
7356 	    ("%s:%d: fail", __func__, __LINE__));
7357 
7358 	return (bwn_phy_g_rf_channels[channel - 1]);
7359 }
7360 
7361 static void
7362 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7363     const struct bwn_rfatt *rfatt, uint8_t txctl)
7364 {
7365 	struct bwn_phy *phy = &mac->mac_phy;
7366 	struct bwn_phy_g *pg = &phy->phy_g;
7367 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7368 	uint16_t bb, rf;
7369 	uint16_t tx_bias, tx_magn;
7370 
7371 	bb = bbatt->att;
7372 	rf = rfatt->att;
7373 	tx_bias = lo->tx_bias;
7374 	tx_magn = lo->tx_magn;
7375 	if (tx_bias == 0xff)
7376 		tx_bias = 0;
7377 
7378 	pg->pg_txctl = txctl;
7379 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7380 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7381 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7382 	bwn_phy_g_set_bbatt(mac, bb);
7383 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7384 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7385 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7386 	else {
7387 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7388 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7389 	}
7390 	if (BWN_HAS_TXMAG(phy))
7391 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7392 	else
7393 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7394 	bwn_lo_g_adjust(mac);
7395 }
7396 
7397 static void
7398 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7399     uint16_t bbatt)
7400 {
7401 	struct bwn_phy *phy = &mac->mac_phy;
7402 
7403 	if (phy->analog == 0) {
7404 		BWN_WRITE_2(mac, BWN_PHY0,
7405 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7406 		return;
7407 	}
7408 	if (phy->analog > 1) {
7409 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7410 		return;
7411 	}
7412 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7413 }
7414 
7415 static uint16_t
7416 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7417 {
7418 	struct bwn_phy *phy = &mac->mac_phy;
7419 	struct bwn_phy_g *pg = &phy->phy_g;
7420 	struct bwn_softc *sc = mac->mac_sc;
7421 	int max_lb_gain;
7422 	uint16_t extlna;
7423 	uint16_t i;
7424 
7425 	if (phy->gmode == 0)
7426 		return (0);
7427 
7428 	if (BWN_HAS_LOOPBACK(phy)) {
7429 		max_lb_gain = pg->pg_max_lb_gain;
7430 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7431 		if (max_lb_gain >= 0x46) {
7432 			extlna = 0x3000;
7433 			max_lb_gain -= 0x46;
7434 		} else if (max_lb_gain >= 0x3a) {
7435 			extlna = 0x1000;
7436 			max_lb_gain -= 0x3a;
7437 		} else if (max_lb_gain >= 0x2e) {
7438 			extlna = 0x2000;
7439 			max_lb_gain -= 0x2e;
7440 		} else {
7441 			extlna = 0;
7442 			max_lb_gain -= 0x10;
7443 		}
7444 
7445 		for (i = 0; i < 16; i++) {
7446 			max_lb_gain -= (i * 6);
7447 			if (max_lb_gain < 6)
7448 				break;
7449 		}
7450 
7451 		if ((phy->rev < 7) ||
7452 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7453 			if (reg == BWN_PHY_RFOVER) {
7454 				return (0x1b3);
7455 			} else if (reg == BWN_PHY_RFOVERVAL) {
7456 				extlna |= (i << 8);
7457 				switch (lpd) {
7458 				case BWN_LPD(0, 1, 1):
7459 					return (0x0f92);
7460 				case BWN_LPD(0, 0, 1):
7461 				case BWN_LPD(1, 0, 1):
7462 					return (0x0092 | extlna);
7463 				case BWN_LPD(1, 0, 0):
7464 					return (0x0093 | extlna);
7465 				}
7466 				KASSERT(0 == 1,
7467 				    ("%s:%d: fail", __func__, __LINE__));
7468 			}
7469 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7470 		} else {
7471 			if (reg == BWN_PHY_RFOVER)
7472 				return (0x9b3);
7473 			if (reg == BWN_PHY_RFOVERVAL) {
7474 				if (extlna)
7475 					extlna |= 0x8000;
7476 				extlna |= (i << 8);
7477 				switch (lpd) {
7478 				case BWN_LPD(0, 1, 1):
7479 					return (0x8f92);
7480 				case BWN_LPD(0, 0, 1):
7481 					return (0x8092 | extlna);
7482 				case BWN_LPD(1, 0, 1):
7483 					return (0x2092 | extlna);
7484 				case BWN_LPD(1, 0, 0):
7485 					return (0x2093 | extlna);
7486 				}
7487 				KASSERT(0 == 1,
7488 				    ("%s:%d: fail", __func__, __LINE__));
7489 			}
7490 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7491 		}
7492 		return (0);
7493 	}
7494 
7495 	if ((phy->rev < 7) ||
7496 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7497 		if (reg == BWN_PHY_RFOVER) {
7498 			return (0x1b3);
7499 		} else if (reg == BWN_PHY_RFOVERVAL) {
7500 			switch (lpd) {
7501 			case BWN_LPD(0, 1, 1):
7502 				return (0x0fb2);
7503 			case BWN_LPD(0, 0, 1):
7504 				return (0x00b2);
7505 			case BWN_LPD(1, 0, 1):
7506 				return (0x30b2);
7507 			case BWN_LPD(1, 0, 0):
7508 				return (0x30b3);
7509 			}
7510 			KASSERT(0 == 1,
7511 			    ("%s:%d: fail", __func__, __LINE__));
7512 		}
7513 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7514 	} else {
7515 		if (reg == BWN_PHY_RFOVER) {
7516 			return (0x9b3);
7517 		} else if (reg == BWN_PHY_RFOVERVAL) {
7518 			switch (lpd) {
7519 			case BWN_LPD(0, 1, 1):
7520 				return (0x8fb2);
7521 			case BWN_LPD(0, 0, 1):
7522 				return (0x80b2);
7523 			case BWN_LPD(1, 0, 1):
7524 				return (0x20b2);
7525 			case BWN_LPD(1, 0, 0):
7526 				return (0x20b3);
7527 			}
7528 			KASSERT(0 == 1,
7529 			    ("%s:%d: fail", __func__, __LINE__));
7530 		}
7531 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7532 	}
7533 	return (0);
7534 }
7535 
7536 static void
7537 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7538 {
7539 
7540 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7541 		return;
7542 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7543 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7544 	DELAY(1000);
7545 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7546 }
7547 
7548 static int
7549 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7550 {
7551 	struct bwn_softc *sc = mac->mac_sc;
7552 	struct bwn_fw *fw = &mac->mac_fw;
7553 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7554 	const char *filename;
7555 	uint32_t high;
7556 	int error;
7557 
7558 	/* microcode */
7559 	if (rev >= 5 && rev <= 10)
7560 		filename = "ucode5";
7561 	else if (rev >= 11 && rev <= 12)
7562 		filename = "ucode11";
7563 	else if (rev == 13)
7564 		filename = "ucode13";
7565 	else if (rev == 14)
7566 		filename = "ucode14";
7567 	else if (rev >= 15)
7568 		filename = "ucode15";
7569 	else {
7570 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7571 		bwn_release_firmware(mac);
7572 		return (EOPNOTSUPP);
7573 	}
7574 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7575 	if (error) {
7576 		bwn_release_firmware(mac);
7577 		return (error);
7578 	}
7579 
7580 	/* PCM */
7581 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7582 	if (rev >= 5 && rev <= 10) {
7583 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7584 		if (error == ENOENT)
7585 			fw->no_pcmfile = 1;
7586 		else if (error) {
7587 			bwn_release_firmware(mac);
7588 			return (error);
7589 		}
7590 	} else if (rev < 11) {
7591 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7592 		return (EOPNOTSUPP);
7593 	}
7594 
7595 	/* initvals */
7596 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7597 	switch (mac->mac_phy.type) {
7598 	case BWN_PHYTYPE_A:
7599 		if (rev < 5 || rev > 10)
7600 			goto fail1;
7601 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7602 			filename = "a0g1initvals5";
7603 		else
7604 			filename = "a0g0initvals5";
7605 		break;
7606 	case BWN_PHYTYPE_G:
7607 		if (rev >= 5 && rev <= 10)
7608 			filename = "b0g0initvals5";
7609 		else if (rev >= 13)
7610 			filename = "b0g0initvals13";
7611 		else
7612 			goto fail1;
7613 		break;
7614 	case BWN_PHYTYPE_LP:
7615 		if (rev == 13)
7616 			filename = "lp0initvals13";
7617 		else if (rev == 14)
7618 			filename = "lp0initvals14";
7619 		else if (rev >= 15)
7620 			filename = "lp0initvals15";
7621 		else
7622 			goto fail1;
7623 		break;
7624 	case BWN_PHYTYPE_N:
7625 		if (rev >= 11 && rev <= 12)
7626 			filename = "n0initvals11";
7627 		else
7628 			goto fail1;
7629 		break;
7630 	default:
7631 		goto fail1;
7632 	}
7633 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7634 	if (error) {
7635 		bwn_release_firmware(mac);
7636 		return (error);
7637 	}
7638 
7639 	/* bandswitch initvals */
7640 	switch (mac->mac_phy.type) {
7641 	case BWN_PHYTYPE_A:
7642 		if (rev >= 5 && rev <= 10) {
7643 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7644 				filename = "a0g1bsinitvals5";
7645 			else
7646 				filename = "a0g0bsinitvals5";
7647 		} else if (rev >= 11)
7648 			filename = NULL;
7649 		else
7650 			goto fail1;
7651 		break;
7652 	case BWN_PHYTYPE_G:
7653 		if (rev >= 5 && rev <= 10)
7654 			filename = "b0g0bsinitvals5";
7655 		else if (rev >= 11)
7656 			filename = NULL;
7657 		else
7658 			goto fail1;
7659 		break;
7660 	case BWN_PHYTYPE_LP:
7661 		if (rev == 13)
7662 			filename = "lp0bsinitvals13";
7663 		else if (rev == 14)
7664 			filename = "lp0bsinitvals14";
7665 		else if (rev >= 15)
7666 			filename = "lp0bsinitvals15";
7667 		else
7668 			goto fail1;
7669 		break;
7670 	case BWN_PHYTYPE_N:
7671 		if (rev >= 11 && rev <= 12)
7672 			filename = "n0bsinitvals11";
7673 		else
7674 			goto fail1;
7675 		break;
7676 	default:
7677 		goto fail1;
7678 	}
7679 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7680 	if (error) {
7681 		bwn_release_firmware(mac);
7682 		return (error);
7683 	}
7684 	return (0);
7685 fail1:
7686 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7687 	bwn_release_firmware(mac);
7688 	return (EOPNOTSUPP);
7689 }
7690 
7691 static int
7692 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7693     const char *name, struct bwn_fwfile *bfw)
7694 {
7695 	const struct bwn_fwhdr *hdr;
7696 	struct bwn_softc *sc = mac->mac_sc;
7697 	const struct firmware *fw;
7698 	char namebuf[64];
7699 
7700 	if (name == NULL) {
7701 		bwn_do_release_fw(bfw);
7702 		return (0);
7703 	}
7704 	if (bfw->filename != NULL) {
7705 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7706 			return (0);
7707 		bwn_do_release_fw(bfw);
7708 	}
7709 
7710 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7711 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7712 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7713 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7714 	fw = firmware_get(namebuf);
7715 	if (fw == NULL) {
7716 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7717 		    namebuf);
7718 		return (ENOENT);
7719 	}
7720 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7721 		goto fail;
7722 	hdr = (const struct bwn_fwhdr *)(fw->data);
7723 	switch (hdr->type) {
7724 	case BWN_FWTYPE_UCODE:
7725 	case BWN_FWTYPE_PCM:
7726 		if (be32toh(hdr->size) !=
7727 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7728 			goto fail;
7729 		/* FALLTHROUGH */
7730 	case BWN_FWTYPE_IV:
7731 		if (hdr->ver != 1)
7732 			goto fail;
7733 		break;
7734 	default:
7735 		goto fail;
7736 	}
7737 	bfw->filename = name;
7738 	bfw->fw = fw;
7739 	bfw->type = type;
7740 	return (0);
7741 fail:
7742 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7743 	if (fw != NULL)
7744 		firmware_put(fw, FIRMWARE_UNLOAD);
7745 	return (EPROTO);
7746 }
7747 
7748 static void
7749 bwn_release_firmware(struct bwn_mac *mac)
7750 {
7751 
7752 	bwn_do_release_fw(&mac->mac_fw.ucode);
7753 	bwn_do_release_fw(&mac->mac_fw.pcm);
7754 	bwn_do_release_fw(&mac->mac_fw.initvals);
7755 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7756 }
7757 
7758 static void
7759 bwn_do_release_fw(struct bwn_fwfile *bfw)
7760 {
7761 
7762 	if (bfw->fw != NULL)
7763 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7764 	bfw->fw = NULL;
7765 	bfw->filename = NULL;
7766 }
7767 
7768 static int
7769 bwn_fw_loaducode(struct bwn_mac *mac)
7770 {
7771 #define	GETFWOFFSET(fwp, offset)	\
7772 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7773 #define	GETFWSIZE(fwp, offset)	\
7774 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7775 	struct bwn_softc *sc = mac->mac_sc;
7776 	const uint32_t *data;
7777 	unsigned int i;
7778 	uint32_t ctl;
7779 	uint16_t date, fwcaps, time;
7780 	int error = 0;
7781 
7782 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7783 	ctl |= BWN_MACCTL_MCODE_JMP0;
7784 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7785 	    __LINE__));
7786 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7787 	for (i = 0; i < 64; i++)
7788 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7789 	for (i = 0; i < 4096; i += 2)
7790 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7791 
7792 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7793 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7794 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7795 	     i++) {
7796 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7797 		DELAY(10);
7798 	}
7799 
7800 	if (mac->mac_fw.pcm.fw) {
7801 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7802 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7803 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7804 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7805 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7806 		    sizeof(struct bwn_fwhdr)); i++) {
7807 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7808 			DELAY(10);
7809 		}
7810 	}
7811 
7812 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7813 	BWN_WRITE_4(mac, BWN_MACCTL,
7814 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7815 	    BWN_MACCTL_MCODE_RUN);
7816 
7817 	for (i = 0; i < 21; i++) {
7818 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7819 			break;
7820 		if (i >= 20) {
7821 			device_printf(sc->sc_dev, "ucode timeout\n");
7822 			error = ENXIO;
7823 			goto error;
7824 		}
7825 		DELAY(50000);
7826 	}
7827 	BWN_READ_4(mac, BWN_INTR_REASON);
7828 
7829 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7830 	if (mac->mac_fw.rev <= 0x128) {
7831 		device_printf(sc->sc_dev, "the firmware is too old\n");
7832 		error = EOPNOTSUPP;
7833 		goto error;
7834 	}
7835 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7836 	    BWN_SHARED_UCODE_PATCH);
7837 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7838 	mac->mac_fw.opensource = (date == 0xffff);
7839 	if (bwn_wme != 0)
7840 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7841 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7842 
7843 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7844 	if (mac->mac_fw.opensource == 0) {
7845 		device_printf(sc->sc_dev,
7846 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7847 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7848 		if (mac->mac_fw.no_pcmfile)
7849 			device_printf(sc->sc_dev,
7850 			    "no HW crypto acceleration due to pcm5\n");
7851 	} else {
7852 		mac->mac_fw.patch = time;
7853 		fwcaps = bwn_fwcaps_read(mac);
7854 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7855 			device_printf(sc->sc_dev,
7856 			    "disabling HW crypto acceleration\n");
7857 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7858 		}
7859 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7860 			device_printf(sc->sc_dev, "disabling WME support\n");
7861 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7862 		}
7863 	}
7864 
7865 	if (BWN_ISOLDFMT(mac))
7866 		device_printf(sc->sc_dev, "using old firmware image\n");
7867 
7868 	return (0);
7869 
7870 error:
7871 	BWN_WRITE_4(mac, BWN_MACCTL,
7872 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7873 	    BWN_MACCTL_MCODE_JMP0);
7874 
7875 	return (error);
7876 #undef GETFWSIZE
7877 #undef GETFWOFFSET
7878 }
7879 
7880 /* OpenFirmware only */
7881 static uint16_t
7882 bwn_fwcaps_read(struct bwn_mac *mac)
7883 {
7884 
7885 	KASSERT(mac->mac_fw.opensource == 1,
7886 	    ("%s:%d: fail", __func__, __LINE__));
7887 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7888 }
7889 
7890 static int
7891 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7892     size_t count, size_t array_size)
7893 {
7894 #define	GET_NEXTIV16(iv)						\
7895 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7896 	    sizeof(uint16_t) + sizeof(uint16_t)))
7897 #define	GET_NEXTIV32(iv)						\
7898 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7899 	    sizeof(uint16_t) + sizeof(uint32_t)))
7900 	struct bwn_softc *sc = mac->mac_sc;
7901 	const struct bwn_fwinitvals *iv;
7902 	uint16_t offset;
7903 	size_t i;
7904 	uint8_t bit32;
7905 
7906 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7907 	    ("%s:%d: fail", __func__, __LINE__));
7908 	iv = ivals;
7909 	for (i = 0; i < count; i++) {
7910 		if (array_size < sizeof(iv->offset_size))
7911 			goto fail;
7912 		array_size -= sizeof(iv->offset_size);
7913 		offset = be16toh(iv->offset_size);
7914 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7915 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7916 		if (offset >= 0x1000)
7917 			goto fail;
7918 		if (bit32) {
7919 			if (array_size < sizeof(iv->data.d32))
7920 				goto fail;
7921 			array_size -= sizeof(iv->data.d32);
7922 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7923 			iv = GET_NEXTIV32(iv);
7924 		} else {
7925 
7926 			if (array_size < sizeof(iv->data.d16))
7927 				goto fail;
7928 			array_size -= sizeof(iv->data.d16);
7929 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7930 
7931 			iv = GET_NEXTIV16(iv);
7932 		}
7933 	}
7934 	if (array_size != 0)
7935 		goto fail;
7936 	return (0);
7937 fail:
7938 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7939 	return (EPROTO);
7940 #undef GET_NEXTIV16
7941 #undef GET_NEXTIV32
7942 }
7943 
7944 static int
7945 bwn_switch_channel(struct bwn_mac *mac, int chan)
7946 {
7947 	struct bwn_phy *phy = &(mac->mac_phy);
7948 	struct bwn_softc *sc = mac->mac_sc;
7949 	struct ifnet *ifp = sc->sc_ifp;
7950 	struct ieee80211com *ic = ifp->if_l2com;
7951 	uint16_t channelcookie, savedcookie;
7952 	int error;
7953 
7954 	if (chan == 0xffff)
7955 		chan = phy->get_default_chan(mac);
7956 
7957 	channelcookie = chan;
7958 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7959 		channelcookie |= 0x100;
7960 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7961 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7962 	error = phy->switch_channel(mac, chan);
7963 	if (error)
7964 		goto fail;
7965 
7966 	mac->mac_phy.chan = chan;
7967 	DELAY(8000);
7968 	return (0);
7969 fail:
7970 	device_printf(sc->sc_dev, "failed to switch channel\n");
7971 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7972 	return (error);
7973 }
7974 
7975 static uint16_t
7976 bwn_ant2phy(int antenna)
7977 {
7978 
7979 	switch (antenna) {
7980 	case BWN_ANT0:
7981 		return (BWN_TX_PHY_ANT0);
7982 	case BWN_ANT1:
7983 		return (BWN_TX_PHY_ANT1);
7984 	case BWN_ANT2:
7985 		return (BWN_TX_PHY_ANT2);
7986 	case BWN_ANT3:
7987 		return (BWN_TX_PHY_ANT3);
7988 	case BWN_ANTAUTO:
7989 		return (BWN_TX_PHY_ANT01AUTO);
7990 	}
7991 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7992 	return (0);
7993 }
7994 
7995 static void
7996 bwn_wme_load(struct bwn_mac *mac)
7997 {
7998 	struct bwn_softc *sc = mac->mac_sc;
7999 	int i;
8000 
8001 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8002 	    ("%s:%d: fail", __func__, __LINE__));
8003 
8004 	bwn_mac_suspend(mac);
8005 	for (i = 0; i < N(sc->sc_wmeParams); i++)
8006 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8007 		    bwn_wme_shm_offsets[i]);
8008 	bwn_mac_enable(mac);
8009 }
8010 
8011 static void
8012 bwn_wme_loadparams(struct bwn_mac *mac,
8013     const struct wmeParams *p, uint16_t shm_offset)
8014 {
8015 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8016 	struct bwn_softc *sc = mac->mac_sc;
8017 	uint16_t params[BWN_NR_WMEPARAMS];
8018 	int slot, tmp;
8019 	unsigned int i;
8020 
8021 	slot = BWN_READ_2(mac, BWN_RNG) &
8022 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8023 
8024 	memset(&params, 0, sizeof(params));
8025 
8026 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8027 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8028 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8029 
8030 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8031 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8032 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8033 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8034 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8035 	params[BWN_WMEPARAM_BSLOTS] = slot;
8036 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8037 
8038 	for (i = 0; i < N(params); i++) {
8039 		if (i == BWN_WMEPARAM_STATUS) {
8040 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8041 			    shm_offset + (i * 2));
8042 			tmp |= 0x100;
8043 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8044 			    tmp);
8045 		} else {
8046 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8047 			    params[i]);
8048 		}
8049 	}
8050 }
8051 
8052 static void
8053 bwn_mac_write_bssid(struct bwn_mac *mac)
8054 {
8055 	struct bwn_softc *sc = mac->mac_sc;
8056 	uint32_t tmp;
8057 	int i;
8058 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8059 
8060 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8061 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8062 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8063 	    IEEE80211_ADDR_LEN);
8064 
8065 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8066 		tmp = (uint32_t) (mac_bssid[i + 0]);
8067 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8068 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8069 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8070 		bwn_ram_write(mac, 0x20 + i, tmp);
8071 	}
8072 }
8073 
8074 static void
8075 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8076     const uint8_t *macaddr)
8077 {
8078 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8079 	uint16_t data;
8080 
8081 	if (!mac)
8082 		macaddr = zero;
8083 
8084 	offset |= 0x0020;
8085 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8086 
8087 	data = macaddr[0];
8088 	data |= macaddr[1] << 8;
8089 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8090 	data = macaddr[2];
8091 	data |= macaddr[3] << 8;
8092 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8093 	data = macaddr[4];
8094 	data |= macaddr[5] << 8;
8095 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8096 }
8097 
8098 static void
8099 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8100     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8101 {
8102 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8103 	uint8_t per_sta_keys_start = 8;
8104 
8105 	if (BWN_SEC_NEWAPI(mac))
8106 		per_sta_keys_start = 4;
8107 
8108 	KASSERT(index < mac->mac_max_nr_keys,
8109 	    ("%s:%d: fail", __func__, __LINE__));
8110 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8111 	    ("%s:%d: fail", __func__, __LINE__));
8112 
8113 	if (index >= per_sta_keys_start)
8114 		bwn_key_macwrite(mac, index, NULL);
8115 	if (key)
8116 		memcpy(buf, key, key_len);
8117 	bwn_key_write(mac, index, algorithm, buf);
8118 	if (index >= per_sta_keys_start)
8119 		bwn_key_macwrite(mac, index, mac_addr);
8120 
8121 	mac->mac_key[index].algorithm = algorithm;
8122 }
8123 
8124 static void
8125 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8126 {
8127 	struct bwn_softc *sc = mac->mac_sc;
8128 	uint32_t addrtmp[2] = { 0, 0 };
8129 	uint8_t start = 8;
8130 
8131 	if (BWN_SEC_NEWAPI(mac))
8132 		start = 4;
8133 
8134 	KASSERT(index >= start,
8135 	    ("%s:%d: fail", __func__, __LINE__));
8136 	index -= start;
8137 
8138 	if (addr) {
8139 		addrtmp[0] = addr[0];
8140 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8141 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8142 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8143 		addrtmp[1] = addr[4];
8144 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8145 	}
8146 
8147 	if (siba_get_revid(sc->sc_dev) >= 5) {
8148 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8149 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8150 	} else {
8151 		if (index >= 8) {
8152 			bwn_shm_write_4(mac, BWN_SHARED,
8153 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8154 			bwn_shm_write_2(mac, BWN_SHARED,
8155 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8156 		}
8157 	}
8158 }
8159 
8160 static void
8161 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8162     const uint8_t *key)
8163 {
8164 	unsigned int i;
8165 	uint32_t offset;
8166 	uint16_t kidx, value;
8167 
8168 	kidx = BWN_SEC_KEY2FW(mac, index);
8169 	bwn_shm_write_2(mac, BWN_SHARED,
8170 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8171 
8172 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8173 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8174 		value = key[i];
8175 		value |= (uint16_t)(key[i + 1]) << 8;
8176 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8177 	}
8178 }
8179 
8180 static void
8181 bwn_phy_exit(struct bwn_mac *mac)
8182 {
8183 
8184 	mac->mac_phy.rf_onoff(mac, 0);
8185 	if (mac->mac_phy.exit != NULL)
8186 		mac->mac_phy.exit(mac);
8187 }
8188 
8189 static void
8190 bwn_dma_free(struct bwn_mac *mac)
8191 {
8192 	struct bwn_dma *dma;
8193 
8194 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8195 		return;
8196 	dma = &mac->mac_method.dma;
8197 
8198 	bwn_dma_ringfree(&dma->rx);
8199 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8200 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8201 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8202 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8203 	bwn_dma_ringfree(&dma->mcast);
8204 }
8205 
8206 static void
8207 bwn_core_stop(struct bwn_mac *mac)
8208 {
8209 	struct bwn_softc *sc = mac->mac_sc;
8210 
8211 	BWN_ASSERT_LOCKED(sc);
8212 
8213 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8214 		return;
8215 
8216 	callout_stop(&sc->sc_rfswitch_ch);
8217 	callout_stop(&sc->sc_task_ch);
8218 	callout_stop(&sc->sc_watchdog_ch);
8219 	sc->sc_watchdog_timer = 0;
8220 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8221 	BWN_READ_4(mac, BWN_INTR_MASK);
8222 	bwn_mac_suspend(mac);
8223 
8224 	mac->mac_status = BWN_MAC_STATUS_INITED;
8225 }
8226 
8227 static int
8228 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8229 {
8230 	struct bwn_mac *up_dev = NULL;
8231 	struct bwn_mac *down_dev;
8232 	struct bwn_mac *mac;
8233 	int err, status;
8234 	uint8_t gmode;
8235 
8236 	BWN_ASSERT_LOCKED(sc);
8237 
8238 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8239 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8240 		    mac->mac_phy.supports_2ghz) {
8241 			up_dev = mac;
8242 			gmode = 1;
8243 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8244 		    mac->mac_phy.supports_5ghz) {
8245 			up_dev = mac;
8246 			gmode = 0;
8247 		} else {
8248 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8249 			return (EINVAL);
8250 		}
8251 		if (up_dev != NULL)
8252 			break;
8253 	}
8254 	if (up_dev == NULL) {
8255 		device_printf(sc->sc_dev, "Could not find a device\n");
8256 		return (ENODEV);
8257 	}
8258 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8259 		return (0);
8260 
8261 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8262 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8263 
8264 	down_dev = sc->sc_curmac;;
8265 	status = down_dev->mac_status;
8266 	if (status >= BWN_MAC_STATUS_STARTED)
8267 		bwn_core_stop(down_dev);
8268 	if (status >= BWN_MAC_STATUS_INITED)
8269 		bwn_core_exit(down_dev);
8270 
8271 	if (down_dev != up_dev)
8272 		bwn_phy_reset(down_dev);
8273 
8274 	up_dev->mac_phy.gmode = gmode;
8275 	if (status >= BWN_MAC_STATUS_INITED) {
8276 		err = bwn_core_init(up_dev);
8277 		if (err) {
8278 			device_printf(sc->sc_dev,
8279 			    "fatal: failed to initialize for %s-GHz\n",
8280 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8281 			goto fail;
8282 		}
8283 	}
8284 	if (status >= BWN_MAC_STATUS_STARTED)
8285 		bwn_core_start(up_dev);
8286 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8287 	sc->sc_curmac = up_dev;
8288 
8289 	return (0);
8290 fail:
8291 	sc->sc_curmac = NULL;
8292 	return (err);
8293 }
8294 
8295 static void
8296 bwn_rf_turnon(struct bwn_mac *mac)
8297 {
8298 
8299 	bwn_mac_suspend(mac);
8300 	mac->mac_phy.rf_onoff(mac, 1);
8301 	mac->mac_phy.rf_on = 1;
8302 	bwn_mac_enable(mac);
8303 }
8304 
8305 static void
8306 bwn_rf_turnoff(struct bwn_mac *mac)
8307 {
8308 
8309 	bwn_mac_suspend(mac);
8310 	mac->mac_phy.rf_onoff(mac, 0);
8311 	mac->mac_phy.rf_on = 0;
8312 	bwn_mac_enable(mac);
8313 }
8314 
8315 static void
8316 bwn_phy_reset(struct bwn_mac *mac)
8317 {
8318 	struct bwn_softc *sc = mac->mac_sc;
8319 
8320 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8322 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8323 	DELAY(1000);
8324 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8325 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8326 	    BWN_TGSLOW_PHYRESET);
8327 	DELAY(1000);
8328 }
8329 
8330 static int
8331 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8332 {
8333 	const struct ieee80211_txparam *tp;
8334 	struct bwn_vap *bvp = BWN_VAP(vap);
8335 	struct ieee80211com *ic= vap->iv_ic;
8336 	struct ifnet *ifp = ic->ic_ifp;
8337 	enum ieee80211_state ostate = vap->iv_state;
8338 	struct bwn_softc *sc = ifp->if_softc;
8339 	struct bwn_mac *mac = sc->sc_curmac;
8340 	int error;
8341 
8342 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8343 	    ieee80211_state_name[vap->iv_state],
8344 	    ieee80211_state_name[nstate]);
8345 
8346 	error = bvp->bv_newstate(vap, nstate, arg);
8347 	if (error != 0)
8348 		return (error);
8349 
8350 	BWN_LOCK(sc);
8351 
8352 	bwn_led_newstate(mac, nstate);
8353 
8354 	/*
8355 	 * Clear the BSSID when we stop a STA
8356 	 */
8357 	if (vap->iv_opmode == IEEE80211_M_STA) {
8358 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8359 			/*
8360 			 * Clear out the BSSID.  If we reassociate to
8361 			 * the same AP, this will reinialize things
8362 			 * correctly...
8363 			 */
8364 			if (ic->ic_opmode == IEEE80211_M_STA &&
8365 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8366 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8367 				bwn_set_macaddr(mac);
8368 			}
8369 		}
8370 	}
8371 
8372 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8373 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8374 		/* XXX nothing to do? */
8375 	} else if (nstate == IEEE80211_S_RUN) {
8376 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8377 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8378 		bwn_set_opmode(mac);
8379 		bwn_set_pretbtt(mac);
8380 		bwn_spu_setdelay(mac, 0);
8381 		bwn_set_macaddr(mac);
8382 
8383 		/* Initializes ratectl for a node. */
8384 		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
8385 		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
8386 			ieee80211_ratectl_node_init(vap->iv_bss);
8387 	}
8388 
8389 	BWN_UNLOCK(sc);
8390 
8391 	return (error);
8392 }
8393 
8394 static void
8395 bwn_set_pretbtt(struct bwn_mac *mac)
8396 {
8397 	struct bwn_softc *sc = mac->mac_sc;
8398 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8399 	uint16_t pretbtt;
8400 
8401 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8402 		pretbtt = 2;
8403 	else
8404 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8405 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8406 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8407 }
8408 
8409 static int
8410 bwn_intr(void *arg)
8411 {
8412 	struct bwn_mac *mac = arg;
8413 	struct bwn_softc *sc = mac->mac_sc;
8414 	uint32_t reason;
8415 
8416 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8417 	    (sc->sc_flags & BWN_FLAG_INVALID))
8418 		return (FILTER_STRAY);
8419 
8420 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8421 	if (reason == 0xffffffff)	/* shared IRQ */
8422 		return (FILTER_STRAY);
8423 	reason &= mac->mac_intr_mask;
8424 	if (reason == 0)
8425 		return (FILTER_HANDLED);
8426 
8427 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8428 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8429 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8430 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8431 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8432 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8433 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8434 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8435 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8436 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8437 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8438 
8439 	/* Disable interrupts. */
8440 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8441 
8442 	mac->mac_reason_intr = reason;
8443 
8444 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8445 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8446 
8447 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8448 	return (FILTER_HANDLED);
8449 }
8450 
8451 static void
8452 bwn_intrtask(void *arg, int npending)
8453 {
8454 	struct bwn_mac *mac = arg;
8455 	struct bwn_softc *sc = mac->mac_sc;
8456 	struct ifnet *ifp = sc->sc_ifp;
8457 	uint32_t merged = 0;
8458 	int i, tx = 0, rx = 0;
8459 
8460 	BWN_LOCK(sc);
8461 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8462 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8463 		BWN_UNLOCK(sc);
8464 		return;
8465 	}
8466 
8467 	for (i = 0; i < N(mac->mac_reason); i++)
8468 		merged |= mac->mac_reason[i];
8469 
8470 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8471 		device_printf(sc->sc_dev, "MAC trans error\n");
8472 
8473 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8474 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8475 		mac->mac_phy.txerrors--;
8476 		if (mac->mac_phy.txerrors == 0) {
8477 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8478 			bwn_restart(mac, "PHY TX errors");
8479 		}
8480 	}
8481 
8482 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8483 		if (merged & BWN_DMAINTR_FATALMASK) {
8484 			device_printf(sc->sc_dev,
8485 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8486 			    mac->mac_reason[0], mac->mac_reason[1],
8487 			    mac->mac_reason[2], mac->mac_reason[3],
8488 			    mac->mac_reason[4], mac->mac_reason[5]);
8489 			bwn_restart(mac, "DMA error");
8490 			BWN_UNLOCK(sc);
8491 			return;
8492 		}
8493 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8494 			device_printf(sc->sc_dev,
8495 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8496 			    mac->mac_reason[0], mac->mac_reason[1],
8497 			    mac->mac_reason[2], mac->mac_reason[3],
8498 			    mac->mac_reason[4], mac->mac_reason[5]);
8499 		}
8500 	}
8501 
8502 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8503 		bwn_intr_ucode_debug(mac);
8504 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8505 		bwn_intr_tbtt_indication(mac);
8506 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8507 		bwn_intr_atim_end(mac);
8508 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8509 		bwn_intr_beacon(mac);
8510 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8511 		bwn_intr_pmq(mac);
8512 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8513 		bwn_intr_noise(mac);
8514 
8515 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8516 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8517 			bwn_dma_rx(mac->mac_method.dma.rx);
8518 			rx = 1;
8519 		}
8520 	} else
8521 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8522 
8523 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8524 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8525 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8526 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8527 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8528 
8529 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8530 		bwn_intr_txeof(mac);
8531 		tx = 1;
8532 	}
8533 
8534 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8535 
8536 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8537 		int evt = BWN_LED_EVENT_NONE;
8538 
8539 		if (tx && rx) {
8540 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8541 				evt = BWN_LED_EVENT_RX;
8542 			else
8543 				evt = BWN_LED_EVENT_TX;
8544 		} else if (tx) {
8545 			evt = BWN_LED_EVENT_TX;
8546 		} else if (rx) {
8547 			evt = BWN_LED_EVENT_RX;
8548 		} else if (rx == 0) {
8549 			evt = BWN_LED_EVENT_POLL;
8550 		}
8551 
8552 		if (evt != BWN_LED_EVENT_NONE)
8553 			bwn_led_event(mac, evt);
8554        }
8555 
8556 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8557 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8558 			bwn_start_locked(ifp);
8559 	}
8560 
8561 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8562 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8563 
8564 	BWN_UNLOCK(sc);
8565 }
8566 
8567 static void
8568 bwn_restart(struct bwn_mac *mac, const char *msg)
8569 {
8570 	struct bwn_softc *sc = mac->mac_sc;
8571 	struct ifnet *ifp = sc->sc_ifp;
8572 	struct ieee80211com *ic = ifp->if_l2com;
8573 
8574 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8575 		return;
8576 
8577 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8578 	ieee80211_runtask(ic, &mac->mac_hwreset);
8579 }
8580 
8581 static void
8582 bwn_intr_ucode_debug(struct bwn_mac *mac)
8583 {
8584 	struct bwn_softc *sc = mac->mac_sc;
8585 	uint16_t reason;
8586 
8587 	if (mac->mac_fw.opensource == 0)
8588 		return;
8589 
8590 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8591 	switch (reason) {
8592 	case BWN_DEBUGINTR_PANIC:
8593 		bwn_handle_fwpanic(mac);
8594 		break;
8595 	case BWN_DEBUGINTR_DUMP_SHM:
8596 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8597 		break;
8598 	case BWN_DEBUGINTR_DUMP_REGS:
8599 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8600 		break;
8601 	case BWN_DEBUGINTR_MARKER:
8602 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8603 		break;
8604 	default:
8605 		device_printf(sc->sc_dev,
8606 		    "ucode debug unknown reason: %#x\n", reason);
8607 	}
8608 
8609 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8610 	    BWN_DEBUGINTR_ACK);
8611 }
8612 
8613 static void
8614 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8615 {
8616 	struct bwn_softc *sc = mac->mac_sc;
8617 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8618 
8619 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8620 		bwn_psctl(mac, 0);
8621 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8622 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8623 }
8624 
8625 static void
8626 bwn_intr_atim_end(struct bwn_mac *mac)
8627 {
8628 
8629 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8630 		BWN_WRITE_4(mac, BWN_MACCMD,
8631 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8632 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8633 	}
8634 }
8635 
8636 static void
8637 bwn_intr_beacon(struct bwn_mac *mac)
8638 {
8639 	struct bwn_softc *sc = mac->mac_sc;
8640 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8641 	uint32_t cmd, beacon0, beacon1;
8642 
8643 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8644 	    ic->ic_opmode == IEEE80211_M_MBSS)
8645 		return;
8646 
8647 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8648 
8649 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8650 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8651 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8652 
8653 	if (beacon0 && beacon1) {
8654 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8655 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8656 		return;
8657 	}
8658 
8659 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8660 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8661 		bwn_load_beacon0(mac);
8662 		bwn_load_beacon1(mac);
8663 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8664 		cmd |= BWN_MACCMD_BEACON0_VALID;
8665 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8666 	} else {
8667 		if (!beacon0) {
8668 			bwn_load_beacon0(mac);
8669 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8670 			cmd |= BWN_MACCMD_BEACON0_VALID;
8671 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8672 		} else if (!beacon1) {
8673 			bwn_load_beacon1(mac);
8674 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8675 			cmd |= BWN_MACCMD_BEACON1_VALID;
8676 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8677 		}
8678 	}
8679 }
8680 
8681 static void
8682 bwn_intr_pmq(struct bwn_mac *mac)
8683 {
8684 	uint32_t tmp;
8685 
8686 	while (1) {
8687 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8688 		if (!(tmp & 0x00000008))
8689 			break;
8690 	}
8691 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8692 }
8693 
8694 static void
8695 bwn_intr_noise(struct bwn_mac *mac)
8696 {
8697 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8698 	uint16_t tmp;
8699 	uint8_t noise[4];
8700 	uint8_t i, j;
8701 	int32_t average;
8702 
8703 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8704 		return;
8705 
8706 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8707 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8708 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8709 	    noise[3] == 0x7f)
8710 		goto new;
8711 
8712 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8713 	    ("%s:%d: fail", __func__, __LINE__));
8714 	i = mac->mac_noise.noi_nsamples;
8715 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8716 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8717 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8718 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8719 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8720 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8721 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8722 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8723 	mac->mac_noise.noi_nsamples++;
8724 	if (mac->mac_noise.noi_nsamples == 8) {
8725 		average = 0;
8726 		for (i = 0; i < 8; i++) {
8727 			for (j = 0; j < 4; j++)
8728 				average += mac->mac_noise.noi_samples[i][j];
8729 		}
8730 		average = (((average / 32) * 125) + 64) / 128;
8731 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8732 		if (tmp >= 8)
8733 			average += 2;
8734 		else
8735 			average -= 25;
8736 		average -= (tmp == 8) ? 72 : 48;
8737 
8738 		mac->mac_stats.link_noise = average;
8739 		mac->mac_noise.noi_running = 0;
8740 		return;
8741 	}
8742 new:
8743 	bwn_noise_gensample(mac);
8744 }
8745 
8746 static int
8747 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8748 {
8749 	struct bwn_mac *mac = prq->prq_mac;
8750 	struct bwn_softc *sc = mac->mac_sc;
8751 	unsigned int i;
8752 
8753 	BWN_ASSERT_LOCKED(sc);
8754 
8755 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8756 		return (0);
8757 
8758 	for (i = 0; i < 5000; i++) {
8759 		if (bwn_pio_rxeof(prq) == 0)
8760 			break;
8761 	}
8762 	if (i >= 5000)
8763 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8764 	return ((i > 0) ? 1 : 0);
8765 }
8766 
8767 static void
8768 bwn_dma_rx(struct bwn_dma_ring *dr)
8769 {
8770 	int slot, curslot;
8771 
8772 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8773 	curslot = dr->get_curslot(dr);
8774 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8775 	    ("%s:%d: fail", __func__, __LINE__));
8776 
8777 	slot = dr->dr_curslot;
8778 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8779 		bwn_dma_rxeof(dr, &slot);
8780 
8781 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8782 	    BUS_DMASYNC_PREWRITE);
8783 
8784 	dr->set_curslot(dr, slot);
8785 	dr->dr_curslot = slot;
8786 }
8787 
8788 static void
8789 bwn_intr_txeof(struct bwn_mac *mac)
8790 {
8791 	struct bwn_txstatus stat;
8792 	uint32_t stat0, stat1;
8793 	uint16_t tmp;
8794 
8795 	BWN_ASSERT_LOCKED(mac->mac_sc);
8796 
8797 	while (1) {
8798 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8799 		if (!(stat0 & 0x00000001))
8800 			break;
8801 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8802 
8803 		stat.cookie = (stat0 >> 16);
8804 		stat.seq = (stat1 & 0x0000ffff);
8805 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8806 		tmp = (stat0 & 0x0000ffff);
8807 		stat.framecnt = ((tmp & 0xf000) >> 12);
8808 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8809 		stat.sreason = ((tmp & 0x001c) >> 2);
8810 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8811 		stat.im = (tmp & 0x0040) ? 1 : 0;
8812 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8813 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8814 
8815 		bwn_handle_txeof(mac, &stat);
8816 	}
8817 }
8818 
8819 static void
8820 bwn_hwreset(void *arg, int npending)
8821 {
8822 	struct bwn_mac *mac = arg;
8823 	struct bwn_softc *sc = mac->mac_sc;
8824 	int error = 0;
8825 	int prev_status;
8826 
8827 	BWN_LOCK(sc);
8828 
8829 	prev_status = mac->mac_status;
8830 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8831 		bwn_core_stop(mac);
8832 	if (prev_status >= BWN_MAC_STATUS_INITED)
8833 		bwn_core_exit(mac);
8834 
8835 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8836 		error = bwn_core_init(mac);
8837 		if (error)
8838 			goto out;
8839 	}
8840 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8841 		bwn_core_start(mac);
8842 out:
8843 	if (error) {
8844 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8845 		sc->sc_curmac = NULL;
8846 	}
8847 	BWN_UNLOCK(sc);
8848 }
8849 
8850 static void
8851 bwn_handle_fwpanic(struct bwn_mac *mac)
8852 {
8853 	struct bwn_softc *sc = mac->mac_sc;
8854 	uint16_t reason;
8855 
8856 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8857 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8858 
8859 	if (reason == BWN_FWPANIC_RESTART)
8860 		bwn_restart(mac, "ucode panic");
8861 }
8862 
8863 static void
8864 bwn_load_beacon0(struct bwn_mac *mac)
8865 {
8866 
8867 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8868 }
8869 
8870 static void
8871 bwn_load_beacon1(struct bwn_mac *mac)
8872 {
8873 
8874 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8875 }
8876 
8877 static uint32_t
8878 bwn_jssi_read(struct bwn_mac *mac)
8879 {
8880 	uint32_t val = 0;
8881 
8882 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8883 	val <<= 16;
8884 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8885 
8886 	return (val);
8887 }
8888 
8889 static void
8890 bwn_noise_gensample(struct bwn_mac *mac)
8891 {
8892 	uint32_t jssi = 0x7f7f7f7f;
8893 
8894 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8895 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8896 	BWN_WRITE_4(mac, BWN_MACCMD,
8897 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8898 }
8899 
8900 static int
8901 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8902 {
8903 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8904 
8905 	return (dr->dr_numslots - dr->dr_usedslot);
8906 }
8907 
8908 static int
8909 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8910 {
8911 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8912 
8913 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8914 	    ("%s:%d: fail", __func__, __LINE__));
8915 	if (slot == dr->dr_numslots - 1)
8916 		return (0);
8917 	return (slot + 1);
8918 }
8919 
8920 static void
8921 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8922 {
8923 	struct bwn_mac *mac = dr->dr_mac;
8924 	struct bwn_softc *sc = mac->mac_sc;
8925 	struct bwn_dma *dma = &mac->mac_method.dma;
8926 	struct bwn_dmadesc_generic *desc;
8927 	struct bwn_dmadesc_meta *meta;
8928 	struct bwn_rxhdr4 *rxhdr;
8929 	struct ifnet *ifp = sc->sc_ifp;
8930 	struct mbuf *m;
8931 	uint32_t macstat;
8932 	int32_t tmp;
8933 	int cnt = 0;
8934 	uint16_t len;
8935 
8936 	dr->getdesc(dr, *slot, &desc, &meta);
8937 
8938 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8939 	m = meta->mt_m;
8940 
8941 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8942 		ifp->if_ierrors++;
8943 		return;
8944 	}
8945 
8946 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8947 	len = le16toh(rxhdr->frame_len);
8948 	if (len <= 0) {
8949 		ifp->if_ierrors++;
8950 		return;
8951 	}
8952 	if (bwn_dma_check_redzone(dr, m)) {
8953 		device_printf(sc->sc_dev, "redzone error.\n");
8954 		bwn_dma_set_redzone(dr, m);
8955 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8956 		    BUS_DMASYNC_PREWRITE);
8957 		return;
8958 	}
8959 	if (len > dr->dr_rx_bufsize) {
8960 		tmp = len;
8961 		while (1) {
8962 			dr->getdesc(dr, *slot, &desc, &meta);
8963 			bwn_dma_set_redzone(dr, meta->mt_m);
8964 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8965 			    BUS_DMASYNC_PREWRITE);
8966 			*slot = bwn_dma_nextslot(dr, *slot);
8967 			cnt++;
8968 			tmp -= dr->dr_rx_bufsize;
8969 			if (tmp <= 0)
8970 				break;
8971 		}
8972 		device_printf(sc->sc_dev, "too small buffer "
8973 		       "(len %u buffer %u dropped %d)\n",
8974 		       len, dr->dr_rx_bufsize, cnt);
8975 		return;
8976 	}
8977 	macstat = le32toh(rxhdr->mac_status);
8978 	if (macstat & BWN_RX_MAC_FCSERR) {
8979 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8980 			device_printf(sc->sc_dev, "RX drop\n");
8981 			return;
8982 		}
8983 	}
8984 
8985 	m->m_pkthdr.rcvif = ifp;
8986 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8987 	m_adj(m, dr->dr_frameoffset);
8988 
8989 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8990 }
8991 
8992 static void
8993 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8994 {
8995 	struct bwn_dma_ring *dr;
8996 	struct bwn_dmadesc_generic *desc;
8997 	struct bwn_dmadesc_meta *meta;
8998 	struct bwn_pio_txqueue *tq;
8999 	struct bwn_pio_txpkt *tp = NULL;
9000 	struct bwn_softc *sc = mac->mac_sc;
9001 	struct bwn_stats *stats = &mac->mac_stats;
9002 	struct ieee80211_node *ni;
9003 	struct ieee80211vap *vap;
9004 	int retrycnt = 0, slot;
9005 
9006 	BWN_ASSERT_LOCKED(mac->mac_sc);
9007 
9008 	if (status->im)
9009 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9010 	if (status->ampdu)
9011 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9012 	if (status->rtscnt) {
9013 		if (status->rtscnt == 0xf)
9014 			stats->rtsfail++;
9015 		else
9016 			stats->rts++;
9017 	}
9018 
9019 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9020 		if (status->ack) {
9021 			dr = bwn_dma_parse_cookie(mac, status,
9022 			    status->cookie, &slot);
9023 			if (dr == NULL) {
9024 				device_printf(sc->sc_dev,
9025 				    "failed to parse cookie\n");
9026 				return;
9027 			}
9028 			while (1) {
9029 				dr->getdesc(dr, slot, &desc, &meta);
9030 				if (meta->mt_islast) {
9031 					ni = meta->mt_ni;
9032 					vap = ni->ni_vap;
9033 					ieee80211_ratectl_tx_complete(vap, ni,
9034 					    status->ack ?
9035 					      IEEE80211_RATECTL_TX_SUCCESS :
9036 					      IEEE80211_RATECTL_TX_FAILURE,
9037 					    &retrycnt, 0);
9038 					break;
9039 				}
9040 				slot = bwn_dma_nextslot(dr, slot);
9041 			}
9042 		}
9043 		bwn_dma_handle_txeof(mac, status);
9044 	} else {
9045 		if (status->ack) {
9046 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9047 			if (tq == NULL) {
9048 				device_printf(sc->sc_dev,
9049 				    "failed to parse cookie\n");
9050 				return;
9051 			}
9052 			ni = tp->tp_ni;
9053 			vap = ni->ni_vap;
9054 			ieee80211_ratectl_tx_complete(vap, ni,
9055 			    status->ack ?
9056 			      IEEE80211_RATECTL_TX_SUCCESS :
9057 			      IEEE80211_RATECTL_TX_FAILURE,
9058 			    &retrycnt, 0);
9059 		}
9060 		bwn_pio_handle_txeof(mac, status);
9061 	}
9062 
9063 	bwn_phy_txpower_check(mac, 0);
9064 }
9065 
9066 static uint8_t
9067 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9068 {
9069 	struct bwn_mac *mac = prq->prq_mac;
9070 	struct bwn_softc *sc = mac->mac_sc;
9071 	struct bwn_rxhdr4 rxhdr;
9072 	struct ifnet *ifp = sc->sc_ifp;
9073 	struct mbuf *m;
9074 	uint32_t ctl32, macstat, v32;
9075 	unsigned int i, padding;
9076 	uint16_t ctl16, len, totlen, v16;
9077 	unsigned char *mp;
9078 	char *data;
9079 
9080 	memset(&rxhdr, 0, sizeof(rxhdr));
9081 
9082 	if (prq->prq_rev >= 8) {
9083 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9084 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9085 			return (0);
9086 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9087 		    BWN_PIO8_RXCTL_FRAMEREADY);
9088 		for (i = 0; i < 10; i++) {
9089 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9090 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9091 				goto ready;
9092 			DELAY(10);
9093 		}
9094 	} else {
9095 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9096 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9097 			return (0);
9098 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9099 		    BWN_PIO_RXCTL_FRAMEREADY);
9100 		for (i = 0; i < 10; i++) {
9101 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9102 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9103 				goto ready;
9104 			DELAY(10);
9105 		}
9106 	}
9107 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9108 	return (1);
9109 ready:
9110 	if (prq->prq_rev >= 8)
9111 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9112 		    prq->prq_base + BWN_PIO8_RXDATA);
9113 	else
9114 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9115 		    prq->prq_base + BWN_PIO_RXDATA);
9116 	len = le16toh(rxhdr.frame_len);
9117 	if (len > 0x700) {
9118 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9119 		goto error;
9120 	}
9121 	if (len == 0) {
9122 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9123 		goto error;
9124 	}
9125 
9126 	macstat = le32toh(rxhdr.mac_status);
9127 	if (macstat & BWN_RX_MAC_FCSERR) {
9128 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9129 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9130 			goto error;
9131 		}
9132 	}
9133 
9134 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9135 	totlen = len + padding;
9136 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9137 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9138 	if (m == NULL) {
9139 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9140 		goto error;
9141 	}
9142 	mp = mtod(m, unsigned char *);
9143 	if (prq->prq_rev >= 8) {
9144 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9145 		    prq->prq_base + BWN_PIO8_RXDATA);
9146 		if (totlen & 3) {
9147 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9148 			data = &(mp[totlen - 1]);
9149 			switch (totlen & 3) {
9150 			case 3:
9151 				*data = (v32 >> 16);
9152 				data--;
9153 			case 2:
9154 				*data = (v32 >> 8);
9155 				data--;
9156 			case 1:
9157 				*data = v32;
9158 			}
9159 		}
9160 	} else {
9161 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9162 		    prq->prq_base + BWN_PIO_RXDATA);
9163 		if (totlen & 1) {
9164 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9165 			mp[totlen - 1] = v16;
9166 		}
9167 	}
9168 
9169 	m->m_pkthdr.rcvif = ifp;
9170 	m->m_len = m->m_pkthdr.len = totlen;
9171 
9172 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9173 
9174 	return (1);
9175 error:
9176 	if (prq->prq_rev >= 8)
9177 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9178 		    BWN_PIO8_RXCTL_DATAREADY);
9179 	else
9180 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9181 	return (1);
9182 }
9183 
9184 static int
9185 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9186     struct bwn_dmadesc_meta *meta, int init)
9187 {
9188 	struct bwn_mac *mac = dr->dr_mac;
9189 	struct bwn_dma *dma = &mac->mac_method.dma;
9190 	struct bwn_rxhdr4 *hdr;
9191 	bus_dmamap_t map;
9192 	bus_addr_t paddr;
9193 	struct mbuf *m;
9194 	int error;
9195 
9196 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9197 	if (m == NULL) {
9198 		error = ENOBUFS;
9199 
9200 		/*
9201 		 * If the NIC is up and running, we need to:
9202 		 * - Clear RX buffer's header.
9203 		 * - Restore RX descriptor settings.
9204 		 */
9205 		if (init)
9206 			return (error);
9207 		else
9208 			goto back;
9209 	}
9210 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9211 
9212 	bwn_dma_set_redzone(dr, m);
9213 
9214 	/*
9215 	 * Try to load RX buf into temporary DMA map
9216 	 */
9217 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9218 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9219 	if (error) {
9220 		m_freem(m);
9221 
9222 		/*
9223 		 * See the comment above
9224 		 */
9225 		if (init)
9226 			return (error);
9227 		else
9228 			goto back;
9229 	}
9230 
9231 	if (!init)
9232 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9233 	meta->mt_m = m;
9234 	meta->mt_paddr = paddr;
9235 
9236 	/*
9237 	 * Swap RX buf's DMA map with the loaded temporary one
9238 	 */
9239 	map = meta->mt_dmap;
9240 	meta->mt_dmap = dr->dr_spare_dmap;
9241 	dr->dr_spare_dmap = map;
9242 
9243 back:
9244 	/*
9245 	 * Clear RX buf header
9246 	 */
9247 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9248 	bzero(hdr, sizeof(*hdr));
9249 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9250 	    BUS_DMASYNC_PREWRITE);
9251 
9252 	/*
9253 	 * Setup RX buf descriptor
9254 	 */
9255 	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9256 	    sizeof(*hdr), 0, 0, 0);
9257 	return (error);
9258 }
9259 
9260 static void
9261 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9262 		 bus_size_t mapsz __unused, int error)
9263 {
9264 
9265 	if (!error) {
9266 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9267 		*((bus_addr_t *)arg) = seg->ds_addr;
9268 	}
9269 }
9270 
9271 static int
9272 bwn_hwrate2ieeerate(int rate)
9273 {
9274 
9275 	switch (rate) {
9276 	case BWN_CCK_RATE_1MB:
9277 		return (2);
9278 	case BWN_CCK_RATE_2MB:
9279 		return (4);
9280 	case BWN_CCK_RATE_5MB:
9281 		return (11);
9282 	case BWN_CCK_RATE_11MB:
9283 		return (22);
9284 	case BWN_OFDM_RATE_6MB:
9285 		return (12);
9286 	case BWN_OFDM_RATE_9MB:
9287 		return (18);
9288 	case BWN_OFDM_RATE_12MB:
9289 		return (24);
9290 	case BWN_OFDM_RATE_18MB:
9291 		return (36);
9292 	case BWN_OFDM_RATE_24MB:
9293 		return (48);
9294 	case BWN_OFDM_RATE_36MB:
9295 		return (72);
9296 	case BWN_OFDM_RATE_48MB:
9297 		return (96);
9298 	case BWN_OFDM_RATE_54MB:
9299 		return (108);
9300 	default:
9301 		printf("Ooops\n");
9302 		return (0);
9303 	}
9304 }
9305 
9306 static void
9307 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9308 {
9309 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9310 	struct bwn_plcp6 *plcp;
9311 	struct bwn_softc *sc = mac->mac_sc;
9312 	struct ieee80211_frame_min *wh;
9313 	struct ieee80211_node *ni;
9314 	struct ifnet *ifp = sc->sc_ifp;
9315 	struct ieee80211com *ic = ifp->if_l2com;
9316 	uint32_t macstat;
9317 	int padding, rate, rssi = 0, noise = 0, type;
9318 	uint16_t phytype, phystat0, phystat3, chanstat;
9319 	unsigned char *mp = mtod(m, unsigned char *);
9320 	static int rx_mac_dec_rpt = 0;
9321 
9322 	BWN_ASSERT_LOCKED(sc);
9323 
9324 	phystat0 = le16toh(rxhdr->phy_status0);
9325 	phystat3 = le16toh(rxhdr->phy_status3);
9326 	macstat = le32toh(rxhdr->mac_status);
9327 	chanstat = le16toh(rxhdr->channel);
9328 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9329 
9330 	if (macstat & BWN_RX_MAC_FCSERR)
9331 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9332 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9333 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9334 	if (macstat & BWN_RX_MAC_DECERR)
9335 		goto drop;
9336 
9337 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9338 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9339 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9340 		    m->m_pkthdr.len);
9341 		goto drop;
9342 	}
9343 	plcp = (struct bwn_plcp6 *)(mp + padding);
9344 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9345 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9346 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9347 		    m->m_pkthdr.len);
9348 		goto drop;
9349 	}
9350 	wh = mtod(m, struct ieee80211_frame_min *);
9351 
9352 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9353 		device_printf(sc->sc_dev,
9354 		    "RX decryption attempted (old %d keyidx %#x)\n",
9355 		    BWN_ISOLDFMT(mac),
9356 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9357 
9358 	/* XXX calculating RSSI & noise & antenna */
9359 
9360 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9361 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9362 		    phytype == BWN_PHYTYPE_A);
9363 	else
9364 		rate = bwn_plcp_get_cckrate(mac, plcp);
9365 	if (rate == -1) {
9366 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9367 			goto drop;
9368 	}
9369 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9370 
9371 	/* RX radio tap */
9372 	if (ieee80211_radiotap_active(ic))
9373 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9374 	m_adj(m, -IEEE80211_CRC_LEN);
9375 
9376 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9377 	noise = mac->mac_stats.link_noise;
9378 
9379 	ifp->if_ipackets++;
9380 
9381 	BWN_UNLOCK(sc);
9382 
9383 	ni = ieee80211_find_rxnode(ic, wh);
9384 	if (ni != NULL) {
9385 		type = ieee80211_input(ni, m, rssi, noise);
9386 		ieee80211_free_node(ni);
9387 	} else
9388 		type = ieee80211_input_all(ic, m, rssi, noise);
9389 
9390 	BWN_LOCK(sc);
9391 	return;
9392 drop:
9393 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9394 }
9395 
9396 static void
9397 bwn_dma_handle_txeof(struct bwn_mac *mac,
9398     const struct bwn_txstatus *status)
9399 {
9400 	struct bwn_dma *dma = &mac->mac_method.dma;
9401 	struct bwn_dma_ring *dr;
9402 	struct bwn_dmadesc_generic *desc;
9403 	struct bwn_dmadesc_meta *meta;
9404 	struct bwn_softc *sc = mac->mac_sc;
9405 	struct ieee80211_node *ni;
9406 	struct ifnet *ifp = sc->sc_ifp;
9407 	struct mbuf *m;
9408 	int slot;
9409 
9410 	BWN_ASSERT_LOCKED(sc);
9411 
9412 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9413 	if (dr == NULL) {
9414 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9415 		return;
9416 	}
9417 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9418 
9419 	while (1) {
9420 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9421 		    ("%s:%d: fail", __func__, __LINE__));
9422 		dr->getdesc(dr, slot, &desc, &meta);
9423 
9424 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9425 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9426 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9427 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9428 
9429 		if (meta->mt_islast) {
9430 			KASSERT(meta->mt_m != NULL,
9431 			    ("%s:%d: fail", __func__, __LINE__));
9432 
9433 			ni = meta->mt_ni;
9434 			m = meta->mt_m;
9435 			if (ni != NULL) {
9436 				/*
9437 				 * Do any tx complete callback. Note this must
9438 				 * be done before releasing the node reference.
9439 				 */
9440 				if (m->m_flags & M_TXCB)
9441 					ieee80211_process_callback(ni, m, 0);
9442 				ieee80211_free_node(ni);
9443 				meta->mt_ni = NULL;
9444 			}
9445 			m_freem(m);
9446 			meta->mt_m = NULL;
9447 		} else {
9448 			KASSERT(meta->mt_m == NULL,
9449 			    ("%s:%d: fail", __func__, __LINE__));
9450 		}
9451 
9452 		dr->dr_usedslot--;
9453 		if (meta->mt_islast) {
9454 			ifp->if_opackets++;
9455 			break;
9456 		}
9457 		slot = bwn_dma_nextslot(dr, slot);
9458 	}
9459 	sc->sc_watchdog_timer = 0;
9460 	if (dr->dr_stop) {
9461 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9462 		    ("%s:%d: fail", __func__, __LINE__));
9463 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9464 		dr->dr_stop = 0;
9465 	}
9466 }
9467 
9468 static void
9469 bwn_pio_handle_txeof(struct bwn_mac *mac,
9470     const struct bwn_txstatus *status)
9471 {
9472 	struct bwn_pio_txqueue *tq;
9473 	struct bwn_pio_txpkt *tp = NULL;
9474 	struct bwn_softc *sc = mac->mac_sc;
9475 	struct ifnet *ifp = sc->sc_ifp;
9476 
9477 	BWN_ASSERT_LOCKED(sc);
9478 
9479 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9480 	if (tq == NULL)
9481 		return;
9482 
9483 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9484 	tq->tq_free++;
9485 
9486 	if (tp->tp_ni != NULL) {
9487 		/*
9488 		 * Do any tx complete callback.  Note this must
9489 		 * be done before releasing the node reference.
9490 		 */
9491 		if (tp->tp_m->m_flags & M_TXCB)
9492 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9493 		ieee80211_free_node(tp->tp_ni);
9494 		tp->tp_ni = NULL;
9495 	}
9496 	m_freem(tp->tp_m);
9497 	tp->tp_m = NULL;
9498 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9499 
9500 	ifp->if_opackets++;
9501 
9502 	sc->sc_watchdog_timer = 0;
9503 	if (tq->tq_stop) {
9504 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9505 		tq->tq_stop = 0;
9506 	}
9507 }
9508 
9509 static void
9510 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9511 {
9512 	struct bwn_softc *sc = mac->mac_sc;
9513 	struct bwn_phy *phy = &mac->mac_phy;
9514 	struct ifnet *ifp = sc->sc_ifp;
9515 	struct ieee80211com *ic = ifp->if_l2com;
9516 	unsigned long now;
9517 	int result;
9518 
9519 	BWN_GETTIME(now);
9520 
9521 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9522 		return;
9523 	phy->nexttime = now + 2 * 1000;
9524 
9525 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9526 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9527 		return;
9528 
9529 	if (phy->recalc_txpwr != NULL) {
9530 		result = phy->recalc_txpwr(mac,
9531 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9532 		if (result == BWN_TXPWR_RES_DONE)
9533 			return;
9534 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9535 		    ("%s: fail", __func__));
9536 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9537 
9538 		ieee80211_runtask(ic, &mac->mac_txpower);
9539 	}
9540 }
9541 
9542 static uint16_t
9543 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9544 {
9545 
9546 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9547 }
9548 
9549 static uint32_t
9550 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9551 {
9552 
9553 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9554 }
9555 
9556 static void
9557 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9558 {
9559 
9560 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9561 }
9562 
9563 static void
9564 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9565 {
9566 
9567 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9568 }
9569 
9570 static int
9571 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9572 {
9573 
9574 	switch (rate) {
9575 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9576 	case 12:
9577 		return (BWN_OFDM_RATE_6MB);
9578 	case 18:
9579 		return (BWN_OFDM_RATE_9MB);
9580 	case 24:
9581 		return (BWN_OFDM_RATE_12MB);
9582 	case 36:
9583 		return (BWN_OFDM_RATE_18MB);
9584 	case 48:
9585 		return (BWN_OFDM_RATE_24MB);
9586 	case 72:
9587 		return (BWN_OFDM_RATE_36MB);
9588 	case 96:
9589 		return (BWN_OFDM_RATE_48MB);
9590 	case 108:
9591 		return (BWN_OFDM_RATE_54MB);
9592 	/* CCK rates (NB: not IEEE std, device-specific) */
9593 	case 2:
9594 		return (BWN_CCK_RATE_1MB);
9595 	case 4:
9596 		return (BWN_CCK_RATE_2MB);
9597 	case 11:
9598 		return (BWN_CCK_RATE_5MB);
9599 	case 22:
9600 		return (BWN_CCK_RATE_11MB);
9601 	}
9602 
9603 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9604 	return (BWN_CCK_RATE_1MB);
9605 }
9606 
9607 static int
9608 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9609     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9610 {
9611 	const struct bwn_phy *phy = &mac->mac_phy;
9612 	struct bwn_softc *sc = mac->mac_sc;
9613 	struct ieee80211_frame *wh;
9614 	struct ieee80211_frame *protwh;
9615 	struct ieee80211_frame_cts *cts;
9616 	struct ieee80211_frame_rts *rts;
9617 	const struct ieee80211_txparam *tp;
9618 	struct ieee80211vap *vap = ni->ni_vap;
9619 	struct ifnet *ifp = sc->sc_ifp;
9620 	struct ieee80211com *ic = ifp->if_l2com;
9621 	struct mbuf *mprot;
9622 	unsigned int len;
9623 	uint32_t macctl = 0;
9624 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9625 	uint16_t phyctl = 0;
9626 	uint8_t rate, rate_fb;
9627 
9628 	wh = mtod(m, struct ieee80211_frame *);
9629 	memset(txhdr, 0, sizeof(*txhdr));
9630 
9631 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9632 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9633 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9634 
9635 	/*
9636 	 * Find TX rate
9637 	 */
9638 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9639 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9640 		rate = rate_fb = tp->mgmtrate;
9641 	else if (ismcast)
9642 		rate = rate_fb = tp->mcastrate;
9643 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9644 		rate = rate_fb = tp->ucastrate;
9645 	else {
9646 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9647 		rate = ni->ni_txrate;
9648 
9649 		if (rix > 0)
9650 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9651 			    IEEE80211_RATE_VAL;
9652 		else
9653 			rate_fb = rate;
9654 	}
9655 
9656 	sc->sc_tx_rate = rate;
9657 
9658 	rate = bwn_ieeerate2hwrate(sc, rate);
9659 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9660 
9661 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9662 	    bwn_plcp_getcck(rate);
9663 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9664 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9665 
9666 	if ((rate_fb == rate) ||
9667 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9668 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9669 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9670 	else
9671 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9672 		    m->m_pkthdr.len, rate, isshort);
9673 
9674 	/* XXX TX encryption */
9675 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9676 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9677 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9678 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9679 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9680 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9681 
9682 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9683 	    BWN_TX_EFT_FB_CCK;
9684 	txhdr->chan = phy->chan;
9685 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9686 	    BWN_TX_PHY_ENC_CCK;
9687 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9688 	     rate == BWN_CCK_RATE_11MB))
9689 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9690 
9691 	/* XXX TX antenna selection */
9692 
9693 	switch (bwn_antenna_sanitize(mac, 0)) {
9694 	case 0:
9695 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9696 		break;
9697 	case 1:
9698 		phyctl |= BWN_TX_PHY_ANT0;
9699 		break;
9700 	case 2:
9701 		phyctl |= BWN_TX_PHY_ANT1;
9702 		break;
9703 	case 3:
9704 		phyctl |= BWN_TX_PHY_ANT2;
9705 		break;
9706 	case 4:
9707 		phyctl |= BWN_TX_PHY_ANT3;
9708 		break;
9709 	default:
9710 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9711 	}
9712 
9713 	if (!ismcast)
9714 		macctl |= BWN_TX_MAC_ACK;
9715 
9716 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9717 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9718 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9719 		macctl |= BWN_TX_MAC_LONGFRAME;
9720 
9721 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9722 		/* XXX RTS rate is always 1MB??? */
9723 		rts_rate = BWN_CCK_RATE_1MB;
9724 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9725 
9726 		protdur = ieee80211_compute_duration(ic->ic_rt,
9727 		    m->m_pkthdr.len, rate, isshort) +
9728 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9729 
9730 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9731 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9732 			    (txhdr->body.old.rts_frame) :
9733 			    (txhdr->body.new.rts_frame));
9734 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9735 			    protdur);
9736 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9737 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9738 			    mprot->m_pkthdr.len);
9739 			m_freem(mprot);
9740 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9741 			len = sizeof(struct ieee80211_frame_cts);
9742 		} else {
9743 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9744 			    (txhdr->body.old.rts_frame) :
9745 			    (txhdr->body.new.rts_frame));
9746 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9747 			    isshort);
9748 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9749 			    wh->i_addr2, protdur);
9750 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9751 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9752 			    mprot->m_pkthdr.len);
9753 			m_freem(mprot);
9754 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9755 			len = sizeof(struct ieee80211_frame_rts);
9756 		}
9757 		len += IEEE80211_CRC_LEN;
9758 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9759 		    &txhdr->body.old.rts_plcp :
9760 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9761 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9762 		    rts_rate_fb);
9763 
9764 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9765 		    (&txhdr->body.old.rts_frame) :
9766 		    (&txhdr->body.new.rts_frame));
9767 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9768 
9769 		if (BWN_ISOFDMRATE(rts_rate)) {
9770 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9771 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9772 		} else {
9773 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9774 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9775 		}
9776 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9777 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9778 	}
9779 
9780 	if (BWN_ISOLDFMT(mac))
9781 		txhdr->body.old.cookie = htole16(cookie);
9782 	else
9783 		txhdr->body.new.cookie = htole16(cookie);
9784 
9785 	txhdr->macctl = htole32(macctl);
9786 	txhdr->phyctl = htole16(phyctl);
9787 
9788 	/*
9789 	 * TX radio tap
9790 	 */
9791 	if (ieee80211_radiotap_active_vap(vap)) {
9792 		sc->sc_tx_th.wt_flags = 0;
9793 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9794 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9795 		if (isshort &&
9796 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9797 		     rate == BWN_CCK_RATE_11MB))
9798 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9799 		sc->sc_tx_th.wt_rate = rate;
9800 
9801 		ieee80211_radiotap_tx(vap, m);
9802 	}
9803 
9804 	return (0);
9805 }
9806 
9807 static void
9808 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9809     const uint8_t rate)
9810 {
9811 	uint32_t d, plen;
9812 	uint8_t *raw = plcp->o.raw;
9813 
9814 	if (BWN_ISOFDMRATE(rate)) {
9815 		d = bwn_plcp_getofdm(rate);
9816 		KASSERT(!(octets & 0xf000),
9817 		    ("%s:%d: fail", __func__, __LINE__));
9818 		d |= (octets << 5);
9819 		plcp->o.data = htole32(d);
9820 	} else {
9821 		plen = octets * 16 / rate;
9822 		if ((octets * 16 % rate) > 0) {
9823 			plen++;
9824 			if ((rate == BWN_CCK_RATE_11MB)
9825 			    && ((octets * 8 % 11) < 4)) {
9826 				raw[1] = 0x84;
9827 			} else
9828 				raw[1] = 0x04;
9829 		} else
9830 			raw[1] = 0x04;
9831 		plcp->o.data |= htole32(plen << 16);
9832 		raw[0] = bwn_plcp_getcck(rate);
9833 	}
9834 }
9835 
9836 static uint8_t
9837 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9838 {
9839 	struct bwn_softc *sc = mac->mac_sc;
9840 	uint8_t mask;
9841 
9842 	if (n == 0)
9843 		return (0);
9844 	if (mac->mac_phy.gmode)
9845 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9846 	else
9847 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9848 	if (!(mask & (1 << (n - 1))))
9849 		return (0);
9850 	return (n);
9851 }
9852 
9853 static uint8_t
9854 bwn_get_fbrate(uint8_t bitrate)
9855 {
9856 	switch (bitrate) {
9857 	case BWN_CCK_RATE_1MB:
9858 		return (BWN_CCK_RATE_1MB);
9859 	case BWN_CCK_RATE_2MB:
9860 		return (BWN_CCK_RATE_1MB);
9861 	case BWN_CCK_RATE_5MB:
9862 		return (BWN_CCK_RATE_2MB);
9863 	case BWN_CCK_RATE_11MB:
9864 		return (BWN_CCK_RATE_5MB);
9865 	case BWN_OFDM_RATE_6MB:
9866 		return (BWN_CCK_RATE_5MB);
9867 	case BWN_OFDM_RATE_9MB:
9868 		return (BWN_OFDM_RATE_6MB);
9869 	case BWN_OFDM_RATE_12MB:
9870 		return (BWN_OFDM_RATE_9MB);
9871 	case BWN_OFDM_RATE_18MB:
9872 		return (BWN_OFDM_RATE_12MB);
9873 	case BWN_OFDM_RATE_24MB:
9874 		return (BWN_OFDM_RATE_18MB);
9875 	case BWN_OFDM_RATE_36MB:
9876 		return (BWN_OFDM_RATE_24MB);
9877 	case BWN_OFDM_RATE_48MB:
9878 		return (BWN_OFDM_RATE_36MB);
9879 	case BWN_OFDM_RATE_54MB:
9880 		return (BWN_OFDM_RATE_48MB);
9881 	}
9882 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9883 	return (0);
9884 }
9885 
9886 static uint32_t
9887 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9888     uint32_t ctl, const void *_data, int len)
9889 {
9890 	struct bwn_softc *sc = mac->mac_sc;
9891 	uint32_t value = 0;
9892 	const uint8_t *data = _data;
9893 
9894 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9895 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9896 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9897 
9898 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9899 	    tq->tq_base + BWN_PIO8_TXDATA);
9900 	if (len & 3) {
9901 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9902 		    BWN_PIO8_TXCTL_24_31);
9903 		data = &(data[len - 1]);
9904 		switch (len & 3) {
9905 		case 3:
9906 			ctl |= BWN_PIO8_TXCTL_16_23;
9907 			value |= (uint32_t)(*data) << 16;
9908 			data--;
9909 		case 2:
9910 			ctl |= BWN_PIO8_TXCTL_8_15;
9911 			value |= (uint32_t)(*data) << 8;
9912 			data--;
9913 		case 1:
9914 			value |= (uint32_t)(*data);
9915 		}
9916 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9917 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9918 	}
9919 
9920 	return (ctl);
9921 }
9922 
9923 static void
9924 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9925     uint16_t offset, uint32_t value)
9926 {
9927 
9928 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9929 }
9930 
9931 static uint16_t
9932 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9933     uint16_t ctl, const void *_data, int len)
9934 {
9935 	struct bwn_softc *sc = mac->mac_sc;
9936 	const uint8_t *data = _data;
9937 
9938 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9939 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9940 
9941 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9942 	    tq->tq_base + BWN_PIO_TXDATA);
9943 	if (len & 1) {
9944 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9945 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9946 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9947 	}
9948 
9949 	return (ctl);
9950 }
9951 
9952 static uint16_t
9953 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9954     uint16_t ctl, struct mbuf *m0)
9955 {
9956 	int i, j = 0;
9957 	uint16_t data = 0;
9958 	const uint8_t *buf;
9959 	struct mbuf *m = m0;
9960 
9961 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9962 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9963 
9964 	for (; m != NULL; m = m->m_next) {
9965 		buf = mtod(m, const uint8_t *);
9966 		for (i = 0; i < m->m_len; i++) {
9967 			if (!((j++) % 2))
9968 				data |= buf[i];
9969 			else {
9970 				data |= (buf[i] << 8);
9971 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9972 				data = 0;
9973 			}
9974 		}
9975 	}
9976 	if (m0->m_pkthdr.len % 2) {
9977 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9978 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9979 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9980 	}
9981 
9982 	return (ctl);
9983 }
9984 
9985 static void
9986 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9987 {
9988 
9989 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9990 		return;
9991 	BWN_WRITE_2(mac, 0x684, 510 + time);
9992 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9993 }
9994 
9995 static struct bwn_dma_ring *
9996 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9997 {
9998 
9999 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10000 		return (mac->mac_method.dma.wme[WME_AC_BE]);
10001 
10002 	switch (prio) {
10003 	case 3:
10004 		return (mac->mac_method.dma.wme[WME_AC_VO]);
10005 	case 2:
10006 		return (mac->mac_method.dma.wme[WME_AC_VI]);
10007 	case 0:
10008 		return (mac->mac_method.dma.wme[WME_AC_BE]);
10009 	case 1:
10010 		return (mac->mac_method.dma.wme[WME_AC_BK]);
10011 	}
10012 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10013 	return (NULL);
10014 }
10015 
10016 static int
10017 bwn_dma_getslot(struct bwn_dma_ring *dr)
10018 {
10019 	int slot;
10020 
10021 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10022 
10023 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10024 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10025 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10026 
10027 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10028 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10029 	dr->dr_curslot = slot;
10030 	dr->dr_usedslot++;
10031 
10032 	return (slot);
10033 }
10034 
10035 static int
10036 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10037 {
10038 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10039 	unsigned int a, b, c, d;
10040 	unsigned int avg;
10041 	uint32_t tmp;
10042 
10043 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10044 	a = tmp & 0xff;
10045 	b = (tmp >> 8) & 0xff;
10046 	c = (tmp >> 16) & 0xff;
10047 	d = (tmp >> 24) & 0xff;
10048 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10049 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10050 		return (ENOENT);
10051 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10052 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10053 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10054 
10055 	if (ofdm) {
10056 		a = (a + 32) & 0x3f;
10057 		b = (b + 32) & 0x3f;
10058 		c = (c + 32) & 0x3f;
10059 		d = (d + 32) & 0x3f;
10060 	}
10061 
10062 	avg = (a + b + c + d + 2) / 4;
10063 	if (ofdm) {
10064 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10065 		    & BWN_HF_4DB_CCK_POWERBOOST)
10066 			avg = (avg >= 13) ? (avg - 13) : 0;
10067 	}
10068 	return (avg);
10069 }
10070 
10071 static void
10072 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10073 {
10074 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10075 	int rfatt = *rfattp;
10076 	int bbatt = *bbattp;
10077 
10078 	while (1) {
10079 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10080 			break;
10081 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10082 			break;
10083 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10084 			break;
10085 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10086 			break;
10087 		if (bbatt > lo->bbatt.max) {
10088 			bbatt -= 4;
10089 			rfatt += 1;
10090 			continue;
10091 		}
10092 		if (bbatt < lo->bbatt.min) {
10093 			bbatt += 4;
10094 			rfatt -= 1;
10095 			continue;
10096 		}
10097 		if (rfatt > lo->rfatt.max) {
10098 			rfatt -= 1;
10099 			bbatt += 4;
10100 			continue;
10101 		}
10102 		if (rfatt < lo->rfatt.min) {
10103 			rfatt += 1;
10104 			bbatt -= 4;
10105 			continue;
10106 		}
10107 		break;
10108 	}
10109 
10110 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10111 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10112 }
10113 
10114 static void
10115 bwn_phy_lock(struct bwn_mac *mac)
10116 {
10117 	struct bwn_softc *sc = mac->mac_sc;
10118 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10119 
10120 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10121 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10122 
10123 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10124 		bwn_psctl(mac, BWN_PS_AWAKE);
10125 }
10126 
10127 static void
10128 bwn_phy_unlock(struct bwn_mac *mac)
10129 {
10130 	struct bwn_softc *sc = mac->mac_sc;
10131 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10132 
10133 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10134 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10135 
10136 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10137 		bwn_psctl(mac, 0);
10138 }
10139 
10140 static void
10141 bwn_rf_lock(struct bwn_mac *mac)
10142 {
10143 
10144 	BWN_WRITE_4(mac, BWN_MACCTL,
10145 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10146 	BWN_READ_4(mac, BWN_MACCTL);
10147 	DELAY(10);
10148 }
10149 
10150 static void
10151 bwn_rf_unlock(struct bwn_mac *mac)
10152 {
10153 
10154 	BWN_READ_2(mac, BWN_PHYVER);
10155 	BWN_WRITE_4(mac, BWN_MACCTL,
10156 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10157 }
10158 
10159 static struct bwn_pio_txqueue *
10160 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10161     struct bwn_pio_txpkt **pack)
10162 {
10163 	struct bwn_pio *pio = &mac->mac_method.pio;
10164 	struct bwn_pio_txqueue *tq = NULL;
10165 	unsigned int index;
10166 
10167 	switch (cookie & 0xf000) {
10168 	case 0x1000:
10169 		tq = &pio->wme[WME_AC_BK];
10170 		break;
10171 	case 0x2000:
10172 		tq = &pio->wme[WME_AC_BE];
10173 		break;
10174 	case 0x3000:
10175 		tq = &pio->wme[WME_AC_VI];
10176 		break;
10177 	case 0x4000:
10178 		tq = &pio->wme[WME_AC_VO];
10179 		break;
10180 	case 0x5000:
10181 		tq = &pio->mcast;
10182 		break;
10183 	}
10184 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10185 	if (tq == NULL)
10186 		return (NULL);
10187 	index = (cookie & 0x0fff);
10188 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10189 	if (index >= N(tq->tq_pkts))
10190 		return (NULL);
10191 	*pack = &tq->tq_pkts[index];
10192 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10193 	return (tq);
10194 }
10195 
10196 static void
10197 bwn_txpwr(void *arg, int npending)
10198 {
10199 	struct bwn_mac *mac = arg;
10200 	struct bwn_softc *sc = mac->mac_sc;
10201 
10202 	BWN_LOCK(sc);
10203 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10204 	    mac->mac_phy.set_txpwr != NULL)
10205 		mac->mac_phy.set_txpwr(mac);
10206 	BWN_UNLOCK(sc);
10207 }
10208 
10209 static void
10210 bwn_task_15s(struct bwn_mac *mac)
10211 {
10212 	uint16_t reg;
10213 
10214 	if (mac->mac_fw.opensource) {
10215 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10216 		if (reg) {
10217 			bwn_restart(mac, "fw watchdog");
10218 			return;
10219 		}
10220 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10221 	}
10222 	if (mac->mac_phy.task_15s)
10223 		mac->mac_phy.task_15s(mac);
10224 
10225 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10226 }
10227 
10228 static void
10229 bwn_task_30s(struct bwn_mac *mac)
10230 {
10231 
10232 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10233 		return;
10234 	mac->mac_noise.noi_running = 1;
10235 	mac->mac_noise.noi_nsamples = 0;
10236 
10237 	bwn_noise_gensample(mac);
10238 }
10239 
10240 static void
10241 bwn_task_60s(struct bwn_mac *mac)
10242 {
10243 
10244 	if (mac->mac_phy.task_60s)
10245 		mac->mac_phy.task_60s(mac);
10246 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10247 }
10248 
10249 static void
10250 bwn_tasks(void *arg)
10251 {
10252 	struct bwn_mac *mac = arg;
10253 	struct bwn_softc *sc = mac->mac_sc;
10254 
10255 	BWN_ASSERT_LOCKED(sc);
10256 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10257 		return;
10258 
10259 	if (mac->mac_task_state % 4 == 0)
10260 		bwn_task_60s(mac);
10261 	if (mac->mac_task_state % 2 == 0)
10262 		bwn_task_30s(mac);
10263 	bwn_task_15s(mac);
10264 
10265 	mac->mac_task_state++;
10266 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10267 }
10268 
10269 static int
10270 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10271 {
10272 	struct bwn_softc *sc = mac->mac_sc;
10273 
10274 	KASSERT(a == 0, ("not support APHY\n"));
10275 
10276 	switch (plcp->o.raw[0] & 0xf) {
10277 	case 0xb:
10278 		return (BWN_OFDM_RATE_6MB);
10279 	case 0xf:
10280 		return (BWN_OFDM_RATE_9MB);
10281 	case 0xa:
10282 		return (BWN_OFDM_RATE_12MB);
10283 	case 0xe:
10284 		return (BWN_OFDM_RATE_18MB);
10285 	case 0x9:
10286 		return (BWN_OFDM_RATE_24MB);
10287 	case 0xd:
10288 		return (BWN_OFDM_RATE_36MB);
10289 	case 0x8:
10290 		return (BWN_OFDM_RATE_48MB);
10291 	case 0xc:
10292 		return (BWN_OFDM_RATE_54MB);
10293 	}
10294 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10295 	    plcp->o.raw[0] & 0xf);
10296 	return (-1);
10297 }
10298 
10299 static int
10300 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10301 {
10302 	struct bwn_softc *sc = mac->mac_sc;
10303 
10304 	switch (plcp->o.raw[0]) {
10305 	case 0x0a:
10306 		return (BWN_CCK_RATE_1MB);
10307 	case 0x14:
10308 		return (BWN_CCK_RATE_2MB);
10309 	case 0x37:
10310 		return (BWN_CCK_RATE_5MB);
10311 	case 0x6e:
10312 		return (BWN_CCK_RATE_11MB);
10313 	}
10314 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10315 	return (-1);
10316 }
10317 
10318 static void
10319 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10320     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10321     int rssi, int noise)
10322 {
10323 	struct bwn_softc *sc = mac->mac_sc;
10324 	const struct ieee80211_frame_min *wh;
10325 	uint64_t tsf;
10326 	uint16_t low_mactime_now;
10327 
10328 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10329 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10330 
10331 	wh = mtod(m, const struct ieee80211_frame_min *);
10332 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10333 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10334 
10335 	bwn_tsf_read(mac, &tsf);
10336 	low_mactime_now = tsf;
10337 	tsf = tsf & ~0xffffULL;
10338 	tsf += le16toh(rxhdr->mac_time);
10339 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10340 		tsf -= 0x10000;
10341 
10342 	sc->sc_rx_th.wr_tsf = tsf;
10343 	sc->sc_rx_th.wr_rate = rate;
10344 	sc->sc_rx_th.wr_antsignal = rssi;
10345 	sc->sc_rx_th.wr_antnoise = noise;
10346 }
10347 
10348 static void
10349 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10350 {
10351 	uint32_t low, high;
10352 
10353 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10354 	    ("%s:%d: fail", __func__, __LINE__));
10355 
10356 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10357 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10358 	*tsf = high;
10359 	*tsf <<= 32;
10360 	*tsf |= low;
10361 }
10362 
10363 static int
10364 bwn_dma_attach(struct bwn_mac *mac)
10365 {
10366 	struct bwn_dma *dma = &mac->mac_method.dma;
10367 	struct bwn_softc *sc = mac->mac_sc;
10368 	bus_addr_t lowaddr = 0;
10369 	int error;
10370 
10371 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10372 		return (0);
10373 
10374 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10375 
10376 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10377 
10378 	dma->dmatype = bwn_dma_gettype(mac);
10379 	if (dma->dmatype == BWN_DMA_30BIT)
10380 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10381 	else if (dma->dmatype == BWN_DMA_32BIT)
10382 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10383 	else
10384 		lowaddr = BUS_SPACE_MAXADDR;
10385 
10386 	/*
10387 	 * Create top level DMA tag
10388 	 */
10389 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10390 			       BWN_ALIGN, 0,		/* alignment, bounds */
10391 			       lowaddr,			/* lowaddr */
10392 			       BUS_SPACE_MAXADDR,	/* highaddr */
10393 			       NULL, NULL,		/* filter, filterarg */
10394 			       MAXBSIZE,		/* maxsize */
10395 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10396 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10397 			       0,			/* flags */
10398 			       NULL, NULL,		/* lockfunc, lockarg */
10399 			       &dma->parent_dtag);
10400 	if (error) {
10401 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10402 		return (error);
10403 	}
10404 
10405 	/*
10406 	 * Create TX/RX mbuf DMA tag
10407 	 */
10408 	error = bus_dma_tag_create(dma->parent_dtag,
10409 				1,
10410 				0,
10411 				BUS_SPACE_MAXADDR,
10412 				BUS_SPACE_MAXADDR,
10413 				NULL, NULL,
10414 				MCLBYTES,
10415 				1,
10416 				BUS_SPACE_MAXSIZE_32BIT,
10417 				0,
10418 				NULL, NULL,
10419 				&dma->rxbuf_dtag);
10420 	if (error) {
10421 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10422 		goto fail0;
10423 	}
10424 	error = bus_dma_tag_create(dma->parent_dtag,
10425 				1,
10426 				0,
10427 				BUS_SPACE_MAXADDR,
10428 				BUS_SPACE_MAXADDR,
10429 				NULL, NULL,
10430 				MCLBYTES,
10431 				1,
10432 				BUS_SPACE_MAXSIZE_32BIT,
10433 				0,
10434 				NULL, NULL,
10435 				&dma->txbuf_dtag);
10436 	if (error) {
10437 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10438 		goto fail1;
10439 	}
10440 
10441 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10442 	if (!dma->wme[WME_AC_BK])
10443 		goto fail2;
10444 
10445 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10446 	if (!dma->wme[WME_AC_BE])
10447 		goto fail3;
10448 
10449 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10450 	if (!dma->wme[WME_AC_VI])
10451 		goto fail4;
10452 
10453 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10454 	if (!dma->wme[WME_AC_VO])
10455 		goto fail5;
10456 
10457 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10458 	if (!dma->mcast)
10459 		goto fail6;
10460 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10461 	if (!dma->rx)
10462 		goto fail7;
10463 
10464 	return (error);
10465 
10466 fail7:	bwn_dma_ringfree(&dma->mcast);
10467 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10468 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10469 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10470 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10471 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10472 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10473 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10474 	return (error);
10475 }
10476 
10477 static struct bwn_dma_ring *
10478 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10479     uint16_t cookie, int *slot)
10480 {
10481 	struct bwn_dma *dma = &mac->mac_method.dma;
10482 	struct bwn_dma_ring *dr;
10483 	struct bwn_softc *sc = mac->mac_sc;
10484 
10485 	BWN_ASSERT_LOCKED(mac->mac_sc);
10486 
10487 	switch (cookie & 0xf000) {
10488 	case 0x1000:
10489 		dr = dma->wme[WME_AC_BK];
10490 		break;
10491 	case 0x2000:
10492 		dr = dma->wme[WME_AC_BE];
10493 		break;
10494 	case 0x3000:
10495 		dr = dma->wme[WME_AC_VI];
10496 		break;
10497 	case 0x4000:
10498 		dr = dma->wme[WME_AC_VO];
10499 		break;
10500 	case 0x5000:
10501 		dr = dma->mcast;
10502 		break;
10503 	default:
10504 		dr = NULL;
10505 		KASSERT(0 == 1,
10506 		    ("invalid cookie value %d", cookie & 0xf000));
10507 	}
10508 	*slot = (cookie & 0x0fff);
10509 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10510 		/*
10511 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10512 		 * that it occurs events which have same H/W sequence numbers.
10513 		 * When it's occurred just prints a WARNING msgs and ignores.
10514 		 */
10515 		KASSERT(status->seq == dma->lastseq,
10516 		    ("%s:%d: fail", __func__, __LINE__));
10517 		device_printf(sc->sc_dev,
10518 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10519 		    dr->dr_numslots);
10520 		return (NULL);
10521 	}
10522 	dma->lastseq = status->seq;
10523 	return (dr);
10524 }
10525 
10526 static void
10527 bwn_dma_stop(struct bwn_mac *mac)
10528 {
10529 	struct bwn_dma *dma;
10530 
10531 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10532 		return;
10533 	dma = &mac->mac_method.dma;
10534 
10535 	bwn_dma_ringstop(&dma->rx);
10536 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10537 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10538 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10539 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10540 	bwn_dma_ringstop(&dma->mcast);
10541 }
10542 
10543 static void
10544 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10545 {
10546 
10547 	if (dr == NULL)
10548 		return;
10549 
10550 	bwn_dma_cleanup(*dr);
10551 }
10552 
10553 static void
10554 bwn_pio_stop(struct bwn_mac *mac)
10555 {
10556 	struct bwn_pio *pio;
10557 
10558 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10559 		return;
10560 	pio = &mac->mac_method.pio;
10561 
10562 	bwn_destroy_queue_tx(&pio->mcast);
10563 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10564 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10565 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10566 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10567 }
10568 
10569 static void
10570 bwn_led_attach(struct bwn_mac *mac)
10571 {
10572 	struct bwn_softc *sc = mac->mac_sc;
10573 	const uint8_t *led_act = NULL;
10574 	uint16_t val[BWN_LED_MAX];
10575 	int i;
10576 
10577 	sc->sc_led_idle = (2350 * hz) / 1000;
10578 	sc->sc_led_blink = 1;
10579 
10580 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10581 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10582 		    bwn_vendor_led_act[i].vid) {
10583 			led_act = bwn_vendor_led_act[i].led_act;
10584 			break;
10585 		}
10586 	}
10587 	if (led_act == NULL)
10588 		led_act = bwn_default_led_act;
10589 
10590 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10591 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10592 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10593 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10594 
10595 	for (i = 0; i < BWN_LED_MAX; ++i) {
10596 		struct bwn_led *led = &sc->sc_leds[i];
10597 
10598 		if (val[i] == 0xff) {
10599 			led->led_act = led_act[i];
10600 		} else {
10601 			if (val[i] & BWN_LED_ACT_LOW)
10602 				led->led_flags |= BWN_LED_F_ACTLOW;
10603 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10604 		}
10605 		led->led_mask = (1 << i);
10606 
10607 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10608 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10609 		    led->led_act == BWN_LED_ACT_BLINK) {
10610 			led->led_flags |= BWN_LED_F_BLINK;
10611 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10612 				led->led_flags |= BWN_LED_F_POLLABLE;
10613 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10614 				led->led_flags |= BWN_LED_F_SLOW;
10615 
10616 			if (sc->sc_blink_led == NULL) {
10617 				sc->sc_blink_led = led;
10618 				if (led->led_flags & BWN_LED_F_SLOW)
10619 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10620 			}
10621 		}
10622 
10623 		DPRINTF(sc, BWN_DEBUG_LED,
10624 		    "%dth led, act %d, lowact %d\n", i,
10625 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10626 	}
10627 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10628 }
10629 
10630 static __inline uint16_t
10631 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10632 {
10633 
10634 	if (led->led_flags & BWN_LED_F_ACTLOW)
10635 		on = !on;
10636 	if (on)
10637 		val |= led->led_mask;
10638 	else
10639 		val &= ~led->led_mask;
10640 	return val;
10641 }
10642 
10643 static void
10644 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10645 {
10646 	struct bwn_softc *sc = mac->mac_sc;
10647 	struct ifnet *ifp = sc->sc_ifp;
10648 	struct ieee80211com *ic = ifp->if_l2com;
10649 	uint16_t val;
10650 	int i;
10651 
10652 	if (nstate == IEEE80211_S_INIT) {
10653 		callout_stop(&sc->sc_led_blink_ch);
10654 		sc->sc_led_blinking = 0;
10655 	}
10656 
10657 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10658 		return;
10659 
10660 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10661 	for (i = 0; i < BWN_LED_MAX; ++i) {
10662 		struct bwn_led *led = &sc->sc_leds[i];
10663 		int on;
10664 
10665 		if (led->led_act == BWN_LED_ACT_UNKN ||
10666 		    led->led_act == BWN_LED_ACT_NULL)
10667 			continue;
10668 
10669 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10670 		    nstate != IEEE80211_S_INIT)
10671 			continue;
10672 
10673 		switch (led->led_act) {
10674 		case BWN_LED_ACT_ON:    /* Always on */
10675 			on = 1;
10676 			break;
10677 		case BWN_LED_ACT_OFF:   /* Always off */
10678 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10679 			on = 0;
10680 			break;
10681 		default:
10682 			on = 1;
10683 			switch (nstate) {
10684 			case IEEE80211_S_INIT:
10685 				on = 0;
10686 				break;
10687 			case IEEE80211_S_RUN:
10688 				if (led->led_act == BWN_LED_ACT_11G &&
10689 				    ic->ic_curmode != IEEE80211_MODE_11G)
10690 					on = 0;
10691 				break;
10692 			default:
10693 				if (led->led_act == BWN_LED_ACT_ASSOC)
10694 					on = 0;
10695 				break;
10696 			}
10697 			break;
10698 		}
10699 
10700 		val = bwn_led_onoff(led, val, on);
10701 	}
10702 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10703 }
10704 
10705 static void
10706 bwn_led_event(struct bwn_mac *mac, int event)
10707 {
10708 	struct bwn_softc *sc = mac->mac_sc;
10709 	struct bwn_led *led = sc->sc_blink_led;
10710 	int rate;
10711 
10712 	if (event == BWN_LED_EVENT_POLL) {
10713 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10714 			return;
10715 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10716 			return;
10717 	}
10718 
10719 	sc->sc_led_ticks = ticks;
10720 	if (sc->sc_led_blinking)
10721 		return;
10722 
10723 	switch (event) {
10724 	case BWN_LED_EVENT_RX:
10725 		rate = sc->sc_rx_rate;
10726 		break;
10727 	case BWN_LED_EVENT_TX:
10728 		rate = sc->sc_tx_rate;
10729 		break;
10730 	case BWN_LED_EVENT_POLL:
10731 		rate = 0;
10732 		break;
10733 	default:
10734 		panic("unknown LED event %d\n", event);
10735 		break;
10736 	}
10737 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10738 	    bwn_led_duration[rate].off_dur);
10739 }
10740 
10741 static void
10742 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10743 {
10744 	struct bwn_softc *sc = mac->mac_sc;
10745 	struct bwn_led *led = sc->sc_blink_led;
10746 	uint16_t val;
10747 
10748 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10749 	val = bwn_led_onoff(led, val, 1);
10750 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10751 
10752 	if (led->led_flags & BWN_LED_F_SLOW) {
10753 		BWN_LED_SLOWDOWN(on_dur);
10754 		BWN_LED_SLOWDOWN(off_dur);
10755 	}
10756 
10757 	sc->sc_led_blinking = 1;
10758 	sc->sc_led_blink_offdur = off_dur;
10759 
10760 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10761 }
10762 
10763 static void
10764 bwn_led_blink_next(void *arg)
10765 {
10766 	struct bwn_mac *mac = arg;
10767 	struct bwn_softc *sc = mac->mac_sc;
10768 	uint16_t val;
10769 
10770 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10771 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10772 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10773 
10774 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10775 	    bwn_led_blink_end, mac);
10776 }
10777 
10778 static void
10779 bwn_led_blink_end(void *arg)
10780 {
10781 	struct bwn_mac *mac = arg;
10782 	struct bwn_softc *sc = mac->mac_sc;
10783 
10784 	sc->sc_led_blinking = 0;
10785 }
10786 
10787 static int
10788 bwn_suspend(device_t dev)
10789 {
10790 	struct bwn_softc *sc = device_get_softc(dev);
10791 
10792 	bwn_stop(sc, 1);
10793 	return (0);
10794 }
10795 
10796 static int
10797 bwn_resume(device_t dev)
10798 {
10799 	struct bwn_softc *sc = device_get_softc(dev);
10800 	struct ifnet *ifp = sc->sc_ifp;
10801 
10802 	if (ifp->if_flags & IFF_UP)
10803 		bwn_init(sc);
10804 	return (0);
10805 }
10806 
10807 static void
10808 bwn_rfswitch(void *arg)
10809 {
10810 	struct bwn_softc *sc = arg;
10811 	struct bwn_mac *mac = sc->sc_curmac;
10812 	int cur = 0, prev = 0;
10813 
10814 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10815 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10816 
10817 	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10818 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10819 			& BWN_RF_HWENABLED_HI_MASK))
10820 			cur = 1;
10821 	} else {
10822 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10823 		    & BWN_RF_HWENABLED_LO_MASK)
10824 			cur = 1;
10825 	}
10826 
10827 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10828 		prev = 1;
10829 
10830 	if (cur != prev) {
10831 		if (cur)
10832 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10833 		else
10834 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10835 
10836 		device_printf(sc->sc_dev,
10837 		    "status of RF switch is changed to %s\n",
10838 		    cur ? "ON" : "OFF");
10839 		if (cur != mac->mac_phy.rf_on) {
10840 			if (cur)
10841 				bwn_rf_turnon(mac);
10842 			else
10843 				bwn_rf_turnoff(mac);
10844 		}
10845 	}
10846 
10847 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10848 }
10849 
10850 static void
10851 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10852 {
10853 	struct bwn_phy *phy = &mac->mac_phy;
10854 	struct bwn_phy_lp *plp = &phy->phy_lp;
10855 
10856 	plp->plp_antenna = BWN_ANT_DEFAULT;
10857 }
10858 
10859 static int
10860 bwn_phy_lp_init(struct bwn_mac *mac)
10861 {
10862 	static const struct bwn_stxtable tables[] = {
10863 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10864 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10865 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10866 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10867 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10868 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10869 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10870 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10871 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10872 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10873 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10874 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10875 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10876 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10877 		{ 2, 11, 0x40, 0, 0x0f }
10878 	};
10879 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10880 	struct bwn_softc *sc = mac->mac_sc;
10881 	const struct bwn_stxtable *st;
10882 	struct ifnet *ifp = sc->sc_ifp;
10883 	struct ieee80211com *ic = ifp->if_l2com;
10884 	int i, error;
10885 	uint16_t tmp;
10886 
10887 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10888 	bwn_phy_lp_bbinit(mac);
10889 
10890 	/* initialize RF */
10891 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10892 	DELAY(1);
10893 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10894 	DELAY(1);
10895 
10896 	if (mac->mac_phy.rf_ver == 0x2062)
10897 		bwn_phy_lp_b2062_init(mac);
10898 	else {
10899 		bwn_phy_lp_b2063_init(mac);
10900 
10901 		/* synchronize stx table. */
10902 		for (i = 0; i < N(tables); i++) {
10903 			st = &tables[i];
10904 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10905 			tmp >>= st->st_rfshift;
10906 			tmp <<= st->st_physhift;
10907 			BWN_PHY_SETMASK(mac,
10908 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10909 			    ~(st->st_mask << st->st_physhift), tmp);
10910 		}
10911 
10912 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10913 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10914 	}
10915 
10916 	/* calibrate RC */
10917 	if (mac->mac_phy.rev >= 2)
10918 		bwn_phy_lp_rxcal_r2(mac);
10919 	else if (!plp->plp_rccap) {
10920 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10921 			bwn_phy_lp_rccal_r12(mac);
10922 	} else
10923 		bwn_phy_lp_set_rccap(mac);
10924 
10925 	error = bwn_phy_lp_switch_channel(mac, 7);
10926 	if (error)
10927 		device_printf(sc->sc_dev,
10928 		    "failed to change channel 7 (%d)\n", error);
10929 	bwn_phy_lp_txpctl_init(mac);
10930 	bwn_phy_lp_calib(mac);
10931 	return (0);
10932 }
10933 
10934 static uint16_t
10935 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10936 {
10937 
10938 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10939 	return (BWN_READ_2(mac, BWN_PHYDATA));
10940 }
10941 
10942 static void
10943 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10944 {
10945 
10946 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10947 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10948 }
10949 
10950 static void
10951 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10952     uint16_t set)
10953 {
10954 
10955 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10956 	BWN_WRITE_2(mac, BWN_PHYDATA,
10957 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10958 }
10959 
10960 static uint16_t
10961 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10962 {
10963 
10964 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10965 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10966 		reg |= 0x100;
10967 	if (mac->mac_phy.rev >= 2)
10968 		reg |= 0x200;
10969 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10970 	return BWN_READ_2(mac, BWN_RFDATALO);
10971 }
10972 
10973 static void
10974 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10975 {
10976 
10977 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10978 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10979 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10980 }
10981 
10982 static void
10983 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10984 {
10985 
10986 	if (on) {
10987 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10988 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10989 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10990 		return;
10991 	}
10992 
10993 	if (mac->mac_phy.rev >= 2) {
10994 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10995 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10996 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10997 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10998 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10999 		return;
11000 	}
11001 
11002 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11003 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11004 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11005 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11006 }
11007 
11008 static int
11009 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11010 {
11011 	struct bwn_phy *phy = &mac->mac_phy;
11012 	struct bwn_phy_lp *plp = &phy->phy_lp;
11013 	int error;
11014 
11015 	if (phy->rf_ver == 0x2063) {
11016 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11017 		if (error)
11018 			return (error);
11019 	} else {
11020 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11021 		if (error)
11022 			return (error);
11023 		bwn_phy_lp_set_anafilter(mac, chan);
11024 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11025 	}
11026 
11027 	plp->plp_chan = chan;
11028 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11029 	return (0);
11030 }
11031 
11032 static uint32_t
11033 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11034 {
11035 	struct bwn_softc *sc = mac->mac_sc;
11036 	struct ifnet *ifp = sc->sc_ifp;
11037 	struct ieee80211com *ic = ifp->if_l2com;
11038 
11039 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11040 }
11041 
11042 static void
11043 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11044 {
11045 	struct bwn_phy *phy = &mac->mac_phy;
11046 	struct bwn_phy_lp *plp = &phy->phy_lp;
11047 
11048 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11049 		return;
11050 
11051 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11052 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11053 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11054 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11055 	plp->plp_antenna = antenna;
11056 }
11057 
11058 static void
11059 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11060 {
11061 
11062 	bwn_phy_lp_calib(mac);
11063 }
11064 
11065 static void
11066 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11067 {
11068 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11069 	struct bwn_softc *sc = mac->mac_sc;
11070 	struct ifnet *ifp = sc->sc_ifp;
11071 	struct ieee80211com *ic = ifp->if_l2com;
11072 
11073 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11074 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11075 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11076 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11077 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11078 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11079 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11080 		return;
11081 	}
11082 
11083 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11084 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11085 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11086 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11087 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11088 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11089 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11090 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11091 }
11092 
11093 static void
11094 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11095 {
11096 
11097 	bwn_phy_lp_tblinit(mac);
11098 	if (mac->mac_phy.rev >= 2)
11099 		bwn_phy_lp_bbinit_r2(mac);
11100 	else
11101 		bwn_phy_lp_bbinit_r01(mac);
11102 }
11103 
11104 static void
11105 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11106 {
11107 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11108 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11109 	struct bwn_softc *sc = mac->mac_sc;
11110 	struct ifnet *ifp = sc->sc_ifp;
11111 	struct ieee80211com *ic = ifp->if_l2com;
11112 
11113 	bwn_phy_lp_set_txgain(mac,
11114 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11115 	bwn_phy_lp_set_bbmult(mac, 150);
11116 }
11117 
11118 static void
11119 bwn_phy_lp_calib(struct bwn_mac *mac)
11120 {
11121 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11122 	struct bwn_softc *sc = mac->mac_sc;
11123 	struct ifnet *ifp = sc->sc_ifp;
11124 	struct ieee80211com *ic = ifp->if_l2com;
11125 	const struct bwn_rxcompco *rc = NULL;
11126 	struct bwn_txgain ogain;
11127 	int i, omode, oafeovr, orf, obbmult;
11128 	uint8_t mode, fc = 0;
11129 
11130 	if (plp->plp_chanfullcal != plp->plp_chan) {
11131 		plp->plp_chanfullcal = plp->plp_chan;
11132 		fc = 1;
11133 	}
11134 
11135 	bwn_mac_suspend(mac);
11136 
11137 	/* BlueTooth Coexistance Override */
11138 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11139 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11140 
11141 	if (mac->mac_phy.rev >= 2)
11142 		bwn_phy_lp_digflt_save(mac);
11143 	bwn_phy_lp_get_txpctlmode(mac);
11144 	mode = plp->plp_txpctlmode;
11145 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11146 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11147 		bwn_phy_lp_bugfix(mac);
11148 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11149 		bwn_phy_lp_get_txpctlmode(mac);
11150 		omode = plp->plp_txpctlmode;
11151 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11152 		if (oafeovr)
11153 			ogain = bwn_phy_lp_get_txgain(mac);
11154 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11155 		obbmult = bwn_phy_lp_get_bbmult(mac);
11156 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11157 		if (oafeovr)
11158 			bwn_phy_lp_set_txgain(mac, &ogain);
11159 		bwn_phy_lp_set_bbmult(mac, obbmult);
11160 		bwn_phy_lp_set_txpctlmode(mac, omode);
11161 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11162 	}
11163 	bwn_phy_lp_set_txpctlmode(mac, mode);
11164 	if (mac->mac_phy.rev >= 2)
11165 		bwn_phy_lp_digflt_restore(mac);
11166 
11167 	/* do RX IQ Calculation; assumes that noise is true. */
11168 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11169 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11170 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11171 				rc = &bwn_rxcompco_5354[i];
11172 		}
11173 	} else if (mac->mac_phy.rev >= 2)
11174 		rc = &bwn_rxcompco_r2;
11175 	else {
11176 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11177 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11178 				rc = &bwn_rxcompco_r12[i];
11179 		}
11180 	}
11181 	if (rc == NULL)
11182 		goto fail;
11183 
11184 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11185 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11186 
11187 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11188 
11189 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11190 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11191 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11192 	} else {
11193 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11194 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11195 	}
11196 
11197 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11198 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11199 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11200 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11201 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11202 	bwn_phy_lp_set_deaf(mac, 0);
11203 	/* XXX no checking return value? */
11204 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11205 	bwn_phy_lp_clear_deaf(mac, 0);
11206 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11207 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11208 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11209 
11210 	/* disable RX GAIN override. */
11211 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11212 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11213 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11214 	if (mac->mac_phy.rev >= 2) {
11215 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11216 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11217 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11218 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11219 		}
11220 	} else {
11221 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11222 	}
11223 
11224 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11225 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11226 fail:
11227 	bwn_mac_enable(mac);
11228 }
11229 
11230 static void
11231 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11232 {
11233 
11234 	if (on) {
11235 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11236 		return;
11237 	}
11238 
11239 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11240 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11241 }
11242 
11243 static int
11244 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11245 {
11246 	static const struct bwn_b206x_chan *bc = NULL;
11247 	struct bwn_softc *sc = mac->mac_sc;
11248 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11249 	    tmp[6];
11250 	uint16_t old, scale, tmp16;
11251 	int i, div;
11252 
11253 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11254 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11255 			bc = &bwn_b2063_chantable[i];
11256 			break;
11257 		}
11258 	}
11259 	if (bc == NULL)
11260 		return (EINVAL);
11261 
11262 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11263 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11264 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11265 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11266 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11267 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11268 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11269 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11270 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11271 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11272 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11273 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11274 
11275 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11276 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11277 
11278 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11279 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11280 	freqref = freqxtal * 3;
11281 	div = (freqxtal <= 26000000 ? 1 : 2);
11282 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11283 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11284 		999999) / 1000000) + 1;
11285 
11286 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11287 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11288 	    0xfff8, timeout >> 2);
11289 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11290 	    0xff9f,timeout << 5);
11291 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11292 
11293 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11294 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11295 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11296 
11297 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11298 	    (timeoutref + 1)) - 1;
11299 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11300 	    0xf0, count >> 8);
11301 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11302 
11303 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11304 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11305 	while (tmp[1] >= freqref) {
11306 		tmp[0]++;
11307 		tmp[1] -= freqref;
11308 	}
11309 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11310 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11311 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11312 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11313 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11314 
11315 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11316 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11317 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11318 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11319 
11320 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11321 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11322 
11323 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11324 		scale = 1;
11325 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11326 	} else {
11327 		scale = 0;
11328 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11329 	}
11330 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11331 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11332 
11333 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11334 	    (scale + 1);
11335 	if (tmp[5] > 150)
11336 		tmp[5] = 0;
11337 
11338 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11339 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11340 
11341 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11342 	if (freqxtal > 26000000)
11343 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11344 	else
11345 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11346 
11347 	if (val[0] == 45)
11348 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11349 	else
11350 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11351 
11352 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11353 	DELAY(1);
11354 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11355 
11356 	/* VCO Calibration */
11357 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11358 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11359 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11360 	DELAY(1);
11361 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11362 	DELAY(1);
11363 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11364 	DELAY(1);
11365 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11366 	DELAY(300);
11367 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11368 
11369 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11370 	return (0);
11371 }
11372 
11373 static int
11374 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11375 {
11376 	struct bwn_softc *sc = mac->mac_sc;
11377 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11378 	const struct bwn_b206x_chan *bc = NULL;
11379 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11380 	uint32_t tmp[9];
11381 	int i;
11382 
11383 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11384 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11385 			bc = &bwn_b2062_chantable[i];
11386 			break;
11387 		}
11388 	}
11389 
11390 	if (bc == NULL)
11391 		return (EINVAL);
11392 
11393 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11394 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11395 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11396 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11397 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11398 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11399 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11400 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11401 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11402 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11403 
11404 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11405 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11406 	bwn_phy_lp_b2062_reset_pllbias(mac);
11407 	tmp[0] = freqxtal / 1000;
11408 	tmp[1] = plp->plp_div * 1000;
11409 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11410 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11411 		tmp[2] *= 2;
11412 	tmp[3] = 48 * tmp[0];
11413 	tmp[5] = tmp[2] / tmp[3];
11414 	tmp[6] = tmp[2] % tmp[3];
11415 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11416 	tmp[4] = tmp[6] * 0x100;
11417 	tmp[5] = tmp[4] / tmp[3];
11418 	tmp[6] = tmp[4] % tmp[3];
11419 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11420 	tmp[4] = tmp[6] * 0x100;
11421 	tmp[5] = tmp[4] / tmp[3];
11422 	tmp[6] = tmp[4] % tmp[3];
11423 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11424 	tmp[4] = tmp[6] * 0x100;
11425 	tmp[5] = tmp[4] / tmp[3];
11426 	tmp[6] = tmp[4] % tmp[3];
11427 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11428 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11429 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11430 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11431 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11432 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11433 
11434 	bwn_phy_lp_b2062_vco_calib(mac);
11435 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11436 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11437 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11438 		bwn_phy_lp_b2062_reset_pllbias(mac);
11439 		bwn_phy_lp_b2062_vco_calib(mac);
11440 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11441 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11442 			return (EIO);
11443 		}
11444 	}
11445 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11446 	return (0);
11447 }
11448 
11449 static void
11450 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11451 {
11452 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11453 	uint16_t tmp = (channel == 14);
11454 
11455 	if (mac->mac_phy.rev < 2) {
11456 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11457 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11458 			bwn_phy_lp_set_rccap(mac);
11459 		return;
11460 	}
11461 
11462 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11463 }
11464 
11465 static void
11466 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11467 {
11468 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11469 	struct bwn_softc *sc = mac->mac_sc;
11470 	struct ifnet *ifp = sc->sc_ifp;
11471 	struct ieee80211com *ic = ifp->if_l2com;
11472 	uint16_t iso, tmp[3];
11473 
11474 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11475 
11476 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11477 		iso = plp->plp_txisoband_m;
11478 	else if (freq <= 5320)
11479 		iso = plp->plp_txisoband_l;
11480 	else if (freq <= 5700)
11481 		iso = plp->plp_txisoband_m;
11482 	else
11483 		iso = plp->plp_txisoband_h;
11484 
11485 	tmp[0] = ((iso - 26) / 12) << 12;
11486 	tmp[1] = tmp[0] + 0x1000;
11487 	tmp[2] = tmp[0] + 0x2000;
11488 
11489 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11490 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11491 }
11492 
11493 static void
11494 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11495 {
11496 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11497 	int i;
11498 	static const uint16_t addr[] = {
11499 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11500 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11501 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11502 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11503 		BWN_PHY_OFDM(0xcf),
11504 	};
11505 	static const uint16_t val[] = {
11506 		0xde5e, 0xe832, 0xe331, 0x4d26,
11507 		0x0026, 0x1420, 0x0020, 0xfe08,
11508 		0x0008,
11509 	};
11510 
11511 	for (i = 0; i < N(addr); i++) {
11512 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11513 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11514 	}
11515 }
11516 
11517 static void
11518 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11519 {
11520 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11521 	struct bwn_softc *sc = mac->mac_sc;
11522 	uint16_t ctl;
11523 
11524 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11525 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11526 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11527 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11528 		break;
11529 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11530 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11531 		break;
11532 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11533 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11534 		break;
11535 	default:
11536 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11537 		device_printf(sc->sc_dev, "unknown command mode\n");
11538 		break;
11539 	}
11540 }
11541 
11542 static void
11543 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11544 {
11545 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11546 	uint16_t ctl;
11547 	uint8_t old;
11548 
11549 	bwn_phy_lp_get_txpctlmode(mac);
11550 	old = plp->plp_txpctlmode;
11551 	if (old == mode)
11552 		return;
11553 	plp->plp_txpctlmode = mode;
11554 
11555 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11556 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11557 		    plp->plp_tssiidx);
11558 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11559 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11560 
11561 		/* disable TX GAIN override */
11562 		if (mac->mac_phy.rev < 2)
11563 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11564 		else {
11565 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11566 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11567 		}
11568 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11569 
11570 		plp->plp_txpwridx = -1;
11571 	}
11572 	if (mac->mac_phy.rev >= 2) {
11573 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11574 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11575 		else
11576 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11577 	}
11578 
11579 	/* writes TX Power Control mode */
11580 	switch (plp->plp_txpctlmode) {
11581 	case BWN_PHYLP_TXPCTL_OFF:
11582 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11583 		break;
11584 	case BWN_PHYLP_TXPCTL_ON_HW:
11585 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11586 		break;
11587 	case BWN_PHYLP_TXPCTL_ON_SW:
11588 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11589 		break;
11590 	default:
11591 		ctl = 0;
11592 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11593 	}
11594 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11595 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11596 }
11597 
11598 static void
11599 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11600 {
11601 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11602 	struct bwn_softc *sc = mac->mac_sc;
11603 	const unsigned int size = 256;
11604 	struct bwn_txgain tg;
11605 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11606 	uint16_t tssinpt, tssiidx, value[2];
11607 	uint8_t mode;
11608 	int8_t txpwridx;
11609 
11610 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11611 	    M_NOWAIT | M_ZERO);
11612 	if (tabs == NULL) {
11613 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11614 		return;
11615 	}
11616 
11617 	bwn_phy_lp_get_txpctlmode(mac);
11618 	mode = plp->plp_txpctlmode;
11619 	txpwridx = plp->plp_txpwridx;
11620 	tssinpt = plp->plp_tssinpt;
11621 	tssiidx = plp->plp_tssiidx;
11622 
11623 	bwn_tab_read_multi(mac,
11624 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11625 	    BWN_TAB_4(7, 0x140), size, tabs);
11626 
11627 	bwn_phy_lp_tblinit(mac);
11628 	bwn_phy_lp_bbinit(mac);
11629 	bwn_phy_lp_txpctl_init(mac);
11630 	bwn_phy_lp_rf_onoff(mac, 1);
11631 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11632 
11633 	bwn_tab_write_multi(mac,
11634 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11635 	    BWN_TAB_4(7, 0x140), size, tabs);
11636 
11637 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11638 	plp->plp_tssinpt = tssinpt;
11639 	plp->plp_tssiidx = tssiidx;
11640 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11641 	if (txpwridx != -1) {
11642 		/* set TX power by index */
11643 		plp->plp_txpwridx = txpwridx;
11644 		bwn_phy_lp_get_txpctlmode(mac);
11645 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11646 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11647 		if (mac->mac_phy.rev >= 2) {
11648 			rxcomp = bwn_tab_read(mac,
11649 			    BWN_TAB_4(7, txpwridx + 320));
11650 			txgain = bwn_tab_read(mac,
11651 			    BWN_TAB_4(7, txpwridx + 192));
11652 			tg.tg_pad = (txgain >> 16) & 0xff;
11653 			tg.tg_gm = txgain & 0xff;
11654 			tg.tg_pga = (txgain >> 8) & 0xff;
11655 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11656 			bwn_phy_lp_set_txgain(mac, &tg);
11657 		} else {
11658 			rxcomp = bwn_tab_read(mac,
11659 			    BWN_TAB_4(10, txpwridx + 320));
11660 			txgain = bwn_tab_read(mac,
11661 			    BWN_TAB_4(10, txpwridx + 192));
11662 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11663 			    0xf800, (txgain >> 4) & 0x7fff);
11664 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11665 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11666 		}
11667 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11668 
11669 		/* set TX IQCC */
11670 		value[0] = (rxcomp >> 10) & 0x3ff;
11671 		value[1] = rxcomp & 0x3ff;
11672 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11673 
11674 		coeff = bwn_tab_read(mac,
11675 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11676 		    BWN_TAB_4(10, txpwridx + 448));
11677 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11678 		if (mac->mac_phy.rev >= 2) {
11679 			rfpwr = bwn_tab_read(mac,
11680 			    BWN_TAB_4(7, txpwridx + 576));
11681 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11682 			    rfpwr & 0xffff);
11683 		}
11684 		bwn_phy_lp_set_txgain_override(mac);
11685 	}
11686 	if (plp->plp_rccap)
11687 		bwn_phy_lp_set_rccap(mac);
11688 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11689 	bwn_phy_lp_set_txpctlmode(mac, mode);
11690 	free(tabs, M_DEVBUF);
11691 }
11692 
11693 static void
11694 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11695 {
11696 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11697 	int i;
11698 	static const uint16_t addr[] = {
11699 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11700 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11701 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11702 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11703 		BWN_PHY_OFDM(0xcf),
11704 	};
11705 
11706 	for (i = 0; i < N(addr); i++)
11707 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11708 }
11709 
11710 static void
11711 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11712 {
11713 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11714 
11715 	if (mac->mac_phy.rev < 2) {
11716 		bwn_phy_lp_tblinit_r01(mac);
11717 		bwn_phy_lp_tblinit_txgain(mac);
11718 		bwn_phy_lp_set_gaintbl(mac, freq);
11719 		return;
11720 	}
11721 
11722 	bwn_phy_lp_tblinit_r2(mac);
11723 	bwn_phy_lp_tblinit_txgain(mac);
11724 }
11725 
11726 struct bwn_wpair {
11727 	uint16_t		reg;
11728 	uint16_t		value;
11729 };
11730 
11731 struct bwn_smpair {
11732 	uint16_t		offset;
11733 	uint16_t		mask;
11734 	uint16_t		set;
11735 };
11736 
11737 static void
11738 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11739 {
11740 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11741 	struct bwn_softc *sc = mac->mac_sc;
11742 	struct ifnet *ifp = sc->sc_ifp;
11743 	struct ieee80211com *ic = ifp->if_l2com;
11744 	static const struct bwn_wpair v1[] = {
11745 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11746 		{ BWN_PHY_AFE_CTL, 0x8800 },
11747 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11748 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11749 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11750 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11751 		{ BWN_PHY_OFDM(0xf9), 0 },
11752 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11753 	};
11754 	static const struct bwn_smpair v2[] = {
11755 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11756 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11757 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11758 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11759 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11760 	};
11761 	static const struct bwn_smpair v3[] = {
11762 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11763 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11764 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11765 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11766 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11767 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11768 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11769 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11770 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11771 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11772 
11773 	};
11774 	int i;
11775 
11776 	for (i = 0; i < N(v1); i++)
11777 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11778 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11779 	for (i = 0; i < N(v2); i++)
11780 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11781 
11782 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11783 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11784 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11785 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11786 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11787 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11788 	} else {
11789 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11790 	}
11791 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11792 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11793 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11794 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11795 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11796 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11797 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11798 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11799 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11800 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11801 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11802 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11803 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11804 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11805 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11806 	} else {
11807 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11808 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11809 	}
11810 	for (i = 0; i < N(v3); i++)
11811 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11812 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11813 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11814 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11815 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11816 	}
11817 
11818 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11819 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11820 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11821 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11822 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11823 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11824 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11825 	} else
11826 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11827 
11828 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11829 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11830 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11831 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11832 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11833 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11834 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11835 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11836 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11837 
11838 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11839 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11840 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11841 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11842 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11843 	}
11844 
11845 	bwn_phy_lp_digflt_save(mac);
11846 }
11847 
11848 static void
11849 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11850 {
11851 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11852 	struct bwn_softc *sc = mac->mac_sc;
11853 	struct ifnet *ifp = sc->sc_ifp;
11854 	struct ieee80211com *ic = ifp->if_l2com;
11855 	static const struct bwn_smpair v1[] = {
11856 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11857 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11858 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11859 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11860 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11861 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11862 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11863 	};
11864 	static const struct bwn_smpair v2[] = {
11865 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11866 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11867 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11868 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11869 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11870 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11871 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11872 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11873 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11874 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11875 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11876 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11877 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11878 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11879 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11880 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11881 	};
11882 	static const struct bwn_smpair v3[] = {
11883 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11884 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11885 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11886 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11887 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11888 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11889 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11890 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11891 	};
11892 	static const struct bwn_smpair v4[] = {
11893 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11894 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11895 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11896 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11897 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11898 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11899 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11900 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11901 	};
11902 	static const struct bwn_smpair v5[] = {
11903 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11904 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11905 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11906 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11907 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11908 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11909 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11910 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11911 	};
11912 	int i;
11913 	uint16_t tmp, tmp2;
11914 
11915 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11916 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11917 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11918 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11919 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11920 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11921 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11922 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11923 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11924 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11925 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11926 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11927 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11928 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11929 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11930 	for (i = 0; i < N(v1); i++)
11931 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11932 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11933 	    0xff00, plp->plp_rxpwroffset);
11934 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11935 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11936 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11937 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11938 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11939 		if (mac->mac_phy.rev == 0)
11940 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11941 			    0xffcf, 0x0010);
11942 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11943 	} else {
11944 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11945 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11946 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11947 	}
11948 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11949 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11950 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11951 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11952 	else
11953 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11954 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11955 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11956 	    0xfff9, (plp->plp_bxarch << 1));
11957 	if (mac->mac_phy.rev == 1 &&
11958 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11959 		for (i = 0; i < N(v2); i++)
11960 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11961 			    v2[i].set);
11962 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11963 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11964 	    ((mac->mac_phy.rev == 0) &&
11965 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11966 		for (i = 0; i < N(v3); i++)
11967 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11968 			    v3[i].set);
11969 	} else if (mac->mac_phy.rev == 1 ||
11970 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11971 		for (i = 0; i < N(v4); i++)
11972 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11973 			    v4[i].set);
11974 	} else {
11975 		for (i = 0; i < N(v5); i++)
11976 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11977 			    v5[i].set);
11978 	}
11979 	if (mac->mac_phy.rev == 1 &&
11980 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11981 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11982 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11983 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11984 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11985 	}
11986 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11987 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11988 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11989 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11990 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11991 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11992 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11993 	}
11994 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11995 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11996 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11997 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11998 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11999 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12000 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12001 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12002 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12003 	} else {
12004 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12005 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12006 	}
12007 	if (mac->mac_phy.rev == 1) {
12008 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12009 		tmp2 = (tmp & 0x03e0) >> 5;
12010 		tmp2 |= tmp2 << 5;
12011 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12012 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12013 		tmp2 = (tmp & 0x1f00) >> 8;
12014 		tmp2 |= tmp2 << 5;
12015 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12016 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12017 		tmp2 = tmp & 0x00ff;
12018 		tmp2 |= tmp << 8;
12019 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12020 	}
12021 }
12022 
12023 struct bwn_b2062_freq {
12024 	uint16_t		freq;
12025 	uint8_t			value[6];
12026 };
12027 
12028 static void
12029 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12030 {
12031 #define	CALC_CTL7(freq, div)						\
12032 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12033 #define	CALC_CTL18(freq, div)						\
12034 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12035 #define	CALC_CTL19(freq, div)						\
12036 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12037 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12038 	struct bwn_softc *sc = mac->mac_sc;
12039 	struct ifnet *ifp = sc->sc_ifp;
12040 	struct ieee80211com *ic = ifp->if_l2com;
12041 	static const struct bwn_b2062_freq freqdata_tab[] = {
12042 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12043 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12044 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12045 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12046 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12047 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12048 	};
12049 	static const struct bwn_wpair v1[] = {
12050 		{ BWN_B2062_N_TXCTL3, 0 },
12051 		{ BWN_B2062_N_TXCTL4, 0 },
12052 		{ BWN_B2062_N_TXCTL5, 0 },
12053 		{ BWN_B2062_N_TXCTL6, 0 },
12054 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12055 		{ BWN_B2062_N_PDNCTL0, 0 },
12056 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12057 		{ BWN_B2062_N_CALIB_TS, 0 }
12058 	};
12059 	const struct bwn_b2062_freq *f = NULL;
12060 	uint32_t xtalfreq, ref;
12061 	unsigned int i;
12062 
12063 	bwn_phy_lp_b2062_tblinit(mac);
12064 
12065 	for (i = 0; i < N(v1); i++)
12066 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12067 	if (mac->mac_phy.rev > 0)
12068 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12069 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12070 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12071 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12072 	else
12073 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12074 
12075 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12076 	    ("%s:%d: fail", __func__, __LINE__));
12077 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12078 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12079 
12080 	if (xtalfreq <= 30000000) {
12081 		plp->plp_div = 1;
12082 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12083 	} else {
12084 		plp->plp_div = 2;
12085 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12086 	}
12087 
12088 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12089 	    CALC_CTL7(xtalfreq, plp->plp_div));
12090 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12091 	    CALC_CTL18(xtalfreq, plp->plp_div));
12092 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12093 	    CALC_CTL19(xtalfreq, plp->plp_div));
12094 
12095 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12096 	ref &= 0xffff;
12097 	for (i = 0; i < N(freqdata_tab); i++) {
12098 		if (ref < freqdata_tab[i].freq) {
12099 			f = &freqdata_tab[i];
12100 			break;
12101 		}
12102 	}
12103 	if (f == NULL)
12104 		f = &freqdata_tab[N(freqdata_tab) - 1];
12105 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12106 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12107 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12108 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12109 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12110 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12111 #undef CALC_CTL7
12112 #undef CALC_CTL18
12113 #undef CALC_CTL19
12114 }
12115 
12116 static void
12117 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12118 {
12119 
12120 	bwn_phy_lp_b2063_tblinit(mac);
12121 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12122 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12123 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12124 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12125 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12126 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12127 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12128 	if (mac->mac_phy.rev == 2) {
12129 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12130 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12131 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12132 	} else {
12133 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12134 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12135 	}
12136 }
12137 
12138 static void
12139 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12140 {
12141 	struct bwn_softc *sc = mac->mac_sc;
12142 	static const struct bwn_wpair v1[] = {
12143 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12144 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12145 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12146 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12147 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12148 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12149 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12150 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12151 	};
12152 	static const struct bwn_wpair v2[] = {
12153 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12154 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12155 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12156 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12157 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12158 	};
12159 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12160 	int i;
12161 	uint8_t tmp;
12162 
12163 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12164 
12165 	for (i = 0; i < 2; i++)
12166 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12167 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12168 	for (i = 2; i < N(v1); i++)
12169 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12170 	for (i = 0; i < 10000; i++) {
12171 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12172 			break;
12173 		DELAY(1000);
12174 	}
12175 
12176 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12177 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12178 
12179 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12180 
12181 	for (i = 0; i < N(v2); i++)
12182 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12183 	if (freqxtal == 24000000) {
12184 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12185 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12186 	} else {
12187 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12188 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12189 	}
12190 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12191 	for (i = 0; i < 10000; i++) {
12192 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12193 			break;
12194 		DELAY(1000);
12195 	}
12196 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12197 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12198 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12199 }
12200 
12201 static void
12202 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12203 {
12204 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12205 	struct bwn_softc *sc = mac->mac_sc;
12206 	struct bwn_phy_lp_iq_est ie;
12207 	struct bwn_txgain tx_gains;
12208 	static const uint32_t pwrtbl[21] = {
12209 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12210 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12211 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12212 		0x0004c, 0x0002c, 0x0001a,
12213 	};
12214 	uint32_t npwr, ipwr, sqpwr, tmp;
12215 	int loopback, i, j, sum, error;
12216 	uint16_t save[7];
12217 	uint8_t txo, bbmult, txpctlmode;
12218 
12219 	error = bwn_phy_lp_switch_channel(mac, 7);
12220 	if (error)
12221 		device_printf(sc->sc_dev,
12222 		    "failed to change channel to 7 (%d)\n", error);
12223 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12224 	bbmult = bwn_phy_lp_get_bbmult(mac);
12225 	if (txo)
12226 		tx_gains = bwn_phy_lp_get_txgain(mac);
12227 
12228 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12229 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12230 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12231 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12232 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12233 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12234 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12235 
12236 	bwn_phy_lp_get_txpctlmode(mac);
12237 	txpctlmode = plp->plp_txpctlmode;
12238 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12239 
12240 	/* disable CRS */
12241 	bwn_phy_lp_set_deaf(mac, 1);
12242 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12243 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12244 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12245 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12246 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12247 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12248 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12249 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12250 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12251 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12252 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12253 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12254 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12255 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12256 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12257 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12258 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12259 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12260 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12261 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12262 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12263 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12264 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12265 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12266 
12267 	loopback = bwn_phy_lp_loopback(mac);
12268 	if (loopback == -1)
12269 		goto done;
12270 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12271 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12272 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12273 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12274 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12275 
12276 	tmp = 0;
12277 	memset(&ie, 0, sizeof(ie));
12278 	for (i = 128; i <= 159; i++) {
12279 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12280 		sum = 0;
12281 		for (j = 5; j <= 25; j++) {
12282 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12283 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12284 				goto done;
12285 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12286 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12287 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12288 			    12);
12289 			sum += ((ipwr - npwr) * (ipwr - npwr));
12290 			if ((i == 128) || (sum < tmp)) {
12291 				plp->plp_rccap = i;
12292 				tmp = sum;
12293 			}
12294 		}
12295 	}
12296 	bwn_phy_lp_ddfs_turnoff(mac);
12297 done:
12298 	/* restore CRS */
12299 	bwn_phy_lp_clear_deaf(mac, 1);
12300 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12301 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12302 
12303 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12304 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12305 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12306 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12307 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12308 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12309 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12310 
12311 	bwn_phy_lp_set_bbmult(mac, bbmult);
12312 	if (txo)
12313 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12314 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12315 	if (plp->plp_rccap)
12316 		bwn_phy_lp_set_rccap(mac);
12317 }
12318 
12319 static void
12320 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12321 {
12322 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12323 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12324 
12325 	if (mac->mac_phy.rev == 1)
12326 		rc_cap = MIN(rc_cap + 5, 15);
12327 
12328 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12329 	    MAX(plp->plp_rccap - 4, 0x80));
12330 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12331 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12332 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12333 }
12334 
12335 static uint32_t
12336 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12337 {
12338 	uint32_t i, q, r;
12339 
12340 	if (div == 0)
12341 		return (0);
12342 
12343 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12344 		q <<= 1;
12345 		if (r << 1 >= div) {
12346 			q++;
12347 			r = (r << 1) - div;
12348 		}
12349 	}
12350 	if (r << 1 >= div)
12351 		q++;
12352 	return (q);
12353 }
12354 
12355 static void
12356 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12357 {
12358 	struct bwn_softc *sc = mac->mac_sc;
12359 
12360 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12361 	DELAY(20);
12362 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12363 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12364 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12365 	} else {
12366 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12367 	}
12368 	DELAY(5);
12369 }
12370 
12371 static void
12372 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12373 {
12374 
12375 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12376 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12377 	DELAY(200);
12378 }
12379 
12380 static void
12381 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12382 {
12383 #define	FLAG_A	0x01
12384 #define	FLAG_G	0x02
12385 	struct bwn_softc *sc = mac->mac_sc;
12386 	struct ifnet *ifp = sc->sc_ifp;
12387 	struct ieee80211com *ic = ifp->if_l2com;
12388 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12389 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12390 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12391 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12392 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12393 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12394 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12395 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12396 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12397 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12398 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12399 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12400 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12401 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12402 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12403 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12404 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12405 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12406 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12407 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12408 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12409 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12410 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12411 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12412 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12413 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12414 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12415 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12416 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12417 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12418 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12419 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12420 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12421 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12422 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12423 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12424 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12425 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12426 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12427 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12428 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12429 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12430 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12431 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12432 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12433 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12434 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12435 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12436 	};
12437 	const struct bwn_b206x_rfinit_entry *br;
12438 	unsigned int i;
12439 
12440 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12441 		br = &bwn_b2062_init_tab[i];
12442 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12443 			if (br->br_flags & FLAG_G)
12444 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12445 		} else {
12446 			if (br->br_flags & FLAG_A)
12447 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12448 		}
12449 	}
12450 #undef FLAG_A
12451 #undef FLAG_B
12452 }
12453 
12454 static void
12455 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12456 {
12457 #define	FLAG_A	0x01
12458 #define	FLAG_G	0x02
12459 	struct bwn_softc *sc = mac->mac_sc;
12460 	struct ifnet *ifp = sc->sc_ifp;
12461 	struct ieee80211com *ic = ifp->if_l2com;
12462 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12463 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12464 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12465 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12466 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12467 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12468 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12469 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12470 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12471 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12472 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12473 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12474 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12475 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12476 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12477 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12478 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12479 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12480 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12481 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12482 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12483 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12484 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12485 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12486 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12487 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12488 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12489 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12490 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12491 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12492 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12493 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12494 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12495 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12496 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12497 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12498 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12499 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12500 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12501 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12502 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12503 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12504 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12505 	};
12506 	const struct bwn_b206x_rfinit_entry *br;
12507 	unsigned int i;
12508 
12509 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12510 		br = &bwn_b2063_init_tab[i];
12511 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12512 			if (br->br_flags & FLAG_G)
12513 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12514 		} else {
12515 			if (br->br_flags & FLAG_A)
12516 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12517 		}
12518 	}
12519 #undef FLAG_A
12520 #undef FLAG_B
12521 }
12522 
12523 static void
12524 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12525     int count, void *_data)
12526 {
12527 	unsigned int i;
12528 	uint32_t offset, type;
12529 	uint8_t *data = _data;
12530 
12531 	type = BWN_TAB_GETTYPE(typenoffset);
12532 	offset = BWN_TAB_GETOFFSET(typenoffset);
12533 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12534 
12535 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12536 
12537 	for (i = 0; i < count; i++) {
12538 		switch (type) {
12539 		case BWN_TAB_8BIT:
12540 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12541 			data++;
12542 			break;
12543 		case BWN_TAB_16BIT:
12544 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12545 			    BWN_PHY_TABLEDATALO);
12546 			data += 2;
12547 			break;
12548 		case BWN_TAB_32BIT:
12549 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12550 			    BWN_PHY_TABLEDATAHI);
12551 			*((uint32_t *)data) <<= 16;
12552 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12553 			    BWN_PHY_TABLEDATALO);
12554 			data += 4;
12555 			break;
12556 		default:
12557 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12558 		}
12559 	}
12560 }
12561 
12562 static void
12563 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12564     int count, const void *_data)
12565 {
12566 	uint32_t offset, type, value;
12567 	const uint8_t *data = _data;
12568 	unsigned int i;
12569 
12570 	type = BWN_TAB_GETTYPE(typenoffset);
12571 	offset = BWN_TAB_GETOFFSET(typenoffset);
12572 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12573 
12574 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12575 
12576 	for (i = 0; i < count; i++) {
12577 		switch (type) {
12578 		case BWN_TAB_8BIT:
12579 			value = *data;
12580 			data++;
12581 			KASSERT(!(value & ~0xff),
12582 			    ("%s:%d: fail", __func__, __LINE__));
12583 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12584 			break;
12585 		case BWN_TAB_16BIT:
12586 			value = *((const uint16_t *)data);
12587 			data += 2;
12588 			KASSERT(!(value & ~0xffff),
12589 			    ("%s:%d: fail", __func__, __LINE__));
12590 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12591 			break;
12592 		case BWN_TAB_32BIT:
12593 			value = *((const uint32_t *)data);
12594 			data += 4;
12595 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12596 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12597 			break;
12598 		default:
12599 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12600 		}
12601 	}
12602 }
12603 
12604 static struct bwn_txgain
12605 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12606 {
12607 	struct bwn_txgain tg;
12608 	uint16_t tmp;
12609 
12610 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12611 	if (mac->mac_phy.rev < 2) {
12612 		tmp = BWN_PHY_READ(mac,
12613 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12614 		tg.tg_gm = tmp & 0x0007;
12615 		tg.tg_pga = (tmp & 0x0078) >> 3;
12616 		tg.tg_pad = (tmp & 0x780) >> 7;
12617 		return (tg);
12618 	}
12619 
12620 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12621 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12622 	tg.tg_gm = tmp & 0xff;
12623 	tg.tg_pga = (tmp >> 8) & 0xff;
12624 	return (tg);
12625 }
12626 
12627 static uint8_t
12628 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12629 {
12630 
12631 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12632 }
12633 
12634 static void
12635 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12636 {
12637 	uint16_t pa;
12638 
12639 	if (mac->mac_phy.rev < 2) {
12640 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12641 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12642 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12643 		bwn_phy_lp_set_txgain_override(mac);
12644 		return;
12645 	}
12646 
12647 	pa = bwn_phy_lp_get_pa_gain(mac);
12648 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12649 	    (tg->tg_pga << 8) | tg->tg_gm);
12650 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12651 	    tg->tg_pad | (pa << 6));
12652 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12653 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12654 	    tg->tg_pad | (pa << 8));
12655 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12656 	bwn_phy_lp_set_txgain_override(mac);
12657 }
12658 
12659 static void
12660 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12661 {
12662 
12663 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12664 }
12665 
12666 static void
12667 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12668 {
12669 	uint16_t trsw = (tx << 1) | rx;
12670 
12671 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12672 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12673 }
12674 
12675 static void
12676 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12677 {
12678 	struct bwn_softc *sc = mac->mac_sc;
12679 	struct ifnet *ifp = sc->sc_ifp;
12680 	struct ieee80211com *ic = ifp->if_l2com;
12681 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12682 
12683 	if (mac->mac_phy.rev < 2) {
12684 		trsw = gain & 0x1;
12685 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12686 		ext_lna = (gain & 2) >> 1;
12687 
12688 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12689 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12690 		    0xfbff, ext_lna << 10);
12691 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12692 		    0xf7ff, ext_lna << 11);
12693 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12694 	} else {
12695 		low_gain = gain & 0xffff;
12696 		high_gain = (gain >> 16) & 0xf;
12697 		ext_lna = (gain >> 21) & 0x1;
12698 		trsw = ~(gain >> 20) & 0x1;
12699 
12700 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12701 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12702 		    0xfdff, ext_lna << 9);
12703 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12704 		    0xfbff, ext_lna << 10);
12705 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12706 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12707 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12708 			tmp = (gain >> 2) & 0x3;
12709 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12710 			    0xe7ff, tmp<<11);
12711 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12712 			    tmp << 3);
12713 		}
12714 	}
12715 
12716 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12717 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12718 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12719 	if (mac->mac_phy.rev >= 2) {
12720 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12721 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12722 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12723 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12724 		}
12725 		return;
12726 	}
12727 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12728 }
12729 
12730 static void
12731 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12732 {
12733 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12734 
12735 	if (user)
12736 		plp->plp_crsusr_off = 1;
12737 	else
12738 		plp->plp_crssys_off = 1;
12739 
12740 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12741 }
12742 
12743 static void
12744 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12745 {
12746 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12747 	struct bwn_softc *sc = mac->mac_sc;
12748 	struct ifnet *ifp = sc->sc_ifp;
12749 	struct ieee80211com *ic = ifp->if_l2com;
12750 
12751 	if (user)
12752 		plp->plp_crsusr_off = 0;
12753 	else
12754 		plp->plp_crssys_off = 0;
12755 
12756 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12757 		return;
12758 
12759 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12760 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12761 	else
12762 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12763 }
12764 
12765 static unsigned int
12766 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12767 {
12768 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12769 	static uint8_t sqrt_table[256] = {
12770 		10, 14, 17, 20, 22, 24, 26, 28,
12771 		30, 31, 33, 34, 36, 37, 38, 40,
12772 		41, 42, 43, 44, 45, 46, 47, 48,
12773 		50, 50, 51, 52, 53, 54, 55, 56,
12774 		57, 58, 59, 60, 60, 61, 62, 63,
12775 		64, 64, 65, 66, 67, 67, 68, 69,
12776 		70, 70, 71, 72, 72, 73, 74, 74,
12777 		75, 76, 76, 77, 78, 78, 79, 80,
12778 		80, 81, 81, 82, 83, 83, 84, 84,
12779 		85, 86, 86, 87, 87, 88, 88, 89,
12780 		90, 90, 91, 91, 92, 92, 93, 93,
12781 		94, 94, 95, 95, 96, 96, 97, 97,
12782 		98, 98, 99, 100, 100, 100, 101, 101,
12783 		102, 102, 103, 103, 104, 104, 105, 105,
12784 		106, 106, 107, 107, 108, 108, 109, 109,
12785 		110, 110, 110, 111, 111, 112, 112, 113,
12786 		113, 114, 114, 114, 115, 115, 116, 116,
12787 		117, 117, 117, 118, 118, 119, 119, 120,
12788 		120, 120, 121, 121, 122, 122, 122, 123,
12789 		123, 124, 124, 124, 125, 125, 126, 126,
12790 		126, 127, 127, 128, 128, 128, 129, 129,
12791 		130, 130, 130, 131, 131, 131, 132, 132,
12792 		133, 133, 133, 134, 134, 134, 135, 135,
12793 		136, 136, 136, 137, 137, 137, 138, 138,
12794 		138, 139, 139, 140, 140, 140, 141, 141,
12795 		141, 142, 142, 142, 143, 143, 143, 144,
12796 		144, 144, 145, 145, 145, 146, 146, 146,
12797 		147, 147, 147, 148, 148, 148, 149, 149,
12798 		150, 150, 150, 150, 151, 151, 151, 152,
12799 		152, 152, 153, 153, 153, 154, 154, 154,
12800 		155, 155, 155, 156, 156, 156, 157, 157,
12801 		157, 158, 158, 158, 159, 159, 159, 160
12802 	};
12803 
12804 	if (x == 0)
12805 		return (0);
12806 	if (x >= 256) {
12807 		unsigned int tmp;
12808 
12809 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12810 			/* do nothing */ ;
12811 		return (tmp);
12812 	}
12813 	return (sqrt_table[x - 1] / 10);
12814 }
12815 
12816 static int
12817 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12818 {
12819 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12820 	int _t;								\
12821 	_t = _x - 20;							\
12822 	if (_t >= 0) {							\
12823 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12824 	} else {							\
12825 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12826 	}								\
12827 } while (0)
12828 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12829 	int _t;								\
12830 	_t = _x - 11;							\
12831 	if (_t >= 0)							\
12832 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12833 	else								\
12834 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12835 } while (0)
12836 	struct bwn_phy_lp_iq_est ie;
12837 	uint16_t v0, v1;
12838 	int tmp[2], ret;
12839 
12840 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12841 	v0 = v1 >> 8;
12842 	v1 |= 0xff;
12843 
12844 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12845 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12846 
12847 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12848 	if (ret == 0)
12849 		goto done;
12850 
12851 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12852 		ret = 0;
12853 		goto done;
12854 	}
12855 
12856 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12857 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12858 
12859 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12860 	v0 = tmp[0] >> 3;
12861 	v1 = tmp[1] >> 4;
12862 done:
12863 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12864 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12865 	return ret;
12866 #undef CALC_COEFF
12867 #undef CALC_COEFF2
12868 }
12869 
12870 static void
12871 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12872 {
12873 	static const uint16_t noisescale[] = {
12874 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12875 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12876 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12877 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12878 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12879 	};
12880 	static const uint16_t crsgainnft[] = {
12881 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12882 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12883 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12884 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12885 		0x013d,
12886 	};
12887 	static const uint16_t filterctl[] = {
12888 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12889 		0xff53, 0x0127,
12890 	};
12891 	static const uint32_t psctl[] = {
12892 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12893 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12894 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12895 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12896 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12897 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12898 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12899 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12900 	};
12901 	static const uint16_t ofdmcckgain_r0[] = {
12902 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12903 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12904 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12905 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12906 		0x755d,
12907 	};
12908 	static const uint16_t ofdmcckgain_r1[] = {
12909 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12910 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12911 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12912 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12913 		0x755d,
12914 	};
12915 	static const uint16_t gaindelta[] = {
12916 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12917 		0x0000,
12918 	};
12919 	static const uint32_t txpwrctl[] = {
12920 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12921 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12922 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12923 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12924 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12925 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12926 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12927 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12928 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12929 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12930 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12931 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12932 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 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, 0x00000000, 0x00000000, 0x00000000,
12958 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12959 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12960 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12961 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12962 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12963 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12964 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12965 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12966 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12967 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12968 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12969 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12970 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12971 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12972 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12973 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12974 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12975 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12976 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12977 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12978 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12979 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12980 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12981 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12982 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12983 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12984 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13000 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13001 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13002 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13003 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13004 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13005 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13006 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13007 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13008 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13009 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13010 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13011 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13012 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13013 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13014 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13015 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13016 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13017 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13018 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13019 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13020 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13021 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13022 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13023 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13024 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13025 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13026 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13027 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13028 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13029 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13030 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13031 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13032 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13033 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13034 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13035 		0x00000702,
13036 	};
13037 
13038 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13039 
13040 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13041 	    bwn_tab_sigsq_tbl);
13042 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13043 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13044 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13045 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13046 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13047 	    bwn_tab_pllfrac_tbl);
13048 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13049 	    bwn_tabl_iqlocal_tbl);
13050 	if (mac->mac_phy.rev == 0) {
13051 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13052 		    ofdmcckgain_r0);
13053 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13054 		    ofdmcckgain_r0);
13055 	} else {
13056 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13057 		    ofdmcckgain_r1);
13058 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13059 		    ofdmcckgain_r1);
13060 	}
13061 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13062 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13063 }
13064 
13065 static void
13066 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13067 {
13068 	struct bwn_softc *sc = mac->mac_sc;
13069 	int i;
13070 	static const uint16_t noisescale[] = {
13071 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13072 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13073 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13074 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13075 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13076 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13077 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13078 	};
13079 	static const uint32_t filterctl[] = {
13080 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13081 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13082 	};
13083 	static const uint32_t psctl[] = {
13084 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13085 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13086 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13087 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13088 	};
13089 	static const uint32_t gainidx[] = {
13090 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13091 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13092 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13093 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13094 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13095 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13096 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13097 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13098 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13099 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13100 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13101 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13102 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13103 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13104 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13105 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13106 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13107 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13108 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13109 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13110 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13111 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13112 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13113 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13114 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13115 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13116 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13117 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13118 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13119 		0x0000001a, 0x64ca55ad, 0x0000001a
13120 	};
13121 	static const uint16_t auxgainidx[] = {
13122 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13123 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13124 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13125 		0x0004, 0x0016
13126 	};
13127 	static const uint16_t swctl[] = {
13128 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13129 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13130 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13131 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13132 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13133 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13134 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13135 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13136 	};
13137 	static const uint8_t hf[] = {
13138 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13139 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13140 	};
13141 	static const uint32_t gainval[] = {
13142 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13143 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13144 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13145 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13146 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13147 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13148 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13149 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13150 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13151 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13152 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13153 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13154 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13155 		0x000000f1, 0x00000000, 0x00000000
13156 	};
13157 	static const uint16_t gain[] = {
13158 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13159 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13160 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13161 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13162 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13163 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 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 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13170 	};
13171 	static const uint32_t papdeps[] = {
13172 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13173 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13174 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13175 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13176 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13177 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13178 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13179 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13180 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13181 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13182 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13183 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13184 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13185 	};
13186 	static const uint32_t papdmult[] = {
13187 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13188 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13189 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13190 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13191 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13192 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13193 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13194 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13195 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13196 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13197 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13198 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13199 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13200 	};
13201 	static const uint32_t gainidx_a0[] = {
13202 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13203 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13204 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13205 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13206 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13207 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13208 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13209 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13210 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13211 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13212 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13213 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13214 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13215 	};
13216 	static const uint16_t auxgainidx_a0[] = {
13217 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13218 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13219 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13220 		0x0002, 0x0014
13221 	};
13222 	static const uint32_t gainval_a0[] = {
13223 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13224 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13225 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13226 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13227 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13228 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13229 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13231 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13232 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13233 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13234 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13235 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13236 		0x000000f7, 0x00000000, 0x00000000
13237 	};
13238 	static const uint16_t gain_a0[] = {
13239 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13240 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13241 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13242 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13243 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13244 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 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 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13251 	};
13252 
13253 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13254 
13255 	for (i = 0; i < 704; i++)
13256 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13257 
13258 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13259 	    bwn_tab_sigsq_tbl);
13260 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13261 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13262 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13263 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13264 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13265 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13266 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13267 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13268 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13269 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13270 	    bwn_tab_pllfrac_tbl);
13271 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13272 	    bwn_tabl_iqlocal_tbl);
13273 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13274 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13275 
13276 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13277 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13278 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13279 		    gainidx_a0);
13280 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13281 		    auxgainidx_a0);
13282 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13283 		    gainval_a0);
13284 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13285 	}
13286 }
13287 
13288 static void
13289 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13290 {
13291 	struct bwn_softc *sc = mac->mac_sc;
13292 	struct ifnet *ifp = sc->sc_ifp;
13293 	struct ieee80211com *ic = ifp->if_l2com;
13294 	static struct bwn_txgain_entry txgain_r2[] = {
13295 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13296 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13297 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13298 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13299 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13300 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13301 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13302 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13303 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13304 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13305 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13306 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13307 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13308 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13309 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13310 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13311 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13312 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13313 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13314 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13315 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13316 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13317 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13318 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13319 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13320 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13321 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13322 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13323 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13324 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13325 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13326 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13327 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13328 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13329 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13330 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13331 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13332 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13333 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13334 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13335 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13336 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13337 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13338 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13339 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13340 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13341 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13342 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13343 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13344 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13345 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13346 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13347 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13348 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13349 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13350 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13351 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13352 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13353 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13354 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13355 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13356 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13357 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13358 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13359 	};
13360 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13361 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13362 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13363 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13364 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13365 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13366 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13367 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13368 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13369 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13370 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13371 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13372 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13373 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13374 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13375 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13376 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13377 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13378 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13379 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13380 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13381 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13382 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13383 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13384 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13385 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13386 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13387 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13388 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13389 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13390 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13391 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13392 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13393 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13394 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13395 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13396 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13397 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13398 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13399 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13400 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13401 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13402 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13403 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13404 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13405 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13406 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13407 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13408 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13409 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13410 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13411 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13412 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13413 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13414 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13415 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13416 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13417 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13418 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13419 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13420 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13421 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13422 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13423 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13424 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13425 	};
13426 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13427 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13428 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13429 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13430 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13431 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13432 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13433 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13434 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13435 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13436 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13437 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13438 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13439 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13440 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13441 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13442 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13443 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13444 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13445 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13446 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13447 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13448 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13449 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13450 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13451 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13452 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13453 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13454 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13455 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13456 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13457 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13458 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13459 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13460 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13461 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13462 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13463 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13464 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13465 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13466 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13467 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13468 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13469 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13470 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13471 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13472 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13473 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13474 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13475 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13476 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13477 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13478 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13479 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13480 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13481 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13482 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13483 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13484 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13485 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13486 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13487 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13488 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13489 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13490 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13491 	};
13492 	static struct bwn_txgain_entry txgain_r0[] = {
13493 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13494 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13495 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13496 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13497 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13498 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13499 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13500 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13501 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13502 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13503 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13504 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13505 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13506 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13507 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13508 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13509 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13510 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13511 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13512 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13513 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13514 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13515 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13516 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13517 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13518 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13519 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13520 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13521 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13522 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13523 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13524 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13525 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13526 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13527 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13528 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13529 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13530 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13531 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13532 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13533 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13534 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13535 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13536 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13537 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13538 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13539 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13540 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13541 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13542 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13543 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13544 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13545 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13546 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13547 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13548 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13549 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13550 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13551 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13552 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13553 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13554 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13555 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13556 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13557 	};
13558 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13559 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13560 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13561 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13562 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13563 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13564 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13565 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13566 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13567 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13568 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13569 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13570 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13571 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13572 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13573 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13574 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13575 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13576 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13577 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13578 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13579 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13580 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13581 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13582 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13583 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13584 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13585 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13586 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13587 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13588 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13589 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13590 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13591 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13592 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13593 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13594 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13595 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13596 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13597 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13598 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13599 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13600 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13601 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13602 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13603 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13604 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13605 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13606 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13607 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13608 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13609 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13610 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13611 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13612 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13613 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13614 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13615 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13616 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13617 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13618 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13619 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13620 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13621 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13622 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13623 	};
13624 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13625 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13626 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13627 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13628 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13629 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13630 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13631 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13632 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13633 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13634 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13635 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13636 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13637 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13638 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13639 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13640 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13641 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13642 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13643 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13644 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13645 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13646 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13647 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13648 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13649 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13650 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13651 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13652 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13653 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13654 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13655 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13656 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13657 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13658 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13659 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13660 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13661 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13662 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13663 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13664 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13665 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13666 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13667 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13668 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13669 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13670 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13671 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13672 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13673 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13674 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13675 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13676 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13677 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13678 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13679 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13680 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13681 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13682 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13683 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13684 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13685 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13686 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13687 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13688 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13689 	};
13690 	static struct bwn_txgain_entry txgain_r1[] = {
13691 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13692 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13693 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13694 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13695 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13696 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13697 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13698 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13699 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13700 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13701 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13702 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13703 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13704 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13705 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13706 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13707 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13708 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13709 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13710 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13711 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13712 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13713 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13714 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13715 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13716 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13717 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13718 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13719 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13720 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13721 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13722 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13723 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13724 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13725 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13726 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13727 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13728 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13729 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13730 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13731 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13732 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13733 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13734 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13735 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13736 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13737 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13738 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13739 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13740 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13741 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13742 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13743 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13744 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13745 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13746 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13747 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13748 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13749 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13750 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13751 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13752 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13753 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13754 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13755 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13756 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13757 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13758 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13759 		{ 7, 11, 6, 0, 71 }
13760 	};
13761 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13762 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13763 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13764 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13765 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13766 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13767 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13768 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13769 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13770 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13771 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13772 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13773 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13774 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13775 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13776 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13777 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13778 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13779 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13780 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13781 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13782 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13783 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13784 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13785 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13786 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13787 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13788 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13789 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13790 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13791 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13792 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13793 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13794 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13795 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13796 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13797 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13798 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13799 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13800 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13801 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13802 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13803 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13804 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13805 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13806 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13807 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13808 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13809 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13810 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13811 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13812 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13813 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13814 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13815 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13816 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13817 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13818 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13819 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13820 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13821 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13822 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13823 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13824 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13825 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13826 	};
13827 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13828 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13829 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13830 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13831 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13832 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13833 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13834 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13835 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13836 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13837 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13838 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13839 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13840 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13841 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13842 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13843 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13844 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13845 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13846 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13847 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13848 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13849 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13850 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13851 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13852 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13853 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13854 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13855 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13856 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13857 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13858 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13859 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13860 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13861 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13862 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13863 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13864 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13865 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13866 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13867 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13868 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13869 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13870 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13871 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13872 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13873 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13874 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13875 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13876 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13877 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13878 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13879 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13880 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13881 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13882 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13883 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13884 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13885 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13886 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13887 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13888 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13889 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13890 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13891 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13892 	};
13893 
13894 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13895 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13896 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13897 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13898 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13899 			    txgain_2ghz_r2);
13900 		else
13901 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902 			    txgain_5ghz_r2);
13903 		return;
13904 	}
13905 
13906 	if (mac->mac_phy.rev == 0) {
13907 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13908 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13909 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13910 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13911 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13912 			    txgain_2ghz_r0);
13913 		else
13914 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13915 			    txgain_5ghz_r0);
13916 		return;
13917 	}
13918 
13919 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13920 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13921 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13922 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13923 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13924 	else
13925 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13926 }
13927 
13928 static void
13929 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13930 {
13931 	uint32_t offset, type;
13932 
13933 	type = BWN_TAB_GETTYPE(typeoffset);
13934 	offset = BWN_TAB_GETOFFSET(typeoffset);
13935 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13936 
13937 	switch (type) {
13938 	case BWN_TAB_8BIT:
13939 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13940 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13941 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13942 		break;
13943 	case BWN_TAB_16BIT:
13944 		KASSERT(!(value & ~0xffff),
13945 		    ("%s:%d: fail", __func__, __LINE__));
13946 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13947 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13948 		break;
13949 	case BWN_TAB_32BIT:
13950 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13951 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13952 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13953 		break;
13954 	default:
13955 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13956 	}
13957 }
13958 
13959 static int
13960 bwn_phy_lp_loopback(struct bwn_mac *mac)
13961 {
13962 	struct bwn_phy_lp_iq_est ie;
13963 	int i, index = -1;
13964 	uint32_t tmp;
13965 
13966 	memset(&ie, 0, sizeof(ie));
13967 
13968 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13969 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13970 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13971 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13972 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13973 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13974 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13975 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13976 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13977 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13978 	for (i = 0; i < 32; i++) {
13979 		bwn_phy_lp_set_rxgain_idx(mac, i);
13980 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13981 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13982 			continue;
13983 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13984 		if ((tmp > 4000) && (tmp < 10000)) {
13985 			index = i;
13986 			break;
13987 		}
13988 	}
13989 	bwn_phy_lp_ddfs_turnoff(mac);
13990 	return (index);
13991 }
13992 
13993 static void
13994 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13995 {
13996 
13997 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13998 }
13999 
14000 static void
14001 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14002     int incr1, int incr2, int scale_idx)
14003 {
14004 
14005 	bwn_phy_lp_ddfs_turnoff(mac);
14006 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14007 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14008 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14009 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14010 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14011 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14012 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14013 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14014 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14015 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14016 }
14017 
14018 static uint8_t
14019 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14020     struct bwn_phy_lp_iq_est *ie)
14021 {
14022 	int i;
14023 
14024 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14025 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14026 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14027 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14028 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14029 
14030 	for (i = 0; i < 500; i++) {
14031 		if (!(BWN_PHY_READ(mac,
14032 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14033 			break;
14034 		DELAY(1000);
14035 	}
14036 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14037 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14038 		return 0;
14039 	}
14040 
14041 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14042 	ie->ie_iqprod <<= 16;
14043 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14044 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14045 	ie->ie_ipwr <<= 16;
14046 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14047 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14048 	ie->ie_qpwr <<= 16;
14049 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14050 
14051 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14052 	return 1;
14053 }
14054 
14055 static uint32_t
14056 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14057 {
14058 	uint32_t offset, type, value;
14059 
14060 	type = BWN_TAB_GETTYPE(typeoffset);
14061 	offset = BWN_TAB_GETOFFSET(typeoffset);
14062 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14063 
14064 	switch (type) {
14065 	case BWN_TAB_8BIT:
14066 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14067 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14068 		break;
14069 	case BWN_TAB_16BIT:
14070 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14071 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14072 		break;
14073 	case BWN_TAB_32BIT:
14074 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14075 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14076 		value <<= 16;
14077 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14078 		break;
14079 	default:
14080 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14081 		value = 0;
14082 	}
14083 
14084 	return (value);
14085 }
14086 
14087 static void
14088 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14089 {
14090 
14091 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14092 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14093 }
14094 
14095 static void
14096 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14097 {
14098 	uint16_t ctl;
14099 
14100 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14101 	ctl |= dac << 7;
14102 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14103 }
14104 
14105 static void
14106 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14107 {
14108 
14109 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14110 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14111 }
14112 
14113 static void
14114 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14115 {
14116 
14117 	if (mac->mac_phy.rev < 2)
14118 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14119 	else {
14120 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14121 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14122 	}
14123 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14124 }
14125 
14126 static uint16_t
14127 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14128 {
14129 
14130 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14131 }
14132 
14133 static uint8_t
14134 bwn_nbits(int32_t val)
14135 {
14136 	uint32_t tmp;
14137 	uint8_t nbits = 0;
14138 
14139 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14140 		nbits++;
14141 	return (nbits);
14142 }
14143 
14144 static void
14145 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14146     struct bwn_txgain_entry *table)
14147 {
14148 	int i;
14149 
14150 	for (i = offset; i < count; i++)
14151 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14152 }
14153 
14154 static void
14155 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14156     struct bwn_txgain_entry data)
14157 {
14158 
14159 	if (mac->mac_phy.rev >= 2)
14160 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14161 	else
14162 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14163 }
14164 
14165 static void
14166 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14167     struct bwn_txgain_entry te)
14168 {
14169 	struct bwn_softc *sc = mac->mac_sc;
14170 	struct ifnet *ifp = sc->sc_ifp;
14171 	struct ieee80211com *ic = ifp->if_l2com;
14172 	uint32_t tmp;
14173 
14174 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14175 
14176 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14177 	if (mac->mac_phy.rev >= 3) {
14178 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14179 		    (0x10 << 24) : (0x70 << 24));
14180 	} else {
14181 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14182 		    (0x14 << 24) : (0x7f << 24));
14183 	}
14184 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14185 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14186 	    te.te_bbmult << 20 | te.te_dac << 28);
14187 }
14188 
14189 static void
14190 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14191     struct bwn_txgain_entry te)
14192 {
14193 
14194 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14195 
14196 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14197 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14198 	    te.te_dac);
14199 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14200 }
14201 
14202 static void
14203 bwn_sysctl_node(struct bwn_softc *sc)
14204 {
14205 	device_t dev = sc->sc_dev;
14206 	struct bwn_mac *mac;
14207 	struct bwn_stats *stats;
14208 
14209 	/* XXX assume that count of MAC is only 1. */
14210 
14211 	if ((mac = sc->sc_curmac) == NULL)
14212 		return;
14213 	stats = &mac->mac_stats;
14214 
14215 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14216 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14217 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14218 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14219 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14220 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14221 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14222 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14223 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14224 
14225 #ifdef BWN_DEBUG
14226 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14227 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14228 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14229 #endif
14230 }
14231 
14232 static device_method_t bwn_methods[] = {
14233 	/* Device interface */
14234 	DEVMETHOD(device_probe,		bwn_probe),
14235 	DEVMETHOD(device_attach,	bwn_attach),
14236 	DEVMETHOD(device_detach,	bwn_detach),
14237 	DEVMETHOD(device_suspend,	bwn_suspend),
14238 	DEVMETHOD(device_resume,	bwn_resume),
14239 	KOBJMETHOD_END
14240 };
14241 static driver_t bwn_driver = {
14242 	"bwn",
14243 	bwn_methods,
14244 	sizeof(struct bwn_softc)
14245 };
14246 static devclass_t bwn_devclass;
14247 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14248 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14249 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14250 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14251 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14252