xref: /freebsd/sys/dev/bwn/if_bwn.c (revision 7d536dc855c85c15bf45f033d108a61b1f3cecc3)
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/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/endian.h>
43 #include <sys/errno.h>
44 #include <sys/firmware.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/bus.h>
50 #include <sys/rman.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 
54 #include <net/ethernet.h>
55 #include <net/if.h>
56 #include <net/if_var.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_llc.h>
60 #include <net/if_media.h>
61 #include <net/if_types.h>
62 
63 #include <dev/pci/pcivar.h>
64 #include <dev/pci/pcireg.h>
65 #include <dev/siba/siba_ids.h>
66 #include <dev/siba/sibareg.h>
67 #include <dev/siba/sibavar.h>
68 
69 #include <net80211/ieee80211_var.h>
70 #include <net80211/ieee80211_radiotap.h>
71 #include <net80211/ieee80211_regdomain.h>
72 #include <net80211/ieee80211_phy.h>
73 #include <net80211/ieee80211_ratectl.h>
74 
75 #include <dev/bwn/if_bwnreg.h>
76 #include <dev/bwn/if_bwnvar.h>
77 
78 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
79     "Broadcom driver parameters");
80 
81 /*
82  * Tunable & sysctl variables.
83  */
84 
85 #ifdef BWN_DEBUG
86 static	int bwn_debug = 0;
87 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
88     "Broadcom debugging printfs");
89 enum {
90 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
91 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
92 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
93 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
94 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
95 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
96 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
97 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
98 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
99 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
100 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
101 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
102 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
103 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
104 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
105 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
106 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
107 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
108 	BWN_DEBUG_ANY		= 0xffffffff
109 };
110 #define	DPRINTF(sc, m, fmt, ...) do {			\
111 	if (sc->sc_debug & (m))				\
112 		printf(fmt, __VA_ARGS__);		\
113 } while (0)
114 #else
115 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
116 #endif
117 
118 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
119 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
120     "uses Bad Frames Preemption");
121 static int	bwn_bluetooth = 1;
122 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
123     "turns on Bluetooth Coexistence");
124 static int	bwn_hwpctl = 0;
125 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
126     "uses H/W power control");
127 static int	bwn_msi_disable = 0;		/* MSI disabled  */
128 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
129 static int	bwn_usedma = 1;
130 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
131     "uses DMA");
132 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
133 static int	bwn_wme = 1;
134 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
135     "uses WME support");
136 
137 static void	bwn_attach_pre(struct bwn_softc *);
138 static int	bwn_attach_post(struct bwn_softc *);
139 static void	bwn_sprom_bugfixes(device_t);
140 static int	bwn_init(struct bwn_softc *);
141 static void	bwn_parent(struct ieee80211com *);
142 static void	bwn_start(struct bwn_softc *);
143 static int	bwn_transmit(struct ieee80211com *, struct mbuf *);
144 static int	bwn_attach_core(struct bwn_mac *);
145 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
146 static int	bwn_phy_getinfo(struct bwn_mac *, int);
147 static int	bwn_chiptest(struct bwn_mac *);
148 static int	bwn_setup_channels(struct bwn_mac *, int, int);
149 static int	bwn_phy_g_attach(struct bwn_mac *);
150 static void	bwn_phy_g_detach(struct bwn_mac *);
151 static void	bwn_phy_g_init_pre(struct bwn_mac *);
152 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
153 static int	bwn_phy_g_init(struct bwn_mac *);
154 static void	bwn_phy_g_exit(struct bwn_mac *);
155 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
156 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
157 		    uint16_t);
158 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
159 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
160 		    uint16_t);
161 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
162 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
163 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
164 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
165 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
166 static int	bwn_phy_g_im(struct bwn_mac *, int);
167 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
168 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
169 static void	bwn_phy_g_task_15s(struct bwn_mac *);
170 static void	bwn_phy_g_task_60s(struct bwn_mac *);
171 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
172 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
173 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
174 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
175 		    uint16_t);
176 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
177 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
178 		    uint32_t);
179 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
180 		    uint16_t);
181 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
182 		    const struct bwn_channelinfo *, int);
183 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
184 		    const struct ieee80211_bpf_params *);
185 static void	bwn_updateslot(struct ieee80211com *);
186 static void	bwn_update_promisc(struct ieee80211com *);
187 static void	bwn_wme_init(struct bwn_mac *);
188 static int	bwn_wme_update(struct ieee80211com *);
189 static void	bwn_wme_clear(struct bwn_softc *);
190 static void	bwn_wme_load(struct bwn_mac *);
191 static void	bwn_wme_loadparams(struct bwn_mac *,
192 		    const struct wmeParams *, uint16_t);
193 static void	bwn_scan_start(struct ieee80211com *);
194 static void	bwn_scan_end(struct ieee80211com *);
195 static void	bwn_set_channel(struct ieee80211com *);
196 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
197 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
198 		    const uint8_t [IEEE80211_ADDR_LEN],
199 		    const uint8_t [IEEE80211_ADDR_LEN]);
200 static void	bwn_vap_delete(struct ieee80211vap *);
201 static void	bwn_stop(struct bwn_softc *);
202 static int	bwn_core_init(struct bwn_mac *);
203 static void	bwn_core_start(struct bwn_mac *);
204 static void	bwn_core_exit(struct bwn_mac *);
205 static void	bwn_bt_disable(struct bwn_mac *);
206 static int	bwn_chip_init(struct bwn_mac *);
207 static uint64_t	bwn_hf_read(struct bwn_mac *);
208 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
209 static void	bwn_set_txretry(struct bwn_mac *, int, int);
210 static void	bwn_rate_init(struct bwn_mac *);
211 static void	bwn_set_phytxctl(struct bwn_mac *);
212 static void	bwn_spu_setdelay(struct bwn_mac *, int);
213 static void	bwn_bt_enable(struct bwn_mac *);
214 static void	bwn_set_macaddr(struct bwn_mac *);
215 static void	bwn_crypt_init(struct bwn_mac *);
216 static void	bwn_chip_exit(struct bwn_mac *);
217 static int	bwn_fw_fillinfo(struct bwn_mac *);
218 static int	bwn_fw_loaducode(struct bwn_mac *);
219 static int	bwn_gpio_init(struct bwn_mac *);
220 static int	bwn_fw_loadinitvals(struct bwn_mac *);
221 static int	bwn_phy_init(struct bwn_mac *);
222 static void	bwn_set_txantenna(struct bwn_mac *, int);
223 static void	bwn_set_opmode(struct bwn_mac *);
224 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
225 static uint8_t	bwn_plcp_getcck(const uint8_t);
226 static uint8_t	bwn_plcp_getofdm(const uint8_t);
227 static void	bwn_pio_init(struct bwn_mac *);
228 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
229 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230 		    int);
231 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
232 		    struct bwn_pio_rxqueue *, int);
233 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235 		    uint16_t);
236 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
238 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239 static void	bwn_pio_handle_txeof(struct bwn_mac *,
240 		    const struct bwn_txstatus *);
241 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244 		    uint16_t);
245 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246 		    uint32_t);
247 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248 		    struct mbuf *);
249 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
251 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
252 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253 		    uint16_t, uint32_t);
254 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
255 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
256 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
257 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259 		    uint16_t, struct bwn_pio_txpkt **);
260 static void	bwn_dma_init(struct bwn_mac *);
261 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262 static int	bwn_dma_mask2type(uint64_t);
263 static uint64_t	bwn_dma_mask(struct bwn_mac *);
264 static uint16_t	bwn_dma_base(int, int);
265 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
266 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
267 		    int, struct bwn_dmadesc_generic **,
268 		    struct bwn_dmadesc_meta **);
269 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
270 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271 		    int, int);
272 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
274 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
275 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
278 		    int, struct bwn_dmadesc_generic **,
279 		    struct bwn_dmadesc_meta **);
280 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
281 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282 		    int, int);
283 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
285 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
286 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
289 static void	bwn_dma_setup(struct bwn_dma_ring *);
290 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
292 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
293 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294 static void	bwn_dma_rx(struct bwn_dma_ring *);
295 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
297 		    struct bwn_dmadesc_meta *);
298 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299 static int	bwn_dma_gettype(struct bwn_mac *);
300 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
302 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
303 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
305 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306 		    int);
307 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308 		    bus_size_t, int);
309 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310 static void	bwn_dma_handle_txeof(struct bwn_mac *,
311 		    const struct bwn_txstatus *);
312 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313 		    struct mbuf *);
314 static int	bwn_dma_getslot(struct bwn_dma_ring *);
315 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316 		    uint8_t);
317 static int	bwn_dma_attach(struct bwn_mac *);
318 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319 		    int, int, int);
320 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321 		    const struct bwn_txstatus *, uint16_t, int *);
322 static void	bwn_dma_free(struct bwn_mac *);
323 static void	bwn_phy_g_init_sub(struct bwn_mac *);
324 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
325 static void	bwn_phy_init_b5(struct bwn_mac *);
326 static void	bwn_phy_init_b6(struct bwn_mac *);
327 static void	bwn_phy_init_a(struct bwn_mac *);
328 static void	bwn_loopback_calcgain(struct bwn_mac *);
329 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
330 static void	bwn_lo_g_init(struct bwn_mac *);
331 static void	bwn_lo_g_adjust(struct bwn_mac *);
332 static void	bwn_lo_get_powervector(struct bwn_mac *);
333 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
335 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
337 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
340 		    uint8_t);
341 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
344 static void	bwn_wa_init(struct bwn_mac *);
345 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346 		    uint16_t);
347 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
348 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349 		    uint32_t);
350 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351 		    uint16_t);
352 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353 static void	bwn_mac_suspend(struct bwn_mac *);
354 static void	bwn_mac_enable(struct bwn_mac *);
355 static void	bwn_psctl(struct bwn_mac *, uint32_t);
356 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
357 static void	bwn_nrssi_offset(struct bwn_mac *);
358 static void	bwn_nrssi_threshold(struct bwn_mac *);
359 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
360 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361 		    int16_t);
362 static void	bwn_set_original_gains(struct bwn_mac *);
363 static void	bwn_hwpctl_early_init(struct bwn_mac *);
364 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
365 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
366 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368 		    const char *, struct bwn_fwfile *);
369 static void	bwn_release_firmware(struct bwn_mac *);
370 static void	bwn_do_release_fw(struct bwn_fwfile *);
371 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
372 static int	bwn_fwinitvals_write(struct bwn_mac *,
373 		    const struct bwn_fwinitvals *, size_t, size_t);
374 static int	bwn_switch_channel(struct bwn_mac *, int);
375 static uint16_t	bwn_ant2phy(int);
376 static void	bwn_mac_write_bssid(struct bwn_mac *);
377 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378 		    const uint8_t *);
379 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380 		    const uint8_t *, size_t, const uint8_t *);
381 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
382 		    const uint8_t *);
383 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384 		    const uint8_t *);
385 static void	bwn_phy_exit(struct bwn_mac *);
386 static void	bwn_core_stop(struct bwn_mac *);
387 static int	bwn_switch_band(struct bwn_softc *,
388 		    struct ieee80211_channel *);
389 static void	bwn_phy_reset(struct bwn_mac *);
390 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391 static void	bwn_set_pretbtt(struct bwn_mac *);
392 static int	bwn_intr(void *);
393 static void	bwn_intrtask(void *, int);
394 static void	bwn_restart(struct bwn_mac *, const char *);
395 static void	bwn_intr_ucode_debug(struct bwn_mac *);
396 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
397 static void	bwn_intr_atim_end(struct bwn_mac *);
398 static void	bwn_intr_beacon(struct bwn_mac *);
399 static void	bwn_intr_pmq(struct bwn_mac *);
400 static void	bwn_intr_noise(struct bwn_mac *);
401 static void	bwn_intr_txeof(struct bwn_mac *);
402 static void	bwn_hwreset(void *, int);
403 static void	bwn_handle_fwpanic(struct bwn_mac *);
404 static void	bwn_load_beacon0(struct bwn_mac *);
405 static void	bwn_load_beacon1(struct bwn_mac *);
406 static uint32_t	bwn_jssi_read(struct bwn_mac *);
407 static void	bwn_noise_gensample(struct bwn_mac *);
408 static void	bwn_handle_txeof(struct bwn_mac *,
409 		    const struct bwn_txstatus *);
410 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
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 		bwn_attach_pre(sc);
933 		bwn_sprom_bugfixes(dev);
934 		sc->sc_flags |= BWN_FLAG_ATTACHED;
935 	}
936 
937 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
938 		if (siba_get_pci_device(dev) != 0x4313 &&
939 		    siba_get_pci_device(dev) != 0x431a &&
940 		    siba_get_pci_device(dev) != 0x4321) {
941 			device_printf(sc->sc_dev,
942 			    "skip 802.11 cores\n");
943 			return (ENODEV);
944 		}
945 	}
946 
947 	mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
948 	mac->mac_sc = sc;
949 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
950 	if (bwn_bfp != 0)
951 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
952 
953 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
954 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
955 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
956 
957 	error = bwn_attach_core(mac);
958 	if (error)
959 		goto fail0;
960 	bwn_led_attach(mac);
961 
962 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
963 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
964 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
965 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
966 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
967 	    mac->mac_phy.rf_rev);
968 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
969 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
970 		    mac->mac_method.dma.dmatype);
971 	else
972 		device_printf(sc->sc_dev, "PIO\n");
973 
974 	/*
975 	 * setup PCI resources and interrupt.
976 	 */
977 	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
978 		msic = pci_msi_count(dev);
979 		if (bootverbose)
980 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
981 	} else
982 		msic = 0;
983 
984 	mac->mac_intr_spec = bwn_res_spec_legacy;
985 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
986 		if (pci_alloc_msi(dev, &msic) == 0) {
987 			device_printf(sc->sc_dev,
988 			    "Using %d MSI messages\n", msic);
989 			mac->mac_intr_spec = bwn_res_spec_msi;
990 			mac->mac_msi = 1;
991 		}
992 	}
993 
994 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
995 	    mac->mac_res_irq);
996 	if (error) {
997 		device_printf(sc->sc_dev,
998 		    "couldn't allocate IRQ resources (%d)\n", error);
999 		goto fail1;
1000 	}
1001 
1002 	if (mac->mac_msi == 0)
1003 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1004 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1005 		    &mac->mac_intrhand[0]);
1006 	else {
1007 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1008 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1009 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1010 			    &mac->mac_intrhand[i]);
1011 			if (error != 0) {
1012 				device_printf(sc->sc_dev,
1013 				    "couldn't setup interrupt (%d)\n", error);
1014 				break;
1015 			}
1016 		}
1017 	}
1018 
1019 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1020 
1021 	/*
1022 	 * calls attach-post routine
1023 	 */
1024 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1025 		bwn_attach_post(sc);
1026 
1027 	return (0);
1028 fail1:
1029 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1030 		pci_release_msi(dev);
1031 fail0:
1032 	free(mac, M_DEVBUF);
1033 	return (error);
1034 }
1035 
1036 static int
1037 bwn_is_valid_ether_addr(uint8_t *addr)
1038 {
1039 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1040 
1041 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1042 		return (FALSE);
1043 
1044 	return (TRUE);
1045 }
1046 
1047 static int
1048 bwn_attach_post(struct bwn_softc *sc)
1049 {
1050 	struct ieee80211com *ic = &sc->sc_ic;
1051 
1052 	ic->ic_softc = sc;
1053 	ic->ic_name = device_get_nameunit(sc->sc_dev);
1054 	/* XXX not right but it's not used anywhere important */
1055 	ic->ic_phytype = IEEE80211_T_OFDM;
1056 	ic->ic_opmode = IEEE80211_M_STA;
1057 	ic->ic_caps =
1058 		  IEEE80211_C_STA		/* station mode supported */
1059 		| IEEE80211_C_MONITOR		/* monitor mode */
1060 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1061 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1062 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1063 		| IEEE80211_C_WME		/* WME/WMM supported */
1064 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1065 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1066 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1067 		;
1068 
1069 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1070 
1071 	IEEE80211_ADDR_COPY(ic->ic_macaddr,
1072 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1073 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1074 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1075 
1076 	/* call MI attach routine. */
1077 	ieee80211_ifattach(ic);
1078 
1079 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1080 
1081 	/* override default methods */
1082 	ic->ic_raw_xmit = bwn_raw_xmit;
1083 	ic->ic_updateslot = bwn_updateslot;
1084 	ic->ic_update_promisc = bwn_update_promisc;
1085 	ic->ic_wme.wme_update = bwn_wme_update;
1086 	ic->ic_scan_start = bwn_scan_start;
1087 	ic->ic_scan_end = bwn_scan_end;
1088 	ic->ic_set_channel = bwn_set_channel;
1089 	ic->ic_vap_create = bwn_vap_create;
1090 	ic->ic_vap_delete = bwn_vap_delete;
1091 	ic->ic_transmit = bwn_transmit;
1092 	ic->ic_parent = bwn_parent;
1093 
1094 	ieee80211_radiotap_attach(ic,
1095 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1096 	    BWN_TX_RADIOTAP_PRESENT,
1097 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1098 	    BWN_RX_RADIOTAP_PRESENT);
1099 
1100 	bwn_sysctl_node(sc);
1101 
1102 	if (bootverbose)
1103 		ieee80211_announce(ic);
1104 	return (0);
1105 }
1106 
1107 static void
1108 bwn_phy_detach(struct bwn_mac *mac)
1109 {
1110 
1111 	if (mac->mac_phy.detach != NULL)
1112 		mac->mac_phy.detach(mac);
1113 }
1114 
1115 static int
1116 bwn_detach(device_t dev)
1117 {
1118 	struct bwn_softc *sc = device_get_softc(dev);
1119 	struct bwn_mac *mac = sc->sc_curmac;
1120 	struct ieee80211com *ic = &sc->sc_ic;
1121 	int i;
1122 
1123 	sc->sc_flags |= BWN_FLAG_INVALID;
1124 
1125 	if (device_is_attached(sc->sc_dev)) {
1126 		BWN_LOCK(sc);
1127 		bwn_stop(sc);
1128 		BWN_UNLOCK(sc);
1129 		bwn_dma_free(mac);
1130 		callout_drain(&sc->sc_led_blink_ch);
1131 		callout_drain(&sc->sc_rfswitch_ch);
1132 		callout_drain(&sc->sc_task_ch);
1133 		callout_drain(&sc->sc_watchdog_ch);
1134 		bwn_phy_detach(mac);
1135 		ieee80211_draintask(ic, &mac->mac_hwreset);
1136 		ieee80211_draintask(ic, &mac->mac_txpower);
1137 		ieee80211_ifdetach(ic);
1138 	}
1139 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1140 	taskqueue_free(sc->sc_tq);
1141 
1142 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1143 		if (mac->mac_intrhand[i] != NULL) {
1144 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1145 			    mac->mac_intrhand[i]);
1146 			mac->mac_intrhand[i] = NULL;
1147 		}
1148 	}
1149 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1150 	if (mac->mac_msi != 0)
1151 		pci_release_msi(dev);
1152 	mbufq_drain(&sc->sc_snd);
1153 	BWN_LOCK_DESTROY(sc);
1154 	return (0);
1155 }
1156 
1157 static void
1158 bwn_attach_pre(struct bwn_softc *sc)
1159 {
1160 
1161 	BWN_LOCK_INIT(sc);
1162 	TAILQ_INIT(&sc->sc_maclist);
1163 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1164 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1165 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1166 	mbufq_init(&sc->sc_snd, ifqmaxlen);
1167 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1168 		taskqueue_thread_enqueue, &sc->sc_tq);
1169 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1170 		"%s taskq", device_get_nameunit(sc->sc_dev));
1171 }
1172 
1173 static void
1174 bwn_sprom_bugfixes(device_t dev)
1175 {
1176 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1177 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1178 	 (siba_get_pci_device(dev) == _device) &&			\
1179 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1180 	 (siba_get_pci_subdevice(dev) == _subdevice))
1181 
1182 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1183 	    siba_get_pci_subdevice(dev) == 0x4e &&
1184 	    siba_get_pci_revid(dev) > 0x40)
1185 		siba_sprom_set_bf_lo(dev,
1186 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1187 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1188 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1189 		siba_sprom_set_bf_lo(dev,
1190 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1191 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1192 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1193 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1194 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1195 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1196 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1197 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1198 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1199 			siba_sprom_set_bf_lo(dev,
1200 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1201 	}
1202 #undef	BWN_ISDEV
1203 }
1204 
1205 static void
1206 bwn_parent(struct ieee80211com *ic)
1207 {
1208 	struct bwn_softc *sc = ic->ic_softc;
1209 	int startall = 0;
1210 
1211 	BWN_LOCK(sc);
1212 	if (ic->ic_nrunning > 0) {
1213 		if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1214 			bwn_init(sc);
1215 			startall = 1;
1216 		} else
1217 			bwn_update_promisc(ic);
1218 	} else if (sc->sc_flags & BWN_FLAG_RUNNING)
1219 		bwn_stop(sc);
1220 	BWN_UNLOCK(sc);
1221 
1222 	if (startall)
1223 		ieee80211_start_all(ic);
1224 }
1225 
1226 static int
1227 bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
1228 {
1229 	struct bwn_softc *sc = ic->ic_softc;
1230 	int error;
1231 
1232 	BWN_LOCK(sc);
1233 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1234 		BWN_UNLOCK(sc);
1235 		return (ENXIO);
1236 	}
1237 	error = mbufq_enqueue(&sc->sc_snd, m);
1238 	if (error) {
1239 		BWN_UNLOCK(sc);
1240 		return (error);
1241 	}
1242 	bwn_start(sc);
1243 	BWN_UNLOCK(sc);
1244 	return (0);
1245 }
1246 
1247 static void
1248 bwn_start(struct bwn_softc *sc)
1249 {
1250 	struct bwn_mac *mac = sc->sc_curmac;
1251 	struct ieee80211_frame *wh;
1252 	struct ieee80211_node *ni;
1253 	struct ieee80211_key *k;
1254 	struct mbuf *m;
1255 
1256 	BWN_ASSERT_LOCKED(sc);
1257 
1258 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
1259 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1260 		return;
1261 
1262 	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
1263 		if (bwn_tx_isfull(sc, m))
1264 			break;
1265 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1266 		if (ni == NULL) {
1267 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1268 			m_freem(m);
1269 			counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1270 			continue;
1271 		}
1272 		wh = mtod(m, struct ieee80211_frame *);
1273 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1274 			k = ieee80211_crypto_encap(ni, m);
1275 			if (k == NULL) {
1276 				if_inc_counter(ni->ni_vap->iv_ifp,
1277 				    IFCOUNTER_OERRORS, 1);
1278 				ieee80211_free_node(ni);
1279 				m_freem(m);
1280 				continue;
1281 			}
1282 		}
1283 		wh = NULL;	/* Catch any invalid use */
1284 		if (bwn_tx_start(sc, ni, m) != 0) {
1285 			if (ni != NULL) {
1286 				if_inc_counter(ni->ni_vap->iv_ifp,
1287 				    IFCOUNTER_OERRORS, 1);
1288 				ieee80211_free_node(ni);
1289 			}
1290 			continue;
1291 		}
1292 		sc->sc_watchdog_timer = 5;
1293 	}
1294 }
1295 
1296 static int
1297 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1298 {
1299 	struct bwn_dma_ring *dr;
1300 	struct bwn_mac *mac = sc->sc_curmac;
1301 	struct bwn_pio_txqueue *tq;
1302 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1303 
1304 	BWN_ASSERT_LOCKED(sc);
1305 
1306 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1307 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1308 		if (dr->dr_stop == 1 ||
1309 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1310 			dr->dr_stop = 1;
1311 			goto full;
1312 		}
1313 	} else {
1314 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1315 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1316 		    pktlen > (tq->tq_size - tq->tq_used))
1317 			goto full;
1318 	}
1319 	return (0);
1320 full:
1321 	mbufq_prepend(&sc->sc_snd, m);
1322 	return (1);
1323 }
1324 
1325 static int
1326 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1327 {
1328 	struct bwn_mac *mac = sc->sc_curmac;
1329 	int error;
1330 
1331 	BWN_ASSERT_LOCKED(sc);
1332 
1333 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1334 		m_freem(m);
1335 		return (ENXIO);
1336 	}
1337 
1338 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1339 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1340 	if (error) {
1341 		m_freem(m);
1342 		return (error);
1343 	}
1344 	return (0);
1345 }
1346 
1347 static int
1348 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1349 {
1350 	struct bwn_pio_txpkt *tp;
1351 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1352 	struct bwn_softc *sc = mac->mac_sc;
1353 	struct bwn_txhdr txhdr;
1354 	struct mbuf *m_new;
1355 	uint32_t ctl32;
1356 	int error;
1357 	uint16_t ctl16;
1358 
1359 	BWN_ASSERT_LOCKED(sc);
1360 
1361 	/* XXX TODO send packets after DTIM */
1362 
1363 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1364 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1365 	tp->tp_ni = ni;
1366 	tp->tp_m = m;
1367 
1368 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1369 	if (error) {
1370 		device_printf(sc->sc_dev, "tx fail\n");
1371 		return (error);
1372 	}
1373 
1374 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1375 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1376 	tq->tq_free--;
1377 
1378 	if (siba_get_revid(sc->sc_dev) >= 8) {
1379 		/*
1380 		 * XXX please removes m_defrag(9)
1381 		 */
1382 		m_new = m_defrag(m, M_NOWAIT);
1383 		if (m_new == NULL) {
1384 			device_printf(sc->sc_dev,
1385 			    "%s: can't defrag TX buffer\n",
1386 			    __func__);
1387 			return (ENOBUFS);
1388 		}
1389 		if (m_new->m_next != NULL)
1390 			device_printf(sc->sc_dev,
1391 			    "TODO: fragmented packets for PIO\n");
1392 		tp->tp_m = m_new;
1393 
1394 		/* send HEADER */
1395 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1396 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1397 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1398 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1399 		/* send BODY */
1400 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1401 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1402 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1403 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1404 	} else {
1405 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1406 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1407 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1408 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1409 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1410 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1411 		    ctl16 | BWN_PIO_TXCTL_EOF);
1412 	}
1413 
1414 	return (0);
1415 }
1416 
1417 static struct bwn_pio_txqueue *
1418 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1419 {
1420 
1421 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1422 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1423 
1424 	switch (prio) {
1425 	case 0:
1426 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1427 	case 1:
1428 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1429 	case 2:
1430 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1431 	case 3:
1432 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1433 	}
1434 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1435 	return (NULL);
1436 }
1437 
1438 static int
1439 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1440 {
1441 #define	BWN_GET_TXHDRCACHE(slot)					\
1442 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1443 	struct bwn_dma *dma = &mac->mac_method.dma;
1444 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1445 	struct bwn_dmadesc_generic *desc;
1446 	struct bwn_dmadesc_meta *mt;
1447 	struct bwn_softc *sc = mac->mac_sc;
1448 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1449 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1450 
1451 	BWN_ASSERT_LOCKED(sc);
1452 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1453 
1454 	/* XXX send after DTIM */
1455 
1456 	slot = bwn_dma_getslot(dr);
1457 	dr->getdesc(dr, slot, &desc, &mt);
1458 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1459 	    ("%s:%d: fail", __func__, __LINE__));
1460 
1461 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1462 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1463 	    BWN_DMA_COOKIE(dr, slot));
1464 	if (error)
1465 		goto fail;
1466 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1467 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1468 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1469 	if (error) {
1470 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1471 		    __func__, error);
1472 		goto fail;
1473 	}
1474 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1475 	    BUS_DMASYNC_PREWRITE);
1476 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1477 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1478 	    BUS_DMASYNC_PREWRITE);
1479 
1480 	slot = bwn_dma_getslot(dr);
1481 	dr->getdesc(dr, slot, &desc, &mt);
1482 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1483 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1484 	mt->mt_m = m;
1485 	mt->mt_ni = ni;
1486 
1487 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1488 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1489 	if (error && error != EFBIG) {
1490 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1491 		    __func__, error);
1492 		goto fail;
1493 	}
1494 	if (error) {    /* error == EFBIG */
1495 		struct mbuf *m_new;
1496 
1497 		m_new = m_defrag(m, M_NOWAIT);
1498 		if (m_new == NULL) {
1499 			device_printf(sc->sc_dev,
1500 			    "%s: can't defrag TX buffer\n",
1501 			    __func__);
1502 			error = ENOBUFS;
1503 			goto fail;
1504 		} else {
1505 			m = m_new;
1506 		}
1507 
1508 		mt->mt_m = m;
1509 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1510 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1511 		if (error) {
1512 			device_printf(sc->sc_dev,
1513 			    "%s: can't load TX buffer (2) %d\n",
1514 			    __func__, error);
1515 			goto fail;
1516 		}
1517 	}
1518 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1519 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1520 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1521 	    BUS_DMASYNC_PREWRITE);
1522 
1523 	/* XXX send after DTIM */
1524 
1525 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1526 	return (0);
1527 fail:
1528 	dr->dr_curslot = backup[0];
1529 	dr->dr_usedslot = backup[1];
1530 	return (error);
1531 #undef BWN_GET_TXHDRCACHE
1532 }
1533 
1534 static void
1535 bwn_watchdog(void *arg)
1536 {
1537 	struct bwn_softc *sc = arg;
1538 
1539 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1540 		device_printf(sc->sc_dev, "device timeout\n");
1541 		counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1542 	}
1543 	callout_schedule(&sc->sc_watchdog_ch, hz);
1544 }
1545 
1546 static int
1547 bwn_attach_core(struct bwn_mac *mac)
1548 {
1549 	struct bwn_softc *sc = mac->mac_sc;
1550 	int error, have_bg = 0, have_a = 0;
1551 	uint32_t high;
1552 
1553 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1554 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1555 
1556 	siba_powerup(sc->sc_dev, 0);
1557 
1558 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1559 	bwn_reset_core(mac,
1560 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1561 	error = bwn_phy_getinfo(mac, high);
1562 	if (error)
1563 		goto fail;
1564 
1565 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1566 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1567 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1568 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1569 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1570 		have_a = have_bg = 0;
1571 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1572 			have_a = 1;
1573 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1574 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1575 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1576 			have_bg = 1;
1577 		else
1578 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1579 			    mac->mac_phy.type));
1580 	}
1581 	/* XXX turns off PHY A because it's not supported */
1582 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1583 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1584 		have_a = 0;
1585 		have_bg = 1;
1586 	}
1587 
1588 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1589 		mac->mac_phy.attach = bwn_phy_g_attach;
1590 		mac->mac_phy.detach = bwn_phy_g_detach;
1591 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1592 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1593 		mac->mac_phy.init = bwn_phy_g_init;
1594 		mac->mac_phy.exit = bwn_phy_g_exit;
1595 		mac->mac_phy.phy_read = bwn_phy_g_read;
1596 		mac->mac_phy.phy_write = bwn_phy_g_write;
1597 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1598 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1599 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1600 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1601 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1602 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1603 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1604 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1605 		mac->mac_phy.set_im = bwn_phy_g_im;
1606 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1607 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1608 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1609 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1610 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1611 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1612 		mac->mac_phy.init = bwn_phy_lp_init;
1613 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1614 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1615 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1616 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1617 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1618 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1619 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1620 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1621 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1622 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1623 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1624 	} else {
1625 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1626 		    mac->mac_phy.type);
1627 		error = ENXIO;
1628 		goto fail;
1629 	}
1630 
1631 	mac->mac_phy.gmode = have_bg;
1632 	if (mac->mac_phy.attach != NULL) {
1633 		error = mac->mac_phy.attach(mac);
1634 		if (error) {
1635 			device_printf(sc->sc_dev, "failed\n");
1636 			goto fail;
1637 		}
1638 	}
1639 
1640 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1641 
1642 	error = bwn_chiptest(mac);
1643 	if (error)
1644 		goto fail;
1645 	error = bwn_setup_channels(mac, have_bg, have_a);
1646 	if (error) {
1647 		device_printf(sc->sc_dev, "failed to setup channels\n");
1648 		goto fail;
1649 	}
1650 
1651 	if (sc->sc_curmac == NULL)
1652 		sc->sc_curmac = mac;
1653 
1654 	error = bwn_dma_attach(mac);
1655 	if (error != 0) {
1656 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1657 		goto fail;
1658 	}
1659 
1660 	mac->mac_phy.switch_analog(mac, 0);
1661 
1662 	siba_dev_down(sc->sc_dev, 0);
1663 fail:
1664 	siba_powerdown(sc->sc_dev);
1665 	return (error);
1666 }
1667 
1668 static void
1669 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1670 {
1671 	struct bwn_softc *sc = mac->mac_sc;
1672 	uint32_t low, ctl;
1673 
1674 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1675 
1676 	siba_dev_up(sc->sc_dev, flags);
1677 	DELAY(2000);
1678 
1679 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1680 	    ~BWN_TGSLOW_PHYRESET;
1681 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1682 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1683 	DELAY(1000);
1684 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1685 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1686 	DELAY(1000);
1687 
1688 	if (mac->mac_phy.switch_analog != NULL)
1689 		mac->mac_phy.switch_analog(mac, 1);
1690 
1691 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1692 	if (flags & BWN_TGSLOW_SUPPORT_G)
1693 		ctl |= BWN_MACCTL_GMODE;
1694 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1695 }
1696 
1697 static int
1698 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1699 {
1700 	struct bwn_phy *phy = &mac->mac_phy;
1701 	struct bwn_softc *sc = mac->mac_sc;
1702 	uint32_t tmp;
1703 
1704 	/* PHY */
1705 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1706 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1707 	phy->rf_on = 1;
1708 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1709 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1710 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1711 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1712 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1713 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1714 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1715 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1716 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1717 		goto unsupphy;
1718 
1719 	/* RADIO */
1720 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1721 		if (siba_get_chiprev(sc->sc_dev) == 0)
1722 			tmp = 0x3205017f;
1723 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1724 			tmp = 0x4205017f;
1725 		else
1726 			tmp = 0x5205017f;
1727 	} else {
1728 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1729 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1730 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1731 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1732 	}
1733 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1734 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1735 	phy->rf_manuf = (tmp & 0x00000fff);
1736 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1737 		goto unsupradio;
1738 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1739 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1740 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1741 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1742 	    (phy->type == BWN_PHYTYPE_N &&
1743 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1744 	    (phy->type == BWN_PHYTYPE_LP &&
1745 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1746 		goto unsupradio;
1747 
1748 	return (0);
1749 unsupphy:
1750 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1751 	    "analog %#x)\n",
1752 	    phy->type, phy->rev, phy->analog);
1753 	return (ENXIO);
1754 unsupradio:
1755 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1756 	    "rev %#x)\n",
1757 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1758 	return (ENXIO);
1759 }
1760 
1761 static int
1762 bwn_chiptest(struct bwn_mac *mac)
1763 {
1764 #define	TESTVAL0	0x55aaaa55
1765 #define	TESTVAL1	0xaa5555aa
1766 	struct bwn_softc *sc = mac->mac_sc;
1767 	uint32_t v, backup;
1768 
1769 	BWN_LOCK(sc);
1770 
1771 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1772 
1773 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1774 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1775 		goto error;
1776 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1777 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1778 		goto error;
1779 
1780 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1781 
1782 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1783 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1784 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1785 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1786 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1787 			goto error;
1788 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1789 			goto error;
1790 	}
1791 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1792 
1793 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1794 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1795 		goto error;
1796 
1797 	BWN_UNLOCK(sc);
1798 	return (0);
1799 error:
1800 	BWN_UNLOCK(sc);
1801 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1802 	return (ENODEV);
1803 }
1804 
1805 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1806 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1807 
1808 static int
1809 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1810 {
1811 	struct bwn_softc *sc = mac->mac_sc;
1812 	struct ieee80211com *ic = &sc->sc_ic;
1813 
1814 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1815 	ic->ic_nchans = 0;
1816 
1817 	if (have_bg)
1818 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1819 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1820 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1821 		if (have_a)
1822 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1823 			    &ic->ic_nchans, &bwn_chantable_n,
1824 			    IEEE80211_CHAN_HTA);
1825 	} else {
1826 		if (have_a)
1827 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1828 			    &ic->ic_nchans, &bwn_chantable_a,
1829 			    IEEE80211_CHAN_A);
1830 	}
1831 
1832 	mac->mac_phy.supports_2ghz = have_bg;
1833 	mac->mac_phy.supports_5ghz = have_a;
1834 
1835 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1836 }
1837 
1838 static uint32_t
1839 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1840 {
1841 	uint32_t ret;
1842 
1843 	BWN_ASSERT_LOCKED(mac->mac_sc);
1844 
1845 	if (way == BWN_SHARED) {
1846 		KASSERT((offset & 0x0001) == 0,
1847 		    ("%s:%d warn", __func__, __LINE__));
1848 		if (offset & 0x0003) {
1849 			bwn_shm_ctlword(mac, way, offset >> 2);
1850 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1851 			ret <<= 16;
1852 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1853 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1854 			goto out;
1855 		}
1856 		offset >>= 2;
1857 	}
1858 	bwn_shm_ctlword(mac, way, offset);
1859 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1860 out:
1861 	return (ret);
1862 }
1863 
1864 static uint16_t
1865 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1866 {
1867 	uint16_t ret;
1868 
1869 	BWN_ASSERT_LOCKED(mac->mac_sc);
1870 
1871 	if (way == BWN_SHARED) {
1872 		KASSERT((offset & 0x0001) == 0,
1873 		    ("%s:%d warn", __func__, __LINE__));
1874 		if (offset & 0x0003) {
1875 			bwn_shm_ctlword(mac, way, offset >> 2);
1876 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1877 			goto out;
1878 		}
1879 		offset >>= 2;
1880 	}
1881 	bwn_shm_ctlword(mac, way, offset);
1882 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1883 out:
1884 
1885 	return (ret);
1886 }
1887 
1888 static void
1889 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1890     uint16_t offset)
1891 {
1892 	uint32_t control;
1893 
1894 	control = way;
1895 	control <<= 16;
1896 	control |= offset;
1897 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1898 }
1899 
1900 static void
1901 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1902     uint32_t value)
1903 {
1904 	BWN_ASSERT_LOCKED(mac->mac_sc);
1905 
1906 	if (way == BWN_SHARED) {
1907 		KASSERT((offset & 0x0001) == 0,
1908 		    ("%s:%d warn", __func__, __LINE__));
1909 		if (offset & 0x0003) {
1910 			bwn_shm_ctlword(mac, way, offset >> 2);
1911 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1912 				    (value >> 16) & 0xffff);
1913 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1914 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1915 			return;
1916 		}
1917 		offset >>= 2;
1918 	}
1919 	bwn_shm_ctlword(mac, way, offset);
1920 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1921 }
1922 
1923 static void
1924 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1925     uint16_t value)
1926 {
1927 	BWN_ASSERT_LOCKED(mac->mac_sc);
1928 
1929 	if (way == BWN_SHARED) {
1930 		KASSERT((offset & 0x0001) == 0,
1931 		    ("%s:%d warn", __func__, __LINE__));
1932 		if (offset & 0x0003) {
1933 			bwn_shm_ctlword(mac, way, offset >> 2);
1934 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1935 			return;
1936 		}
1937 		offset >>= 2;
1938 	}
1939 	bwn_shm_ctlword(mac, way, offset);
1940 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1941 }
1942 
1943 static void
1944 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1945     int txpow)
1946 {
1947 
1948 	c->ic_freq = freq;
1949 	c->ic_flags = flags;
1950 	c->ic_ieee = ieee;
1951 	c->ic_minpower = 0;
1952 	c->ic_maxpower = 2 * txpow;
1953 	c->ic_maxregpower = txpow;
1954 }
1955 
1956 static void
1957 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1958     const struct bwn_channelinfo *ci, int flags)
1959 {
1960 	struct ieee80211_channel *c;
1961 	int i;
1962 
1963 	c = &chans[*nchans];
1964 
1965 	for (i = 0; i < ci->nchannels; i++) {
1966 		const struct bwn_channel *hc;
1967 
1968 		hc = &ci->channels[i];
1969 		if (*nchans >= maxchans)
1970 			break;
1971 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
1972 		c++, (*nchans)++;
1973 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
1974 			/* g channel have a separate b-only entry */
1975 			if (*nchans >= maxchans)
1976 				break;
1977 			c[0] = c[-1];
1978 			c[-1].ic_flags = IEEE80211_CHAN_B;
1979 			c++, (*nchans)++;
1980 		}
1981 		if (flags == IEEE80211_CHAN_HTG) {
1982 			/* HT g channel have a separate g-only entry */
1983 			if (*nchans >= maxchans)
1984 				break;
1985 			c[-1].ic_flags = IEEE80211_CHAN_G;
1986 			c[0] = c[-1];
1987 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1988 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1989 			c++, (*nchans)++;
1990 		}
1991 		if (flags == IEEE80211_CHAN_HTA) {
1992 			/* HT a channel have a separate a-only entry */
1993 			if (*nchans >= maxchans)
1994 				break;
1995 			c[-1].ic_flags = IEEE80211_CHAN_A;
1996 			c[0] = c[-1];
1997 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1998 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1999 			c++, (*nchans)++;
2000 		}
2001 	}
2002 }
2003 
2004 static int
2005 bwn_phy_g_attach(struct bwn_mac *mac)
2006 {
2007 	struct bwn_softc *sc = mac->mac_sc;
2008 	struct bwn_phy *phy = &mac->mac_phy;
2009 	struct bwn_phy_g *pg = &phy->phy_g;
2010 	unsigned int i;
2011 	int16_t pab0, pab1, pab2;
2012 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2013 	int8_t bg;
2014 
2015 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2016 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2017 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2018 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2019 
2020 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2021 		device_printf(sc->sc_dev, "not supported anymore\n");
2022 
2023 	pg->pg_flags = 0;
2024 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2025 	    pab2 == -1) {
2026 		pg->pg_idletssi = 52;
2027 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2028 		return (0);
2029 	}
2030 
2031 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2032 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2033 	if (pg->pg_tssi2dbm == NULL) {
2034 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2035 		return (ENOMEM);
2036 	}
2037 	for (i = 0; i < 64; i++) {
2038 		int32_t m1, m2, f, q, delta;
2039 		int8_t j = 0;
2040 
2041 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2042 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2043 		f = 256;
2044 
2045 		do {
2046 			if (j > 15) {
2047 				device_printf(sc->sc_dev,
2048 				    "failed to generate tssi2dBm\n");
2049 				free(pg->pg_tssi2dbm, M_DEVBUF);
2050 				return (ENOMEM);
2051 			}
2052 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2053 			    f, 2048);
2054 			delta = abs(q - f);
2055 			f = q;
2056 			j++;
2057 		} while (delta >= 2);
2058 
2059 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2060 		    128);
2061 	}
2062 
2063 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2064 	return (0);
2065 }
2066 
2067 static void
2068 bwn_phy_g_detach(struct bwn_mac *mac)
2069 {
2070 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2071 
2072 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2073 		free(pg->pg_tssi2dbm, M_DEVBUF);
2074 		pg->pg_tssi2dbm = NULL;
2075 	}
2076 	pg->pg_flags = 0;
2077 }
2078 
2079 static void
2080 bwn_phy_g_init_pre(struct bwn_mac *mac)
2081 {
2082 	struct bwn_phy *phy = &mac->mac_phy;
2083 	struct bwn_phy_g *pg = &phy->phy_g;
2084 	void *tssi2dbm;
2085 	int idletssi;
2086 	unsigned int i;
2087 
2088 	tssi2dbm = pg->pg_tssi2dbm;
2089 	idletssi = pg->pg_idletssi;
2090 
2091 	memset(pg, 0, sizeof(*pg));
2092 
2093 	pg->pg_tssi2dbm = tssi2dbm;
2094 	pg->pg_idletssi = idletssi;
2095 
2096 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2097 
2098 	for (i = 0; i < N(pg->pg_nrssi); i++)
2099 		pg->pg_nrssi[i] = -1000;
2100 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2101 		pg->pg_nrssi_lt[i] = i;
2102 	pg->pg_lofcal = 0xffff;
2103 	pg->pg_initval = 0xffff;
2104 	pg->pg_immode = BWN_IMMODE_NONE;
2105 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2106 	pg->pg_avgtssi = 0xff;
2107 
2108 	pg->pg_loctl.tx_bias = 0xff;
2109 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2110 }
2111 
2112 static int
2113 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2114 {
2115 	struct bwn_phy *phy = &mac->mac_phy;
2116 	struct bwn_phy_g *pg = &phy->phy_g;
2117 	struct bwn_softc *sc = mac->mac_sc;
2118 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2119 	static const struct bwn_rfatt rfatt0[] = {
2120 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2121 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2122 		{ 3, 1 }, { 4, 1 }
2123 	};
2124 	static const struct bwn_rfatt rfatt1[] = {
2125 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2126 		{ 14, 1 }
2127 	};
2128 	static const struct bwn_rfatt rfatt2[] = {
2129 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2130 		{ 9, 1 }
2131 	};
2132 	static const struct bwn_bbatt bbatt_0[] = {
2133 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2134 	};
2135 
2136 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2137 
2138 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2139 		pg->pg_bbatt.att = 0;
2140 	else
2141 		pg->pg_bbatt.att = 2;
2142 
2143 	/* prepare Radio Attenuation */
2144 	pg->pg_rfatt.padmix = 0;
2145 
2146 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2147 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2148 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2149 			pg->pg_rfatt.att = 2;
2150 			goto done;
2151 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2152 			pg->pg_rfatt.att = 3;
2153 			goto done;
2154 		}
2155 	}
2156 
2157 	if (phy->type == BWN_PHYTYPE_A) {
2158 		pg->pg_rfatt.att = 0x60;
2159 		goto done;
2160 	}
2161 
2162 	switch (phy->rf_ver) {
2163 	case 0x2050:
2164 		switch (phy->rf_rev) {
2165 		case 0:
2166 			pg->pg_rfatt.att = 5;
2167 			goto done;
2168 		case 1:
2169 			if (phy->type == BWN_PHYTYPE_G) {
2170 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2171 				    SIBA_BOARDVENDOR_BCM &&
2172 				    siba_get_pci_subdevice(sc->sc_dev) ==
2173 				    SIBA_BOARD_BCM4309G &&
2174 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2175 					pg->pg_rfatt.att = 3;
2176 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2177 				    SIBA_BOARDVENDOR_BCM &&
2178 				    siba_get_pci_subdevice(sc->sc_dev) ==
2179 				    SIBA_BOARD_BU4306)
2180 					pg->pg_rfatt.att = 3;
2181 				else
2182 					pg->pg_rfatt.att = 1;
2183 			} else {
2184 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2185 				    SIBA_BOARDVENDOR_BCM &&
2186 				    siba_get_pci_subdevice(sc->sc_dev) ==
2187 				    SIBA_BOARD_BCM4309G &&
2188 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2189 					pg->pg_rfatt.att = 7;
2190 				else
2191 					pg->pg_rfatt.att = 6;
2192 			}
2193 			goto done;
2194 		case 2:
2195 			if (phy->type == BWN_PHYTYPE_G) {
2196 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2197 				    SIBA_BOARDVENDOR_BCM &&
2198 				    siba_get_pci_subdevice(sc->sc_dev) ==
2199 				    SIBA_BOARD_BCM4309G &&
2200 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2201 					pg->pg_rfatt.att = 3;
2202 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2203 				    SIBA_BOARDVENDOR_BCM &&
2204 				    siba_get_pci_subdevice(sc->sc_dev) ==
2205 				    SIBA_BOARD_BU4306)
2206 					pg->pg_rfatt.att = 5;
2207 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2208 					pg->pg_rfatt.att = 4;
2209 				else
2210 					pg->pg_rfatt.att = 3;
2211 			} else
2212 				pg->pg_rfatt.att = 6;
2213 			goto done;
2214 		case 3:
2215 			pg->pg_rfatt.att = 5;
2216 			goto done;
2217 		case 4:
2218 		case 5:
2219 			pg->pg_rfatt.att = 1;
2220 			goto done;
2221 		case 6:
2222 		case 7:
2223 			pg->pg_rfatt.att = 5;
2224 			goto done;
2225 		case 8:
2226 			pg->pg_rfatt.att = 0xa;
2227 			pg->pg_rfatt.padmix = 1;
2228 			goto done;
2229 		case 9:
2230 		default:
2231 			pg->pg_rfatt.att = 5;
2232 			goto done;
2233 		}
2234 		break;
2235 	case 0x2053:
2236 		switch (phy->rf_rev) {
2237 		case 1:
2238 			pg->pg_rfatt.att = 6;
2239 			goto done;
2240 		}
2241 		break;
2242 	}
2243 	pg->pg_rfatt.att = 5;
2244 done:
2245 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2246 
2247 	if (!bwn_has_hwpctl(mac)) {
2248 		lo->rfatt.array = rfatt0;
2249 		lo->rfatt.len = N(rfatt0);
2250 		lo->rfatt.min = 0;
2251 		lo->rfatt.max = 9;
2252 		goto genbbatt;
2253 	}
2254 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2255 		lo->rfatt.array = rfatt1;
2256 		lo->rfatt.len = N(rfatt1);
2257 		lo->rfatt.min = 0;
2258 		lo->rfatt.max = 14;
2259 		goto genbbatt;
2260 	}
2261 	lo->rfatt.array = rfatt2;
2262 	lo->rfatt.len = N(rfatt2);
2263 	lo->rfatt.min = 0;
2264 	lo->rfatt.max = 9;
2265 genbbatt:
2266 	lo->bbatt.array = bbatt_0;
2267 	lo->bbatt.len = N(bbatt_0);
2268 	lo->bbatt.min = 0;
2269 	lo->bbatt.max = 8;
2270 
2271 	BWN_READ_4(mac, BWN_MACCTL);
2272 	if (phy->rev == 1) {
2273 		phy->gmode = 0;
2274 		bwn_reset_core(mac, 0);
2275 		bwn_phy_g_init_sub(mac);
2276 		phy->gmode = 1;
2277 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2278 	}
2279 	return (0);
2280 }
2281 
2282 static uint16_t
2283 bwn_phy_g_txctl(struct bwn_mac *mac)
2284 {
2285 	struct bwn_phy *phy = &mac->mac_phy;
2286 
2287 	if (phy->rf_ver != 0x2050)
2288 		return (0);
2289 	if (phy->rf_rev == 1)
2290 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2291 	if (phy->rf_rev < 6)
2292 		return (BWN_TXCTL_PA2DB);
2293 	if (phy->rf_rev == 8)
2294 		return (BWN_TXCTL_TXMIX);
2295 	return (0);
2296 }
2297 
2298 static int
2299 bwn_phy_g_init(struct bwn_mac *mac)
2300 {
2301 
2302 	bwn_phy_g_init_sub(mac);
2303 	return (0);
2304 }
2305 
2306 static void
2307 bwn_phy_g_exit(struct bwn_mac *mac)
2308 {
2309 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2310 	struct bwn_lo_calib *cal, *tmp;
2311 
2312 	if (lo == NULL)
2313 		return;
2314 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2315 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2316 		free(cal, M_DEVBUF);
2317 	}
2318 }
2319 
2320 static uint16_t
2321 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2322 {
2323 
2324 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2325 	return (BWN_READ_2(mac, BWN_PHYDATA));
2326 }
2327 
2328 static void
2329 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2330 {
2331 
2332 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2333 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2334 }
2335 
2336 static uint16_t
2337 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2338 {
2339 
2340 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2341 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2342 	return (BWN_READ_2(mac, BWN_RFDATALO));
2343 }
2344 
2345 static void
2346 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2347 {
2348 
2349 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2350 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2351 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2352 }
2353 
2354 static int
2355 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2356 {
2357 
2358 	return (mac->mac_phy.rev >= 6);
2359 }
2360 
2361 static void
2362 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2363 {
2364 	struct bwn_phy *phy = &mac->mac_phy;
2365 	struct bwn_phy_g *pg = &phy->phy_g;
2366 	unsigned int channel;
2367 	uint16_t rfover, rfoverval;
2368 
2369 	if (on) {
2370 		if (phy->rf_on)
2371 			return;
2372 
2373 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2374 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2375 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2376 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2377 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2378 			    pg->pg_radioctx_over);
2379 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2380 			    pg->pg_radioctx_overval);
2381 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2382 		}
2383 		channel = phy->chan;
2384 		bwn_phy_g_switch_chan(mac, 6, 1);
2385 		bwn_phy_g_switch_chan(mac, channel, 0);
2386 		return;
2387 	}
2388 
2389 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2390 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2391 	pg->pg_radioctx_over = rfover;
2392 	pg->pg_radioctx_overval = rfoverval;
2393 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2394 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2395 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2396 }
2397 
2398 static int
2399 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2400 {
2401 
2402 	if ((newchan < 1) || (newchan > 14))
2403 		return (EINVAL);
2404 	bwn_phy_g_switch_chan(mac, newchan, 0);
2405 
2406 	return (0);
2407 }
2408 
2409 static uint32_t
2410 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2411 {
2412 
2413 	return (1);
2414 }
2415 
2416 static void
2417 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2418 {
2419 	struct bwn_phy *phy = &mac->mac_phy;
2420 	uint64_t hf;
2421 	int autodiv = 0;
2422 	uint16_t tmp;
2423 
2424 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2425 		autodiv = 1;
2426 
2427 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2428 	bwn_hf_write(mac, hf);
2429 
2430 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2431 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2432 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2433 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2434 
2435 	if (autodiv) {
2436 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2437 		if (antenna == BWN_ANTAUTO1)
2438 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2439 		else
2440 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2441 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2442 	}
2443 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2444 	if (autodiv)
2445 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2446 	else
2447 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2448 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2449 	if (phy->rev >= 2) {
2450 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2451 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2452 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2453 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2454 		    0x15);
2455 		if (phy->rev == 2)
2456 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2457 		else
2458 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2459 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2460 			    8);
2461 	}
2462 	if (phy->rev >= 6)
2463 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2464 
2465 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2466 	bwn_hf_write(mac, hf);
2467 }
2468 
2469 static int
2470 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2471 {
2472 	struct bwn_phy *phy = &mac->mac_phy;
2473 	struct bwn_phy_g *pg = &phy->phy_g;
2474 
2475 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2476 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2477 
2478 	if (phy->rev == 0 || !phy->gmode)
2479 		return (ENODEV);
2480 
2481 	pg->pg_aci_wlan_automatic = 0;
2482 	return (0);
2483 }
2484 
2485 static int
2486 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2487 {
2488 	struct bwn_phy *phy = &mac->mac_phy;
2489 	struct bwn_phy_g *pg = &phy->phy_g;
2490 	struct bwn_softc *sc = mac->mac_sc;
2491 	unsigned int tssi;
2492 	int cck, ofdm;
2493 	int power;
2494 	int rfatt, bbatt;
2495 	unsigned int max;
2496 
2497 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2498 
2499 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2500 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2501 	if (cck < 0 && ofdm < 0) {
2502 		if (ignore_tssi == 0)
2503 			return (BWN_TXPWR_RES_DONE);
2504 		cck = 0;
2505 		ofdm = 0;
2506 	}
2507 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2508 	if (pg->pg_avgtssi != 0xff)
2509 		tssi = (tssi + pg->pg_avgtssi) / 2;
2510 	pg->pg_avgtssi = tssi;
2511 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2512 
2513 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2514 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2515 		max -= 3;
2516 	if (max >= 120) {
2517 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2518 		max = 80;
2519 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2520 	}
2521 
2522 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2523 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2524 	     tssi, 0x00), 0x3f)]);
2525 	if (power == 0)
2526 		return (BWN_TXPWR_RES_DONE);
2527 
2528 	rfatt = -((power + 7) / 8);
2529 	bbatt = (-(power / 2)) - (4 * rfatt);
2530 	if ((rfatt == 0) && (bbatt == 0))
2531 		return (BWN_TXPWR_RES_DONE);
2532 	pg->pg_bbatt_delta = bbatt;
2533 	pg->pg_rfatt_delta = rfatt;
2534 	return (BWN_TXPWR_RES_NEED_ADJUST);
2535 }
2536 
2537 static void
2538 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2539 {
2540 	struct bwn_phy *phy = &mac->mac_phy;
2541 	struct bwn_phy_g *pg = &phy->phy_g;
2542 	struct bwn_softc *sc = mac->mac_sc;
2543 	int rfatt, bbatt;
2544 	uint8_t txctl;
2545 
2546 	bwn_mac_suspend(mac);
2547 
2548 	BWN_ASSERT_LOCKED(sc);
2549 
2550 	bbatt = pg->pg_bbatt.att;
2551 	bbatt += pg->pg_bbatt_delta;
2552 	rfatt = pg->pg_rfatt.att;
2553 	rfatt += pg->pg_rfatt_delta;
2554 
2555 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2556 	txctl = pg->pg_txctl;
2557 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2558 		if (rfatt <= 1) {
2559 			if (txctl == 0) {
2560 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2561 				rfatt += 2;
2562 				bbatt += 2;
2563 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2564 			    BWN_BFL_PACTRL) {
2565 				bbatt += 4 * (rfatt - 2);
2566 				rfatt = 2;
2567 			}
2568 		} else if (rfatt > 4 && txctl) {
2569 			txctl = 0;
2570 			if (bbatt < 3) {
2571 				rfatt -= 3;
2572 				bbatt += 2;
2573 			} else {
2574 				rfatt -= 2;
2575 				bbatt -= 2;
2576 			}
2577 		}
2578 	}
2579 	pg->pg_txctl = txctl;
2580 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2581 	pg->pg_rfatt.att = rfatt;
2582 	pg->pg_bbatt.att = bbatt;
2583 
2584 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2585 
2586 	bwn_phy_lock(mac);
2587 	bwn_rf_lock(mac);
2588 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2589 	    pg->pg_txctl);
2590 	bwn_rf_unlock(mac);
2591 	bwn_phy_unlock(mac);
2592 
2593 	bwn_mac_enable(mac);
2594 }
2595 
2596 static void
2597 bwn_phy_g_task_15s(struct bwn_mac *mac)
2598 {
2599 	struct bwn_phy *phy = &mac->mac_phy;
2600 	struct bwn_phy_g *pg = &phy->phy_g;
2601 	struct bwn_softc *sc = mac->mac_sc;
2602 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2603 	unsigned long expire, now;
2604 	struct bwn_lo_calib *cal, *tmp;
2605 	uint8_t expired = 0;
2606 
2607 	bwn_mac_suspend(mac);
2608 
2609 	if (lo == NULL)
2610 		goto fail;
2611 
2612 	BWN_GETTIME(now);
2613 	if (bwn_has_hwpctl(mac)) {
2614 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2615 		if (time_before(lo->pwr_vec_read_time, expire)) {
2616 			bwn_lo_get_powervector(mac);
2617 			bwn_phy_g_dc_lookup_init(mac, 0);
2618 		}
2619 		goto fail;
2620 	}
2621 
2622 	expire = now - BWN_LO_CALIB_EXPIRE;
2623 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2624 		if (!time_before(cal->calib_time, expire))
2625 			continue;
2626 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2627 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2628 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2629 			expired = 1;
2630 		}
2631 
2632 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2633 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2634 		    cal->ctl.i, cal->ctl.q);
2635 
2636 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2637 		free(cal, M_DEVBUF);
2638 	}
2639 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2640 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2641 		    &pg->pg_rfatt);
2642 		if (cal == NULL) {
2643 			device_printf(sc->sc_dev,
2644 			    "failed to recalibrate LO\n");
2645 			goto fail;
2646 		}
2647 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2648 		bwn_lo_write(mac, &cal->ctl);
2649 	}
2650 
2651 fail:
2652 	bwn_mac_enable(mac);
2653 }
2654 
2655 static void
2656 bwn_phy_g_task_60s(struct bwn_mac *mac)
2657 {
2658 	struct bwn_phy *phy = &mac->mac_phy;
2659 	struct bwn_softc *sc = mac->mac_sc;
2660 	uint8_t old = phy->chan;
2661 
2662 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2663 		return;
2664 
2665 	bwn_mac_suspend(mac);
2666 	bwn_nrssi_slope_11g(mac);
2667 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2668 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2669 		bwn_switch_channel(mac, old);
2670 	}
2671 	bwn_mac_enable(mac);
2672 }
2673 
2674 static void
2675 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2676 {
2677 
2678 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2679 }
2680 
2681 static int
2682 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2683 	const struct ieee80211_bpf_params *params)
2684 {
2685 	struct ieee80211com *ic = ni->ni_ic;
2686 	struct bwn_softc *sc = ic->ic_softc;
2687 	struct bwn_mac *mac = sc->sc_curmac;
2688 	int error;
2689 
2690 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
2691 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2692 		m_freem(m);
2693 		return (ENETDOWN);
2694 	}
2695 
2696 	BWN_LOCK(sc);
2697 	if (bwn_tx_isfull(sc, m)) {
2698 		m_freem(m);
2699 		BWN_UNLOCK(sc);
2700 		return (ENOBUFS);
2701 	}
2702 
2703 	error = bwn_tx_start(sc, ni, m);
2704 	if (error == 0)
2705 		sc->sc_watchdog_timer = 5;
2706 	BWN_UNLOCK(sc);
2707 	return (error);
2708 }
2709 
2710 /*
2711  * Callback from the 802.11 layer to update the slot time
2712  * based on the current setting.  We use it to notify the
2713  * firmware of ERP changes and the f/w takes care of things
2714  * like slot time and preamble.
2715  */
2716 static void
2717 bwn_updateslot(struct ieee80211com *ic)
2718 {
2719 	struct bwn_softc *sc = ic->ic_softc;
2720 	struct bwn_mac *mac;
2721 
2722 	BWN_LOCK(sc);
2723 	if (sc->sc_flags & BWN_FLAG_RUNNING) {
2724 		mac = (struct bwn_mac *)sc->sc_curmac;
2725 		bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
2726 	}
2727 	BWN_UNLOCK(sc);
2728 }
2729 
2730 /*
2731  * Callback from the 802.11 layer after a promiscuous mode change.
2732  * Note this interface does not check the operating mode as this
2733  * is an internal callback and we are expected to honor the current
2734  * state (e.g. this is used for setting the interface in promiscuous
2735  * mode when operating in hostap mode to do ACS).
2736  */
2737 static void
2738 bwn_update_promisc(struct ieee80211com *ic)
2739 {
2740 	struct bwn_softc *sc = ic->ic_softc;
2741 	struct bwn_mac *mac = sc->sc_curmac;
2742 
2743 	BWN_LOCK(sc);
2744 	mac = sc->sc_curmac;
2745 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2746 		if (ic->ic_promisc > 0)
2747 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2748 		else
2749 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2750 		bwn_set_opmode(mac);
2751 	}
2752 	BWN_UNLOCK(sc);
2753 }
2754 
2755 /*
2756  * Callback from the 802.11 layer to update WME parameters.
2757  */
2758 static int
2759 bwn_wme_update(struct ieee80211com *ic)
2760 {
2761 	struct bwn_softc *sc = ic->ic_softc;
2762 	struct bwn_mac *mac = sc->sc_curmac;
2763 	struct wmeParams *wmep;
2764 	int i;
2765 
2766 	BWN_LOCK(sc);
2767 	mac = sc->sc_curmac;
2768 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2769 		bwn_mac_suspend(mac);
2770 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2771 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2772 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2773 		}
2774 		bwn_mac_enable(mac);
2775 	}
2776 	BWN_UNLOCK(sc);
2777 	return (0);
2778 }
2779 
2780 static void
2781 bwn_scan_start(struct ieee80211com *ic)
2782 {
2783 	struct bwn_softc *sc = ic->ic_softc;
2784 	struct bwn_mac *mac;
2785 
2786 	BWN_LOCK(sc);
2787 	mac = sc->sc_curmac;
2788 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2789 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2790 		bwn_set_opmode(mac);
2791 		/* disable CFP update during scan */
2792 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2793 	}
2794 	BWN_UNLOCK(sc);
2795 }
2796 
2797 static void
2798 bwn_scan_end(struct ieee80211com *ic)
2799 {
2800 	struct bwn_softc *sc = ic->ic_softc;
2801 	struct bwn_mac *mac;
2802 
2803 	BWN_LOCK(sc);
2804 	mac = sc->sc_curmac;
2805 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2806 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2807 		bwn_set_opmode(mac);
2808 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2809 	}
2810 	BWN_UNLOCK(sc);
2811 }
2812 
2813 static void
2814 bwn_set_channel(struct ieee80211com *ic)
2815 {
2816 	struct bwn_softc *sc = ic->ic_softc;
2817 	struct bwn_mac *mac = sc->sc_curmac;
2818 	struct bwn_phy *phy = &mac->mac_phy;
2819 	int chan, error;
2820 
2821 	BWN_LOCK(sc);
2822 
2823 	error = bwn_switch_band(sc, ic->ic_curchan);
2824 	if (error)
2825 		goto fail;
2826 	bwn_mac_suspend(mac);
2827 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2828 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2829 	if (chan != phy->chan)
2830 		bwn_switch_channel(mac, chan);
2831 
2832 	/* TX power level */
2833 	if (ic->ic_curchan->ic_maxpower != 0 &&
2834 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2835 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2836 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2837 		    BWN_TXPWR_IGNORE_TSSI);
2838 	}
2839 
2840 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2841 	if (phy->set_antenna)
2842 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2843 
2844 	if (sc->sc_rf_enabled != phy->rf_on) {
2845 		if (sc->sc_rf_enabled) {
2846 			bwn_rf_turnon(mac);
2847 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2848 				device_printf(sc->sc_dev,
2849 				    "please turn on the RF switch\n");
2850 		} else
2851 			bwn_rf_turnoff(mac);
2852 	}
2853 
2854 	bwn_mac_enable(mac);
2855 
2856 fail:
2857 	/*
2858 	 * Setup radio tap channel freq and flags
2859 	 */
2860 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2861 		htole16(ic->ic_curchan->ic_freq);
2862 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2863 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2864 
2865 	BWN_UNLOCK(sc);
2866 }
2867 
2868 static struct ieee80211vap *
2869 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2870     enum ieee80211_opmode opmode, int flags,
2871     const uint8_t bssid[IEEE80211_ADDR_LEN],
2872     const uint8_t mac[IEEE80211_ADDR_LEN])
2873 {
2874 	struct ieee80211vap *vap;
2875 	struct bwn_vap *bvp;
2876 
2877 	switch (opmode) {
2878 	case IEEE80211_M_HOSTAP:
2879 	case IEEE80211_M_MBSS:
2880 	case IEEE80211_M_STA:
2881 	case IEEE80211_M_WDS:
2882 	case IEEE80211_M_MONITOR:
2883 	case IEEE80211_M_IBSS:
2884 	case IEEE80211_M_AHDEMO:
2885 		break;
2886 	default:
2887 		return (NULL);
2888 	}
2889 
2890 	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2891 	vap = &bvp->bv_vap;
2892 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2893 	/* override with driver methods */
2894 	bvp->bv_newstate = vap->iv_newstate;
2895 	vap->iv_newstate = bwn_newstate;
2896 
2897 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2898 	vap->iv_max_aid = BWN_STAID_MAX;
2899 
2900 	ieee80211_ratectl_init(vap);
2901 
2902 	/* complete setup */
2903 	ieee80211_vap_attach(vap, ieee80211_media_change,
2904 	    ieee80211_media_status, mac);
2905 	return (vap);
2906 }
2907 
2908 static void
2909 bwn_vap_delete(struct ieee80211vap *vap)
2910 {
2911 	struct bwn_vap *bvp = BWN_VAP(vap);
2912 
2913 	ieee80211_ratectl_deinit(vap);
2914 	ieee80211_vap_detach(vap);
2915 	free(bvp, M_80211_VAP);
2916 }
2917 
2918 static int
2919 bwn_init(struct bwn_softc *sc)
2920 {
2921 	struct bwn_mac *mac;
2922 	int error;
2923 
2924 	BWN_ASSERT_LOCKED(sc);
2925 
2926 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2927 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2928 	sc->sc_filters = 0;
2929 	bwn_wme_clear(sc);
2930 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2931 	sc->sc_rf_enabled = 1;
2932 
2933 	mac = sc->sc_curmac;
2934 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2935 		error = bwn_core_init(mac);
2936 		if (error != 0)
2937 			return (error);
2938 	}
2939 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2940 		bwn_core_start(mac);
2941 
2942 	bwn_set_opmode(mac);
2943 	bwn_set_pretbtt(mac);
2944 	bwn_spu_setdelay(mac, 0);
2945 	bwn_set_macaddr(mac);
2946 
2947 	sc->sc_flags |= BWN_FLAG_RUNNING;
2948 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2949 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2950 
2951 	return (0);
2952 }
2953 
2954 static void
2955 bwn_stop(struct bwn_softc *sc)
2956 {
2957 	struct bwn_mac *mac = sc->sc_curmac;
2958 
2959 	BWN_ASSERT_LOCKED(sc);
2960 
2961 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2962 		/* XXX FIXME opmode not based on VAP */
2963 		bwn_set_opmode(mac);
2964 		bwn_set_macaddr(mac);
2965 	}
2966 
2967 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2968 		bwn_core_stop(mac);
2969 
2970 	callout_stop(&sc->sc_led_blink_ch);
2971 	sc->sc_led_blinking = 0;
2972 
2973 	bwn_core_exit(mac);
2974 	sc->sc_rf_enabled = 0;
2975 
2976 	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2977 }
2978 
2979 static void
2980 bwn_wme_clear(struct bwn_softc *sc)
2981 {
2982 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
2983 	struct wmeParams *p;
2984 	unsigned int i;
2985 
2986 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2987 	    ("%s:%d: fail", __func__, __LINE__));
2988 
2989 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2990 		p = &(sc->sc_wmeParams[i]);
2991 
2992 		switch (bwn_wme_shm_offsets[i]) {
2993 		case BWN_WME_VOICE:
2994 			p->wmep_txopLimit = 0;
2995 			p->wmep_aifsn = 2;
2996 			/* XXX FIXME: log2(cwmin) */
2997 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2998 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2999 			break;
3000 		case BWN_WME_VIDEO:
3001 			p->wmep_txopLimit = 0;
3002 			p->wmep_aifsn = 2;
3003 			/* XXX FIXME: log2(cwmin) */
3004 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3005 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3006 			break;
3007 		case BWN_WME_BESTEFFORT:
3008 			p->wmep_txopLimit = 0;
3009 			p->wmep_aifsn = 3;
3010 			/* XXX FIXME: log2(cwmin) */
3011 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3012 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3013 			break;
3014 		case BWN_WME_BACKGROUND:
3015 			p->wmep_txopLimit = 0;
3016 			p->wmep_aifsn = 7;
3017 			/* XXX FIXME: log2(cwmin) */
3018 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3019 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3020 			break;
3021 		default:
3022 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3023 		}
3024 	}
3025 }
3026 
3027 static int
3028 bwn_core_init(struct bwn_mac *mac)
3029 {
3030 	struct bwn_softc *sc = mac->mac_sc;
3031 	uint64_t hf;
3032 	int error;
3033 
3034 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3035 	    ("%s:%d: fail", __func__, __LINE__));
3036 
3037 	siba_powerup(sc->sc_dev, 0);
3038 	if (!siba_dev_isup(sc->sc_dev))
3039 		bwn_reset_core(mac,
3040 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3041 
3042 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3043 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3044 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3045 	BWN_GETTIME(mac->mac_phy.nexttime);
3046 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3047 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3048 	mac->mac_stats.link_noise = -95;
3049 	mac->mac_reason_intr = 0;
3050 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3051 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3052 #ifdef BWN_DEBUG
3053 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3054 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3055 #endif
3056 	mac->mac_suspended = 1;
3057 	mac->mac_task_state = 0;
3058 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3059 
3060 	mac->mac_phy.init_pre(mac);
3061 
3062 	siba_pcicore_intr(sc->sc_dev);
3063 
3064 	siba_fix_imcfglobug(sc->sc_dev);
3065 	bwn_bt_disable(mac);
3066 	if (mac->mac_phy.prepare_hw) {
3067 		error = mac->mac_phy.prepare_hw(mac);
3068 		if (error)
3069 			goto fail0;
3070 	}
3071 	error = bwn_chip_init(mac);
3072 	if (error)
3073 		goto fail0;
3074 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3075 	    siba_get_revid(sc->sc_dev));
3076 	hf = bwn_hf_read(mac);
3077 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3078 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3079 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3080 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3081 		if (mac->mac_phy.rev == 1)
3082 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3083 	}
3084 	if (mac->mac_phy.rf_ver == 0x2050) {
3085 		if (mac->mac_phy.rf_rev < 6)
3086 			hf |= BWN_HF_FORCE_VCO_RECALC;
3087 		if (mac->mac_phy.rf_rev == 6)
3088 			hf |= BWN_HF_4318_TSSI;
3089 	}
3090 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3091 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3092 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3093 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3094 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3095 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3096 	bwn_hf_write(mac, hf);
3097 
3098 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3099 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3100 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3101 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3102 
3103 	bwn_rate_init(mac);
3104 	bwn_set_phytxctl(mac);
3105 
3106 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3107 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3108 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3109 
3110 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3111 		bwn_pio_init(mac);
3112 	else
3113 		bwn_dma_init(mac);
3114 	bwn_wme_init(mac);
3115 	bwn_spu_setdelay(mac, 1);
3116 	bwn_bt_enable(mac);
3117 
3118 	siba_powerup(sc->sc_dev,
3119 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3120 	bwn_set_macaddr(mac);
3121 	bwn_crypt_init(mac);
3122 
3123 	/* XXX LED initializatin */
3124 
3125 	mac->mac_status = BWN_MAC_STATUS_INITED;
3126 
3127 	return (error);
3128 
3129 fail0:
3130 	siba_powerdown(sc->sc_dev);
3131 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3132 	    ("%s:%d: fail", __func__, __LINE__));
3133 	return (error);
3134 }
3135 
3136 static void
3137 bwn_core_start(struct bwn_mac *mac)
3138 {
3139 	struct bwn_softc *sc = mac->mac_sc;
3140 	uint32_t tmp;
3141 
3142 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3143 	    ("%s:%d: fail", __func__, __LINE__));
3144 
3145 	if (siba_get_revid(sc->sc_dev) < 5)
3146 		return;
3147 
3148 	while (1) {
3149 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3150 		if (!(tmp & 0x00000001))
3151 			break;
3152 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3153 	}
3154 
3155 	bwn_mac_enable(mac);
3156 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3157 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3158 
3159 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3160 }
3161 
3162 static void
3163 bwn_core_exit(struct bwn_mac *mac)
3164 {
3165 	struct bwn_softc *sc = mac->mac_sc;
3166 	uint32_t macctl;
3167 
3168 	BWN_ASSERT_LOCKED(mac->mac_sc);
3169 
3170 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3171 	    ("%s:%d: fail", __func__, __LINE__));
3172 
3173 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3174 		return;
3175 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3176 
3177 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3178 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3179 	macctl |= BWN_MACCTL_MCODE_JMP0;
3180 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3181 
3182 	bwn_dma_stop(mac);
3183 	bwn_pio_stop(mac);
3184 	bwn_chip_exit(mac);
3185 	mac->mac_phy.switch_analog(mac, 0);
3186 	siba_dev_down(sc->sc_dev, 0);
3187 	siba_powerdown(sc->sc_dev);
3188 }
3189 
3190 static void
3191 bwn_bt_disable(struct bwn_mac *mac)
3192 {
3193 	struct bwn_softc *sc = mac->mac_sc;
3194 
3195 	(void)sc;
3196 	/* XXX do nothing yet */
3197 }
3198 
3199 static int
3200 bwn_chip_init(struct bwn_mac *mac)
3201 {
3202 	struct bwn_softc *sc = mac->mac_sc;
3203 	struct bwn_phy *phy = &mac->mac_phy;
3204 	uint32_t macctl;
3205 	int error;
3206 
3207 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3208 	if (phy->gmode)
3209 		macctl |= BWN_MACCTL_GMODE;
3210 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3211 
3212 	error = bwn_fw_fillinfo(mac);
3213 	if (error)
3214 		return (error);
3215 	error = bwn_fw_loaducode(mac);
3216 	if (error)
3217 		return (error);
3218 
3219 	error = bwn_gpio_init(mac);
3220 	if (error)
3221 		return (error);
3222 
3223 	error = bwn_fw_loadinitvals(mac);
3224 	if (error) {
3225 		siba_gpio_set(sc->sc_dev, 0);
3226 		return (error);
3227 	}
3228 	phy->switch_analog(mac, 1);
3229 	error = bwn_phy_init(mac);
3230 	if (error) {
3231 		siba_gpio_set(sc->sc_dev, 0);
3232 		return (error);
3233 	}
3234 	if (phy->set_im)
3235 		phy->set_im(mac, BWN_IMMODE_NONE);
3236 	if (phy->set_antenna)
3237 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3238 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3239 
3240 	if (phy->type == BWN_PHYTYPE_B)
3241 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3242 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3243 	if (siba_get_revid(sc->sc_dev) < 5)
3244 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3245 
3246 	BWN_WRITE_4(mac, BWN_MACCTL,
3247 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3248 	BWN_WRITE_4(mac, BWN_MACCTL,
3249 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3250 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3251 
3252 	bwn_set_opmode(mac);
3253 	if (siba_get_revid(sc->sc_dev) < 3) {
3254 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3255 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3256 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3257 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3258 	} else {
3259 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3260 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3261 	}
3262 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3263 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3264 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3265 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3266 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3267 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3268 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3269 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3270 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3271 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3272 	return (error);
3273 }
3274 
3275 /* read hostflags */
3276 static uint64_t
3277 bwn_hf_read(struct bwn_mac *mac)
3278 {
3279 	uint64_t ret;
3280 
3281 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3282 	ret <<= 16;
3283 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3284 	ret <<= 16;
3285 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3286 	return (ret);
3287 }
3288 
3289 static void
3290 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3291 {
3292 
3293 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3294 	    (value & 0x00000000ffffull));
3295 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3296 	    (value & 0x0000ffff0000ull) >> 16);
3297 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3298 	    (value & 0xffff00000000ULL) >> 32);
3299 }
3300 
3301 static void
3302 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3303 {
3304 
3305 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3306 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3307 }
3308 
3309 static void
3310 bwn_rate_init(struct bwn_mac *mac)
3311 {
3312 
3313 	switch (mac->mac_phy.type) {
3314 	case BWN_PHYTYPE_A:
3315 	case BWN_PHYTYPE_G:
3316 	case BWN_PHYTYPE_LP:
3317 	case BWN_PHYTYPE_N:
3318 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3319 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3320 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3321 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3322 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3323 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3324 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3325 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3326 			break;
3327 		/* FALLTHROUGH */
3328 	case BWN_PHYTYPE_B:
3329 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3330 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3331 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3332 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3333 		break;
3334 	default:
3335 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3336 	}
3337 }
3338 
3339 static void
3340 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3341 {
3342 	uint16_t offset;
3343 
3344 	if (ofdm) {
3345 		offset = 0x480;
3346 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3347 	} else {
3348 		offset = 0x4c0;
3349 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3350 	}
3351 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3352 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3353 }
3354 
3355 static uint8_t
3356 bwn_plcp_getcck(const uint8_t bitrate)
3357 {
3358 
3359 	switch (bitrate) {
3360 	case BWN_CCK_RATE_1MB:
3361 		return (0x0a);
3362 	case BWN_CCK_RATE_2MB:
3363 		return (0x14);
3364 	case BWN_CCK_RATE_5MB:
3365 		return (0x37);
3366 	case BWN_CCK_RATE_11MB:
3367 		return (0x6e);
3368 	}
3369 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3370 	return (0);
3371 }
3372 
3373 static uint8_t
3374 bwn_plcp_getofdm(const uint8_t bitrate)
3375 {
3376 
3377 	switch (bitrate) {
3378 	case BWN_OFDM_RATE_6MB:
3379 		return (0xb);
3380 	case BWN_OFDM_RATE_9MB:
3381 		return (0xf);
3382 	case BWN_OFDM_RATE_12MB:
3383 		return (0xa);
3384 	case BWN_OFDM_RATE_18MB:
3385 		return (0xe);
3386 	case BWN_OFDM_RATE_24MB:
3387 		return (0x9);
3388 	case BWN_OFDM_RATE_36MB:
3389 		return (0xd);
3390 	case BWN_OFDM_RATE_48MB:
3391 		return (0x8);
3392 	case BWN_OFDM_RATE_54MB:
3393 		return (0xc);
3394 	}
3395 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3396 	return (0);
3397 }
3398 
3399 static void
3400 bwn_set_phytxctl(struct bwn_mac *mac)
3401 {
3402 	uint16_t ctl;
3403 
3404 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3405 	    BWN_TX_PHY_TXPWR);
3406 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3407 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3408 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3409 }
3410 
3411 static void
3412 bwn_pio_init(struct bwn_mac *mac)
3413 {
3414 	struct bwn_pio *pio = &mac->mac_method.pio;
3415 
3416 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3417 	    & ~BWN_MACCTL_BIGENDIAN);
3418 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3419 
3420 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3421 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3422 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3423 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3424 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3425 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3426 }
3427 
3428 static void
3429 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3430     int index)
3431 {
3432 	struct bwn_pio_txpkt *tp;
3433 	struct bwn_softc *sc = mac->mac_sc;
3434 	unsigned int i;
3435 
3436 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3437 	tq->tq_index = index;
3438 
3439 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3440 	if (siba_get_revid(sc->sc_dev) >= 8)
3441 		tq->tq_size = 1920;
3442 	else {
3443 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3444 		tq->tq_size -= 80;
3445 	}
3446 
3447 	TAILQ_INIT(&tq->tq_pktlist);
3448 	for (i = 0; i < N(tq->tq_pkts); i++) {
3449 		tp = &(tq->tq_pkts[i]);
3450 		tp->tp_index = i;
3451 		tp->tp_queue = tq;
3452 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3453 	}
3454 }
3455 
3456 static uint16_t
3457 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3458 {
3459 	struct bwn_softc *sc = mac->mac_sc;
3460 	static const uint16_t bases[] = {
3461 		BWN_PIO_BASE0,
3462 		BWN_PIO_BASE1,
3463 		BWN_PIO_BASE2,
3464 		BWN_PIO_BASE3,
3465 		BWN_PIO_BASE4,
3466 		BWN_PIO_BASE5,
3467 		BWN_PIO_BASE6,
3468 		BWN_PIO_BASE7,
3469 	};
3470 	static const uint16_t bases_rev11[] = {
3471 		BWN_PIO11_BASE0,
3472 		BWN_PIO11_BASE1,
3473 		BWN_PIO11_BASE2,
3474 		BWN_PIO11_BASE3,
3475 		BWN_PIO11_BASE4,
3476 		BWN_PIO11_BASE5,
3477 	};
3478 
3479 	if (siba_get_revid(sc->sc_dev) >= 11) {
3480 		if (index >= N(bases_rev11))
3481 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3482 		return (bases_rev11[index]);
3483 	}
3484 	if (index >= N(bases))
3485 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3486 	return (bases[index]);
3487 }
3488 
3489 static void
3490 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3491     int index)
3492 {
3493 	struct bwn_softc *sc = mac->mac_sc;
3494 
3495 	prq->prq_mac = mac;
3496 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3497 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3498 	bwn_dma_rxdirectfifo(mac, index, 1);
3499 }
3500 
3501 static void
3502 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3503 {
3504 	if (tq == NULL)
3505 		return;
3506 	bwn_pio_cancel_tx_packets(tq);
3507 }
3508 
3509 static void
3510 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3511 {
3512 
3513 	bwn_destroy_pioqueue_tx(pio);
3514 }
3515 
3516 static uint16_t
3517 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3518     uint16_t offset)
3519 {
3520 
3521 	return (BWN_READ_2(mac, tq->tq_base + offset));
3522 }
3523 
3524 static void
3525 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3526 {
3527 	uint32_t ctl;
3528 	int type;
3529 	uint16_t base;
3530 
3531 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3532 	base = bwn_dma_base(type, idx);
3533 	if (type == BWN_DMA_64BIT) {
3534 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3535 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3536 		if (enable)
3537 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3538 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3539 	} else {
3540 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3541 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3542 		if (enable)
3543 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3544 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3545 	}
3546 }
3547 
3548 static uint64_t
3549 bwn_dma_mask(struct bwn_mac *mac)
3550 {
3551 	uint32_t tmp;
3552 	uint16_t base;
3553 
3554 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3555 	if (tmp & SIBA_TGSHIGH_DMA64)
3556 		return (BWN_DMA_BIT_MASK(64));
3557 	base = bwn_dma_base(0, 0);
3558 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3559 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3560 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3561 		return (BWN_DMA_BIT_MASK(32));
3562 
3563 	return (BWN_DMA_BIT_MASK(30));
3564 }
3565 
3566 static int
3567 bwn_dma_mask2type(uint64_t dmamask)
3568 {
3569 
3570 	if (dmamask == BWN_DMA_BIT_MASK(30))
3571 		return (BWN_DMA_30BIT);
3572 	if (dmamask == BWN_DMA_BIT_MASK(32))
3573 		return (BWN_DMA_32BIT);
3574 	if (dmamask == BWN_DMA_BIT_MASK(64))
3575 		return (BWN_DMA_64BIT);
3576 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3577 	return (BWN_DMA_30BIT);
3578 }
3579 
3580 static void
3581 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3582 {
3583 	struct bwn_pio_txpkt *tp;
3584 	unsigned int i;
3585 
3586 	for (i = 0; i < N(tq->tq_pkts); i++) {
3587 		tp = &(tq->tq_pkts[i]);
3588 		if (tp->tp_m) {
3589 			m_freem(tp->tp_m);
3590 			tp->tp_m = NULL;
3591 		}
3592 	}
3593 }
3594 
3595 static uint16_t
3596 bwn_dma_base(int type, int controller_idx)
3597 {
3598 	static const uint16_t map64[] = {
3599 		BWN_DMA64_BASE0,
3600 		BWN_DMA64_BASE1,
3601 		BWN_DMA64_BASE2,
3602 		BWN_DMA64_BASE3,
3603 		BWN_DMA64_BASE4,
3604 		BWN_DMA64_BASE5,
3605 	};
3606 	static const uint16_t map32[] = {
3607 		BWN_DMA32_BASE0,
3608 		BWN_DMA32_BASE1,
3609 		BWN_DMA32_BASE2,
3610 		BWN_DMA32_BASE3,
3611 		BWN_DMA32_BASE4,
3612 		BWN_DMA32_BASE5,
3613 	};
3614 
3615 	if (type == BWN_DMA_64BIT) {
3616 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3617 		    ("%s:%d: fail", __func__, __LINE__));
3618 		return (map64[controller_idx]);
3619 	}
3620 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3621 	    ("%s:%d: fail", __func__, __LINE__));
3622 	return (map32[controller_idx]);
3623 }
3624 
3625 static void
3626 bwn_dma_init(struct bwn_mac *mac)
3627 {
3628 	struct bwn_dma *dma = &mac->mac_method.dma;
3629 
3630 	/* setup TX DMA channels. */
3631 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3632 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3633 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3634 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3635 	bwn_dma_setup(dma->mcast);
3636 	/* setup RX DMA channel. */
3637 	bwn_dma_setup(dma->rx);
3638 }
3639 
3640 static struct bwn_dma_ring *
3641 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3642     int for_tx, int type)
3643 {
3644 	struct bwn_dma *dma = &mac->mac_method.dma;
3645 	struct bwn_dma_ring *dr;
3646 	struct bwn_dmadesc_generic *desc;
3647 	struct bwn_dmadesc_meta *mt;
3648 	struct bwn_softc *sc = mac->mac_sc;
3649 	int error, i;
3650 
3651 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3652 	if (dr == NULL)
3653 		goto out;
3654 	dr->dr_numslots = BWN_RXRING_SLOTS;
3655 	if (for_tx)
3656 		dr->dr_numslots = BWN_TXRING_SLOTS;
3657 
3658 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3659 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3660 	if (dr->dr_meta == NULL)
3661 		goto fail0;
3662 
3663 	dr->dr_type = type;
3664 	dr->dr_mac = mac;
3665 	dr->dr_base = bwn_dma_base(type, controller_index);
3666 	dr->dr_index = controller_index;
3667 	if (type == BWN_DMA_64BIT) {
3668 		dr->getdesc = bwn_dma_64_getdesc;
3669 		dr->setdesc = bwn_dma_64_setdesc;
3670 		dr->start_transfer = bwn_dma_64_start_transfer;
3671 		dr->suspend = bwn_dma_64_suspend;
3672 		dr->resume = bwn_dma_64_resume;
3673 		dr->get_curslot = bwn_dma_64_get_curslot;
3674 		dr->set_curslot = bwn_dma_64_set_curslot;
3675 	} else {
3676 		dr->getdesc = bwn_dma_32_getdesc;
3677 		dr->setdesc = bwn_dma_32_setdesc;
3678 		dr->start_transfer = bwn_dma_32_start_transfer;
3679 		dr->suspend = bwn_dma_32_suspend;
3680 		dr->resume = bwn_dma_32_resume;
3681 		dr->get_curslot = bwn_dma_32_get_curslot;
3682 		dr->set_curslot = bwn_dma_32_set_curslot;
3683 	}
3684 	if (for_tx) {
3685 		dr->dr_tx = 1;
3686 		dr->dr_curslot = -1;
3687 	} else {
3688 		if (dr->dr_index == 0) {
3689 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3690 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3691 		} else
3692 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3693 	}
3694 
3695 	error = bwn_dma_allocringmemory(dr);
3696 	if (error)
3697 		goto fail2;
3698 
3699 	if (for_tx) {
3700 		/*
3701 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3702 		 * BWN_TX_SLOTS_PER_FRAME
3703 		 */
3704 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3705 		    ("%s:%d: fail", __func__, __LINE__));
3706 
3707 		dr->dr_txhdr_cache =
3708 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3709 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3710 		KASSERT(dr->dr_txhdr_cache != NULL,
3711 		    ("%s:%d: fail", __func__, __LINE__));
3712 
3713 		/*
3714 		 * Create TX ring DMA stuffs
3715 		 */
3716 		error = bus_dma_tag_create(dma->parent_dtag,
3717 				    BWN_ALIGN, 0,
3718 				    BUS_SPACE_MAXADDR,
3719 				    BUS_SPACE_MAXADDR,
3720 				    NULL, NULL,
3721 				    BWN_HDRSIZE(mac),
3722 				    1,
3723 				    BUS_SPACE_MAXSIZE_32BIT,
3724 				    0,
3725 				    NULL, NULL,
3726 				    &dr->dr_txring_dtag);
3727 		if (error) {
3728 			device_printf(sc->sc_dev,
3729 			    "can't create TX ring DMA tag: TODO frees\n");
3730 			goto fail1;
3731 		}
3732 
3733 		for (i = 0; i < dr->dr_numslots; i += 2) {
3734 			dr->getdesc(dr, i, &desc, &mt);
3735 
3736 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3737 			mt->mt_m = NULL;
3738 			mt->mt_ni = NULL;
3739 			mt->mt_islast = 0;
3740 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3741 			    &mt->mt_dmap);
3742 			if (error) {
3743 				device_printf(sc->sc_dev,
3744 				     "can't create RX buf DMA map\n");
3745 				goto fail1;
3746 			}
3747 
3748 			dr->getdesc(dr, i + 1, &desc, &mt);
3749 
3750 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3751 			mt->mt_m = NULL;
3752 			mt->mt_ni = NULL;
3753 			mt->mt_islast = 1;
3754 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3755 			    &mt->mt_dmap);
3756 			if (error) {
3757 				device_printf(sc->sc_dev,
3758 				     "can't create RX buf DMA map\n");
3759 				goto fail1;
3760 			}
3761 		}
3762 	} else {
3763 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3764 		    &dr->dr_spare_dmap);
3765 		if (error) {
3766 			device_printf(sc->sc_dev,
3767 			    "can't create RX buf DMA map\n");
3768 			goto out;		/* XXX wrong! */
3769 		}
3770 
3771 		for (i = 0; i < dr->dr_numslots; i++) {
3772 			dr->getdesc(dr, i, &desc, &mt);
3773 
3774 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3775 			    &mt->mt_dmap);
3776 			if (error) {
3777 				device_printf(sc->sc_dev,
3778 				    "can't create RX buf DMA map\n");
3779 				goto out;	/* XXX wrong! */
3780 			}
3781 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3782 			if (error) {
3783 				device_printf(sc->sc_dev,
3784 				    "failed to allocate RX buf\n");
3785 				goto out;	/* XXX wrong! */
3786 			}
3787 		}
3788 
3789 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3790 		    BUS_DMASYNC_PREWRITE);
3791 
3792 		dr->dr_usedslot = dr->dr_numslots;
3793 	}
3794 
3795       out:
3796 	return (dr);
3797 
3798 fail2:
3799 	free(dr->dr_txhdr_cache, M_DEVBUF);
3800 fail1:
3801 	free(dr->dr_meta, M_DEVBUF);
3802 fail0:
3803 	free(dr, M_DEVBUF);
3804 	return (NULL);
3805 }
3806 
3807 static void
3808 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3809 {
3810 
3811 	if (dr == NULL)
3812 		return;
3813 
3814 	bwn_dma_free_descbufs(*dr);
3815 	bwn_dma_free_ringmemory(*dr);
3816 
3817 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3818 	free((*dr)->dr_meta, M_DEVBUF);
3819 	free(*dr, M_DEVBUF);
3820 
3821 	*dr = NULL;
3822 }
3823 
3824 static void
3825 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3826     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3827 {
3828 	struct bwn_dmadesc32 *desc;
3829 
3830 	*meta = &(dr->dr_meta[slot]);
3831 	desc = dr->dr_ring_descbase;
3832 	desc = &(desc[slot]);
3833 
3834 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3835 }
3836 
3837 static void
3838 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3839     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3840     int start, int end, int irq)
3841 {
3842 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3843 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3844 	uint32_t addr, addrext, ctl;
3845 	int slot;
3846 
3847 	slot = (int)(&(desc->dma.dma32) - descbase);
3848 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3849 	    ("%s:%d: fail", __func__, __LINE__));
3850 
3851 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3852 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3853 	addr |= siba_dma_translation(sc->sc_dev);
3854 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3855 	if (slot == dr->dr_numslots - 1)
3856 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3857 	if (start)
3858 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3859 	if (end)
3860 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3861 	if (irq)
3862 		ctl |= BWN_DMA32_DCTL_IRQ;
3863 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3864 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3865 
3866 	desc->dma.dma32.control = htole32(ctl);
3867 	desc->dma.dma32.address = htole32(addr);
3868 }
3869 
3870 static void
3871 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3872 {
3873 
3874 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3875 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3876 }
3877 
3878 static void
3879 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3880 {
3881 
3882 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3883 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3884 }
3885 
3886 static void
3887 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3888 {
3889 
3890 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3891 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3892 }
3893 
3894 static int
3895 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3896 {
3897 	uint32_t val;
3898 
3899 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3900 	val &= BWN_DMA32_RXDPTR;
3901 
3902 	return (val / sizeof(struct bwn_dmadesc32));
3903 }
3904 
3905 static void
3906 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3907 {
3908 
3909 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3910 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3911 }
3912 
3913 static void
3914 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3915     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3916 {
3917 	struct bwn_dmadesc64 *desc;
3918 
3919 	*meta = &(dr->dr_meta[slot]);
3920 	desc = dr->dr_ring_descbase;
3921 	desc = &(desc[slot]);
3922 
3923 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3924 }
3925 
3926 static void
3927 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3928     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3929     int start, int end, int irq)
3930 {
3931 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3932 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3933 	int slot;
3934 	uint32_t ctl0 = 0, ctl1 = 0;
3935 	uint32_t addrlo, addrhi;
3936 	uint32_t addrext;
3937 
3938 	slot = (int)(&(desc->dma.dma64) - descbase);
3939 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3940 	    ("%s:%d: fail", __func__, __LINE__));
3941 
3942 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3943 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3944 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3945 	    30;
3946 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3947 	if (slot == dr->dr_numslots - 1)
3948 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3949 	if (start)
3950 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3951 	if (end)
3952 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3953 	if (irq)
3954 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3955 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3956 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3957 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3958 
3959 	desc->dma.dma64.control0 = htole32(ctl0);
3960 	desc->dma.dma64.control1 = htole32(ctl1);
3961 	desc->dma.dma64.address_low = htole32(addrlo);
3962 	desc->dma.dma64.address_high = htole32(addrhi);
3963 }
3964 
3965 static void
3966 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3967 {
3968 
3969 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3970 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3971 }
3972 
3973 static void
3974 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3975 {
3976 
3977 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3978 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3979 }
3980 
3981 static void
3982 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3983 {
3984 
3985 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3986 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3987 }
3988 
3989 static int
3990 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3991 {
3992 	uint32_t val;
3993 
3994 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3995 	val &= BWN_DMA64_RXSTATDPTR;
3996 
3997 	return (val / sizeof(struct bwn_dmadesc64));
3998 }
3999 
4000 static void
4001 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4002 {
4003 
4004 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4005 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4006 }
4007 
4008 static int
4009 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4010 {
4011 	struct bwn_mac *mac = dr->dr_mac;
4012 	struct bwn_dma *dma = &mac->mac_method.dma;
4013 	struct bwn_softc *sc = mac->mac_sc;
4014 	int error;
4015 
4016 	error = bus_dma_tag_create(dma->parent_dtag,
4017 			    BWN_ALIGN, 0,
4018 			    BUS_SPACE_MAXADDR,
4019 			    BUS_SPACE_MAXADDR,
4020 			    NULL, NULL,
4021 			    BWN_DMA_RINGMEMSIZE,
4022 			    1,
4023 			    BUS_SPACE_MAXSIZE_32BIT,
4024 			    0,
4025 			    NULL, NULL,
4026 			    &dr->dr_ring_dtag);
4027 	if (error) {
4028 		device_printf(sc->sc_dev,
4029 		    "can't create TX ring DMA tag: TODO frees\n");
4030 		return (-1);
4031 	}
4032 
4033 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4034 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4035 	    &dr->dr_ring_dmap);
4036 	if (error) {
4037 		device_printf(sc->sc_dev,
4038 		    "can't allocate DMA mem: TODO frees\n");
4039 		return (-1);
4040 	}
4041 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4042 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4043 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4044 	if (error) {
4045 		device_printf(sc->sc_dev,
4046 		    "can't load DMA mem: TODO free\n");
4047 		return (-1);
4048 	}
4049 
4050 	return (0);
4051 }
4052 
4053 static void
4054 bwn_dma_setup(struct bwn_dma_ring *dr)
4055 {
4056 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4057 	uint64_t ring64;
4058 	uint32_t addrext, ring32, value;
4059 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4060 
4061 	if (dr->dr_tx) {
4062 		dr->dr_curslot = -1;
4063 
4064 		if (dr->dr_type == BWN_DMA_64BIT) {
4065 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4066 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4067 			    >> 30;
4068 			value = BWN_DMA64_TXENABLE;
4069 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4070 			    & BWN_DMA64_TXADDREXT_MASK;
4071 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4072 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4073 			    (ring64 & 0xffffffff));
4074 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4075 			    ((ring64 >> 32) &
4076 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4077 		} else {
4078 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4079 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4080 			value = BWN_DMA32_TXENABLE;
4081 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4082 			    & BWN_DMA32_TXADDREXT_MASK;
4083 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4084 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4085 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4086 		}
4087 		return;
4088 	}
4089 
4090 	/*
4091 	 * set for RX
4092 	 */
4093 	dr->dr_usedslot = dr->dr_numslots;
4094 
4095 	if (dr->dr_type == BWN_DMA_64BIT) {
4096 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4097 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4098 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4099 		value |= BWN_DMA64_RXENABLE;
4100 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4101 		    & BWN_DMA64_RXADDREXT_MASK;
4102 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4103 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4104 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4105 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4106 		    | (trans << 1));
4107 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4108 		    sizeof(struct bwn_dmadesc64));
4109 	} else {
4110 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4111 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4112 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4113 		value |= BWN_DMA32_RXENABLE;
4114 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4115 		    & BWN_DMA32_RXADDREXT_MASK;
4116 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4117 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4118 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4119 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4120 		    sizeof(struct bwn_dmadesc32));
4121 	}
4122 }
4123 
4124 static void
4125 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4126 {
4127 
4128 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4129 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4130 	    dr->dr_ring_dmap);
4131 }
4132 
4133 static void
4134 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4135 {
4136 
4137 	if (dr->dr_tx) {
4138 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4139 		if (dr->dr_type == BWN_DMA_64BIT) {
4140 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4141 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4142 		} else
4143 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4144 	} else {
4145 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4146 		if (dr->dr_type == BWN_DMA_64BIT) {
4147 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4148 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4149 		} else
4150 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4151 	}
4152 }
4153 
4154 static void
4155 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4156 {
4157 	struct bwn_dmadesc_generic *desc;
4158 	struct bwn_dmadesc_meta *meta;
4159 	struct bwn_mac *mac = dr->dr_mac;
4160 	struct bwn_dma *dma = &mac->mac_method.dma;
4161 	struct bwn_softc *sc = mac->mac_sc;
4162 	int i;
4163 
4164 	if (!dr->dr_usedslot)
4165 		return;
4166 	for (i = 0; i < dr->dr_numslots; i++) {
4167 		dr->getdesc(dr, i, &desc, &meta);
4168 
4169 		if (meta->mt_m == NULL) {
4170 			if (!dr->dr_tx)
4171 				device_printf(sc->sc_dev, "%s: not TX?\n",
4172 				    __func__);
4173 			continue;
4174 		}
4175 		if (dr->dr_tx) {
4176 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4177 				bus_dmamap_unload(dr->dr_txring_dtag,
4178 				    meta->mt_dmap);
4179 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4180 				bus_dmamap_unload(dma->txbuf_dtag,
4181 				    meta->mt_dmap);
4182 		} else
4183 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4184 		bwn_dma_free_descbuf(dr, meta);
4185 	}
4186 }
4187 
4188 static int
4189 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4190     int type)
4191 {
4192 	struct bwn_softc *sc = mac->mac_sc;
4193 	uint32_t value;
4194 	int i;
4195 	uint16_t offset;
4196 
4197 	for (i = 0; i < 10; i++) {
4198 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4199 		    BWN_DMA32_TXSTATUS;
4200 		value = BWN_READ_4(mac, base + offset);
4201 		if (type == BWN_DMA_64BIT) {
4202 			value &= BWN_DMA64_TXSTAT;
4203 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4204 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4205 			    value == BWN_DMA64_TXSTAT_STOPPED)
4206 				break;
4207 		} else {
4208 			value &= BWN_DMA32_TXSTATE;
4209 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4210 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4211 			    value == BWN_DMA32_TXSTAT_STOPPED)
4212 				break;
4213 		}
4214 		DELAY(1000);
4215 	}
4216 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4217 	BWN_WRITE_4(mac, base + offset, 0);
4218 	for (i = 0; i < 10; i++) {
4219 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4220 						   BWN_DMA32_TXSTATUS;
4221 		value = BWN_READ_4(mac, base + offset);
4222 		if (type == BWN_DMA_64BIT) {
4223 			value &= BWN_DMA64_TXSTAT;
4224 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4225 				i = -1;
4226 				break;
4227 			}
4228 		} else {
4229 			value &= BWN_DMA32_TXSTATE;
4230 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4231 				i = -1;
4232 				break;
4233 			}
4234 		}
4235 		DELAY(1000);
4236 	}
4237 	if (i != -1) {
4238 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4239 		return (ENODEV);
4240 	}
4241 	DELAY(1000);
4242 
4243 	return (0);
4244 }
4245 
4246 static int
4247 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4248     int type)
4249 {
4250 	struct bwn_softc *sc = mac->mac_sc;
4251 	uint32_t value;
4252 	int i;
4253 	uint16_t offset;
4254 
4255 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4256 	BWN_WRITE_4(mac, base + offset, 0);
4257 	for (i = 0; i < 10; i++) {
4258 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4259 		    BWN_DMA32_RXSTATUS;
4260 		value = BWN_READ_4(mac, base + offset);
4261 		if (type == BWN_DMA_64BIT) {
4262 			value &= BWN_DMA64_RXSTAT;
4263 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4264 				i = -1;
4265 				break;
4266 			}
4267 		} else {
4268 			value &= BWN_DMA32_RXSTATE;
4269 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4270 				i = -1;
4271 				break;
4272 			}
4273 		}
4274 		DELAY(1000);
4275 	}
4276 	if (i != -1) {
4277 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4278 		return (ENODEV);
4279 	}
4280 
4281 	return (0);
4282 }
4283 
4284 static void
4285 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4286     struct bwn_dmadesc_meta *meta)
4287 {
4288 
4289 	if (meta->mt_m != NULL) {
4290 		m_freem(meta->mt_m);
4291 		meta->mt_m = NULL;
4292 	}
4293 	if (meta->mt_ni != NULL) {
4294 		ieee80211_free_node(meta->mt_ni);
4295 		meta->mt_ni = NULL;
4296 	}
4297 }
4298 
4299 static void
4300 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4301 {
4302 	struct bwn_rxhdr4 *rxhdr;
4303 	unsigned char *frame;
4304 
4305 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4306 	rxhdr->frame_len = 0;
4307 
4308 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4309 	    sizeof(struct bwn_plcp6) + 2,
4310 	    ("%s:%d: fail", __func__, __LINE__));
4311 	frame = mtod(m, char *) + dr->dr_frameoffset;
4312 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4313 }
4314 
4315 static uint8_t
4316 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4317 {
4318 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4319 
4320 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4321 	    == 0xff);
4322 }
4323 
4324 static void
4325 bwn_wme_init(struct bwn_mac *mac)
4326 {
4327 
4328 	bwn_wme_load(mac);
4329 
4330 	/* enable WME support. */
4331 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4332 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4333 	    BWN_IFSCTL_USE_EDCF);
4334 }
4335 
4336 static void
4337 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4338 {
4339 	struct bwn_softc *sc = mac->mac_sc;
4340 	struct ieee80211com *ic = &sc->sc_ic;
4341 	uint16_t delay;	/* microsec */
4342 
4343 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4344 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4345 		delay = 500;
4346 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4347 		delay = max(delay, (uint16_t)2400);
4348 
4349 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4350 }
4351 
4352 static void
4353 bwn_bt_enable(struct bwn_mac *mac)
4354 {
4355 	struct bwn_softc *sc = mac->mac_sc;
4356 	uint64_t hf;
4357 
4358 	if (bwn_bluetooth == 0)
4359 		return;
4360 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4361 		return;
4362 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4363 		return;
4364 
4365 	hf = bwn_hf_read(mac);
4366 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4367 		hf |= BWN_HF_BT_COEXISTALT;
4368 	else
4369 		hf |= BWN_HF_BT_COEXIST;
4370 	bwn_hf_write(mac, hf);
4371 }
4372 
4373 static void
4374 bwn_set_macaddr(struct bwn_mac *mac)
4375 {
4376 
4377 	bwn_mac_write_bssid(mac);
4378 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
4379 	    mac->mac_sc->sc_ic.ic_macaddr);
4380 }
4381 
4382 static void
4383 bwn_clear_keys(struct bwn_mac *mac)
4384 {
4385 	int i;
4386 
4387 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4388 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4389 		    ("%s:%d: fail", __func__, __LINE__));
4390 
4391 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4392 		    NULL, BWN_SEC_KEYSIZE, NULL);
4393 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4394 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4395 			    NULL, BWN_SEC_KEYSIZE, NULL);
4396 		}
4397 		mac->mac_key[i].keyconf = NULL;
4398 	}
4399 }
4400 
4401 static void
4402 bwn_crypt_init(struct bwn_mac *mac)
4403 {
4404 	struct bwn_softc *sc = mac->mac_sc;
4405 
4406 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4407 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4408 	    ("%s:%d: fail", __func__, __LINE__));
4409 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4410 	mac->mac_ktp *= 2;
4411 	if (siba_get_revid(sc->sc_dev) >= 5)
4412 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4413 	bwn_clear_keys(mac);
4414 }
4415 
4416 static void
4417 bwn_chip_exit(struct bwn_mac *mac)
4418 {
4419 	struct bwn_softc *sc = mac->mac_sc;
4420 
4421 	bwn_phy_exit(mac);
4422 	siba_gpio_set(sc->sc_dev, 0);
4423 }
4424 
4425 static int
4426 bwn_fw_fillinfo(struct bwn_mac *mac)
4427 {
4428 	int error;
4429 
4430 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4431 	if (error == 0)
4432 		return (0);
4433 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4434 	if (error == 0)
4435 		return (0);
4436 	return (error);
4437 }
4438 
4439 static int
4440 bwn_gpio_init(struct bwn_mac *mac)
4441 {
4442 	struct bwn_softc *sc = mac->mac_sc;
4443 	uint32_t mask = 0x1f, set = 0xf, value;
4444 
4445 	BWN_WRITE_4(mac, BWN_MACCTL,
4446 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4447 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4448 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4449 
4450 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4451 		mask |= 0x0060;
4452 		set |= 0x0060;
4453 	}
4454 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4455 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4456 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4457 		mask |= 0x0200;
4458 		set |= 0x0200;
4459 	}
4460 	if (siba_get_revid(sc->sc_dev) >= 2)
4461 		mask |= 0x0010;
4462 
4463 	value = siba_gpio_get(sc->sc_dev);
4464 	if (value == -1)
4465 		return (0);
4466 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4467 
4468 	return (0);
4469 }
4470 
4471 static int
4472 bwn_fw_loadinitvals(struct bwn_mac *mac)
4473 {
4474 #define	GETFWOFFSET(fwp, offset)				\
4475 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4476 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4477 	const struct bwn_fwhdr *hdr;
4478 	struct bwn_fw *fw = &mac->mac_fw;
4479 	int error;
4480 
4481 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4482 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4483 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4484 	if (error)
4485 		return (error);
4486 	if (fw->initvals_band.fw) {
4487 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4488 		error = bwn_fwinitvals_write(mac,
4489 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4490 		    be32toh(hdr->size),
4491 		    fw->initvals_band.fw->datasize - hdr_len);
4492 	}
4493 	return (error);
4494 #undef GETFWOFFSET
4495 }
4496 
4497 static int
4498 bwn_phy_init(struct bwn_mac *mac)
4499 {
4500 	struct bwn_softc *sc = mac->mac_sc;
4501 	int error;
4502 
4503 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4504 	mac->mac_phy.rf_onoff(mac, 1);
4505 	error = mac->mac_phy.init(mac);
4506 	if (error) {
4507 		device_printf(sc->sc_dev, "PHY init failed\n");
4508 		goto fail0;
4509 	}
4510 	error = bwn_switch_channel(mac,
4511 	    mac->mac_phy.get_default_chan(mac));
4512 	if (error) {
4513 		device_printf(sc->sc_dev,
4514 		    "failed to switch default channel\n");
4515 		goto fail1;
4516 	}
4517 	return (0);
4518 fail1:
4519 	if (mac->mac_phy.exit)
4520 		mac->mac_phy.exit(mac);
4521 fail0:
4522 	mac->mac_phy.rf_onoff(mac, 0);
4523 
4524 	return (error);
4525 }
4526 
4527 static void
4528 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4529 {
4530 	uint16_t ant;
4531 	uint16_t tmp;
4532 
4533 	ant = bwn_ant2phy(antenna);
4534 
4535 	/* For ACK/CTS */
4536 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4537 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4538 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4539 	/* For Probe Resposes */
4540 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4541 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4542 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4543 }
4544 
4545 static void
4546 bwn_set_opmode(struct bwn_mac *mac)
4547 {
4548 	struct bwn_softc *sc = mac->mac_sc;
4549 	struct ieee80211com *ic = &sc->sc_ic;
4550 	uint32_t ctl;
4551 	uint16_t cfp_pretbtt;
4552 
4553 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4554 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4555 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4556 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4557 	ctl |= BWN_MACCTL_STA;
4558 
4559 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4560 	    ic->ic_opmode == IEEE80211_M_MBSS)
4561 		ctl |= BWN_MACCTL_HOSTAP;
4562 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4563 		ctl &= ~BWN_MACCTL_STA;
4564 	ctl |= sc->sc_filters;
4565 
4566 	if (siba_get_revid(sc->sc_dev) <= 4)
4567 		ctl |= BWN_MACCTL_PROMISC;
4568 
4569 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4570 
4571 	cfp_pretbtt = 2;
4572 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4573 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4574 		    siba_get_chiprev(sc->sc_dev) == 3)
4575 			cfp_pretbtt = 100;
4576 		else
4577 			cfp_pretbtt = 50;
4578 	}
4579 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4580 }
4581 
4582 static int
4583 bwn_dma_gettype(struct bwn_mac *mac)
4584 {
4585 	uint32_t tmp;
4586 	uint16_t base;
4587 
4588 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4589 	if (tmp & SIBA_TGSHIGH_DMA64)
4590 		return (BWN_DMA_64BIT);
4591 	base = bwn_dma_base(0, 0);
4592 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4593 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4594 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4595 		return (BWN_DMA_32BIT);
4596 
4597 	return (BWN_DMA_30BIT);
4598 }
4599 
4600 static void
4601 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4602 {
4603 	if (!error) {
4604 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4605 		*((bus_addr_t *)arg) = seg->ds_addr;
4606 	}
4607 }
4608 
4609 static void
4610 bwn_phy_g_init_sub(struct bwn_mac *mac)
4611 {
4612 	struct bwn_phy *phy = &mac->mac_phy;
4613 	struct bwn_phy_g *pg = &phy->phy_g;
4614 	struct bwn_softc *sc = mac->mac_sc;
4615 	uint16_t i, tmp;
4616 
4617 	if (phy->rev == 1)
4618 		bwn_phy_init_b5(mac);
4619 	else
4620 		bwn_phy_init_b6(mac);
4621 
4622 	if (phy->rev >= 2 || phy->gmode)
4623 		bwn_phy_init_a(mac);
4624 
4625 	if (phy->rev >= 2) {
4626 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4627 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4628 	}
4629 	if (phy->rev == 2) {
4630 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4631 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4632 	}
4633 	if (phy->rev > 5) {
4634 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4635 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4636 	}
4637 	if (phy->gmode || phy->rev >= 2) {
4638 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4639 		tmp &= BWN_PHYVER_VERSION;
4640 		if (tmp == 3 || tmp == 5) {
4641 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4642 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4643 		}
4644 		if (tmp == 5) {
4645 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4646 			    0x1f00);
4647 		}
4648 	}
4649 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4650 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4651 	if (phy->rf_rev == 8) {
4652 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4653 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4654 	}
4655 	if (BWN_HAS_LOOPBACK(phy))
4656 		bwn_loopback_calcgain(mac);
4657 
4658 	if (phy->rf_rev != 8) {
4659 		if (pg->pg_initval == 0xffff)
4660 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4661 		else
4662 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4663 	}
4664 	bwn_lo_g_init(mac);
4665 	if (BWN_HAS_TXMAG(phy)) {
4666 		BWN_RF_WRITE(mac, 0x52,
4667 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4668 		    | pg->pg_loctl.tx_bias |
4669 		    pg->pg_loctl.tx_magn);
4670 	} else {
4671 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4672 	}
4673 	if (phy->rev >= 6) {
4674 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4675 		    (pg->pg_loctl.tx_bias << 12));
4676 	}
4677 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4678 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4679 	else
4680 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4681 	if (phy->rev < 2)
4682 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4683 	else
4684 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4685 	if (phy->gmode || phy->rev >= 2) {
4686 		bwn_lo_g_adjust(mac);
4687 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4688 	}
4689 
4690 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4691 		for (i = 0; i < 64; i++) {
4692 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4693 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4694 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4695 			    -32), 31));
4696 		}
4697 		bwn_nrssi_threshold(mac);
4698 	} else if (phy->gmode || phy->rev >= 2) {
4699 		if (pg->pg_nrssi[0] == -1000) {
4700 			KASSERT(pg->pg_nrssi[1] == -1000,
4701 			    ("%s:%d: fail", __func__, __LINE__));
4702 			bwn_nrssi_slope_11g(mac);
4703 		} else
4704 			bwn_nrssi_threshold(mac);
4705 	}
4706 	if (phy->rf_rev == 8)
4707 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4708 	bwn_phy_hwpctl_init(mac);
4709 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4710 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4711 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4712 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4713 	}
4714 }
4715 
4716 static uint8_t
4717 bwn_has_hwpctl(struct bwn_mac *mac)
4718 {
4719 
4720 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4721 		return (0);
4722 	return (mac->mac_phy.use_hwpctl(mac));
4723 }
4724 
4725 static void
4726 bwn_phy_init_b5(struct bwn_mac *mac)
4727 {
4728 	struct bwn_phy *phy = &mac->mac_phy;
4729 	struct bwn_phy_g *pg = &phy->phy_g;
4730 	struct bwn_softc *sc = mac->mac_sc;
4731 	uint16_t offset, value;
4732 	uint8_t old_channel;
4733 
4734 	if (phy->analog == 1)
4735 		BWN_RF_SET(mac, 0x007a, 0x0050);
4736 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4737 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4738 		value = 0x2120;
4739 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4740 			BWN_PHY_WRITE(mac, offset, value);
4741 			value += 0x202;
4742 		}
4743 	}
4744 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4745 	if (phy->rf_ver == 0x2050)
4746 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4747 
4748 	if (phy->gmode || phy->rev >= 2) {
4749 		if (phy->rf_ver == 0x2050) {
4750 			BWN_RF_SET(mac, 0x007a, 0x0020);
4751 			BWN_RF_SET(mac, 0x0051, 0x0004);
4752 		}
4753 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4754 
4755 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4756 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4757 
4758 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4759 
4760 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4761 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4762 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4763 	}
4764 
4765 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4766 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4767 
4768 	if (phy->analog == 1) {
4769 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4770 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4771 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4772 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4773 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4774 	} else
4775 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4776 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4777 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4778 
4779 	if (phy->analog == 1)
4780 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4781 	else
4782 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4783 
4784 	if (phy->analog == 0)
4785 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4786 
4787 	old_channel = phy->chan;
4788 	bwn_phy_g_switch_chan(mac, 7, 0);
4789 
4790 	if (phy->rf_ver != 0x2050) {
4791 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4792 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4793 	}
4794 
4795 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4796 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4797 
4798 	if (phy->rf_ver == 0x2050) {
4799 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4800 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4801 	}
4802 
4803 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4804 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4805 	BWN_RF_SET(mac, 0x007a, 0x0007);
4806 
4807 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4808 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4809 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4810 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4811 
4812 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4813 	    pg->pg_txctl);
4814 
4815 	if (phy->rf_ver == 0x2050)
4816 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4817 
4818 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4819 }
4820 
4821 static void
4822 bwn_loopback_calcgain(struct bwn_mac *mac)
4823 {
4824 	struct bwn_phy *phy = &mac->mac_phy;
4825 	struct bwn_phy_g *pg = &phy->phy_g;
4826 	struct bwn_softc *sc = mac->mac_sc;
4827 	uint16_t backup_phy[16] = { 0 };
4828 	uint16_t backup_radio[3];
4829 	uint16_t backup_bband;
4830 	uint16_t i, j, loop_i_max;
4831 	uint16_t trsw_rx;
4832 	uint16_t loop1_outer_done, loop1_inner_done;
4833 
4834 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4835 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4836 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4837 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4838 	if (phy->rev != 1) {
4839 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4840 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4841 	}
4842 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4843 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4844 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4845 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4846 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4847 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4848 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4849 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4850 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4851 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4852 	backup_bband = pg->pg_bbatt.att;
4853 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4854 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4855 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4856 
4857 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4858 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4859 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4860 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4861 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4862 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4863 	if (phy->rev != 1) {
4864 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4865 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4866 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4867 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4868 	}
4869 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4870 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4871 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4872 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4873 
4874 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4875 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4876 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4877 
4878 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4879 	if (phy->rev != 1) {
4880 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4881 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4882 	}
4883 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4884 
4885 	if (phy->rf_rev == 8)
4886 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4887 	else {
4888 		BWN_RF_WRITE(mac, 0x52, 0);
4889 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4890 	}
4891 	bwn_phy_g_set_bbatt(mac, 11);
4892 
4893 	if (phy->rev >= 3)
4894 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4895 	else
4896 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4897 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4898 
4899 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4900 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4901 
4902 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4903 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4904 
4905 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4906 		if (phy->rev >= 7) {
4907 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4908 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4909 		}
4910 	}
4911 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4912 
4913 	j = 0;
4914 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4915 	for (i = 0; i < loop_i_max; i++) {
4916 		for (j = 0; j < 16; j++) {
4917 			BWN_RF_WRITE(mac, 0x43, i);
4918 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4919 			    (j << 8));
4920 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4921 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4922 			DELAY(20);
4923 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4924 				goto done0;
4925 		}
4926 	}
4927 done0:
4928 	loop1_outer_done = i;
4929 	loop1_inner_done = j;
4930 	if (j >= 8) {
4931 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4932 		trsw_rx = 0x1b;
4933 		for (j = j - 8; j < 16; j++) {
4934 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4935 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4936 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4937 			DELAY(20);
4938 			trsw_rx -= 3;
4939 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4940 				goto done1;
4941 		}
4942 	} else
4943 		trsw_rx = 0x18;
4944 done1:
4945 
4946 	if (phy->rev != 1) {
4947 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4948 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4949 	}
4950 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4951 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4952 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4953 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4954 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4955 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4956 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4957 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4958 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4959 
4960 	bwn_phy_g_set_bbatt(mac, backup_bband);
4961 
4962 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4963 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4964 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4965 
4966 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4967 	DELAY(10);
4968 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4969 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4970 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4971 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4972 
4973 	pg->pg_max_lb_gain =
4974 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4975 	pg->pg_trsw_rx_gain = trsw_rx * 2;
4976 }
4977 
4978 static uint16_t
4979 bwn_rf_init_bcm2050(struct bwn_mac *mac)
4980 {
4981 	struct bwn_phy *phy = &mac->mac_phy;
4982 	uint32_t tmp1 = 0, tmp2 = 0;
4983 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
4984 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
4985 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
4986 	static const uint8_t rcc_table[] = {
4987 		0x02, 0x03, 0x01, 0x0f,
4988 		0x06, 0x07, 0x05, 0x0f,
4989 		0x0a, 0x0b, 0x09, 0x0f,
4990 		0x0e, 0x0f, 0x0d, 0x0f,
4991 	};
4992 
4993 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
4994 	    rfoverval = rfover = cck3 = 0;
4995 	radio0 = BWN_RF_READ(mac, 0x43);
4996 	radio1 = BWN_RF_READ(mac, 0x51);
4997 	radio2 = BWN_RF_READ(mac, 0x52);
4998 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4999 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5000 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5001 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5002 
5003 	if (phy->type == BWN_PHYTYPE_B) {
5004 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5005 		reg0 = BWN_READ_2(mac, 0x3ec);
5006 
5007 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5008 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5009 	} else if (phy->gmode || phy->rev >= 2) {
5010 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5011 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5012 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5013 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5014 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5015 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5016 
5017 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5018 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5019 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5020 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5021 		if (BWN_HAS_LOOPBACK(phy)) {
5022 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5023 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5024 			if (phy->rev >= 3)
5025 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5026 			else
5027 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5028 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5029 		}
5030 
5031 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5032 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5033 			BWN_LPD(0, 1, 1)));
5034 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5035 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5036 	}
5037 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5038 
5039 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5040 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5041 	reg1 = BWN_READ_2(mac, 0x3e6);
5042 	reg2 = BWN_READ_2(mac, 0x3f4);
5043 
5044 	if (phy->analog == 0)
5045 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5046 	else {
5047 		if (phy->analog >= 2)
5048 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5049 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5050 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5051 	}
5052 
5053 	reg = BWN_RF_READ(mac, 0x60);
5054 	index = (reg & 0x001e) >> 1;
5055 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5056 
5057 	if (phy->type == BWN_PHYTYPE_B)
5058 		BWN_RF_WRITE(mac, 0x78, 0x26);
5059 	if (phy->gmode || phy->rev >= 2) {
5060 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5061 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5062 			BWN_LPD(0, 1, 1)));
5063 	}
5064 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5065 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5066 	if (phy->gmode || phy->rev >= 2) {
5067 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5068 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5069 			BWN_LPD(0, 0, 1)));
5070 	}
5071 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5072 	BWN_RF_SET(mac, 0x51, 0x0004);
5073 	if (phy->rf_rev == 8)
5074 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5075 	else {
5076 		BWN_RF_WRITE(mac, 0x52, 0);
5077 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5078 	}
5079 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5080 
5081 	for (i = 0; i < 16; i++) {
5082 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5083 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5084 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5085 		if (phy->gmode || phy->rev >= 2) {
5086 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5087 			    bwn_rf_2050_rfoverval(mac,
5088 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5089 		}
5090 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5091 		DELAY(10);
5092 		if (phy->gmode || phy->rev >= 2) {
5093 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5094 			    bwn_rf_2050_rfoverval(mac,
5095 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5096 		}
5097 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5098 		DELAY(10);
5099 		if (phy->gmode || phy->rev >= 2) {
5100 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5101 			    bwn_rf_2050_rfoverval(mac,
5102 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5103 		}
5104 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5105 		DELAY(20);
5106 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5107 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5108 		if (phy->gmode || phy->rev >= 2) {
5109 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5110 			    bwn_rf_2050_rfoverval(mac,
5111 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5112 		}
5113 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5114 	}
5115 	DELAY(10);
5116 
5117 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5118 	tmp1++;
5119 	tmp1 >>= 9;
5120 
5121 	for (i = 0; i < 16; i++) {
5122 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5123 		BWN_RF_WRITE(mac, 0x78, radio78);
5124 		DELAY(10);
5125 		for (j = 0; j < 16; j++) {
5126 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5127 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5128 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5129 			if (phy->gmode || phy->rev >= 2) {
5130 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5131 				    bwn_rf_2050_rfoverval(mac,
5132 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5133 			}
5134 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5135 			DELAY(10);
5136 			if (phy->gmode || phy->rev >= 2) {
5137 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5138 				    bwn_rf_2050_rfoverval(mac,
5139 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5140 			}
5141 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5142 			DELAY(10);
5143 			if (phy->gmode || phy->rev >= 2) {
5144 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5145 				    bwn_rf_2050_rfoverval(mac,
5146 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5147 			}
5148 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5149 			DELAY(10);
5150 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5151 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5152 			if (phy->gmode || phy->rev >= 2) {
5153 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5154 				    bwn_rf_2050_rfoverval(mac,
5155 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5156 			}
5157 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5158 		}
5159 		tmp2++;
5160 		tmp2 >>= 8;
5161 		if (tmp1 < tmp2)
5162 			break;
5163 	}
5164 
5165 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5166 	BWN_RF_WRITE(mac, 0x51, radio1);
5167 	BWN_RF_WRITE(mac, 0x52, radio2);
5168 	BWN_RF_WRITE(mac, 0x43, radio0);
5169 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5170 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5171 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5172 	BWN_WRITE_2(mac, 0x3e6, reg1);
5173 	if (phy->analog != 0)
5174 		BWN_WRITE_2(mac, 0x3f4, reg2);
5175 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5176 	bwn_spu_workaround(mac, phy->chan);
5177 	if (phy->type == BWN_PHYTYPE_B) {
5178 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5179 		BWN_WRITE_2(mac, 0x3ec, reg0);
5180 	} else if (phy->gmode) {
5181 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5182 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5183 			    & 0x7fff);
5184 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5185 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5186 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5187 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5188 			      analogoverval);
5189 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5190 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5191 		if (BWN_HAS_LOOPBACK(phy)) {
5192 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5193 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5194 		}
5195 	}
5196 
5197 	return ((i > 15) ? radio78 : rcc);
5198 }
5199 
5200 static void
5201 bwn_phy_init_b6(struct bwn_mac *mac)
5202 {
5203 	struct bwn_phy *phy = &mac->mac_phy;
5204 	struct bwn_phy_g *pg = &phy->phy_g;
5205 	struct bwn_softc *sc = mac->mac_sc;
5206 	uint16_t offset, val;
5207 	uint8_t old_channel;
5208 
5209 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5210 	    ("%s:%d: fail", __func__, __LINE__));
5211 
5212 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5213 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5214 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5215 		BWN_RF_WRITE(mac, 0x51, 0x37);
5216 		BWN_RF_WRITE(mac, 0x52, 0x70);
5217 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5218 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5219 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5220 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5221 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5222 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5223 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5224 		bwn_hf_write(mac,
5225 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5226 	}
5227 	if (phy->rf_rev == 8) {
5228 		BWN_RF_WRITE(mac, 0x51, 0);
5229 		BWN_RF_WRITE(mac, 0x52, 0x40);
5230 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5231 		BWN_RF_WRITE(mac, 0x54, 0x98);
5232 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5233 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5234 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5235 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5236 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5237 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5238 		} else {
5239 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5240 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5241 		}
5242 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5243 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5244 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5245 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5246 	}
5247 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5248 		BWN_PHY_WRITE(mac, offset, val);
5249 		val -= 0x0202;
5250 	}
5251 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5252 		BWN_PHY_WRITE(mac, offset, val);
5253 		val -= 0x0202;
5254 	}
5255 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5256 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5257 		val += 0x0202;
5258 	}
5259 	if (phy->type == BWN_PHYTYPE_G) {
5260 		BWN_RF_SET(mac, 0x007a, 0x0020);
5261 		BWN_RF_SET(mac, 0x0051, 0x0004);
5262 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5263 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5264 		BWN_PHY_WRITE(mac, 0x5b, 0);
5265 		BWN_PHY_WRITE(mac, 0x5c, 0);
5266 	}
5267 
5268 	old_channel = phy->chan;
5269 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5270 
5271 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5272 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5273 	DELAY(40);
5274 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5275 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5276 		BWN_RF_WRITE(mac, 0x50, 0x20);
5277 	}
5278 	if (phy->rf_rev <= 2) {
5279 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5280 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5281 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5282 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5283 	}
5284 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5285 
5286 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5287 
5288 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5289 	if (phy->rf_rev >= 6)
5290 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5291 	else
5292 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5293 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5294 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5295 	    pg->pg_txctl);
5296 	if (phy->rf_rev <= 5)
5297 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5298 	if (phy->rf_rev <= 2)
5299 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5300 
5301 	if (phy->analog == 4) {
5302 		BWN_WRITE_2(mac, 0x3e4, 9);
5303 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5304 	} else
5305 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5306 	if (phy->type == BWN_PHYTYPE_B)
5307 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5308 	else if (phy->type == BWN_PHYTYPE_G)
5309 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5310 }
5311 
5312 static void
5313 bwn_phy_init_a(struct bwn_mac *mac)
5314 {
5315 	struct bwn_phy *phy = &mac->mac_phy;
5316 	struct bwn_softc *sc = mac->mac_sc;
5317 
5318 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5319 	    ("%s:%d: fail", __func__, __LINE__));
5320 
5321 	if (phy->rev >= 6) {
5322 		if (phy->type == BWN_PHYTYPE_A)
5323 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5324 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5325 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5326 		else
5327 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5328 	}
5329 
5330 	bwn_wa_init(mac);
5331 
5332 	if (phy->type == BWN_PHYTYPE_G &&
5333 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5334 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5335 }
5336 
5337 static void
5338 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5339 {
5340 	int i;
5341 
5342 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5343 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5344 }
5345 
5346 static void
5347 bwn_wa_agc(struct bwn_mac *mac)
5348 {
5349 	struct bwn_phy *phy = &mac->mac_phy;
5350 
5351 	if (phy->rev == 1) {
5352 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5353 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5354 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5355 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5356 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5357 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5358 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5359 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5360 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5361 	} else {
5362 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5363 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5364 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5365 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5366 	}
5367 
5368 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5369 	    0x5700);
5370 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5371 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5372 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5373 	BWN_RF_SET(mac, 0x7a, 0x0008);
5374 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5375 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5376 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5377 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5378 	if (phy->rev == 1)
5379 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5380 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5381 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5382 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5383 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5384 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5385 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5386 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5387 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5388 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5389 	if (phy->rev == 1) {
5390 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5391 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5392 	} else {
5393 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5394 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5395 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5396 		if (phy->rev >= 6) {
5397 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5398 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5399 			    (uint16_t)~0xf000, 0x3000);
5400 		}
5401 	}
5402 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5403 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5404 	if (phy->rev == 1) {
5405 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5406 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5407 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5408 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5409 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5410 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5411 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5412 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5413 	} else {
5414 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5415 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5416 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5417 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5418 	}
5419 	if (phy->rev >= 6) {
5420 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5421 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5422 	}
5423 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5424 }
5425 
5426 static void
5427 bwn_wa_grev1(struct bwn_mac *mac)
5428 {
5429 	struct bwn_phy *phy = &mac->mac_phy;
5430 	int i;
5431 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5432 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5433 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5434 
5435 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5436 
5437 	/* init CRSTHRES and ANTDWELL */
5438 	if (phy->rev == 1) {
5439 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5440 	} else if (phy->rev == 2) {
5441 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5442 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5443 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5444 	} else {
5445 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5446 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5447 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5448 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5449 	}
5450 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5451 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5452 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5453 
5454 	/* XXX support PHY-A??? */
5455 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5456 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5457 		    bwn_tab_finefreqg[i]);
5458 
5459 	/* XXX support PHY-A??? */
5460 	if (phy->rev == 1)
5461 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5462 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5463 			    bwn_tab_noise_g1[i]);
5464 	else
5465 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5466 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5467 			    bwn_tab_noise_g2[i]);
5468 
5469 
5470 	for (i = 0; i < N(bwn_tab_rotor); i++)
5471 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5472 		    bwn_tab_rotor[i]);
5473 
5474 	/* XXX support PHY-A??? */
5475 	if (phy->rev >= 6) {
5476 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5477 		    BWN_PHY_ENCORE_EN)
5478 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5479 		else
5480 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5481 	} else
5482 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5483 
5484 	for (i = 0; i < N(bwn_tab_retard); i++)
5485 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5486 		    bwn_tab_retard[i]);
5487 
5488 	if (phy->rev == 1) {
5489 		for (i = 0; i < 16; i++)
5490 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5491 			    i, 0x0020);
5492 	} else {
5493 		for (i = 0; i < 32; i++)
5494 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5495 	}
5496 
5497 	bwn_wa_agc(mac);
5498 }
5499 
5500 static void
5501 bwn_wa_grev26789(struct bwn_mac *mac)
5502 {
5503 	struct bwn_phy *phy = &mac->mac_phy;
5504 	int i;
5505 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5506 	uint16_t ofdmrev;
5507 
5508 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5509 
5510 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5511 
5512 	/* init CRSTHRES and ANTDWELL */
5513 	if (phy->rev == 1)
5514 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5515 	else if (phy->rev == 2) {
5516 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5517 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5518 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5519 	} else {
5520 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5521 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5522 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5523 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5524 	}
5525 
5526 	for (i = 0; i < 64; i++)
5527 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5528 
5529 	/* XXX support PHY-A??? */
5530 	if (phy->rev == 1)
5531 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5532 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5533 			    bwn_tab_noise_g1[i]);
5534 	else
5535 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5536 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5537 			    bwn_tab_noise_g2[i]);
5538 
5539 	/* XXX support PHY-A??? */
5540 	if (phy->rev >= 6) {
5541 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5542 		    BWN_PHY_ENCORE_EN)
5543 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5544 		else
5545 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5546 	} else
5547 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5548 
5549 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5550 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5551 		    bwn_tab_sigmasqr2[i]);
5552 
5553 	if (phy->rev == 1) {
5554 		for (i = 0; i < 16; i++)
5555 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5556 			    0x0020);
5557 	} else {
5558 		for (i = 0; i < 32; i++)
5559 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5560 	}
5561 
5562 	bwn_wa_agc(mac);
5563 
5564 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5565 	if (ofdmrev > 2) {
5566 		if (phy->type == BWN_PHYTYPE_A)
5567 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5568 		else
5569 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5570 	} else {
5571 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5572 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5573 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5574 	}
5575 
5576 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5577 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5578 }
5579 
5580 static void
5581 bwn_wa_init(struct bwn_mac *mac)
5582 {
5583 	struct bwn_phy *phy = &mac->mac_phy;
5584 	struct bwn_softc *sc = mac->mac_sc;
5585 
5586 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5587 
5588 	switch (phy->rev) {
5589 	case 1:
5590 		bwn_wa_grev1(mac);
5591 		break;
5592 	case 2:
5593 	case 6:
5594 	case 7:
5595 	case 8:
5596 	case 9:
5597 		bwn_wa_grev26789(mac);
5598 		break;
5599 	default:
5600 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5601 	}
5602 
5603 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5604 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5605 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5606 		if (phy->rev < 2) {
5607 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5608 			    0x0002);
5609 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5610 			    0x0001);
5611 		} else {
5612 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5613 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5614 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5615 			     BWN_BFL_EXTLNA) &&
5616 			    (phy->rev >= 7)) {
5617 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5618 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5619 				    0x0020, 0x0001);
5620 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5621 				    0x0021, 0x0001);
5622 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5623 				    0x0022, 0x0001);
5624 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5625 				    0x0023, 0x0000);
5626 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5627 				    0x0000, 0x0000);
5628 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5629 				    0x0003, 0x0002);
5630 			}
5631 		}
5632 	}
5633 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5634 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5635 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5636 	}
5637 
5638 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5639 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5640 }
5641 
5642 static void
5643 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5644     uint16_t value)
5645 {
5646 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5647 	uint16_t addr;
5648 
5649 	addr = table + offset;
5650 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5651 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5652 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5653 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5654 	}
5655 	pg->pg_ofdmtab_addr = addr;
5656 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5657 }
5658 
5659 static void
5660 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5661     uint32_t value)
5662 {
5663 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5664 	uint16_t addr;
5665 
5666 	addr = table + offset;
5667 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5668 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5669 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5670 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5671 	}
5672 	pg->pg_ofdmtab_addr = addr;
5673 
5674 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5675 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5676 }
5677 
5678 static void
5679 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5680     uint16_t value)
5681 {
5682 
5683 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5684 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5685 }
5686 
5687 static void
5688 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5689 {
5690 	struct bwn_phy *phy = &mac->mac_phy;
5691 	struct bwn_softc *sc = mac->mac_sc;
5692 	unsigned int i, max_loop;
5693 	uint16_t value;
5694 	uint32_t buffer[5] = {
5695 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5696 	};
5697 
5698 	if (ofdm) {
5699 		max_loop = 0x1e;
5700 		buffer[0] = 0x000201cc;
5701 	} else {
5702 		max_loop = 0xfa;
5703 		buffer[0] = 0x000b846e;
5704 	}
5705 
5706 	BWN_ASSERT_LOCKED(mac->mac_sc);
5707 
5708 	for (i = 0; i < 5; i++)
5709 		bwn_ram_write(mac, i * 4, buffer[i]);
5710 
5711 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5712 	BWN_WRITE_2(mac, 0x07c0,
5713 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5714 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5715 	BWN_WRITE_2(mac, 0x050c, value);
5716 	if (phy->type == BWN_PHYTYPE_LP)
5717 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5718 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5719 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5720 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5721 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5722 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5723 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5724 	if (phy->type == BWN_PHYTYPE_LP)
5725 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5726 	else
5727 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5728 
5729 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5730 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5731 	for (i = 0x00; i < max_loop; i++) {
5732 		value = BWN_READ_2(mac, 0x050e);
5733 		if (value & 0x0080)
5734 			break;
5735 		DELAY(10);
5736 	}
5737 	for (i = 0x00; i < 0x0a; i++) {
5738 		value = BWN_READ_2(mac, 0x050e);
5739 		if (value & 0x0400)
5740 			break;
5741 		DELAY(10);
5742 	}
5743 	for (i = 0x00; i < 0x19; i++) {
5744 		value = BWN_READ_2(mac, 0x0690);
5745 		if (!(value & 0x0100))
5746 			break;
5747 		DELAY(10);
5748 	}
5749 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5750 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5751 }
5752 
5753 static void
5754 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5755 {
5756 	uint32_t macctl;
5757 
5758 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5759 
5760 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5761 	if (macctl & BWN_MACCTL_BIGENDIAN)
5762 		printf("TODO: need swap\n");
5763 
5764 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5765 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5766 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5767 }
5768 
5769 static void
5770 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5771 {
5772 	uint16_t value;
5773 
5774 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5775 	    ("%s:%d: fail", __func__, __LINE__));
5776 
5777 	value = (uint8_t) (ctl->q);
5778 	value |= ((uint8_t) (ctl->i)) << 8;
5779 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5780 }
5781 
5782 static uint16_t
5783 bwn_lo_calcfeed(struct bwn_mac *mac,
5784     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5785 {
5786 	struct bwn_phy *phy = &mac->mac_phy;
5787 	struct bwn_softc *sc = mac->mac_sc;
5788 	uint16_t rfover;
5789 	uint16_t feedthrough;
5790 
5791 	if (phy->gmode) {
5792 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5793 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5794 
5795 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5796 		    ("%s:%d: fail", __func__, __LINE__));
5797 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5798 		    ("%s:%d: fail", __func__, __LINE__));
5799 
5800 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5801 
5802 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5803 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5804 		    phy->rev > 6)
5805 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5806 
5807 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5808 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5809 		DELAY(10);
5810 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5811 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5812 		DELAY(10);
5813 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5814 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5815 		DELAY(10);
5816 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5817 	} else {
5818 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5819 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5820 		DELAY(10);
5821 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5822 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5823 		DELAY(10);
5824 		pga |= BWN_PHY_PGACTL_LPF;
5825 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5826 	}
5827 	DELAY(21);
5828 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5829 
5830 	return (feedthrough);
5831 }
5832 
5833 static uint16_t
5834 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5835     uint16_t *value, uint16_t *pad_mix_gain)
5836 {
5837 	struct bwn_phy *phy = &mac->mac_phy;
5838 	uint16_t reg, v, padmix;
5839 
5840 	if (phy->type == BWN_PHYTYPE_B) {
5841 		v = 0x30;
5842 		if (phy->rf_rev <= 5) {
5843 			reg = 0x43;
5844 			padmix = 0;
5845 		} else {
5846 			reg = 0x52;
5847 			padmix = 5;
5848 		}
5849 	} else {
5850 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5851 			reg = 0x43;
5852 			v = 0x10;
5853 			padmix = 2;
5854 		} else {
5855 			reg = 0x52;
5856 			v = 0x30;
5857 			padmix = 5;
5858 		}
5859 	}
5860 	if (value)
5861 		*value = v;
5862 	if (pad_mix_gain)
5863 		*pad_mix_gain = padmix;
5864 
5865 	return (reg);
5866 }
5867 
5868 static void
5869 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5870 {
5871 	struct bwn_phy *phy = &mac->mac_phy;
5872 	struct bwn_phy_g *pg = &phy->phy_g;
5873 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5874 	uint16_t reg, mask;
5875 	uint16_t trsw_rx, pga;
5876 	uint16_t rf_pctl_reg;
5877 
5878 	static const uint8_t tx_bias_values[] = {
5879 		0x09, 0x08, 0x0a, 0x01, 0x00,
5880 		0x02, 0x05, 0x04, 0x06,
5881 	};
5882 	static const uint8_t tx_magn_values[] = {
5883 		0x70, 0x40,
5884 	};
5885 
5886 	if (!BWN_HAS_LOOPBACK(phy)) {
5887 		rf_pctl_reg = 6;
5888 		trsw_rx = 2;
5889 		pga = 0;
5890 	} else {
5891 		int lb_gain;
5892 
5893 		trsw_rx = 0;
5894 		lb_gain = pg->pg_max_lb_gain / 2;
5895 		if (lb_gain > 10) {
5896 			rf_pctl_reg = 0;
5897 			pga = abs(10 - lb_gain) / 6;
5898 			pga = MIN(MAX(pga, 0), 15);
5899 		} else {
5900 			int cmp_val;
5901 			int tmp;
5902 
5903 			pga = 0;
5904 			cmp_val = 0x24;
5905 			if ((phy->rev >= 2) &&
5906 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5907 				cmp_val = 0x3c;
5908 			tmp = lb_gain;
5909 			if ((10 - lb_gain) < cmp_val)
5910 				tmp = (10 - lb_gain);
5911 			if (tmp < 0)
5912 				tmp += 6;
5913 			else
5914 				tmp += 3;
5915 			cmp_val /= 4;
5916 			tmp /= 4;
5917 			if (tmp >= cmp_val)
5918 				rf_pctl_reg = cmp_val;
5919 			else
5920 				rf_pctl_reg = tmp;
5921 		}
5922 	}
5923 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5924 	bwn_phy_g_set_bbatt(mac, 2);
5925 
5926 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5927 	mask = ~mask;
5928 	BWN_RF_MASK(mac, reg, mask);
5929 
5930 	if (BWN_HAS_TXMAG(phy)) {
5931 		int i, j;
5932 		int feedthrough;
5933 		int min_feedth = 0xffff;
5934 		uint8_t tx_magn, tx_bias;
5935 
5936 		for (i = 0; i < N(tx_magn_values); i++) {
5937 			tx_magn = tx_magn_values[i];
5938 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5939 			for (j = 0; j < N(tx_bias_values); j++) {
5940 				tx_bias = tx_bias_values[j];
5941 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5942 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5943 				    trsw_rx);
5944 				if (feedthrough < min_feedth) {
5945 					lo->tx_bias = tx_bias;
5946 					lo->tx_magn = tx_magn;
5947 					min_feedth = feedthrough;
5948 				}
5949 				if (lo->tx_bias == 0)
5950 					break;
5951 			}
5952 			BWN_RF_WRITE(mac, 0x52,
5953 					  (BWN_RF_READ(mac, 0x52)
5954 					   & 0xff00) | lo->tx_bias | lo->
5955 					  tx_magn);
5956 		}
5957 	} else {
5958 		lo->tx_magn = 0;
5959 		lo->tx_bias = 0;
5960 		BWN_RF_MASK(mac, 0x52, 0xfff0);
5961 	}
5962 
5963 	BWN_GETTIME(lo->txctl_measured_time);
5964 }
5965 
5966 static void
5967 bwn_lo_get_powervector(struct bwn_mac *mac)
5968 {
5969 	struct bwn_phy *phy = &mac->mac_phy;
5970 	struct bwn_phy_g *pg = &phy->phy_g;
5971 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5972 	int i;
5973 	uint64_t tmp;
5974 	uint64_t power_vector = 0;
5975 
5976 	for (i = 0; i < 8; i += 2) {
5977 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5978 		power_vector |= (tmp << (i * 8));
5979 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
5980 	}
5981 	if (power_vector)
5982 		lo->power_vector = power_vector;
5983 
5984 	BWN_GETTIME(lo->pwr_vec_read_time);
5985 }
5986 
5987 static void
5988 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
5989     int use_trsw_rx)
5990 {
5991 	struct bwn_phy *phy = &mac->mac_phy;
5992 	struct bwn_phy_g *pg = &phy->phy_g;
5993 	uint16_t tmp;
5994 
5995 	if (max_rx_gain < 0)
5996 		max_rx_gain = 0;
5997 
5998 	if (BWN_HAS_LOOPBACK(phy)) {
5999 		int trsw_rx = 0;
6000 		int trsw_rx_gain;
6001 
6002 		if (use_trsw_rx) {
6003 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6004 			if (max_rx_gain >= trsw_rx_gain) {
6005 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6006 				trsw_rx = 0x20;
6007 			}
6008 		} else
6009 			trsw_rx_gain = max_rx_gain;
6010 		if (trsw_rx_gain < 9) {
6011 			pg->pg_lna_lod_gain = 0;
6012 		} else {
6013 			pg->pg_lna_lod_gain = 1;
6014 			trsw_rx_gain -= 8;
6015 		}
6016 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6017 		pg->pg_pga_gain = trsw_rx_gain / 3;
6018 		if (pg->pg_pga_gain >= 5) {
6019 			pg->pg_pga_gain -= 5;
6020 			pg->pg_lna_gain = 2;
6021 		} else
6022 			pg->pg_lna_gain = 0;
6023 	} else {
6024 		pg->pg_lna_gain = 0;
6025 		pg->pg_trsw_rx_gain = 0x20;
6026 		if (max_rx_gain >= 0x14) {
6027 			pg->pg_lna_lod_gain = 1;
6028 			pg->pg_pga_gain = 2;
6029 		} else if (max_rx_gain >= 0x12) {
6030 			pg->pg_lna_lod_gain = 1;
6031 			pg->pg_pga_gain = 1;
6032 		} else if (max_rx_gain >= 0xf) {
6033 			pg->pg_lna_lod_gain = 1;
6034 			pg->pg_pga_gain = 0;
6035 		} else {
6036 			pg->pg_lna_lod_gain = 0;
6037 			pg->pg_pga_gain = 0;
6038 		}
6039 	}
6040 
6041 	tmp = BWN_RF_READ(mac, 0x7a);
6042 	if (pg->pg_lna_lod_gain == 0)
6043 		tmp &= ~0x0008;
6044 	else
6045 		tmp |= 0x0008;
6046 	BWN_RF_WRITE(mac, 0x7a, tmp);
6047 }
6048 
6049 static void
6050 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6051 {
6052 	struct bwn_phy *phy = &mac->mac_phy;
6053 	struct bwn_phy_g *pg = &phy->phy_g;
6054 	struct bwn_softc *sc = mac->mac_sc;
6055 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6056 	struct timespec ts;
6057 	uint16_t tmp;
6058 
6059 	if (bwn_has_hwpctl(mac)) {
6060 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6061 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6062 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6063 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6064 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6065 
6066 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6067 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6068 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6069 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6070 	}
6071 	if (phy->type == BWN_PHYTYPE_B &&
6072 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6073 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6074 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6075 	}
6076 	if (phy->rev >= 2) {
6077 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6078 		sav->phy_analogoverval =
6079 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6080 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6081 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6082 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6083 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6084 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6085 
6086 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6087 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6088 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6089 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6090 		if (phy->type == BWN_PHYTYPE_G) {
6091 			if ((phy->rev >= 7) &&
6092 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6093 			     BWN_BFL_EXTLNA)) {
6094 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6095 			} else {
6096 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6097 			}
6098 		} else {
6099 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6100 		}
6101 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6102 	}
6103 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6104 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6105 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6106 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6107 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6108 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6109 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6110 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6111 
6112 	if (!BWN_HAS_TXMAG(phy)) {
6113 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6114 		sav->rf2 &= 0x00f0;
6115 	}
6116 	if (phy->type == BWN_PHYTYPE_B) {
6117 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6118 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6119 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6120 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6121 	} else {
6122 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6123 			    | 0x8000);
6124 	}
6125 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6126 		    & 0xf000);
6127 
6128 	tmp =
6129 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6130 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6131 
6132 	tmp = sav->phy_syncctl;
6133 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6134 	tmp = sav->rf1;
6135 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6136 
6137 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6138 	if (phy->type == BWN_PHYTYPE_G ||
6139 	    (phy->type == BWN_PHYTYPE_B &&
6140 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6141 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6142 	} else
6143 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6144 	if (phy->rev >= 2)
6145 		bwn_dummy_transmission(mac, 0, 1);
6146 	bwn_phy_g_switch_chan(mac, 6, 0);
6147 	BWN_RF_READ(mac, 0x51);
6148 	if (phy->type == BWN_PHYTYPE_G)
6149 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6150 
6151 	nanouptime(&ts);
6152 	if (time_before(lo->txctl_measured_time,
6153 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6154 		bwn_lo_measure_txctl_values(mac);
6155 
6156 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6157 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6158 	else {
6159 		if (phy->type == BWN_PHYTYPE_B)
6160 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6161 		else
6162 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6163 	}
6164 }
6165 
6166 static void
6167 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6168 {
6169 	struct bwn_phy *phy = &mac->mac_phy;
6170 	struct bwn_phy_g *pg = &phy->phy_g;
6171 	uint16_t tmp;
6172 
6173 	if (phy->rev >= 2) {
6174 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6175 		tmp = (pg->pg_pga_gain << 8);
6176 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6177 		DELAY(5);
6178 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6179 		DELAY(2);
6180 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6181 	} else {
6182 		tmp = (pg->pg_pga_gain | 0xefa0);
6183 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6184 	}
6185 	if (phy->type == BWN_PHYTYPE_G) {
6186 		if (phy->rev >= 3)
6187 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6188 		else
6189 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6190 		if (phy->rev >= 2)
6191 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6192 		else
6193 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6194 	}
6195 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6196 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6197 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6198 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6199 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6200 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6201 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6202 	if (!BWN_HAS_TXMAG(phy)) {
6203 		tmp = sav->rf2;
6204 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6205 	}
6206 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6207 	if (phy->type == BWN_PHYTYPE_B &&
6208 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6209 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6210 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6211 	}
6212 	if (phy->rev >= 2) {
6213 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6214 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6215 			      sav->phy_analogoverval);
6216 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6217 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6218 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6219 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6220 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6221 	}
6222 	if (bwn_has_hwpctl(mac)) {
6223 		tmp = (sav->phy_lomask & 0xbfff);
6224 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6225 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6226 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6227 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6228 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6229 	}
6230 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6231 }
6232 
6233 static int
6234 bwn_lo_probe_loctl(struct bwn_mac *mac,
6235     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6236 {
6237 	struct bwn_phy *phy = &mac->mac_phy;
6238 	struct bwn_phy_g *pg = &phy->phy_g;
6239 	struct bwn_loctl orig, test;
6240 	struct bwn_loctl prev = { -100, -100 };
6241 	static const struct bwn_loctl modifiers[] = {
6242 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6243 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6244 	};
6245 	int begin, end, lower = 0, i;
6246 	uint16_t feedth;
6247 
6248 	if (d->curstate == 0) {
6249 		begin = 1;
6250 		end = 8;
6251 	} else if (d->curstate % 2 == 0) {
6252 		begin = d->curstate - 1;
6253 		end = d->curstate + 1;
6254 	} else {
6255 		begin = d->curstate - 2;
6256 		end = d->curstate + 2;
6257 	}
6258 	if (begin < 1)
6259 		begin += 8;
6260 	if (end > 8)
6261 		end -= 8;
6262 
6263 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6264 	i = begin;
6265 	d->curstate = i;
6266 	while (1) {
6267 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6268 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6269 		test.i += modifiers[i - 1].i * d->multipler;
6270 		test.q += modifiers[i - 1].q * d->multipler;
6271 		if ((test.i != prev.i || test.q != prev.q) &&
6272 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6273 			bwn_lo_write(mac, &test);
6274 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6275 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6276 			if (feedth < d->feedth) {
6277 				memcpy(probe, &test,
6278 				    sizeof(struct bwn_loctl));
6279 				lower = 1;
6280 				d->feedth = feedth;
6281 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6282 					break;
6283 			}
6284 		}
6285 		memcpy(&prev, &test, sizeof(prev));
6286 		if (i == end)
6287 			break;
6288 		if (i == 8)
6289 			i = 1;
6290 		else
6291 			i++;
6292 		d->curstate = i;
6293 	}
6294 
6295 	return (lower);
6296 }
6297 
6298 static void
6299 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6300 {
6301 	struct bwn_phy *phy = &mac->mac_phy;
6302 	struct bwn_phy_g *pg = &phy->phy_g;
6303 	struct bwn_lo_g_sm d;
6304 	struct bwn_loctl probe;
6305 	int lower, repeat, cnt = 0;
6306 	uint16_t feedth;
6307 
6308 	d.nmeasure = 0;
6309 	d.multipler = 1;
6310 	if (BWN_HAS_LOOPBACK(phy))
6311 		d.multipler = 3;
6312 
6313 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6314 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6315 
6316 	do {
6317 		bwn_lo_write(mac, &d.loctl);
6318 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6319 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6320 		if (feedth < 0x258) {
6321 			if (feedth >= 0x12c)
6322 				*rxgain += 6;
6323 			else
6324 				*rxgain += 3;
6325 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6326 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6327 		}
6328 		d.feedth = feedth;
6329 		d.curstate = 0;
6330 		do {
6331 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6332 			    ("%s:%d: fail", __func__, __LINE__));
6333 			memcpy(&probe, &d.loctl,
6334 			       sizeof(struct bwn_loctl));
6335 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6336 			if (!lower)
6337 				break;
6338 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6339 				break;
6340 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6341 			d.nmeasure++;
6342 		} while (d.nmeasure < 24);
6343 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6344 
6345 		if (BWN_HAS_LOOPBACK(phy)) {
6346 			if (d.feedth > 0x1194)
6347 				*rxgain -= 6;
6348 			else if (d.feedth < 0x5dc)
6349 				*rxgain += 3;
6350 			if (cnt == 0) {
6351 				if (d.feedth <= 0x5dc) {
6352 					d.multipler = 1;
6353 					cnt++;
6354 				} else
6355 					d.multipler = 2;
6356 			} else if (cnt == 2)
6357 				d.multipler = 1;
6358 		}
6359 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6360 	} while (++cnt < repeat);
6361 }
6362 
6363 static struct bwn_lo_calib *
6364 bwn_lo_calibset(struct bwn_mac *mac,
6365     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6366 {
6367 	struct bwn_phy *phy = &mac->mac_phy;
6368 	struct bwn_phy_g *pg = &phy->phy_g;
6369 	struct bwn_loctl loctl = { 0, 0 };
6370 	struct bwn_lo_calib *cal;
6371 	struct bwn_lo_g_value sval = { 0 };
6372 	int rxgain;
6373 	uint16_t pad, reg, value;
6374 
6375 	sval.old_channel = phy->chan;
6376 	bwn_mac_suspend(mac);
6377 	bwn_lo_save(mac, &sval);
6378 
6379 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6380 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6381 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6382 
6383 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6384 	if (rfatt->padmix)
6385 		rxgain -= pad;
6386 	if (BWN_HAS_LOOPBACK(phy))
6387 		rxgain += pg->pg_max_lb_gain;
6388 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6389 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6390 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6391 
6392 	bwn_lo_restore(mac, &sval);
6393 	bwn_mac_enable(mac);
6394 
6395 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6396 	if (!cal) {
6397 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6398 		return (NULL);
6399 	}
6400 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6401 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6402 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6403 
6404 	BWN_GETTIME(cal->calib_time);
6405 
6406 	return (cal);
6407 }
6408 
6409 static struct bwn_lo_calib *
6410 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6411     const struct bwn_rfatt *rfatt)
6412 {
6413 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6414 	struct bwn_lo_calib *c;
6415 
6416 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6417 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6418 			continue;
6419 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6420 			continue;
6421 		return (c);
6422 	}
6423 
6424 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6425 	if (!c)
6426 		return (NULL);
6427 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6428 
6429 	return (c);
6430 }
6431 
6432 static void
6433 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6434 {
6435 	struct bwn_phy *phy = &mac->mac_phy;
6436 	struct bwn_phy_g *pg = &phy->phy_g;
6437 	struct bwn_softc *sc = mac->mac_sc;
6438 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6439 	const struct bwn_rfatt *rfatt;
6440 	const struct bwn_bbatt *bbatt;
6441 	uint64_t pvector;
6442 	int i;
6443 	int rf_offset, bb_offset;
6444 	uint8_t changed = 0;
6445 
6446 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6447 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6448 	    ("%s:%d: fail", __func__, __LINE__));
6449 
6450 	pvector = lo->power_vector;
6451 	if (!update && !pvector)
6452 		return;
6453 
6454 	bwn_mac_suspend(mac);
6455 
6456 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6457 		struct bwn_lo_calib *cal;
6458 		int idx;
6459 		uint16_t val;
6460 
6461 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6462 			continue;
6463 		bb_offset = i / lo->rfatt.len;
6464 		rf_offset = i % lo->rfatt.len;
6465 		bbatt = &(lo->bbatt.array[bb_offset]);
6466 		rfatt = &(lo->rfatt.array[rf_offset]);
6467 
6468 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6469 		if (!cal) {
6470 			device_printf(sc->sc_dev, "LO: Could not "
6471 			    "calibrate DC table entry\n");
6472 			continue;
6473 		}
6474 		val = (uint8_t)(cal->ctl.q);
6475 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6476 		free(cal, M_DEVBUF);
6477 
6478 		idx = i / 2;
6479 		if (i % 2)
6480 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6481 			    | ((val & 0x00ff) << 8);
6482 		else
6483 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6484 			    | (val & 0x00ff);
6485 		changed = 1;
6486 	}
6487 	if (changed) {
6488 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6489 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6490 	}
6491 	bwn_mac_enable(mac);
6492 }
6493 
6494 static void
6495 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6496 {
6497 
6498 	if (!rf->padmix)
6499 		return;
6500 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6501 		rf->att = 4;
6502 }
6503 
6504 static void
6505 bwn_lo_g_adjust(struct bwn_mac *mac)
6506 {
6507 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6508 	struct bwn_lo_calib *cal;
6509 	struct bwn_rfatt rf;
6510 
6511 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6512 	bwn_lo_fixup_rfatt(&rf);
6513 
6514 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6515 	if (!cal)
6516 		return;
6517 	bwn_lo_write(mac, &cal->ctl);
6518 }
6519 
6520 static void
6521 bwn_lo_g_init(struct bwn_mac *mac)
6522 {
6523 
6524 	if (!bwn_has_hwpctl(mac))
6525 		return;
6526 
6527 	bwn_lo_get_powervector(mac);
6528 	bwn_phy_g_dc_lookup_init(mac, 1);
6529 }
6530 
6531 static void
6532 bwn_mac_suspend(struct bwn_mac *mac)
6533 {
6534 	struct bwn_softc *sc = mac->mac_sc;
6535 	int i;
6536 	uint32_t tmp;
6537 
6538 	KASSERT(mac->mac_suspended >= 0,
6539 	    ("%s:%d: fail", __func__, __LINE__));
6540 
6541 	if (mac->mac_suspended == 0) {
6542 		bwn_psctl(mac, BWN_PS_AWAKE);
6543 		BWN_WRITE_4(mac, BWN_MACCTL,
6544 			    BWN_READ_4(mac, BWN_MACCTL)
6545 			    & ~BWN_MACCTL_ON);
6546 		BWN_READ_4(mac, BWN_MACCTL);
6547 		for (i = 35; i; i--) {
6548 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6549 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6550 				goto out;
6551 			DELAY(10);
6552 		}
6553 		for (i = 40; i; i--) {
6554 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6555 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6556 				goto out;
6557 			DELAY(1000);
6558 		}
6559 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6560 	}
6561 out:
6562 	mac->mac_suspended++;
6563 }
6564 
6565 static void
6566 bwn_mac_enable(struct bwn_mac *mac)
6567 {
6568 	struct bwn_softc *sc = mac->mac_sc;
6569 	uint16_t state;
6570 
6571 	state = bwn_shm_read_2(mac, BWN_SHARED,
6572 	    BWN_SHARED_UCODESTAT);
6573 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6574 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6575 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6576 
6577 	mac->mac_suspended--;
6578 	KASSERT(mac->mac_suspended >= 0,
6579 	    ("%s:%d: fail", __func__, __LINE__));
6580 	if (mac->mac_suspended == 0) {
6581 		BWN_WRITE_4(mac, BWN_MACCTL,
6582 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6583 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6584 		BWN_READ_4(mac, BWN_MACCTL);
6585 		BWN_READ_4(mac, BWN_INTR_REASON);
6586 		bwn_psctl(mac, 0);
6587 	}
6588 }
6589 
6590 static void
6591 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6592 {
6593 	struct bwn_softc *sc = mac->mac_sc;
6594 	int i;
6595 	uint16_t ucstat;
6596 
6597 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6598 	    ("%s:%d: fail", __func__, __LINE__));
6599 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6600 	    ("%s:%d: fail", __func__, __LINE__));
6601 
6602 	/* XXX forcibly awake and hwps-off */
6603 
6604 	BWN_WRITE_4(mac, BWN_MACCTL,
6605 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6606 	    ~BWN_MACCTL_HWPS);
6607 	BWN_READ_4(mac, BWN_MACCTL);
6608 	if (siba_get_revid(sc->sc_dev) >= 5) {
6609 		for (i = 0; i < 100; i++) {
6610 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6611 			    BWN_SHARED_UCODESTAT);
6612 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6613 				break;
6614 			DELAY(10);
6615 		}
6616 	}
6617 }
6618 
6619 static int16_t
6620 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6621 {
6622 
6623 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6624 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6625 }
6626 
6627 static void
6628 bwn_nrssi_threshold(struct bwn_mac *mac)
6629 {
6630 	struct bwn_phy *phy = &mac->mac_phy;
6631 	struct bwn_phy_g *pg = &phy->phy_g;
6632 	struct bwn_softc *sc = mac->mac_sc;
6633 	int32_t a, b;
6634 	int16_t tmp16;
6635 	uint16_t tmpu16;
6636 
6637 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6638 
6639 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6640 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6641 			a = 0x13;
6642 			b = 0x12;
6643 		} else {
6644 			a = 0xe;
6645 			b = 0x11;
6646 		}
6647 
6648 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6649 		a += (pg->pg_nrssi[0] << 6);
6650 		a += (a < 32) ? 31 : 32;
6651 		a = a >> 6;
6652 		a = MIN(MAX(a, -31), 31);
6653 
6654 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6655 		b += (pg->pg_nrssi[0] << 6);
6656 		if (b < 32)
6657 			b += 31;
6658 		else
6659 			b += 32;
6660 		b = b >> 6;
6661 		b = MIN(MAX(b, -31), 31);
6662 
6663 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6664 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6665 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6666 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6667 		return;
6668 	}
6669 
6670 	tmp16 = bwn_nrssi_read(mac, 0x20);
6671 	if (tmp16 >= 0x20)
6672 		tmp16 -= 0x40;
6673 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6674 }
6675 
6676 static void
6677 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6678 {
6679 #define	SAVE_RF_MAX		3
6680 #define	SAVE_PHY_COMM_MAX	4
6681 #define	SAVE_PHY3_MAX		8
6682 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6683 		{ 0x7a, 0x52, 0x43 };
6684 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6685 		{ 0x15, 0x5a, 0x59, 0x58 };
6686 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6687 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6688 		0x0801, 0x0060, 0x0014, 0x0478
6689 	};
6690 	struct bwn_phy *phy = &mac->mac_phy;
6691 	struct bwn_phy_g *pg = &phy->phy_g;
6692 	int32_t i, tmp32, phy3_idx = 0;
6693 	uint16_t delta, tmp;
6694 	uint16_t save_rf[SAVE_RF_MAX];
6695 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6696 	uint16_t save_phy3[SAVE_PHY3_MAX];
6697 	uint16_t ant_div, phy0, chan_ex;
6698 	int16_t nrssi0, nrssi1;
6699 
6700 	KASSERT(phy->type == BWN_PHYTYPE_G,
6701 	    ("%s:%d: fail", __func__, __LINE__));
6702 
6703 	if (phy->rf_rev >= 9)
6704 		return;
6705 	if (phy->rf_rev == 8)
6706 		bwn_nrssi_offset(mac);
6707 
6708 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6709 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6710 
6711 	/*
6712 	 * Save RF/PHY registers for later restoration
6713 	 */
6714 	ant_div = BWN_READ_2(mac, 0x03e2);
6715 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6716 	for (i = 0; i < SAVE_RF_MAX; ++i)
6717 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6718 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6719 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6720 
6721 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6722 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6723 	if (phy->rev >= 3) {
6724 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6725 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6726 		BWN_PHY_WRITE(mac, 0x002e, 0);
6727 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6728 		switch (phy->rev) {
6729 		case 4:
6730 		case 6:
6731 		case 7:
6732 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6733 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6734 			break;
6735 		case 3:
6736 		case 5:
6737 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6738 			break;
6739 		}
6740 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6741 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6742 	}
6743 	/*
6744 	 * Calculate nrssi0
6745 	 */
6746 	BWN_RF_SET(mac, 0x007a, 0x0070);
6747 	bwn_set_all_gains(mac, 0, 8, 0);
6748 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6749 	if (phy->rev >= 2) {
6750 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6751 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6752 	}
6753 	BWN_RF_SET(mac, 0x007a, 0x0080);
6754 	DELAY(20);
6755 
6756 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6757 	if (nrssi0 >= 0x0020)
6758 		nrssi0 -= 0x0040;
6759 
6760 	/*
6761 	 * Calculate nrssi1
6762 	 */
6763 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6764 	if (phy->rev >= 2)
6765 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6766 
6767 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6768 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6769 	BWN_RF_SET(mac, 0x007a, 0x000f);
6770 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6771 	if (phy->rev >= 2) {
6772 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6773 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6774 	}
6775 
6776 	bwn_set_all_gains(mac, 3, 0, 1);
6777 	if (phy->rf_rev == 8) {
6778 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6779 	} else {
6780 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6781 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6782 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6783 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6784 	}
6785 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6786 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6787 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6788 	DELAY(20);
6789 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6790 
6791 	/*
6792 	 * Install calculated narrow RSSI values
6793 	 */
6794 	if (nrssi1 >= 0x0020)
6795 		nrssi1 -= 0x0040;
6796 	if (nrssi0 == nrssi1)
6797 		pg->pg_nrssi_slope = 0x00010000;
6798 	else
6799 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6800 	if (nrssi0 >= -4) {
6801 		pg->pg_nrssi[0] = nrssi1;
6802 		pg->pg_nrssi[1] = nrssi0;
6803 	}
6804 
6805 	/*
6806 	 * Restore saved RF/PHY registers
6807 	 */
6808 	if (phy->rev >= 3) {
6809 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6810 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6811 			    save_phy3[phy3_idx]);
6812 		}
6813 	}
6814 	if (phy->rev >= 2) {
6815 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6816 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6817 	}
6818 
6819 	for (i = 0; i < SAVE_RF_MAX; ++i)
6820 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6821 
6822 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6823 	BWN_WRITE_2(mac, 0x03e6, phy0);
6824 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6825 
6826 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6827 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6828 
6829 	bwn_spu_workaround(mac, phy->chan);
6830 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6831 	bwn_set_original_gains(mac);
6832 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6833 	if (phy->rev >= 3) {
6834 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6835 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6836 			    save_phy3[phy3_idx]);
6837 		}
6838 	}
6839 
6840 	delta = 0x1f - pg->pg_nrssi[0];
6841 	for (i = 0; i < 64; i++) {
6842 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6843 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6844 		pg->pg_nrssi_lt[i] = tmp32;
6845 	}
6846 
6847 	bwn_nrssi_threshold(mac);
6848 #undef SAVE_RF_MAX
6849 #undef SAVE_PHY_COMM_MAX
6850 #undef SAVE_PHY3_MAX
6851 }
6852 
6853 static void
6854 bwn_nrssi_offset(struct bwn_mac *mac)
6855 {
6856 #define	SAVE_RF_MAX		2
6857 #define	SAVE_PHY_COMM_MAX	10
6858 #define	SAVE_PHY6_MAX		8
6859 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6860 		{ 0x7a, 0x43 };
6861 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6862 		0x0001, 0x0811, 0x0812, 0x0814,
6863 		0x0815, 0x005a, 0x0059, 0x0058,
6864 		0x000a, 0x0003
6865 	};
6866 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6867 		0x002e, 0x002f, 0x080f, 0x0810,
6868 		0x0801, 0x0060, 0x0014, 0x0478
6869 	};
6870 	struct bwn_phy *phy = &mac->mac_phy;
6871 	int i, phy6_idx = 0;
6872 	uint16_t save_rf[SAVE_RF_MAX];
6873 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6874 	uint16_t save_phy6[SAVE_PHY6_MAX];
6875 	int16_t nrssi;
6876 	uint16_t saved = 0xffff;
6877 
6878 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6879 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6880 	for (i = 0; i < SAVE_RF_MAX; ++i)
6881 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6882 
6883 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6884 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6885 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6886 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6887 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6888 	if (phy->rev >= 6) {
6889 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6890 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6891 
6892 		BWN_PHY_WRITE(mac, 0x002e, 0);
6893 		BWN_PHY_WRITE(mac, 0x002f, 0);
6894 		BWN_PHY_WRITE(mac, 0x080f, 0);
6895 		BWN_PHY_WRITE(mac, 0x0810, 0);
6896 		BWN_PHY_SET(mac, 0x0478, 0x0100);
6897 		BWN_PHY_SET(mac, 0x0801, 0x0040);
6898 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6899 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6900 	}
6901 	BWN_RF_SET(mac, 0x007a, 0x0070);
6902 	BWN_RF_SET(mac, 0x007a, 0x0080);
6903 	DELAY(30);
6904 
6905 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6906 	if (nrssi >= 0x20)
6907 		nrssi -= 0x40;
6908 	if (nrssi == 31) {
6909 		for (i = 7; i >= 4; i--) {
6910 			BWN_RF_WRITE(mac, 0x007b, i);
6911 			DELAY(20);
6912 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6913 			    0x003f);
6914 			if (nrssi >= 0x20)
6915 				nrssi -= 0x40;
6916 			if (nrssi < 31 && saved == 0xffff)
6917 				saved = i;
6918 		}
6919 		if (saved == 0xffff)
6920 			saved = 4;
6921 	} else {
6922 		BWN_RF_MASK(mac, 0x007a, 0x007f);
6923 		if (phy->rev != 1) {
6924 			BWN_PHY_SET(mac, 0x0814, 0x0001);
6925 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6926 		}
6927 		BWN_PHY_SET(mac, 0x0811, 0x000c);
6928 		BWN_PHY_SET(mac, 0x0812, 0x000c);
6929 		BWN_PHY_SET(mac, 0x0811, 0x0030);
6930 		BWN_PHY_SET(mac, 0x0812, 0x0030);
6931 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6932 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6933 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6934 		if (phy->rev == 0)
6935 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6936 		else
6937 			BWN_PHY_SET(mac, 0x000a, 0x2000);
6938 		if (phy->rev != 1) {
6939 			BWN_PHY_SET(mac, 0x0814, 0x0004);
6940 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6941 		}
6942 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6943 		BWN_RF_SET(mac, 0x007a, 0x000f);
6944 		bwn_set_all_gains(mac, 3, 0, 1);
6945 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6946 		DELAY(30);
6947 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6948 		if (nrssi >= 0x20)
6949 			nrssi -= 0x40;
6950 		if (nrssi == -32) {
6951 			for (i = 0; i < 4; i++) {
6952 				BWN_RF_WRITE(mac, 0x007b, i);
6953 				DELAY(20);
6954 				nrssi = (int16_t)((BWN_PHY_READ(mac,
6955 				    0x047f) >> 8) & 0x003f);
6956 				if (nrssi >= 0x20)
6957 					nrssi -= 0x40;
6958 				if (nrssi > -31 && saved == 0xffff)
6959 					saved = i;
6960 			}
6961 			if (saved == 0xffff)
6962 				saved = 3;
6963 		} else
6964 			saved = 0;
6965 	}
6966 	BWN_RF_WRITE(mac, 0x007b, saved);
6967 
6968 	/*
6969 	 * Restore saved RF/PHY registers
6970 	 */
6971 	if (phy->rev >= 6) {
6972 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6973 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6974 			    save_phy6[phy6_idx]);
6975 		}
6976 	}
6977 	if (phy->rev != 1) {
6978 		for (i = 3; i < 5; i++)
6979 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6980 			    save_phy_comm[i]);
6981 	}
6982 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6983 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6984 
6985 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
6986 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6987 
6988 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
6989 	BWN_PHY_SET(mac, 0x0429, 0x8000);
6990 	bwn_set_original_gains(mac);
6991 	if (phy->rev >= 6) {
6992 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
6993 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6994 			    save_phy6[phy6_idx]);
6995 		}
6996 	}
6997 
6998 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
6999 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7000 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7001 }
7002 
7003 static void
7004 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7005     int16_t third)
7006 {
7007 	struct bwn_phy *phy = &mac->mac_phy;
7008 	uint16_t i;
7009 	uint16_t start = 0x08, end = 0x18;
7010 	uint16_t tmp;
7011 	uint16_t table;
7012 
7013 	if (phy->rev <= 1) {
7014 		start = 0x10;
7015 		end = 0x20;
7016 	}
7017 
7018 	table = BWN_OFDMTAB_GAINX;
7019 	if (phy->rev <= 1)
7020 		table = BWN_OFDMTAB_GAINX_R1;
7021 	for (i = 0; i < 4; i++)
7022 		bwn_ofdmtab_write_2(mac, table, i, first);
7023 
7024 	for (i = start; i < end; i++)
7025 		bwn_ofdmtab_write_2(mac, table, i, second);
7026 
7027 	if (third != -1) {
7028 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7029 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7030 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7031 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7032 	}
7033 	bwn_dummy_transmission(mac, 0, 1);
7034 }
7035 
7036 static void
7037 bwn_set_original_gains(struct bwn_mac *mac)
7038 {
7039 	struct bwn_phy *phy = &mac->mac_phy;
7040 	uint16_t i, tmp;
7041 	uint16_t table;
7042 	uint16_t start = 0x0008, end = 0x0018;
7043 
7044 	if (phy->rev <= 1) {
7045 		start = 0x0010;
7046 		end = 0x0020;
7047 	}
7048 
7049 	table = BWN_OFDMTAB_GAINX;
7050 	if (phy->rev <= 1)
7051 		table = BWN_OFDMTAB_GAINX_R1;
7052 	for (i = 0; i < 4; i++) {
7053 		tmp = (i & 0xfffc);
7054 		tmp |= (i & 0x0001) << 1;
7055 		tmp |= (i & 0x0002) >> 1;
7056 
7057 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7058 	}
7059 
7060 	for (i = start; i < end; i++)
7061 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7062 
7063 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7064 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7065 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7066 	bwn_dummy_transmission(mac, 0, 1);
7067 }
7068 
7069 static void
7070 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7071 {
7072 	struct bwn_phy *phy = &mac->mac_phy;
7073 	struct bwn_phy_g *pg = &phy->phy_g;
7074 	struct bwn_rfatt old_rfatt, rfatt;
7075 	struct bwn_bbatt old_bbatt, bbatt;
7076 	struct bwn_softc *sc = mac->mac_sc;
7077 	uint8_t old_txctl = 0;
7078 
7079 	KASSERT(phy->type == BWN_PHYTYPE_G,
7080 	    ("%s:%d: fail", __func__, __LINE__));
7081 
7082 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7083 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7084 		return;
7085 
7086 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7087 
7088 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7089 
7090 	if (!phy->gmode)
7091 		return;
7092 	bwn_hwpctl_early_init(mac);
7093 	if (pg->pg_curtssi == 0) {
7094 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7095 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7096 		} else {
7097 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7098 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7099 			old_txctl = pg->pg_txctl;
7100 
7101 			bbatt.att = 11;
7102 			if (phy->rf_rev == 8) {
7103 				rfatt.att = 15;
7104 				rfatt.padmix = 1;
7105 			} else {
7106 				rfatt.att = 9;
7107 				rfatt.padmix = 0;
7108 			}
7109 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7110 		}
7111 		bwn_dummy_transmission(mac, 0, 1);
7112 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7113 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7114 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7115 		else
7116 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7117 			    &old_rfatt, old_txctl);
7118 	}
7119 	bwn_hwpctl_init_gphy(mac);
7120 
7121 	/* clear TSSI */
7122 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7123 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7124 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7125 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7126 }
7127 
7128 static void
7129 bwn_hwpctl_early_init(struct bwn_mac *mac)
7130 {
7131 	struct bwn_phy *phy = &mac->mac_phy;
7132 
7133 	if (!bwn_has_hwpctl(mac)) {
7134 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7135 		return;
7136 	}
7137 
7138 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7139 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7140 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7141 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7142 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7143 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7144 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7145 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7146 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7147 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7148 	} else {
7149 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7150 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7151 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7152 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7153 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7154 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7155 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7156 	}
7157 }
7158 
7159 static void
7160 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7161 {
7162 	struct bwn_phy *phy = &mac->mac_phy;
7163 	struct bwn_phy_g *pg = &phy->phy_g;
7164 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7165 	int i;
7166 	uint16_t nr_written = 0, tmp, value;
7167 	uint8_t rf, bb;
7168 
7169 	if (!bwn_has_hwpctl(mac)) {
7170 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7171 		return;
7172 	}
7173 
7174 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7175 	    (pg->pg_idletssi - pg->pg_curtssi));
7176 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7177 	    (pg->pg_idletssi - pg->pg_curtssi));
7178 
7179 	for (i = 0; i < 32; i++)
7180 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7181 	for (i = 32; i < 64; i++)
7182 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7183 	for (i = 0; i < 64; i += 2) {
7184 		value = (uint16_t) pg->pg_tssi2dbm[i];
7185 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7186 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7187 	}
7188 
7189 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7190 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7191 			if (nr_written >= 0x40)
7192 				return;
7193 			tmp = lo->bbatt.array[bb].att;
7194 			tmp <<= 8;
7195 			if (phy->rf_rev == 8)
7196 				tmp |= 0x50;
7197 			else
7198 				tmp |= 0x40;
7199 			tmp |= lo->rfatt.array[rf].att;
7200 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7201 			nr_written++;
7202 		}
7203 	}
7204 
7205 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7206 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7207 
7208 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7209 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7210 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7211 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7212 
7213 	bwn_phy_g_dc_lookup_init(mac, 1);
7214 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7215 }
7216 
7217 static void
7218 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7219 {
7220 	struct bwn_softc *sc = mac->mac_sc;
7221 
7222 	if (spu != 0)
7223 		bwn_spu_workaround(mac, channel);
7224 
7225 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7226 
7227 	if (channel == 14) {
7228 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7229 			bwn_hf_write(mac,
7230 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7231 		else
7232 			bwn_hf_write(mac,
7233 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7234 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7235 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7236 		return;
7237 	}
7238 
7239 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7240 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7241 }
7242 
7243 static uint16_t
7244 bwn_phy_g_chan2freq(uint8_t channel)
7245 {
7246 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7247 
7248 	KASSERT(channel >= 1 && channel <= 14,
7249 	    ("%s:%d: fail", __func__, __LINE__));
7250 
7251 	return (bwn_phy_g_rf_channels[channel - 1]);
7252 }
7253 
7254 static void
7255 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7256     const struct bwn_rfatt *rfatt, uint8_t txctl)
7257 {
7258 	struct bwn_phy *phy = &mac->mac_phy;
7259 	struct bwn_phy_g *pg = &phy->phy_g;
7260 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7261 	uint16_t bb, rf;
7262 	uint16_t tx_bias, tx_magn;
7263 
7264 	bb = bbatt->att;
7265 	rf = rfatt->att;
7266 	tx_bias = lo->tx_bias;
7267 	tx_magn = lo->tx_magn;
7268 	if (tx_bias == 0xff)
7269 		tx_bias = 0;
7270 
7271 	pg->pg_txctl = txctl;
7272 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7273 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7274 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7275 	bwn_phy_g_set_bbatt(mac, bb);
7276 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7277 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7278 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7279 	else {
7280 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7281 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7282 	}
7283 	if (BWN_HAS_TXMAG(phy))
7284 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7285 	else
7286 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7287 	bwn_lo_g_adjust(mac);
7288 }
7289 
7290 static void
7291 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7292     uint16_t bbatt)
7293 {
7294 	struct bwn_phy *phy = &mac->mac_phy;
7295 
7296 	if (phy->analog == 0) {
7297 		BWN_WRITE_2(mac, BWN_PHY0,
7298 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7299 		return;
7300 	}
7301 	if (phy->analog > 1) {
7302 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7303 		return;
7304 	}
7305 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7306 }
7307 
7308 static uint16_t
7309 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7310 {
7311 	struct bwn_phy *phy = &mac->mac_phy;
7312 	struct bwn_phy_g *pg = &phy->phy_g;
7313 	struct bwn_softc *sc = mac->mac_sc;
7314 	int max_lb_gain;
7315 	uint16_t extlna;
7316 	uint16_t i;
7317 
7318 	if (phy->gmode == 0)
7319 		return (0);
7320 
7321 	if (BWN_HAS_LOOPBACK(phy)) {
7322 		max_lb_gain = pg->pg_max_lb_gain;
7323 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7324 		if (max_lb_gain >= 0x46) {
7325 			extlna = 0x3000;
7326 			max_lb_gain -= 0x46;
7327 		} else if (max_lb_gain >= 0x3a) {
7328 			extlna = 0x1000;
7329 			max_lb_gain -= 0x3a;
7330 		} else if (max_lb_gain >= 0x2e) {
7331 			extlna = 0x2000;
7332 			max_lb_gain -= 0x2e;
7333 		} else {
7334 			extlna = 0;
7335 			max_lb_gain -= 0x10;
7336 		}
7337 
7338 		for (i = 0; i < 16; i++) {
7339 			max_lb_gain -= (i * 6);
7340 			if (max_lb_gain < 6)
7341 				break;
7342 		}
7343 
7344 		if ((phy->rev < 7) ||
7345 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7346 			if (reg == BWN_PHY_RFOVER) {
7347 				return (0x1b3);
7348 			} else if (reg == BWN_PHY_RFOVERVAL) {
7349 				extlna |= (i << 8);
7350 				switch (lpd) {
7351 				case BWN_LPD(0, 1, 1):
7352 					return (0x0f92);
7353 				case BWN_LPD(0, 0, 1):
7354 				case BWN_LPD(1, 0, 1):
7355 					return (0x0092 | extlna);
7356 				case BWN_LPD(1, 0, 0):
7357 					return (0x0093 | extlna);
7358 				}
7359 				KASSERT(0 == 1,
7360 				    ("%s:%d: fail", __func__, __LINE__));
7361 			}
7362 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7363 		} else {
7364 			if (reg == BWN_PHY_RFOVER)
7365 				return (0x9b3);
7366 			if (reg == BWN_PHY_RFOVERVAL) {
7367 				if (extlna)
7368 					extlna |= 0x8000;
7369 				extlna |= (i << 8);
7370 				switch (lpd) {
7371 				case BWN_LPD(0, 1, 1):
7372 					return (0x8f92);
7373 				case BWN_LPD(0, 0, 1):
7374 					return (0x8092 | extlna);
7375 				case BWN_LPD(1, 0, 1):
7376 					return (0x2092 | extlna);
7377 				case BWN_LPD(1, 0, 0):
7378 					return (0x2093 | extlna);
7379 				}
7380 				KASSERT(0 == 1,
7381 				    ("%s:%d: fail", __func__, __LINE__));
7382 			}
7383 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7384 		}
7385 		return (0);
7386 	}
7387 
7388 	if ((phy->rev < 7) ||
7389 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7390 		if (reg == BWN_PHY_RFOVER) {
7391 			return (0x1b3);
7392 		} else if (reg == BWN_PHY_RFOVERVAL) {
7393 			switch (lpd) {
7394 			case BWN_LPD(0, 1, 1):
7395 				return (0x0fb2);
7396 			case BWN_LPD(0, 0, 1):
7397 				return (0x00b2);
7398 			case BWN_LPD(1, 0, 1):
7399 				return (0x30b2);
7400 			case BWN_LPD(1, 0, 0):
7401 				return (0x30b3);
7402 			}
7403 			KASSERT(0 == 1,
7404 			    ("%s:%d: fail", __func__, __LINE__));
7405 		}
7406 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7407 	} else {
7408 		if (reg == BWN_PHY_RFOVER) {
7409 			return (0x9b3);
7410 		} else if (reg == BWN_PHY_RFOVERVAL) {
7411 			switch (lpd) {
7412 			case BWN_LPD(0, 1, 1):
7413 				return (0x8fb2);
7414 			case BWN_LPD(0, 0, 1):
7415 				return (0x80b2);
7416 			case BWN_LPD(1, 0, 1):
7417 				return (0x20b2);
7418 			case BWN_LPD(1, 0, 0):
7419 				return (0x20b3);
7420 			}
7421 			KASSERT(0 == 1,
7422 			    ("%s:%d: fail", __func__, __LINE__));
7423 		}
7424 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7425 	}
7426 	return (0);
7427 }
7428 
7429 static void
7430 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7431 {
7432 
7433 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7434 		return;
7435 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7436 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7437 	DELAY(1000);
7438 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7439 }
7440 
7441 static int
7442 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7443 {
7444 	struct bwn_softc *sc = mac->mac_sc;
7445 	struct bwn_fw *fw = &mac->mac_fw;
7446 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7447 	const char *filename;
7448 	uint32_t high;
7449 	int error;
7450 
7451 	/* microcode */
7452 	if (rev >= 5 && rev <= 10)
7453 		filename = "ucode5";
7454 	else if (rev >= 11 && rev <= 12)
7455 		filename = "ucode11";
7456 	else if (rev == 13)
7457 		filename = "ucode13";
7458 	else if (rev == 14)
7459 		filename = "ucode14";
7460 	else if (rev >= 15)
7461 		filename = "ucode15";
7462 	else {
7463 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7464 		bwn_release_firmware(mac);
7465 		return (EOPNOTSUPP);
7466 	}
7467 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7468 	if (error) {
7469 		bwn_release_firmware(mac);
7470 		return (error);
7471 	}
7472 
7473 	/* PCM */
7474 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7475 	if (rev >= 5 && rev <= 10) {
7476 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7477 		if (error == ENOENT)
7478 			fw->no_pcmfile = 1;
7479 		else if (error) {
7480 			bwn_release_firmware(mac);
7481 			return (error);
7482 		}
7483 	} else if (rev < 11) {
7484 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7485 		return (EOPNOTSUPP);
7486 	}
7487 
7488 	/* initvals */
7489 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7490 	switch (mac->mac_phy.type) {
7491 	case BWN_PHYTYPE_A:
7492 		if (rev < 5 || rev > 10)
7493 			goto fail1;
7494 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7495 			filename = "a0g1initvals5";
7496 		else
7497 			filename = "a0g0initvals5";
7498 		break;
7499 	case BWN_PHYTYPE_G:
7500 		if (rev >= 5 && rev <= 10)
7501 			filename = "b0g0initvals5";
7502 		else if (rev >= 13)
7503 			filename = "b0g0initvals13";
7504 		else
7505 			goto fail1;
7506 		break;
7507 	case BWN_PHYTYPE_LP:
7508 		if (rev == 13)
7509 			filename = "lp0initvals13";
7510 		else if (rev == 14)
7511 			filename = "lp0initvals14";
7512 		else if (rev >= 15)
7513 			filename = "lp0initvals15";
7514 		else
7515 			goto fail1;
7516 		break;
7517 	case BWN_PHYTYPE_N:
7518 		if (rev >= 11 && rev <= 12)
7519 			filename = "n0initvals11";
7520 		else
7521 			goto fail1;
7522 		break;
7523 	default:
7524 		goto fail1;
7525 	}
7526 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7527 	if (error) {
7528 		bwn_release_firmware(mac);
7529 		return (error);
7530 	}
7531 
7532 	/* bandswitch initvals */
7533 	switch (mac->mac_phy.type) {
7534 	case BWN_PHYTYPE_A:
7535 		if (rev >= 5 && rev <= 10) {
7536 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7537 				filename = "a0g1bsinitvals5";
7538 			else
7539 				filename = "a0g0bsinitvals5";
7540 		} else if (rev >= 11)
7541 			filename = NULL;
7542 		else
7543 			goto fail1;
7544 		break;
7545 	case BWN_PHYTYPE_G:
7546 		if (rev >= 5 && rev <= 10)
7547 			filename = "b0g0bsinitvals5";
7548 		else if (rev >= 11)
7549 			filename = NULL;
7550 		else
7551 			goto fail1;
7552 		break;
7553 	case BWN_PHYTYPE_LP:
7554 		if (rev == 13)
7555 			filename = "lp0bsinitvals13";
7556 		else if (rev == 14)
7557 			filename = "lp0bsinitvals14";
7558 		else if (rev >= 15)
7559 			filename = "lp0bsinitvals15";
7560 		else
7561 			goto fail1;
7562 		break;
7563 	case BWN_PHYTYPE_N:
7564 		if (rev >= 11 && rev <= 12)
7565 			filename = "n0bsinitvals11";
7566 		else
7567 			goto fail1;
7568 		break;
7569 	default:
7570 		goto fail1;
7571 	}
7572 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7573 	if (error) {
7574 		bwn_release_firmware(mac);
7575 		return (error);
7576 	}
7577 	return (0);
7578 fail1:
7579 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7580 	bwn_release_firmware(mac);
7581 	return (EOPNOTSUPP);
7582 }
7583 
7584 static int
7585 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7586     const char *name, struct bwn_fwfile *bfw)
7587 {
7588 	const struct bwn_fwhdr *hdr;
7589 	struct bwn_softc *sc = mac->mac_sc;
7590 	const struct firmware *fw;
7591 	char namebuf[64];
7592 
7593 	if (name == NULL) {
7594 		bwn_do_release_fw(bfw);
7595 		return (0);
7596 	}
7597 	if (bfw->filename != NULL) {
7598 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7599 			return (0);
7600 		bwn_do_release_fw(bfw);
7601 	}
7602 
7603 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7604 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7605 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7606 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7607 	fw = firmware_get(namebuf);
7608 	if (fw == NULL) {
7609 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7610 		    namebuf);
7611 		return (ENOENT);
7612 	}
7613 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7614 		goto fail;
7615 	hdr = (const struct bwn_fwhdr *)(fw->data);
7616 	switch (hdr->type) {
7617 	case BWN_FWTYPE_UCODE:
7618 	case BWN_FWTYPE_PCM:
7619 		if (be32toh(hdr->size) !=
7620 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7621 			goto fail;
7622 		/* FALLTHROUGH */
7623 	case BWN_FWTYPE_IV:
7624 		if (hdr->ver != 1)
7625 			goto fail;
7626 		break;
7627 	default:
7628 		goto fail;
7629 	}
7630 	bfw->filename = name;
7631 	bfw->fw = fw;
7632 	bfw->type = type;
7633 	return (0);
7634 fail:
7635 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7636 	if (fw != NULL)
7637 		firmware_put(fw, FIRMWARE_UNLOAD);
7638 	return (EPROTO);
7639 }
7640 
7641 static void
7642 bwn_release_firmware(struct bwn_mac *mac)
7643 {
7644 
7645 	bwn_do_release_fw(&mac->mac_fw.ucode);
7646 	bwn_do_release_fw(&mac->mac_fw.pcm);
7647 	bwn_do_release_fw(&mac->mac_fw.initvals);
7648 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7649 }
7650 
7651 static void
7652 bwn_do_release_fw(struct bwn_fwfile *bfw)
7653 {
7654 
7655 	if (bfw->fw != NULL)
7656 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7657 	bfw->fw = NULL;
7658 	bfw->filename = NULL;
7659 }
7660 
7661 static int
7662 bwn_fw_loaducode(struct bwn_mac *mac)
7663 {
7664 #define	GETFWOFFSET(fwp, offset)	\
7665 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7666 #define	GETFWSIZE(fwp, offset)	\
7667 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7668 	struct bwn_softc *sc = mac->mac_sc;
7669 	const uint32_t *data;
7670 	unsigned int i;
7671 	uint32_t ctl;
7672 	uint16_t date, fwcaps, time;
7673 	int error = 0;
7674 
7675 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7676 	ctl |= BWN_MACCTL_MCODE_JMP0;
7677 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7678 	    __LINE__));
7679 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7680 	for (i = 0; i < 64; i++)
7681 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7682 	for (i = 0; i < 4096; i += 2)
7683 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7684 
7685 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7686 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7687 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7688 	     i++) {
7689 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7690 		DELAY(10);
7691 	}
7692 
7693 	if (mac->mac_fw.pcm.fw) {
7694 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7695 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7696 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7697 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7698 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7699 		    sizeof(struct bwn_fwhdr)); i++) {
7700 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7701 			DELAY(10);
7702 		}
7703 	}
7704 
7705 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7706 	BWN_WRITE_4(mac, BWN_MACCTL,
7707 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7708 	    BWN_MACCTL_MCODE_RUN);
7709 
7710 	for (i = 0; i < 21; i++) {
7711 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7712 			break;
7713 		if (i >= 20) {
7714 			device_printf(sc->sc_dev, "ucode timeout\n");
7715 			error = ENXIO;
7716 			goto error;
7717 		}
7718 		DELAY(50000);
7719 	}
7720 	BWN_READ_4(mac, BWN_INTR_REASON);
7721 
7722 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7723 	if (mac->mac_fw.rev <= 0x128) {
7724 		device_printf(sc->sc_dev, "the firmware is too old\n");
7725 		error = EOPNOTSUPP;
7726 		goto error;
7727 	}
7728 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7729 	    BWN_SHARED_UCODE_PATCH);
7730 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7731 	mac->mac_fw.opensource = (date == 0xffff);
7732 	if (bwn_wme != 0)
7733 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7734 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7735 
7736 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7737 	if (mac->mac_fw.opensource == 0) {
7738 		device_printf(sc->sc_dev,
7739 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7740 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7741 		if (mac->mac_fw.no_pcmfile)
7742 			device_printf(sc->sc_dev,
7743 			    "no HW crypto acceleration due to pcm5\n");
7744 	} else {
7745 		mac->mac_fw.patch = time;
7746 		fwcaps = bwn_fwcaps_read(mac);
7747 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7748 			device_printf(sc->sc_dev,
7749 			    "disabling HW crypto acceleration\n");
7750 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7751 		}
7752 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7753 			device_printf(sc->sc_dev, "disabling WME support\n");
7754 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7755 		}
7756 	}
7757 
7758 	if (BWN_ISOLDFMT(mac))
7759 		device_printf(sc->sc_dev, "using old firmware image\n");
7760 
7761 	return (0);
7762 
7763 error:
7764 	BWN_WRITE_4(mac, BWN_MACCTL,
7765 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7766 	    BWN_MACCTL_MCODE_JMP0);
7767 
7768 	return (error);
7769 #undef GETFWSIZE
7770 #undef GETFWOFFSET
7771 }
7772 
7773 /* OpenFirmware only */
7774 static uint16_t
7775 bwn_fwcaps_read(struct bwn_mac *mac)
7776 {
7777 
7778 	KASSERT(mac->mac_fw.opensource == 1,
7779 	    ("%s:%d: fail", __func__, __LINE__));
7780 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7781 }
7782 
7783 static int
7784 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7785     size_t count, size_t array_size)
7786 {
7787 #define	GET_NEXTIV16(iv)						\
7788 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7789 	    sizeof(uint16_t) + sizeof(uint16_t)))
7790 #define	GET_NEXTIV32(iv)						\
7791 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7792 	    sizeof(uint16_t) + sizeof(uint32_t)))
7793 	struct bwn_softc *sc = mac->mac_sc;
7794 	const struct bwn_fwinitvals *iv;
7795 	uint16_t offset;
7796 	size_t i;
7797 	uint8_t bit32;
7798 
7799 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7800 	    ("%s:%d: fail", __func__, __LINE__));
7801 	iv = ivals;
7802 	for (i = 0; i < count; i++) {
7803 		if (array_size < sizeof(iv->offset_size))
7804 			goto fail;
7805 		array_size -= sizeof(iv->offset_size);
7806 		offset = be16toh(iv->offset_size);
7807 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7808 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7809 		if (offset >= 0x1000)
7810 			goto fail;
7811 		if (bit32) {
7812 			if (array_size < sizeof(iv->data.d32))
7813 				goto fail;
7814 			array_size -= sizeof(iv->data.d32);
7815 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7816 			iv = GET_NEXTIV32(iv);
7817 		} else {
7818 
7819 			if (array_size < sizeof(iv->data.d16))
7820 				goto fail;
7821 			array_size -= sizeof(iv->data.d16);
7822 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7823 
7824 			iv = GET_NEXTIV16(iv);
7825 		}
7826 	}
7827 	if (array_size != 0)
7828 		goto fail;
7829 	return (0);
7830 fail:
7831 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7832 	return (EPROTO);
7833 #undef GET_NEXTIV16
7834 #undef GET_NEXTIV32
7835 }
7836 
7837 static int
7838 bwn_switch_channel(struct bwn_mac *mac, int chan)
7839 {
7840 	struct bwn_phy *phy = &(mac->mac_phy);
7841 	struct bwn_softc *sc = mac->mac_sc;
7842 	struct ieee80211com *ic = &sc->sc_ic;
7843 	uint16_t channelcookie, savedcookie;
7844 	int error;
7845 
7846 	if (chan == 0xffff)
7847 		chan = phy->get_default_chan(mac);
7848 
7849 	channelcookie = chan;
7850 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7851 		channelcookie |= 0x100;
7852 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7853 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7854 	error = phy->switch_channel(mac, chan);
7855 	if (error)
7856 		goto fail;
7857 
7858 	mac->mac_phy.chan = chan;
7859 	DELAY(8000);
7860 	return (0);
7861 fail:
7862 	device_printf(sc->sc_dev, "failed to switch channel\n");
7863 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7864 	return (error);
7865 }
7866 
7867 static uint16_t
7868 bwn_ant2phy(int antenna)
7869 {
7870 
7871 	switch (antenna) {
7872 	case BWN_ANT0:
7873 		return (BWN_TX_PHY_ANT0);
7874 	case BWN_ANT1:
7875 		return (BWN_TX_PHY_ANT1);
7876 	case BWN_ANT2:
7877 		return (BWN_TX_PHY_ANT2);
7878 	case BWN_ANT3:
7879 		return (BWN_TX_PHY_ANT3);
7880 	case BWN_ANTAUTO:
7881 		return (BWN_TX_PHY_ANT01AUTO);
7882 	}
7883 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7884 	return (0);
7885 }
7886 
7887 static void
7888 bwn_wme_load(struct bwn_mac *mac)
7889 {
7890 	struct bwn_softc *sc = mac->mac_sc;
7891 	int i;
7892 
7893 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7894 	    ("%s:%d: fail", __func__, __LINE__));
7895 
7896 	bwn_mac_suspend(mac);
7897 	for (i = 0; i < N(sc->sc_wmeParams); i++)
7898 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7899 		    bwn_wme_shm_offsets[i]);
7900 	bwn_mac_enable(mac);
7901 }
7902 
7903 static void
7904 bwn_wme_loadparams(struct bwn_mac *mac,
7905     const struct wmeParams *p, uint16_t shm_offset)
7906 {
7907 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7908 	struct bwn_softc *sc = mac->mac_sc;
7909 	uint16_t params[BWN_NR_WMEPARAMS];
7910 	int slot, tmp;
7911 	unsigned int i;
7912 
7913 	slot = BWN_READ_2(mac, BWN_RNG) &
7914 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7915 
7916 	memset(&params, 0, sizeof(params));
7917 
7918 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7919 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7920 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7921 
7922 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7923 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7924 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7925 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7926 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7927 	params[BWN_WMEPARAM_BSLOTS] = slot;
7928 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7929 
7930 	for (i = 0; i < N(params); i++) {
7931 		if (i == BWN_WMEPARAM_STATUS) {
7932 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7933 			    shm_offset + (i * 2));
7934 			tmp |= 0x100;
7935 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7936 			    tmp);
7937 		} else {
7938 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7939 			    params[i]);
7940 		}
7941 	}
7942 }
7943 
7944 static void
7945 bwn_mac_write_bssid(struct bwn_mac *mac)
7946 {
7947 	struct bwn_softc *sc = mac->mac_sc;
7948 	uint32_t tmp;
7949 	int i;
7950 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7951 
7952 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7953 	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
7954 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7955 	    IEEE80211_ADDR_LEN);
7956 
7957 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7958 		tmp = (uint32_t) (mac_bssid[i + 0]);
7959 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7960 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7961 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7962 		bwn_ram_write(mac, 0x20 + i, tmp);
7963 	}
7964 }
7965 
7966 static void
7967 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7968     const uint8_t *macaddr)
7969 {
7970 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7971 	uint16_t data;
7972 
7973 	if (!mac)
7974 		macaddr = zero;
7975 
7976 	offset |= 0x0020;
7977 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7978 
7979 	data = macaddr[0];
7980 	data |= macaddr[1] << 8;
7981 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7982 	data = macaddr[2];
7983 	data |= macaddr[3] << 8;
7984 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7985 	data = macaddr[4];
7986 	data |= macaddr[5] << 8;
7987 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7988 }
7989 
7990 static void
7991 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
7992     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
7993 {
7994 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
7995 	uint8_t per_sta_keys_start = 8;
7996 
7997 	if (BWN_SEC_NEWAPI(mac))
7998 		per_sta_keys_start = 4;
7999 
8000 	KASSERT(index < mac->mac_max_nr_keys,
8001 	    ("%s:%d: fail", __func__, __LINE__));
8002 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8003 	    ("%s:%d: fail", __func__, __LINE__));
8004 
8005 	if (index >= per_sta_keys_start)
8006 		bwn_key_macwrite(mac, index, NULL);
8007 	if (key)
8008 		memcpy(buf, key, key_len);
8009 	bwn_key_write(mac, index, algorithm, buf);
8010 	if (index >= per_sta_keys_start)
8011 		bwn_key_macwrite(mac, index, mac_addr);
8012 
8013 	mac->mac_key[index].algorithm = algorithm;
8014 }
8015 
8016 static void
8017 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8018 {
8019 	struct bwn_softc *sc = mac->mac_sc;
8020 	uint32_t addrtmp[2] = { 0, 0 };
8021 	uint8_t start = 8;
8022 
8023 	if (BWN_SEC_NEWAPI(mac))
8024 		start = 4;
8025 
8026 	KASSERT(index >= start,
8027 	    ("%s:%d: fail", __func__, __LINE__));
8028 	index -= start;
8029 
8030 	if (addr) {
8031 		addrtmp[0] = addr[0];
8032 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8033 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8034 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8035 		addrtmp[1] = addr[4];
8036 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8037 	}
8038 
8039 	if (siba_get_revid(sc->sc_dev) >= 5) {
8040 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8041 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8042 	} else {
8043 		if (index >= 8) {
8044 			bwn_shm_write_4(mac, BWN_SHARED,
8045 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8046 			bwn_shm_write_2(mac, BWN_SHARED,
8047 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8048 		}
8049 	}
8050 }
8051 
8052 static void
8053 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8054     const uint8_t *key)
8055 {
8056 	unsigned int i;
8057 	uint32_t offset;
8058 	uint16_t kidx, value;
8059 
8060 	kidx = BWN_SEC_KEY2FW(mac, index);
8061 	bwn_shm_write_2(mac, BWN_SHARED,
8062 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8063 
8064 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8065 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8066 		value = key[i];
8067 		value |= (uint16_t)(key[i + 1]) << 8;
8068 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8069 	}
8070 }
8071 
8072 static void
8073 bwn_phy_exit(struct bwn_mac *mac)
8074 {
8075 
8076 	mac->mac_phy.rf_onoff(mac, 0);
8077 	if (mac->mac_phy.exit != NULL)
8078 		mac->mac_phy.exit(mac);
8079 }
8080 
8081 static void
8082 bwn_dma_free(struct bwn_mac *mac)
8083 {
8084 	struct bwn_dma *dma;
8085 
8086 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8087 		return;
8088 	dma = &mac->mac_method.dma;
8089 
8090 	bwn_dma_ringfree(&dma->rx);
8091 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8092 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8093 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8094 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8095 	bwn_dma_ringfree(&dma->mcast);
8096 }
8097 
8098 static void
8099 bwn_core_stop(struct bwn_mac *mac)
8100 {
8101 	struct bwn_softc *sc = mac->mac_sc;
8102 
8103 	BWN_ASSERT_LOCKED(sc);
8104 
8105 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8106 		return;
8107 
8108 	callout_stop(&sc->sc_rfswitch_ch);
8109 	callout_stop(&sc->sc_task_ch);
8110 	callout_stop(&sc->sc_watchdog_ch);
8111 	sc->sc_watchdog_timer = 0;
8112 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8113 	BWN_READ_4(mac, BWN_INTR_MASK);
8114 	bwn_mac_suspend(mac);
8115 
8116 	mac->mac_status = BWN_MAC_STATUS_INITED;
8117 }
8118 
8119 static int
8120 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8121 {
8122 	struct bwn_mac *up_dev = NULL;
8123 	struct bwn_mac *down_dev;
8124 	struct bwn_mac *mac;
8125 	int err, status;
8126 	uint8_t gmode;
8127 
8128 	BWN_ASSERT_LOCKED(sc);
8129 
8130 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8131 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8132 		    mac->mac_phy.supports_2ghz) {
8133 			up_dev = mac;
8134 			gmode = 1;
8135 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8136 		    mac->mac_phy.supports_5ghz) {
8137 			up_dev = mac;
8138 			gmode = 0;
8139 		} else {
8140 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8141 			return (EINVAL);
8142 		}
8143 		if (up_dev != NULL)
8144 			break;
8145 	}
8146 	if (up_dev == NULL) {
8147 		device_printf(sc->sc_dev, "Could not find a device\n");
8148 		return (ENODEV);
8149 	}
8150 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8151 		return (0);
8152 
8153 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8154 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8155 
8156 	down_dev = sc->sc_curmac;
8157 	status = down_dev->mac_status;
8158 	if (status >= BWN_MAC_STATUS_STARTED)
8159 		bwn_core_stop(down_dev);
8160 	if (status >= BWN_MAC_STATUS_INITED)
8161 		bwn_core_exit(down_dev);
8162 
8163 	if (down_dev != up_dev)
8164 		bwn_phy_reset(down_dev);
8165 
8166 	up_dev->mac_phy.gmode = gmode;
8167 	if (status >= BWN_MAC_STATUS_INITED) {
8168 		err = bwn_core_init(up_dev);
8169 		if (err) {
8170 			device_printf(sc->sc_dev,
8171 			    "fatal: failed to initialize for %s-GHz\n",
8172 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8173 			goto fail;
8174 		}
8175 	}
8176 	if (status >= BWN_MAC_STATUS_STARTED)
8177 		bwn_core_start(up_dev);
8178 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8179 	sc->sc_curmac = up_dev;
8180 
8181 	return (0);
8182 fail:
8183 	sc->sc_curmac = NULL;
8184 	return (err);
8185 }
8186 
8187 static void
8188 bwn_rf_turnon(struct bwn_mac *mac)
8189 {
8190 
8191 	bwn_mac_suspend(mac);
8192 	mac->mac_phy.rf_onoff(mac, 1);
8193 	mac->mac_phy.rf_on = 1;
8194 	bwn_mac_enable(mac);
8195 }
8196 
8197 static void
8198 bwn_rf_turnoff(struct bwn_mac *mac)
8199 {
8200 
8201 	bwn_mac_suspend(mac);
8202 	mac->mac_phy.rf_onoff(mac, 0);
8203 	mac->mac_phy.rf_on = 0;
8204 	bwn_mac_enable(mac);
8205 }
8206 
8207 static void
8208 bwn_phy_reset(struct bwn_mac *mac)
8209 {
8210 	struct bwn_softc *sc = mac->mac_sc;
8211 
8212 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8213 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8214 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8215 	DELAY(1000);
8216 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8217 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8218 	    BWN_TGSLOW_PHYRESET);
8219 	DELAY(1000);
8220 }
8221 
8222 static int
8223 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8224 {
8225 	struct bwn_vap *bvp = BWN_VAP(vap);
8226 	struct ieee80211com *ic= vap->iv_ic;
8227 	enum ieee80211_state ostate = vap->iv_state;
8228 	struct bwn_softc *sc = ic->ic_softc;
8229 	struct bwn_mac *mac = sc->sc_curmac;
8230 	int error;
8231 
8232 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8233 	    ieee80211_state_name[vap->iv_state],
8234 	    ieee80211_state_name[nstate]);
8235 
8236 	error = bvp->bv_newstate(vap, nstate, arg);
8237 	if (error != 0)
8238 		return (error);
8239 
8240 	BWN_LOCK(sc);
8241 
8242 	bwn_led_newstate(mac, nstate);
8243 
8244 	/*
8245 	 * Clear the BSSID when we stop a STA
8246 	 */
8247 	if (vap->iv_opmode == IEEE80211_M_STA) {
8248 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8249 			/*
8250 			 * Clear out the BSSID.  If we reassociate to
8251 			 * the same AP, this will reinialize things
8252 			 * correctly...
8253 			 */
8254 			if (ic->ic_opmode == IEEE80211_M_STA &&
8255 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8256 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8257 				bwn_set_macaddr(mac);
8258 			}
8259 		}
8260 	}
8261 
8262 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8263 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8264 		/* XXX nothing to do? */
8265 	} else if (nstate == IEEE80211_S_RUN) {
8266 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8267 		bwn_set_opmode(mac);
8268 		bwn_set_pretbtt(mac);
8269 		bwn_spu_setdelay(mac, 0);
8270 		bwn_set_macaddr(mac);
8271 	}
8272 
8273 	BWN_UNLOCK(sc);
8274 
8275 	return (error);
8276 }
8277 
8278 static void
8279 bwn_set_pretbtt(struct bwn_mac *mac)
8280 {
8281 	struct bwn_softc *sc = mac->mac_sc;
8282 	struct ieee80211com *ic = &sc->sc_ic;
8283 	uint16_t pretbtt;
8284 
8285 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8286 		pretbtt = 2;
8287 	else
8288 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8289 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8290 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8291 }
8292 
8293 static int
8294 bwn_intr(void *arg)
8295 {
8296 	struct bwn_mac *mac = arg;
8297 	struct bwn_softc *sc = mac->mac_sc;
8298 	uint32_t reason;
8299 
8300 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8301 	    (sc->sc_flags & BWN_FLAG_INVALID))
8302 		return (FILTER_STRAY);
8303 
8304 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8305 	if (reason == 0xffffffff)	/* shared IRQ */
8306 		return (FILTER_STRAY);
8307 	reason &= mac->mac_intr_mask;
8308 	if (reason == 0)
8309 		return (FILTER_HANDLED);
8310 
8311 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8312 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8313 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8314 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8315 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8316 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8317 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8318 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8319 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8320 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8321 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8322 
8323 	/* Disable interrupts. */
8324 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8325 
8326 	mac->mac_reason_intr = reason;
8327 
8328 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8329 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8330 
8331 	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
8332 	return (FILTER_HANDLED);
8333 }
8334 
8335 static void
8336 bwn_intrtask(void *arg, int npending)
8337 {
8338 	struct bwn_mac *mac = arg;
8339 	struct bwn_softc *sc = mac->mac_sc;
8340 	uint32_t merged = 0;
8341 	int i, tx = 0, rx = 0;
8342 
8343 	BWN_LOCK(sc);
8344 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8345 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8346 		BWN_UNLOCK(sc);
8347 		return;
8348 	}
8349 
8350 	for (i = 0; i < N(mac->mac_reason); i++)
8351 		merged |= mac->mac_reason[i];
8352 
8353 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8354 		device_printf(sc->sc_dev, "MAC trans error\n");
8355 
8356 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8357 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8358 		mac->mac_phy.txerrors--;
8359 		if (mac->mac_phy.txerrors == 0) {
8360 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8361 			bwn_restart(mac, "PHY TX errors");
8362 		}
8363 	}
8364 
8365 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8366 		if (merged & BWN_DMAINTR_FATALMASK) {
8367 			device_printf(sc->sc_dev,
8368 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8369 			    mac->mac_reason[0], mac->mac_reason[1],
8370 			    mac->mac_reason[2], mac->mac_reason[3],
8371 			    mac->mac_reason[4], mac->mac_reason[5]);
8372 			bwn_restart(mac, "DMA error");
8373 			BWN_UNLOCK(sc);
8374 			return;
8375 		}
8376 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8377 			device_printf(sc->sc_dev,
8378 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8379 			    mac->mac_reason[0], mac->mac_reason[1],
8380 			    mac->mac_reason[2], mac->mac_reason[3],
8381 			    mac->mac_reason[4], mac->mac_reason[5]);
8382 		}
8383 	}
8384 
8385 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8386 		bwn_intr_ucode_debug(mac);
8387 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8388 		bwn_intr_tbtt_indication(mac);
8389 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8390 		bwn_intr_atim_end(mac);
8391 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8392 		bwn_intr_beacon(mac);
8393 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8394 		bwn_intr_pmq(mac);
8395 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8396 		bwn_intr_noise(mac);
8397 
8398 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8399 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8400 			bwn_dma_rx(mac->mac_method.dma.rx);
8401 			rx = 1;
8402 		}
8403 	} else
8404 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8405 
8406 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8407 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8408 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8409 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8410 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8411 
8412 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8413 		bwn_intr_txeof(mac);
8414 		tx = 1;
8415 	}
8416 
8417 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8418 
8419 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8420 		int evt = BWN_LED_EVENT_NONE;
8421 
8422 		if (tx && rx) {
8423 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8424 				evt = BWN_LED_EVENT_RX;
8425 			else
8426 				evt = BWN_LED_EVENT_TX;
8427 		} else if (tx) {
8428 			evt = BWN_LED_EVENT_TX;
8429 		} else if (rx) {
8430 			evt = BWN_LED_EVENT_RX;
8431 		} else if (rx == 0) {
8432 			evt = BWN_LED_EVENT_POLL;
8433 		}
8434 
8435 		if (evt != BWN_LED_EVENT_NONE)
8436 			bwn_led_event(mac, evt);
8437        }
8438 
8439 	if (mbufq_first(&sc->sc_snd) != NULL)
8440 		bwn_start(sc);
8441 
8442 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8443 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8444 
8445 	BWN_UNLOCK(sc);
8446 }
8447 
8448 static void
8449 bwn_restart(struct bwn_mac *mac, const char *msg)
8450 {
8451 	struct bwn_softc *sc = mac->mac_sc;
8452 	struct ieee80211com *ic = &sc->sc_ic;
8453 
8454 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8455 		return;
8456 
8457 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8458 	ieee80211_runtask(ic, &mac->mac_hwreset);
8459 }
8460 
8461 static void
8462 bwn_intr_ucode_debug(struct bwn_mac *mac)
8463 {
8464 	struct bwn_softc *sc = mac->mac_sc;
8465 	uint16_t reason;
8466 
8467 	if (mac->mac_fw.opensource == 0)
8468 		return;
8469 
8470 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8471 	switch (reason) {
8472 	case BWN_DEBUGINTR_PANIC:
8473 		bwn_handle_fwpanic(mac);
8474 		break;
8475 	case BWN_DEBUGINTR_DUMP_SHM:
8476 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8477 		break;
8478 	case BWN_DEBUGINTR_DUMP_REGS:
8479 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8480 		break;
8481 	case BWN_DEBUGINTR_MARKER:
8482 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8483 		break;
8484 	default:
8485 		device_printf(sc->sc_dev,
8486 		    "ucode debug unknown reason: %#x\n", reason);
8487 	}
8488 
8489 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8490 	    BWN_DEBUGINTR_ACK);
8491 }
8492 
8493 static void
8494 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8495 {
8496 	struct bwn_softc *sc = mac->mac_sc;
8497 	struct ieee80211com *ic = &sc->sc_ic;
8498 
8499 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8500 		bwn_psctl(mac, 0);
8501 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8502 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8503 }
8504 
8505 static void
8506 bwn_intr_atim_end(struct bwn_mac *mac)
8507 {
8508 
8509 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8510 		BWN_WRITE_4(mac, BWN_MACCMD,
8511 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8512 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8513 	}
8514 }
8515 
8516 static void
8517 bwn_intr_beacon(struct bwn_mac *mac)
8518 {
8519 	struct bwn_softc *sc = mac->mac_sc;
8520 	struct ieee80211com *ic = &sc->sc_ic;
8521 	uint32_t cmd, beacon0, beacon1;
8522 
8523 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8524 	    ic->ic_opmode == IEEE80211_M_MBSS)
8525 		return;
8526 
8527 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8528 
8529 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8530 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8531 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8532 
8533 	if (beacon0 && beacon1) {
8534 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8535 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8536 		return;
8537 	}
8538 
8539 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8540 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8541 		bwn_load_beacon0(mac);
8542 		bwn_load_beacon1(mac);
8543 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8544 		cmd |= BWN_MACCMD_BEACON0_VALID;
8545 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8546 	} else {
8547 		if (!beacon0) {
8548 			bwn_load_beacon0(mac);
8549 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8550 			cmd |= BWN_MACCMD_BEACON0_VALID;
8551 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8552 		} else if (!beacon1) {
8553 			bwn_load_beacon1(mac);
8554 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8555 			cmd |= BWN_MACCMD_BEACON1_VALID;
8556 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8557 		}
8558 	}
8559 }
8560 
8561 static void
8562 bwn_intr_pmq(struct bwn_mac *mac)
8563 {
8564 	uint32_t tmp;
8565 
8566 	while (1) {
8567 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8568 		if (!(tmp & 0x00000008))
8569 			break;
8570 	}
8571 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8572 }
8573 
8574 static void
8575 bwn_intr_noise(struct bwn_mac *mac)
8576 {
8577 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8578 	uint16_t tmp;
8579 	uint8_t noise[4];
8580 	uint8_t i, j;
8581 	int32_t average;
8582 
8583 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8584 		return;
8585 
8586 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8587 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8588 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8589 	    noise[3] == 0x7f)
8590 		goto new;
8591 
8592 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8593 	    ("%s:%d: fail", __func__, __LINE__));
8594 	i = mac->mac_noise.noi_nsamples;
8595 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8596 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8597 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8598 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8599 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8600 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8601 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8602 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8603 	mac->mac_noise.noi_nsamples++;
8604 	if (mac->mac_noise.noi_nsamples == 8) {
8605 		average = 0;
8606 		for (i = 0; i < 8; i++) {
8607 			for (j = 0; j < 4; j++)
8608 				average += mac->mac_noise.noi_samples[i][j];
8609 		}
8610 		average = (((average / 32) * 125) + 64) / 128;
8611 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8612 		if (tmp >= 8)
8613 			average += 2;
8614 		else
8615 			average -= 25;
8616 		average -= (tmp == 8) ? 72 : 48;
8617 
8618 		mac->mac_stats.link_noise = average;
8619 		mac->mac_noise.noi_running = 0;
8620 		return;
8621 	}
8622 new:
8623 	bwn_noise_gensample(mac);
8624 }
8625 
8626 static int
8627 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8628 {
8629 	struct bwn_mac *mac = prq->prq_mac;
8630 	struct bwn_softc *sc = mac->mac_sc;
8631 	unsigned int i;
8632 
8633 	BWN_ASSERT_LOCKED(sc);
8634 
8635 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8636 		return (0);
8637 
8638 	for (i = 0; i < 5000; i++) {
8639 		if (bwn_pio_rxeof(prq) == 0)
8640 			break;
8641 	}
8642 	if (i >= 5000)
8643 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8644 	return ((i > 0) ? 1 : 0);
8645 }
8646 
8647 static void
8648 bwn_dma_rx(struct bwn_dma_ring *dr)
8649 {
8650 	int slot, curslot;
8651 
8652 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8653 	curslot = dr->get_curslot(dr);
8654 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8655 	    ("%s:%d: fail", __func__, __LINE__));
8656 
8657 	slot = dr->dr_curslot;
8658 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8659 		bwn_dma_rxeof(dr, &slot);
8660 
8661 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8662 	    BUS_DMASYNC_PREWRITE);
8663 
8664 	dr->set_curslot(dr, slot);
8665 	dr->dr_curslot = slot;
8666 }
8667 
8668 static void
8669 bwn_intr_txeof(struct bwn_mac *mac)
8670 {
8671 	struct bwn_txstatus stat;
8672 	uint32_t stat0, stat1;
8673 	uint16_t tmp;
8674 
8675 	BWN_ASSERT_LOCKED(mac->mac_sc);
8676 
8677 	while (1) {
8678 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8679 		if (!(stat0 & 0x00000001))
8680 			break;
8681 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8682 
8683 		stat.cookie = (stat0 >> 16);
8684 		stat.seq = (stat1 & 0x0000ffff);
8685 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8686 		tmp = (stat0 & 0x0000ffff);
8687 		stat.framecnt = ((tmp & 0xf000) >> 12);
8688 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8689 		stat.sreason = ((tmp & 0x001c) >> 2);
8690 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8691 		stat.im = (tmp & 0x0040) ? 1 : 0;
8692 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8693 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8694 
8695 		bwn_handle_txeof(mac, &stat);
8696 	}
8697 }
8698 
8699 static void
8700 bwn_hwreset(void *arg, int npending)
8701 {
8702 	struct bwn_mac *mac = arg;
8703 	struct bwn_softc *sc = mac->mac_sc;
8704 	int error = 0;
8705 	int prev_status;
8706 
8707 	BWN_LOCK(sc);
8708 
8709 	prev_status = mac->mac_status;
8710 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8711 		bwn_core_stop(mac);
8712 	if (prev_status >= BWN_MAC_STATUS_INITED)
8713 		bwn_core_exit(mac);
8714 
8715 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8716 		error = bwn_core_init(mac);
8717 		if (error)
8718 			goto out;
8719 	}
8720 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8721 		bwn_core_start(mac);
8722 out:
8723 	if (error) {
8724 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8725 		sc->sc_curmac = NULL;
8726 	}
8727 	BWN_UNLOCK(sc);
8728 }
8729 
8730 static void
8731 bwn_handle_fwpanic(struct bwn_mac *mac)
8732 {
8733 	struct bwn_softc *sc = mac->mac_sc;
8734 	uint16_t reason;
8735 
8736 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8737 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8738 
8739 	if (reason == BWN_FWPANIC_RESTART)
8740 		bwn_restart(mac, "ucode panic");
8741 }
8742 
8743 static void
8744 bwn_load_beacon0(struct bwn_mac *mac)
8745 {
8746 
8747 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8748 }
8749 
8750 static void
8751 bwn_load_beacon1(struct bwn_mac *mac)
8752 {
8753 
8754 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8755 }
8756 
8757 static uint32_t
8758 bwn_jssi_read(struct bwn_mac *mac)
8759 {
8760 	uint32_t val = 0;
8761 
8762 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8763 	val <<= 16;
8764 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8765 
8766 	return (val);
8767 }
8768 
8769 static void
8770 bwn_noise_gensample(struct bwn_mac *mac)
8771 {
8772 	uint32_t jssi = 0x7f7f7f7f;
8773 
8774 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8775 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8776 	BWN_WRITE_4(mac, BWN_MACCMD,
8777 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8778 }
8779 
8780 static int
8781 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8782 {
8783 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8784 
8785 	return (dr->dr_numslots - dr->dr_usedslot);
8786 }
8787 
8788 static int
8789 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8790 {
8791 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8792 
8793 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8794 	    ("%s:%d: fail", __func__, __LINE__));
8795 	if (slot == dr->dr_numslots - 1)
8796 		return (0);
8797 	return (slot + 1);
8798 }
8799 
8800 static void
8801 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8802 {
8803 	struct bwn_mac *mac = dr->dr_mac;
8804 	struct bwn_softc *sc = mac->mac_sc;
8805 	struct bwn_dma *dma = &mac->mac_method.dma;
8806 	struct bwn_dmadesc_generic *desc;
8807 	struct bwn_dmadesc_meta *meta;
8808 	struct bwn_rxhdr4 *rxhdr;
8809 	struct mbuf *m;
8810 	uint32_t macstat;
8811 	int32_t tmp;
8812 	int cnt = 0;
8813 	uint16_t len;
8814 
8815 	dr->getdesc(dr, *slot, &desc, &meta);
8816 
8817 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8818 	m = meta->mt_m;
8819 
8820 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8821 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8822 		return;
8823 	}
8824 
8825 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8826 	len = le16toh(rxhdr->frame_len);
8827 	if (len <= 0) {
8828 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8829 		return;
8830 	}
8831 	if (bwn_dma_check_redzone(dr, m)) {
8832 		device_printf(sc->sc_dev, "redzone error.\n");
8833 		bwn_dma_set_redzone(dr, m);
8834 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8835 		    BUS_DMASYNC_PREWRITE);
8836 		return;
8837 	}
8838 	if (len > dr->dr_rx_bufsize) {
8839 		tmp = len;
8840 		while (1) {
8841 			dr->getdesc(dr, *slot, &desc, &meta);
8842 			bwn_dma_set_redzone(dr, meta->mt_m);
8843 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8844 			    BUS_DMASYNC_PREWRITE);
8845 			*slot = bwn_dma_nextslot(dr, *slot);
8846 			cnt++;
8847 			tmp -= dr->dr_rx_bufsize;
8848 			if (tmp <= 0)
8849 				break;
8850 		}
8851 		device_printf(sc->sc_dev, "too small buffer "
8852 		       "(len %u buffer %u dropped %d)\n",
8853 		       len, dr->dr_rx_bufsize, cnt);
8854 		return;
8855 	}
8856 	macstat = le32toh(rxhdr->mac_status);
8857 	if (macstat & BWN_RX_MAC_FCSERR) {
8858 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8859 			device_printf(sc->sc_dev, "RX drop\n");
8860 			return;
8861 		}
8862 	}
8863 
8864 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8865 	m_adj(m, dr->dr_frameoffset);
8866 
8867 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8868 }
8869 
8870 static void
8871 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8872 {
8873 	struct bwn_dma_ring *dr;
8874 	struct bwn_dmadesc_generic *desc;
8875 	struct bwn_dmadesc_meta *meta;
8876 	struct bwn_pio_txqueue *tq;
8877 	struct bwn_pio_txpkt *tp = NULL;
8878 	struct bwn_softc *sc = mac->mac_sc;
8879 	struct bwn_stats *stats = &mac->mac_stats;
8880 	struct ieee80211_node *ni;
8881 	struct ieee80211vap *vap;
8882 	int retrycnt = 0, slot;
8883 
8884 	BWN_ASSERT_LOCKED(mac->mac_sc);
8885 
8886 	if (status->im)
8887 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8888 	if (status->ampdu)
8889 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8890 	if (status->rtscnt) {
8891 		if (status->rtscnt == 0xf)
8892 			stats->rtsfail++;
8893 		else
8894 			stats->rts++;
8895 	}
8896 
8897 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8898 		if (status->ack) {
8899 			dr = bwn_dma_parse_cookie(mac, status,
8900 			    status->cookie, &slot);
8901 			if (dr == NULL) {
8902 				device_printf(sc->sc_dev,
8903 				    "failed to parse cookie\n");
8904 				return;
8905 			}
8906 			while (1) {
8907 				dr->getdesc(dr, slot, &desc, &meta);
8908 				if (meta->mt_islast) {
8909 					ni = meta->mt_ni;
8910 					vap = ni->ni_vap;
8911 					ieee80211_ratectl_tx_complete(vap, ni,
8912 					    status->ack ?
8913 					      IEEE80211_RATECTL_TX_SUCCESS :
8914 					      IEEE80211_RATECTL_TX_FAILURE,
8915 					    &retrycnt, 0);
8916 					break;
8917 				}
8918 				slot = bwn_dma_nextslot(dr, slot);
8919 			}
8920 		}
8921 		bwn_dma_handle_txeof(mac, status);
8922 	} else {
8923 		if (status->ack) {
8924 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8925 			if (tq == NULL) {
8926 				device_printf(sc->sc_dev,
8927 				    "failed to parse cookie\n");
8928 				return;
8929 			}
8930 			ni = tp->tp_ni;
8931 			vap = ni->ni_vap;
8932 			ieee80211_ratectl_tx_complete(vap, ni,
8933 			    status->ack ?
8934 			      IEEE80211_RATECTL_TX_SUCCESS :
8935 			      IEEE80211_RATECTL_TX_FAILURE,
8936 			    &retrycnt, 0);
8937 		}
8938 		bwn_pio_handle_txeof(mac, status);
8939 	}
8940 
8941 	bwn_phy_txpower_check(mac, 0);
8942 }
8943 
8944 static uint8_t
8945 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8946 {
8947 	struct bwn_mac *mac = prq->prq_mac;
8948 	struct bwn_softc *sc = mac->mac_sc;
8949 	struct bwn_rxhdr4 rxhdr;
8950 	struct mbuf *m;
8951 	uint32_t ctl32, macstat, v32;
8952 	unsigned int i, padding;
8953 	uint16_t ctl16, len, totlen, v16;
8954 	unsigned char *mp;
8955 	char *data;
8956 
8957 	memset(&rxhdr, 0, sizeof(rxhdr));
8958 
8959 	if (prq->prq_rev >= 8) {
8960 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8961 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8962 			return (0);
8963 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8964 		    BWN_PIO8_RXCTL_FRAMEREADY);
8965 		for (i = 0; i < 10; i++) {
8966 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8967 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8968 				goto ready;
8969 			DELAY(10);
8970 		}
8971 	} else {
8972 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8973 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8974 			return (0);
8975 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8976 		    BWN_PIO_RXCTL_FRAMEREADY);
8977 		for (i = 0; i < 10; i++) {
8978 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8979 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
8980 				goto ready;
8981 			DELAY(10);
8982 		}
8983 	}
8984 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
8985 	return (1);
8986 ready:
8987 	if (prq->prq_rev >= 8)
8988 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8989 		    prq->prq_base + BWN_PIO8_RXDATA);
8990 	else
8991 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8992 		    prq->prq_base + BWN_PIO_RXDATA);
8993 	len = le16toh(rxhdr.frame_len);
8994 	if (len > 0x700) {
8995 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
8996 		goto error;
8997 	}
8998 	if (len == 0) {
8999 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9000 		goto error;
9001 	}
9002 
9003 	macstat = le32toh(rxhdr.mac_status);
9004 	if (macstat & BWN_RX_MAC_FCSERR) {
9005 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9006 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9007 			goto error;
9008 		}
9009 	}
9010 
9011 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9012 	totlen = len + padding;
9013 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9014 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9015 	if (m == NULL) {
9016 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9017 		goto error;
9018 	}
9019 	mp = mtod(m, unsigned char *);
9020 	if (prq->prq_rev >= 8) {
9021 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9022 		    prq->prq_base + BWN_PIO8_RXDATA);
9023 		if (totlen & 3) {
9024 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9025 			data = &(mp[totlen - 1]);
9026 			switch (totlen & 3) {
9027 			case 3:
9028 				*data = (v32 >> 16);
9029 				data--;
9030 			case 2:
9031 				*data = (v32 >> 8);
9032 				data--;
9033 			case 1:
9034 				*data = v32;
9035 			}
9036 		}
9037 	} else {
9038 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9039 		    prq->prq_base + BWN_PIO_RXDATA);
9040 		if (totlen & 1) {
9041 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9042 			mp[totlen - 1] = v16;
9043 		}
9044 	}
9045 
9046 	m->m_len = m->m_pkthdr.len = totlen;
9047 
9048 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9049 
9050 	return (1);
9051 error:
9052 	if (prq->prq_rev >= 8)
9053 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9054 		    BWN_PIO8_RXCTL_DATAREADY);
9055 	else
9056 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9057 	return (1);
9058 }
9059 
9060 static int
9061 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9062     struct bwn_dmadesc_meta *meta, int init)
9063 {
9064 	struct bwn_mac *mac = dr->dr_mac;
9065 	struct bwn_dma *dma = &mac->mac_method.dma;
9066 	struct bwn_rxhdr4 *hdr;
9067 	bus_dmamap_t map;
9068 	bus_addr_t paddr;
9069 	struct mbuf *m;
9070 	int error;
9071 
9072 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9073 	if (m == NULL) {
9074 		error = ENOBUFS;
9075 
9076 		/*
9077 		 * If the NIC is up and running, we need to:
9078 		 * - Clear RX buffer's header.
9079 		 * - Restore RX descriptor settings.
9080 		 */
9081 		if (init)
9082 			return (error);
9083 		else
9084 			goto back;
9085 	}
9086 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9087 
9088 	bwn_dma_set_redzone(dr, m);
9089 
9090 	/*
9091 	 * Try to load RX buf into temporary DMA map
9092 	 */
9093 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9094 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9095 	if (error) {
9096 		m_freem(m);
9097 
9098 		/*
9099 		 * See the comment above
9100 		 */
9101 		if (init)
9102 			return (error);
9103 		else
9104 			goto back;
9105 	}
9106 
9107 	if (!init)
9108 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9109 	meta->mt_m = m;
9110 	meta->mt_paddr = paddr;
9111 
9112 	/*
9113 	 * Swap RX buf's DMA map with the loaded temporary one
9114 	 */
9115 	map = meta->mt_dmap;
9116 	meta->mt_dmap = dr->dr_spare_dmap;
9117 	dr->dr_spare_dmap = map;
9118 
9119 back:
9120 	/*
9121 	 * Clear RX buf header
9122 	 */
9123 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9124 	bzero(hdr, sizeof(*hdr));
9125 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9126 	    BUS_DMASYNC_PREWRITE);
9127 
9128 	/*
9129 	 * Setup RX buf descriptor
9130 	 */
9131 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9132 	    sizeof(*hdr), 0, 0, 0);
9133 	return (error);
9134 }
9135 
9136 static void
9137 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9138 		 bus_size_t mapsz __unused, int error)
9139 {
9140 
9141 	if (!error) {
9142 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9143 		*((bus_addr_t *)arg) = seg->ds_addr;
9144 	}
9145 }
9146 
9147 static int
9148 bwn_hwrate2ieeerate(int rate)
9149 {
9150 
9151 	switch (rate) {
9152 	case BWN_CCK_RATE_1MB:
9153 		return (2);
9154 	case BWN_CCK_RATE_2MB:
9155 		return (4);
9156 	case BWN_CCK_RATE_5MB:
9157 		return (11);
9158 	case BWN_CCK_RATE_11MB:
9159 		return (22);
9160 	case BWN_OFDM_RATE_6MB:
9161 		return (12);
9162 	case BWN_OFDM_RATE_9MB:
9163 		return (18);
9164 	case BWN_OFDM_RATE_12MB:
9165 		return (24);
9166 	case BWN_OFDM_RATE_18MB:
9167 		return (36);
9168 	case BWN_OFDM_RATE_24MB:
9169 		return (48);
9170 	case BWN_OFDM_RATE_36MB:
9171 		return (72);
9172 	case BWN_OFDM_RATE_48MB:
9173 		return (96);
9174 	case BWN_OFDM_RATE_54MB:
9175 		return (108);
9176 	default:
9177 		printf("Ooops\n");
9178 		return (0);
9179 	}
9180 }
9181 
9182 static void
9183 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9184 {
9185 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9186 	struct bwn_plcp6 *plcp;
9187 	struct bwn_softc *sc = mac->mac_sc;
9188 	struct ieee80211_frame_min *wh;
9189 	struct ieee80211_node *ni;
9190 	struct ieee80211com *ic = &sc->sc_ic;
9191 	uint32_t macstat;
9192 	int padding, rate, rssi = 0, noise = 0, type;
9193 	uint16_t phytype, phystat0, phystat3, chanstat;
9194 	unsigned char *mp = mtod(m, unsigned char *);
9195 	static int rx_mac_dec_rpt = 0;
9196 
9197 	BWN_ASSERT_LOCKED(sc);
9198 
9199 	phystat0 = le16toh(rxhdr->phy_status0);
9200 	phystat3 = le16toh(rxhdr->phy_status3);
9201 	macstat = le32toh(rxhdr->mac_status);
9202 	chanstat = le16toh(rxhdr->channel);
9203 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9204 
9205 	if (macstat & BWN_RX_MAC_FCSERR)
9206 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9207 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9208 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9209 	if (macstat & BWN_RX_MAC_DECERR)
9210 		goto drop;
9211 
9212 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9213 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9214 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9215 		    m->m_pkthdr.len);
9216 		goto drop;
9217 	}
9218 	plcp = (struct bwn_plcp6 *)(mp + padding);
9219 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9220 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9221 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9222 		    m->m_pkthdr.len);
9223 		goto drop;
9224 	}
9225 	wh = mtod(m, struct ieee80211_frame_min *);
9226 
9227 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9228 		device_printf(sc->sc_dev,
9229 		    "RX decryption attempted (old %d keyidx %#x)\n",
9230 		    BWN_ISOLDFMT(mac),
9231 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9232 
9233 	/* XXX calculating RSSI & noise & antenna */
9234 
9235 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9236 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9237 		    phytype == BWN_PHYTYPE_A);
9238 	else
9239 		rate = bwn_plcp_get_cckrate(mac, plcp);
9240 	if (rate == -1) {
9241 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9242 			goto drop;
9243 	}
9244 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9245 
9246 	/* RX radio tap */
9247 	if (ieee80211_radiotap_active(ic))
9248 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9249 	m_adj(m, -IEEE80211_CRC_LEN);
9250 
9251 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9252 	noise = mac->mac_stats.link_noise;
9253 
9254 	BWN_UNLOCK(sc);
9255 
9256 	ni = ieee80211_find_rxnode(ic, wh);
9257 	if (ni != NULL) {
9258 		type = ieee80211_input(ni, m, rssi, noise);
9259 		ieee80211_free_node(ni);
9260 	} else
9261 		type = ieee80211_input_all(ic, m, rssi, noise);
9262 
9263 	BWN_LOCK(sc);
9264 	return;
9265 drop:
9266 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9267 }
9268 
9269 static void
9270 bwn_dma_handle_txeof(struct bwn_mac *mac,
9271     const struct bwn_txstatus *status)
9272 {
9273 	struct bwn_dma *dma = &mac->mac_method.dma;
9274 	struct bwn_dma_ring *dr;
9275 	struct bwn_dmadesc_generic *desc;
9276 	struct bwn_dmadesc_meta *meta;
9277 	struct bwn_softc *sc = mac->mac_sc;
9278 	int slot;
9279 
9280 	BWN_ASSERT_LOCKED(sc);
9281 
9282 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9283 	if (dr == NULL) {
9284 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9285 		return;
9286 	}
9287 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9288 
9289 	while (1) {
9290 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9291 		    ("%s:%d: fail", __func__, __LINE__));
9292 		dr->getdesc(dr, slot, &desc, &meta);
9293 
9294 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9295 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9296 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9297 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9298 
9299 		if (meta->mt_islast) {
9300 			KASSERT(meta->mt_m != NULL,
9301 			    ("%s:%d: fail", __func__, __LINE__));
9302 
9303 			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
9304 			meta->mt_ni = NULL;
9305 			meta->mt_m = NULL;
9306 		} else
9307 			KASSERT(meta->mt_m == NULL,
9308 			    ("%s:%d: fail", __func__, __LINE__));
9309 
9310 		dr->dr_usedslot--;
9311 		if (meta->mt_islast)
9312 			break;
9313 		slot = bwn_dma_nextslot(dr, slot);
9314 	}
9315 	sc->sc_watchdog_timer = 0;
9316 	if (dr->dr_stop) {
9317 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9318 		    ("%s:%d: fail", __func__, __LINE__));
9319 		dr->dr_stop = 0;
9320 	}
9321 }
9322 
9323 static void
9324 bwn_pio_handle_txeof(struct bwn_mac *mac,
9325     const struct bwn_txstatus *status)
9326 {
9327 	struct bwn_pio_txqueue *tq;
9328 	struct bwn_pio_txpkt *tp = NULL;
9329 	struct bwn_softc *sc = mac->mac_sc;
9330 
9331 	BWN_ASSERT_LOCKED(sc);
9332 
9333 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9334 	if (tq == NULL)
9335 		return;
9336 
9337 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9338 	tq->tq_free++;
9339 
9340 	if (tp->tp_ni != NULL) {
9341 		/*
9342 		 * Do any tx complete callback.  Note this must
9343 		 * be done before releasing the node reference.
9344 		 */
9345 		if (tp->tp_m->m_flags & M_TXCB)
9346 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9347 		ieee80211_free_node(tp->tp_ni);
9348 		tp->tp_ni = NULL;
9349 	}
9350 	m_freem(tp->tp_m);
9351 	tp->tp_m = NULL;
9352 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9353 
9354 	sc->sc_watchdog_timer = 0;
9355 }
9356 
9357 static void
9358 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9359 {
9360 	struct bwn_softc *sc = mac->mac_sc;
9361 	struct bwn_phy *phy = &mac->mac_phy;
9362 	struct ieee80211com *ic = &sc->sc_ic;
9363 	unsigned long now;
9364 	int result;
9365 
9366 	BWN_GETTIME(now);
9367 
9368 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9369 		return;
9370 	phy->nexttime = now + 2 * 1000;
9371 
9372 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9373 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9374 		return;
9375 
9376 	if (phy->recalc_txpwr != NULL) {
9377 		result = phy->recalc_txpwr(mac,
9378 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9379 		if (result == BWN_TXPWR_RES_DONE)
9380 			return;
9381 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9382 		    ("%s: fail", __func__));
9383 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9384 
9385 		ieee80211_runtask(ic, &mac->mac_txpower);
9386 	}
9387 }
9388 
9389 static uint16_t
9390 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9391 {
9392 
9393 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9394 }
9395 
9396 static uint32_t
9397 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9398 {
9399 
9400 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9401 }
9402 
9403 static void
9404 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9405 {
9406 
9407 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9408 }
9409 
9410 static void
9411 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9412 {
9413 
9414 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9415 }
9416 
9417 static int
9418 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9419 {
9420 
9421 	switch (rate) {
9422 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9423 	case 12:
9424 		return (BWN_OFDM_RATE_6MB);
9425 	case 18:
9426 		return (BWN_OFDM_RATE_9MB);
9427 	case 24:
9428 		return (BWN_OFDM_RATE_12MB);
9429 	case 36:
9430 		return (BWN_OFDM_RATE_18MB);
9431 	case 48:
9432 		return (BWN_OFDM_RATE_24MB);
9433 	case 72:
9434 		return (BWN_OFDM_RATE_36MB);
9435 	case 96:
9436 		return (BWN_OFDM_RATE_48MB);
9437 	case 108:
9438 		return (BWN_OFDM_RATE_54MB);
9439 	/* CCK rates (NB: not IEEE std, device-specific) */
9440 	case 2:
9441 		return (BWN_CCK_RATE_1MB);
9442 	case 4:
9443 		return (BWN_CCK_RATE_2MB);
9444 	case 11:
9445 		return (BWN_CCK_RATE_5MB);
9446 	case 22:
9447 		return (BWN_CCK_RATE_11MB);
9448 	}
9449 
9450 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9451 	return (BWN_CCK_RATE_1MB);
9452 }
9453 
9454 static int
9455 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9456     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9457 {
9458 	const struct bwn_phy *phy = &mac->mac_phy;
9459 	struct bwn_softc *sc = mac->mac_sc;
9460 	struct ieee80211_frame *wh;
9461 	struct ieee80211_frame *protwh;
9462 	struct ieee80211_frame_cts *cts;
9463 	struct ieee80211_frame_rts *rts;
9464 	const struct ieee80211_txparam *tp;
9465 	struct ieee80211vap *vap = ni->ni_vap;
9466 	struct ieee80211com *ic = &sc->sc_ic;
9467 	struct mbuf *mprot;
9468 	unsigned int len;
9469 	uint32_t macctl = 0;
9470 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9471 	uint16_t phyctl = 0;
9472 	uint8_t rate, rate_fb;
9473 
9474 	wh = mtod(m, struct ieee80211_frame *);
9475 	memset(txhdr, 0, sizeof(*txhdr));
9476 
9477 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9478 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9479 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9480 
9481 	/*
9482 	 * Find TX rate
9483 	 */
9484 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9485 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9486 		rate = rate_fb = tp->mgmtrate;
9487 	else if (ismcast)
9488 		rate = rate_fb = tp->mcastrate;
9489 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9490 		rate = rate_fb = tp->ucastrate;
9491 	else {
9492 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9493 		rate = ni->ni_txrate;
9494 
9495 		if (rix > 0)
9496 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9497 			    IEEE80211_RATE_VAL;
9498 		else
9499 			rate_fb = rate;
9500 	}
9501 
9502 	sc->sc_tx_rate = rate;
9503 
9504 	rate = bwn_ieeerate2hwrate(sc, rate);
9505 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9506 
9507 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9508 	    bwn_plcp_getcck(rate);
9509 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9510 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9511 
9512 	if ((rate_fb == rate) ||
9513 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9514 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9515 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9516 	else
9517 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9518 		    m->m_pkthdr.len, rate, isshort);
9519 
9520 	/* XXX TX encryption */
9521 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9522 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9523 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9524 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9525 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9526 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9527 
9528 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9529 	    BWN_TX_EFT_FB_CCK;
9530 	txhdr->chan = phy->chan;
9531 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9532 	    BWN_TX_PHY_ENC_CCK;
9533 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9534 	     rate == BWN_CCK_RATE_11MB))
9535 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9536 
9537 	/* XXX TX antenna selection */
9538 
9539 	switch (bwn_antenna_sanitize(mac, 0)) {
9540 	case 0:
9541 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9542 		break;
9543 	case 1:
9544 		phyctl |= BWN_TX_PHY_ANT0;
9545 		break;
9546 	case 2:
9547 		phyctl |= BWN_TX_PHY_ANT1;
9548 		break;
9549 	case 3:
9550 		phyctl |= BWN_TX_PHY_ANT2;
9551 		break;
9552 	case 4:
9553 		phyctl |= BWN_TX_PHY_ANT3;
9554 		break;
9555 	default:
9556 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9557 	}
9558 
9559 	if (!ismcast)
9560 		macctl |= BWN_TX_MAC_ACK;
9561 
9562 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9563 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9564 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9565 		macctl |= BWN_TX_MAC_LONGFRAME;
9566 
9567 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9568 		/* XXX RTS rate is always 1MB??? */
9569 		rts_rate = BWN_CCK_RATE_1MB;
9570 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9571 
9572 		protdur = ieee80211_compute_duration(ic->ic_rt,
9573 		    m->m_pkthdr.len, rate, isshort) +
9574 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9575 
9576 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9577 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9578 			    (txhdr->body.old.rts_frame) :
9579 			    (txhdr->body.new.rts_frame));
9580 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9581 			    protdur);
9582 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9583 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9584 			    mprot->m_pkthdr.len);
9585 			m_freem(mprot);
9586 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9587 			len = sizeof(struct ieee80211_frame_cts);
9588 		} else {
9589 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9590 			    (txhdr->body.old.rts_frame) :
9591 			    (txhdr->body.new.rts_frame));
9592 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9593 			    isshort);
9594 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9595 			    wh->i_addr2, protdur);
9596 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9597 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9598 			    mprot->m_pkthdr.len);
9599 			m_freem(mprot);
9600 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9601 			len = sizeof(struct ieee80211_frame_rts);
9602 		}
9603 		len += IEEE80211_CRC_LEN;
9604 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9605 		    &txhdr->body.old.rts_plcp :
9606 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9607 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9608 		    rts_rate_fb);
9609 
9610 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9611 		    (&txhdr->body.old.rts_frame) :
9612 		    (&txhdr->body.new.rts_frame));
9613 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9614 
9615 		if (BWN_ISOFDMRATE(rts_rate)) {
9616 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9617 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9618 		} else {
9619 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9620 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9621 		}
9622 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9623 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9624 	}
9625 
9626 	if (BWN_ISOLDFMT(mac))
9627 		txhdr->body.old.cookie = htole16(cookie);
9628 	else
9629 		txhdr->body.new.cookie = htole16(cookie);
9630 
9631 	txhdr->macctl = htole32(macctl);
9632 	txhdr->phyctl = htole16(phyctl);
9633 
9634 	/*
9635 	 * TX radio tap
9636 	 */
9637 	if (ieee80211_radiotap_active_vap(vap)) {
9638 		sc->sc_tx_th.wt_flags = 0;
9639 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9640 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9641 		if (isshort &&
9642 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9643 		     rate == BWN_CCK_RATE_11MB))
9644 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9645 		sc->sc_tx_th.wt_rate = rate;
9646 
9647 		ieee80211_radiotap_tx(vap, m);
9648 	}
9649 
9650 	return (0);
9651 }
9652 
9653 static void
9654 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9655     const uint8_t rate)
9656 {
9657 	uint32_t d, plen;
9658 	uint8_t *raw = plcp->o.raw;
9659 
9660 	if (BWN_ISOFDMRATE(rate)) {
9661 		d = bwn_plcp_getofdm(rate);
9662 		KASSERT(!(octets & 0xf000),
9663 		    ("%s:%d: fail", __func__, __LINE__));
9664 		d |= (octets << 5);
9665 		plcp->o.data = htole32(d);
9666 	} else {
9667 		plen = octets * 16 / rate;
9668 		if ((octets * 16 % rate) > 0) {
9669 			plen++;
9670 			if ((rate == BWN_CCK_RATE_11MB)
9671 			    && ((octets * 8 % 11) < 4)) {
9672 				raw[1] = 0x84;
9673 			} else
9674 				raw[1] = 0x04;
9675 		} else
9676 			raw[1] = 0x04;
9677 		plcp->o.data |= htole32(plen << 16);
9678 		raw[0] = bwn_plcp_getcck(rate);
9679 	}
9680 }
9681 
9682 static uint8_t
9683 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9684 {
9685 	struct bwn_softc *sc = mac->mac_sc;
9686 	uint8_t mask;
9687 
9688 	if (n == 0)
9689 		return (0);
9690 	if (mac->mac_phy.gmode)
9691 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9692 	else
9693 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9694 	if (!(mask & (1 << (n - 1))))
9695 		return (0);
9696 	return (n);
9697 }
9698 
9699 static uint8_t
9700 bwn_get_fbrate(uint8_t bitrate)
9701 {
9702 	switch (bitrate) {
9703 	case BWN_CCK_RATE_1MB:
9704 		return (BWN_CCK_RATE_1MB);
9705 	case BWN_CCK_RATE_2MB:
9706 		return (BWN_CCK_RATE_1MB);
9707 	case BWN_CCK_RATE_5MB:
9708 		return (BWN_CCK_RATE_2MB);
9709 	case BWN_CCK_RATE_11MB:
9710 		return (BWN_CCK_RATE_5MB);
9711 	case BWN_OFDM_RATE_6MB:
9712 		return (BWN_CCK_RATE_5MB);
9713 	case BWN_OFDM_RATE_9MB:
9714 		return (BWN_OFDM_RATE_6MB);
9715 	case BWN_OFDM_RATE_12MB:
9716 		return (BWN_OFDM_RATE_9MB);
9717 	case BWN_OFDM_RATE_18MB:
9718 		return (BWN_OFDM_RATE_12MB);
9719 	case BWN_OFDM_RATE_24MB:
9720 		return (BWN_OFDM_RATE_18MB);
9721 	case BWN_OFDM_RATE_36MB:
9722 		return (BWN_OFDM_RATE_24MB);
9723 	case BWN_OFDM_RATE_48MB:
9724 		return (BWN_OFDM_RATE_36MB);
9725 	case BWN_OFDM_RATE_54MB:
9726 		return (BWN_OFDM_RATE_48MB);
9727 	}
9728 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9729 	return (0);
9730 }
9731 
9732 static uint32_t
9733 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9734     uint32_t ctl, const void *_data, int len)
9735 {
9736 	struct bwn_softc *sc = mac->mac_sc;
9737 	uint32_t value = 0;
9738 	const uint8_t *data = _data;
9739 
9740 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9741 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9742 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9743 
9744 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9745 	    tq->tq_base + BWN_PIO8_TXDATA);
9746 	if (len & 3) {
9747 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9748 		    BWN_PIO8_TXCTL_24_31);
9749 		data = &(data[len - 1]);
9750 		switch (len & 3) {
9751 		case 3:
9752 			ctl |= BWN_PIO8_TXCTL_16_23;
9753 			value |= (uint32_t)(*data) << 16;
9754 			data--;
9755 		case 2:
9756 			ctl |= BWN_PIO8_TXCTL_8_15;
9757 			value |= (uint32_t)(*data) << 8;
9758 			data--;
9759 		case 1:
9760 			value |= (uint32_t)(*data);
9761 		}
9762 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9763 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9764 	}
9765 
9766 	return (ctl);
9767 }
9768 
9769 static void
9770 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9771     uint16_t offset, uint32_t value)
9772 {
9773 
9774 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9775 }
9776 
9777 static uint16_t
9778 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9779     uint16_t ctl, const void *_data, int len)
9780 {
9781 	struct bwn_softc *sc = mac->mac_sc;
9782 	const uint8_t *data = _data;
9783 
9784 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9785 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9786 
9787 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9788 	    tq->tq_base + BWN_PIO_TXDATA);
9789 	if (len & 1) {
9790 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9791 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9792 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9793 	}
9794 
9795 	return (ctl);
9796 }
9797 
9798 static uint16_t
9799 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9800     uint16_t ctl, struct mbuf *m0)
9801 {
9802 	int i, j = 0;
9803 	uint16_t data = 0;
9804 	const uint8_t *buf;
9805 	struct mbuf *m = m0;
9806 
9807 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9808 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9809 
9810 	for (; m != NULL; m = m->m_next) {
9811 		buf = mtod(m, const uint8_t *);
9812 		for (i = 0; i < m->m_len; i++) {
9813 			if (!((j++) % 2))
9814 				data |= buf[i];
9815 			else {
9816 				data |= (buf[i] << 8);
9817 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9818 				data = 0;
9819 			}
9820 		}
9821 	}
9822 	if (m0->m_pkthdr.len % 2) {
9823 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9824 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9825 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9826 	}
9827 
9828 	return (ctl);
9829 }
9830 
9831 static void
9832 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9833 {
9834 
9835 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9836 		return;
9837 	BWN_WRITE_2(mac, 0x684, 510 + time);
9838 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9839 }
9840 
9841 static struct bwn_dma_ring *
9842 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9843 {
9844 
9845 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9846 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9847 
9848 	switch (prio) {
9849 	case 3:
9850 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9851 	case 2:
9852 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9853 	case 0:
9854 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9855 	case 1:
9856 		return (mac->mac_method.dma.wme[WME_AC_BK]);
9857 	}
9858 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9859 	return (NULL);
9860 }
9861 
9862 static int
9863 bwn_dma_getslot(struct bwn_dma_ring *dr)
9864 {
9865 	int slot;
9866 
9867 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
9868 
9869 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9870 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9871 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9872 
9873 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9874 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9875 	dr->dr_curslot = slot;
9876 	dr->dr_usedslot++;
9877 
9878 	return (slot);
9879 }
9880 
9881 static int
9882 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9883 {
9884 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9885 	unsigned int a, b, c, d;
9886 	unsigned int avg;
9887 	uint32_t tmp;
9888 
9889 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9890 	a = tmp & 0xff;
9891 	b = (tmp >> 8) & 0xff;
9892 	c = (tmp >> 16) & 0xff;
9893 	d = (tmp >> 24) & 0xff;
9894 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9895 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9896 		return (ENOENT);
9897 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9898 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9899 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9900 
9901 	if (ofdm) {
9902 		a = (a + 32) & 0x3f;
9903 		b = (b + 32) & 0x3f;
9904 		c = (c + 32) & 0x3f;
9905 		d = (d + 32) & 0x3f;
9906 	}
9907 
9908 	avg = (a + b + c + d + 2) / 4;
9909 	if (ofdm) {
9910 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9911 		    & BWN_HF_4DB_CCK_POWERBOOST)
9912 			avg = (avg >= 13) ? (avg - 13) : 0;
9913 	}
9914 	return (avg);
9915 }
9916 
9917 static void
9918 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9919 {
9920 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9921 	int rfatt = *rfattp;
9922 	int bbatt = *bbattp;
9923 
9924 	while (1) {
9925 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9926 			break;
9927 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9928 			break;
9929 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9930 			break;
9931 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9932 			break;
9933 		if (bbatt > lo->bbatt.max) {
9934 			bbatt -= 4;
9935 			rfatt += 1;
9936 			continue;
9937 		}
9938 		if (bbatt < lo->bbatt.min) {
9939 			bbatt += 4;
9940 			rfatt -= 1;
9941 			continue;
9942 		}
9943 		if (rfatt > lo->rfatt.max) {
9944 			rfatt -= 1;
9945 			bbatt += 4;
9946 			continue;
9947 		}
9948 		if (rfatt < lo->rfatt.min) {
9949 			rfatt += 1;
9950 			bbatt -= 4;
9951 			continue;
9952 		}
9953 		break;
9954 	}
9955 
9956 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
9957 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
9958 }
9959 
9960 static void
9961 bwn_phy_lock(struct bwn_mac *mac)
9962 {
9963 	struct bwn_softc *sc = mac->mac_sc;
9964 	struct ieee80211com *ic = &sc->sc_ic;
9965 
9966 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9967 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9968 
9969 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9970 		bwn_psctl(mac, BWN_PS_AWAKE);
9971 }
9972 
9973 static void
9974 bwn_phy_unlock(struct bwn_mac *mac)
9975 {
9976 	struct bwn_softc *sc = mac->mac_sc;
9977 	struct ieee80211com *ic = &sc->sc_ic;
9978 
9979 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9980 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9981 
9982 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9983 		bwn_psctl(mac, 0);
9984 }
9985 
9986 static void
9987 bwn_rf_lock(struct bwn_mac *mac)
9988 {
9989 
9990 	BWN_WRITE_4(mac, BWN_MACCTL,
9991 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
9992 	BWN_READ_4(mac, BWN_MACCTL);
9993 	DELAY(10);
9994 }
9995 
9996 static void
9997 bwn_rf_unlock(struct bwn_mac *mac)
9998 {
9999 
10000 	BWN_READ_2(mac, BWN_PHYVER);
10001 	BWN_WRITE_4(mac, BWN_MACCTL,
10002 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10003 }
10004 
10005 static struct bwn_pio_txqueue *
10006 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10007     struct bwn_pio_txpkt **pack)
10008 {
10009 	struct bwn_pio *pio = &mac->mac_method.pio;
10010 	struct bwn_pio_txqueue *tq = NULL;
10011 	unsigned int index;
10012 
10013 	switch (cookie & 0xf000) {
10014 	case 0x1000:
10015 		tq = &pio->wme[WME_AC_BK];
10016 		break;
10017 	case 0x2000:
10018 		tq = &pio->wme[WME_AC_BE];
10019 		break;
10020 	case 0x3000:
10021 		tq = &pio->wme[WME_AC_VI];
10022 		break;
10023 	case 0x4000:
10024 		tq = &pio->wme[WME_AC_VO];
10025 		break;
10026 	case 0x5000:
10027 		tq = &pio->mcast;
10028 		break;
10029 	}
10030 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10031 	if (tq == NULL)
10032 		return (NULL);
10033 	index = (cookie & 0x0fff);
10034 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10035 	if (index >= N(tq->tq_pkts))
10036 		return (NULL);
10037 	*pack = &tq->tq_pkts[index];
10038 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10039 	return (tq);
10040 }
10041 
10042 static void
10043 bwn_txpwr(void *arg, int npending)
10044 {
10045 	struct bwn_mac *mac = arg;
10046 	struct bwn_softc *sc = mac->mac_sc;
10047 
10048 	BWN_LOCK(sc);
10049 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10050 	    mac->mac_phy.set_txpwr != NULL)
10051 		mac->mac_phy.set_txpwr(mac);
10052 	BWN_UNLOCK(sc);
10053 }
10054 
10055 static void
10056 bwn_task_15s(struct bwn_mac *mac)
10057 {
10058 	uint16_t reg;
10059 
10060 	if (mac->mac_fw.opensource) {
10061 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10062 		if (reg) {
10063 			bwn_restart(mac, "fw watchdog");
10064 			return;
10065 		}
10066 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10067 	}
10068 	if (mac->mac_phy.task_15s)
10069 		mac->mac_phy.task_15s(mac);
10070 
10071 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10072 }
10073 
10074 static void
10075 bwn_task_30s(struct bwn_mac *mac)
10076 {
10077 
10078 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10079 		return;
10080 	mac->mac_noise.noi_running = 1;
10081 	mac->mac_noise.noi_nsamples = 0;
10082 
10083 	bwn_noise_gensample(mac);
10084 }
10085 
10086 static void
10087 bwn_task_60s(struct bwn_mac *mac)
10088 {
10089 
10090 	if (mac->mac_phy.task_60s)
10091 		mac->mac_phy.task_60s(mac);
10092 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10093 }
10094 
10095 static void
10096 bwn_tasks(void *arg)
10097 {
10098 	struct bwn_mac *mac = arg;
10099 	struct bwn_softc *sc = mac->mac_sc;
10100 
10101 	BWN_ASSERT_LOCKED(sc);
10102 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10103 		return;
10104 
10105 	if (mac->mac_task_state % 4 == 0)
10106 		bwn_task_60s(mac);
10107 	if (mac->mac_task_state % 2 == 0)
10108 		bwn_task_30s(mac);
10109 	bwn_task_15s(mac);
10110 
10111 	mac->mac_task_state++;
10112 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10113 }
10114 
10115 static int
10116 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10117 {
10118 	struct bwn_softc *sc = mac->mac_sc;
10119 
10120 	KASSERT(a == 0, ("not support APHY\n"));
10121 
10122 	switch (plcp->o.raw[0] & 0xf) {
10123 	case 0xb:
10124 		return (BWN_OFDM_RATE_6MB);
10125 	case 0xf:
10126 		return (BWN_OFDM_RATE_9MB);
10127 	case 0xa:
10128 		return (BWN_OFDM_RATE_12MB);
10129 	case 0xe:
10130 		return (BWN_OFDM_RATE_18MB);
10131 	case 0x9:
10132 		return (BWN_OFDM_RATE_24MB);
10133 	case 0xd:
10134 		return (BWN_OFDM_RATE_36MB);
10135 	case 0x8:
10136 		return (BWN_OFDM_RATE_48MB);
10137 	case 0xc:
10138 		return (BWN_OFDM_RATE_54MB);
10139 	}
10140 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10141 	    plcp->o.raw[0] & 0xf);
10142 	return (-1);
10143 }
10144 
10145 static int
10146 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10147 {
10148 	struct bwn_softc *sc = mac->mac_sc;
10149 
10150 	switch (plcp->o.raw[0]) {
10151 	case 0x0a:
10152 		return (BWN_CCK_RATE_1MB);
10153 	case 0x14:
10154 		return (BWN_CCK_RATE_2MB);
10155 	case 0x37:
10156 		return (BWN_CCK_RATE_5MB);
10157 	case 0x6e:
10158 		return (BWN_CCK_RATE_11MB);
10159 	}
10160 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10161 	return (-1);
10162 }
10163 
10164 static void
10165 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10166     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10167     int rssi, int noise)
10168 {
10169 	struct bwn_softc *sc = mac->mac_sc;
10170 	const struct ieee80211_frame_min *wh;
10171 	uint64_t tsf;
10172 	uint16_t low_mactime_now;
10173 
10174 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10175 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10176 
10177 	wh = mtod(m, const struct ieee80211_frame_min *);
10178 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10179 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10180 
10181 	bwn_tsf_read(mac, &tsf);
10182 	low_mactime_now = tsf;
10183 	tsf = tsf & ~0xffffULL;
10184 	tsf += le16toh(rxhdr->mac_time);
10185 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10186 		tsf -= 0x10000;
10187 
10188 	sc->sc_rx_th.wr_tsf = tsf;
10189 	sc->sc_rx_th.wr_rate = rate;
10190 	sc->sc_rx_th.wr_antsignal = rssi;
10191 	sc->sc_rx_th.wr_antnoise = noise;
10192 }
10193 
10194 static void
10195 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10196 {
10197 	uint32_t low, high;
10198 
10199 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10200 	    ("%s:%d: fail", __func__, __LINE__));
10201 
10202 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10203 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10204 	*tsf = high;
10205 	*tsf <<= 32;
10206 	*tsf |= low;
10207 }
10208 
10209 static int
10210 bwn_dma_attach(struct bwn_mac *mac)
10211 {
10212 	struct bwn_dma *dma = &mac->mac_method.dma;
10213 	struct bwn_softc *sc = mac->mac_sc;
10214 	bus_addr_t lowaddr = 0;
10215 	int error;
10216 
10217 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10218 		return (0);
10219 
10220 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10221 
10222 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10223 
10224 	dma->dmatype = bwn_dma_gettype(mac);
10225 	if (dma->dmatype == BWN_DMA_30BIT)
10226 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10227 	else if (dma->dmatype == BWN_DMA_32BIT)
10228 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10229 	else
10230 		lowaddr = BUS_SPACE_MAXADDR;
10231 
10232 	/*
10233 	 * Create top level DMA tag
10234 	 */
10235 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10236 			       BWN_ALIGN, 0,		/* alignment, bounds */
10237 			       lowaddr,			/* lowaddr */
10238 			       BUS_SPACE_MAXADDR,	/* highaddr */
10239 			       NULL, NULL,		/* filter, filterarg */
10240 			       BUS_SPACE_MAXSIZE,	/* maxsize */
10241 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10242 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10243 			       0,			/* flags */
10244 			       NULL, NULL,		/* lockfunc, lockarg */
10245 			       &dma->parent_dtag);
10246 	if (error) {
10247 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10248 		return (error);
10249 	}
10250 
10251 	/*
10252 	 * Create TX/RX mbuf DMA tag
10253 	 */
10254 	error = bus_dma_tag_create(dma->parent_dtag,
10255 				1,
10256 				0,
10257 				BUS_SPACE_MAXADDR,
10258 				BUS_SPACE_MAXADDR,
10259 				NULL, NULL,
10260 				MCLBYTES,
10261 				1,
10262 				BUS_SPACE_MAXSIZE_32BIT,
10263 				0,
10264 				NULL, NULL,
10265 				&dma->rxbuf_dtag);
10266 	if (error) {
10267 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10268 		goto fail0;
10269 	}
10270 	error = bus_dma_tag_create(dma->parent_dtag,
10271 				1,
10272 				0,
10273 				BUS_SPACE_MAXADDR,
10274 				BUS_SPACE_MAXADDR,
10275 				NULL, NULL,
10276 				MCLBYTES,
10277 				1,
10278 				BUS_SPACE_MAXSIZE_32BIT,
10279 				0,
10280 				NULL, NULL,
10281 				&dma->txbuf_dtag);
10282 	if (error) {
10283 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10284 		goto fail1;
10285 	}
10286 
10287 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10288 	if (!dma->wme[WME_AC_BK])
10289 		goto fail2;
10290 
10291 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10292 	if (!dma->wme[WME_AC_BE])
10293 		goto fail3;
10294 
10295 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10296 	if (!dma->wme[WME_AC_VI])
10297 		goto fail4;
10298 
10299 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10300 	if (!dma->wme[WME_AC_VO])
10301 		goto fail5;
10302 
10303 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10304 	if (!dma->mcast)
10305 		goto fail6;
10306 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10307 	if (!dma->rx)
10308 		goto fail7;
10309 
10310 	return (error);
10311 
10312 fail7:	bwn_dma_ringfree(&dma->mcast);
10313 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10314 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10315 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10316 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10317 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10318 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10319 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10320 	return (error);
10321 }
10322 
10323 static struct bwn_dma_ring *
10324 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10325     uint16_t cookie, int *slot)
10326 {
10327 	struct bwn_dma *dma = &mac->mac_method.dma;
10328 	struct bwn_dma_ring *dr;
10329 	struct bwn_softc *sc = mac->mac_sc;
10330 
10331 	BWN_ASSERT_LOCKED(mac->mac_sc);
10332 
10333 	switch (cookie & 0xf000) {
10334 	case 0x1000:
10335 		dr = dma->wme[WME_AC_BK];
10336 		break;
10337 	case 0x2000:
10338 		dr = dma->wme[WME_AC_BE];
10339 		break;
10340 	case 0x3000:
10341 		dr = dma->wme[WME_AC_VI];
10342 		break;
10343 	case 0x4000:
10344 		dr = dma->wme[WME_AC_VO];
10345 		break;
10346 	case 0x5000:
10347 		dr = dma->mcast;
10348 		break;
10349 	default:
10350 		dr = NULL;
10351 		KASSERT(0 == 1,
10352 		    ("invalid cookie value %d", cookie & 0xf000));
10353 	}
10354 	*slot = (cookie & 0x0fff);
10355 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10356 		/*
10357 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10358 		 * that it occurs events which have same H/W sequence numbers.
10359 		 * When it's occurred just prints a WARNING msgs and ignores.
10360 		 */
10361 		KASSERT(status->seq == dma->lastseq,
10362 		    ("%s:%d: fail", __func__, __LINE__));
10363 		device_printf(sc->sc_dev,
10364 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10365 		    dr->dr_numslots);
10366 		return (NULL);
10367 	}
10368 	dma->lastseq = status->seq;
10369 	return (dr);
10370 }
10371 
10372 static void
10373 bwn_dma_stop(struct bwn_mac *mac)
10374 {
10375 	struct bwn_dma *dma;
10376 
10377 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10378 		return;
10379 	dma = &mac->mac_method.dma;
10380 
10381 	bwn_dma_ringstop(&dma->rx);
10382 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10383 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10384 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10385 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10386 	bwn_dma_ringstop(&dma->mcast);
10387 }
10388 
10389 static void
10390 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10391 {
10392 
10393 	if (dr == NULL)
10394 		return;
10395 
10396 	bwn_dma_cleanup(*dr);
10397 }
10398 
10399 static void
10400 bwn_pio_stop(struct bwn_mac *mac)
10401 {
10402 	struct bwn_pio *pio;
10403 
10404 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10405 		return;
10406 	pio = &mac->mac_method.pio;
10407 
10408 	bwn_destroy_queue_tx(&pio->mcast);
10409 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10410 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10411 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10412 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10413 }
10414 
10415 static void
10416 bwn_led_attach(struct bwn_mac *mac)
10417 {
10418 	struct bwn_softc *sc = mac->mac_sc;
10419 	const uint8_t *led_act = NULL;
10420 	uint16_t val[BWN_LED_MAX];
10421 	int i;
10422 
10423 	sc->sc_led_idle = (2350 * hz) / 1000;
10424 	sc->sc_led_blink = 1;
10425 
10426 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10427 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10428 		    bwn_vendor_led_act[i].vid) {
10429 			led_act = bwn_vendor_led_act[i].led_act;
10430 			break;
10431 		}
10432 	}
10433 	if (led_act == NULL)
10434 		led_act = bwn_default_led_act;
10435 
10436 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10437 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10438 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10439 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10440 
10441 	for (i = 0; i < BWN_LED_MAX; ++i) {
10442 		struct bwn_led *led = &sc->sc_leds[i];
10443 
10444 		if (val[i] == 0xff) {
10445 			led->led_act = led_act[i];
10446 		} else {
10447 			if (val[i] & BWN_LED_ACT_LOW)
10448 				led->led_flags |= BWN_LED_F_ACTLOW;
10449 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10450 		}
10451 		led->led_mask = (1 << i);
10452 
10453 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10454 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10455 		    led->led_act == BWN_LED_ACT_BLINK) {
10456 			led->led_flags |= BWN_LED_F_BLINK;
10457 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10458 				led->led_flags |= BWN_LED_F_POLLABLE;
10459 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10460 				led->led_flags |= BWN_LED_F_SLOW;
10461 
10462 			if (sc->sc_blink_led == NULL) {
10463 				sc->sc_blink_led = led;
10464 				if (led->led_flags & BWN_LED_F_SLOW)
10465 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10466 			}
10467 		}
10468 
10469 		DPRINTF(sc, BWN_DEBUG_LED,
10470 		    "%dth led, act %d, lowact %d\n", i,
10471 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10472 	}
10473 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10474 }
10475 
10476 static __inline uint16_t
10477 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10478 {
10479 
10480 	if (led->led_flags & BWN_LED_F_ACTLOW)
10481 		on = !on;
10482 	if (on)
10483 		val |= led->led_mask;
10484 	else
10485 		val &= ~led->led_mask;
10486 	return val;
10487 }
10488 
10489 static void
10490 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10491 {
10492 	struct bwn_softc *sc = mac->mac_sc;
10493 	struct ieee80211com *ic = &sc->sc_ic;
10494 	uint16_t val;
10495 	int i;
10496 
10497 	if (nstate == IEEE80211_S_INIT) {
10498 		callout_stop(&sc->sc_led_blink_ch);
10499 		sc->sc_led_blinking = 0;
10500 	}
10501 
10502 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
10503 		return;
10504 
10505 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10506 	for (i = 0; i < BWN_LED_MAX; ++i) {
10507 		struct bwn_led *led = &sc->sc_leds[i];
10508 		int on;
10509 
10510 		if (led->led_act == BWN_LED_ACT_UNKN ||
10511 		    led->led_act == BWN_LED_ACT_NULL)
10512 			continue;
10513 
10514 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10515 		    nstate != IEEE80211_S_INIT)
10516 			continue;
10517 
10518 		switch (led->led_act) {
10519 		case BWN_LED_ACT_ON:    /* Always on */
10520 			on = 1;
10521 			break;
10522 		case BWN_LED_ACT_OFF:   /* Always off */
10523 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10524 			on = 0;
10525 			break;
10526 		default:
10527 			on = 1;
10528 			switch (nstate) {
10529 			case IEEE80211_S_INIT:
10530 				on = 0;
10531 				break;
10532 			case IEEE80211_S_RUN:
10533 				if (led->led_act == BWN_LED_ACT_11G &&
10534 				    ic->ic_curmode != IEEE80211_MODE_11G)
10535 					on = 0;
10536 				break;
10537 			default:
10538 				if (led->led_act == BWN_LED_ACT_ASSOC)
10539 					on = 0;
10540 				break;
10541 			}
10542 			break;
10543 		}
10544 
10545 		val = bwn_led_onoff(led, val, on);
10546 	}
10547 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10548 }
10549 
10550 static void
10551 bwn_led_event(struct bwn_mac *mac, int event)
10552 {
10553 	struct bwn_softc *sc = mac->mac_sc;
10554 	struct bwn_led *led = sc->sc_blink_led;
10555 	int rate;
10556 
10557 	if (event == BWN_LED_EVENT_POLL) {
10558 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10559 			return;
10560 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10561 			return;
10562 	}
10563 
10564 	sc->sc_led_ticks = ticks;
10565 	if (sc->sc_led_blinking)
10566 		return;
10567 
10568 	switch (event) {
10569 	case BWN_LED_EVENT_RX:
10570 		rate = sc->sc_rx_rate;
10571 		break;
10572 	case BWN_LED_EVENT_TX:
10573 		rate = sc->sc_tx_rate;
10574 		break;
10575 	case BWN_LED_EVENT_POLL:
10576 		rate = 0;
10577 		break;
10578 	default:
10579 		panic("unknown LED event %d\n", event);
10580 		break;
10581 	}
10582 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10583 	    bwn_led_duration[rate].off_dur);
10584 }
10585 
10586 static void
10587 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10588 {
10589 	struct bwn_softc *sc = mac->mac_sc;
10590 	struct bwn_led *led = sc->sc_blink_led;
10591 	uint16_t val;
10592 
10593 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10594 	val = bwn_led_onoff(led, val, 1);
10595 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10596 
10597 	if (led->led_flags & BWN_LED_F_SLOW) {
10598 		BWN_LED_SLOWDOWN(on_dur);
10599 		BWN_LED_SLOWDOWN(off_dur);
10600 	}
10601 
10602 	sc->sc_led_blinking = 1;
10603 	sc->sc_led_blink_offdur = off_dur;
10604 
10605 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10606 }
10607 
10608 static void
10609 bwn_led_blink_next(void *arg)
10610 {
10611 	struct bwn_mac *mac = arg;
10612 	struct bwn_softc *sc = mac->mac_sc;
10613 	uint16_t val;
10614 
10615 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10616 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10617 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10618 
10619 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10620 	    bwn_led_blink_end, mac);
10621 }
10622 
10623 static void
10624 bwn_led_blink_end(void *arg)
10625 {
10626 	struct bwn_mac *mac = arg;
10627 	struct bwn_softc *sc = mac->mac_sc;
10628 
10629 	sc->sc_led_blinking = 0;
10630 }
10631 
10632 static int
10633 bwn_suspend(device_t dev)
10634 {
10635 	struct bwn_softc *sc = device_get_softc(dev);
10636 
10637 	BWN_LOCK(sc);
10638 	bwn_stop(sc);
10639 	BWN_UNLOCK(sc);
10640 	return (0);
10641 }
10642 
10643 static int
10644 bwn_resume(device_t dev)
10645 {
10646 	struct bwn_softc *sc = device_get_softc(dev);
10647 	int error = EDOOFUS;
10648 
10649 	BWN_LOCK(sc);
10650 	if (sc->sc_ic.ic_nrunning > 0)
10651 		error = bwn_init(sc);
10652 	BWN_UNLOCK(sc);
10653 	if (error == 0)
10654 		ieee80211_start_all(&sc->sc_ic);
10655 	return (0);
10656 }
10657 
10658 static void
10659 bwn_rfswitch(void *arg)
10660 {
10661 	struct bwn_softc *sc = arg;
10662 	struct bwn_mac *mac = sc->sc_curmac;
10663 	int cur = 0, prev = 0;
10664 
10665 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10666 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10667 
10668 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10669 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10670 			& BWN_RF_HWENABLED_HI_MASK))
10671 			cur = 1;
10672 	} else {
10673 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10674 		    & BWN_RF_HWENABLED_LO_MASK)
10675 			cur = 1;
10676 	}
10677 
10678 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10679 		prev = 1;
10680 
10681 	if (cur != prev) {
10682 		if (cur)
10683 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10684 		else
10685 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10686 
10687 		device_printf(sc->sc_dev,
10688 		    "status of RF switch is changed to %s\n",
10689 		    cur ? "ON" : "OFF");
10690 		if (cur != mac->mac_phy.rf_on) {
10691 			if (cur)
10692 				bwn_rf_turnon(mac);
10693 			else
10694 				bwn_rf_turnoff(mac);
10695 		}
10696 	}
10697 
10698 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10699 }
10700 
10701 static void
10702 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10703 {
10704 	struct bwn_phy *phy = &mac->mac_phy;
10705 	struct bwn_phy_lp *plp = &phy->phy_lp;
10706 
10707 	plp->plp_antenna = BWN_ANT_DEFAULT;
10708 }
10709 
10710 static int
10711 bwn_phy_lp_init(struct bwn_mac *mac)
10712 {
10713 	static const struct bwn_stxtable tables[] = {
10714 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10715 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10716 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10717 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10718 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10719 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10720 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10721 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10722 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10723 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10724 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10725 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10726 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10727 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10728 		{ 2, 11, 0x40, 0, 0x0f }
10729 	};
10730 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10731 	struct bwn_softc *sc = mac->mac_sc;
10732 	const struct bwn_stxtable *st;
10733 	struct ieee80211com *ic = &sc->sc_ic;
10734 	int i, error;
10735 	uint16_t tmp;
10736 
10737 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10738 	bwn_phy_lp_bbinit(mac);
10739 
10740 	/* initialize RF */
10741 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10742 	DELAY(1);
10743 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10744 	DELAY(1);
10745 
10746 	if (mac->mac_phy.rf_ver == 0x2062)
10747 		bwn_phy_lp_b2062_init(mac);
10748 	else {
10749 		bwn_phy_lp_b2063_init(mac);
10750 
10751 		/* synchronize stx table. */
10752 		for (i = 0; i < N(tables); i++) {
10753 			st = &tables[i];
10754 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10755 			tmp >>= st->st_rfshift;
10756 			tmp <<= st->st_physhift;
10757 			BWN_PHY_SETMASK(mac,
10758 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10759 			    ~(st->st_mask << st->st_physhift), tmp);
10760 		}
10761 
10762 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10763 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10764 	}
10765 
10766 	/* calibrate RC */
10767 	if (mac->mac_phy.rev >= 2)
10768 		bwn_phy_lp_rxcal_r2(mac);
10769 	else if (!plp->plp_rccap) {
10770 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10771 			bwn_phy_lp_rccal_r12(mac);
10772 	} else
10773 		bwn_phy_lp_set_rccap(mac);
10774 
10775 	error = bwn_phy_lp_switch_channel(mac, 7);
10776 	if (error)
10777 		device_printf(sc->sc_dev,
10778 		    "failed to change channel 7 (%d)\n", error);
10779 	bwn_phy_lp_txpctl_init(mac);
10780 	bwn_phy_lp_calib(mac);
10781 	return (0);
10782 }
10783 
10784 static uint16_t
10785 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10786 {
10787 
10788 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10789 	return (BWN_READ_2(mac, BWN_PHYDATA));
10790 }
10791 
10792 static void
10793 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10794 {
10795 
10796 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10797 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10798 }
10799 
10800 static void
10801 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10802     uint16_t set)
10803 {
10804 
10805 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10806 	BWN_WRITE_2(mac, BWN_PHYDATA,
10807 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10808 }
10809 
10810 static uint16_t
10811 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10812 {
10813 
10814 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10815 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10816 		reg |= 0x100;
10817 	if (mac->mac_phy.rev >= 2)
10818 		reg |= 0x200;
10819 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10820 	return BWN_READ_2(mac, BWN_RFDATALO);
10821 }
10822 
10823 static void
10824 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10825 {
10826 
10827 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10828 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10829 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10830 }
10831 
10832 static void
10833 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10834 {
10835 
10836 	if (on) {
10837 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10838 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10839 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10840 		return;
10841 	}
10842 
10843 	if (mac->mac_phy.rev >= 2) {
10844 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10845 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10846 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10847 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10848 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10849 		return;
10850 	}
10851 
10852 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10853 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10854 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10855 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10856 }
10857 
10858 static int
10859 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10860 {
10861 	struct bwn_phy *phy = &mac->mac_phy;
10862 	struct bwn_phy_lp *plp = &phy->phy_lp;
10863 	int error;
10864 
10865 	if (phy->rf_ver == 0x2063) {
10866 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10867 		if (error)
10868 			return (error);
10869 	} else {
10870 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10871 		if (error)
10872 			return (error);
10873 		bwn_phy_lp_set_anafilter(mac, chan);
10874 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10875 	}
10876 
10877 	plp->plp_chan = chan;
10878 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10879 	return (0);
10880 }
10881 
10882 static uint32_t
10883 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10884 {
10885 	struct bwn_softc *sc = mac->mac_sc;
10886 	struct ieee80211com *ic = &sc->sc_ic;
10887 
10888 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10889 }
10890 
10891 static void
10892 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10893 {
10894 	struct bwn_phy *phy = &mac->mac_phy;
10895 	struct bwn_phy_lp *plp = &phy->phy_lp;
10896 
10897 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10898 		return;
10899 
10900 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10901 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10902 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10903 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10904 	plp->plp_antenna = antenna;
10905 }
10906 
10907 static void
10908 bwn_phy_lp_task_60s(struct bwn_mac *mac)
10909 {
10910 
10911 	bwn_phy_lp_calib(mac);
10912 }
10913 
10914 static void
10915 bwn_phy_lp_readsprom(struct bwn_mac *mac)
10916 {
10917 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10918 	struct bwn_softc *sc = mac->mac_sc;
10919 	struct ieee80211com *ic = &sc->sc_ic;
10920 
10921 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10922 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10923 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10924 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10925 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10926 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10927 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10928 		return;
10929 	}
10930 
10931 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10932 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10933 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10934 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10935 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10936 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10937 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10938 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10939 }
10940 
10941 static void
10942 bwn_phy_lp_bbinit(struct bwn_mac *mac)
10943 {
10944 
10945 	bwn_phy_lp_tblinit(mac);
10946 	if (mac->mac_phy.rev >= 2)
10947 		bwn_phy_lp_bbinit_r2(mac);
10948 	else
10949 		bwn_phy_lp_bbinit_r01(mac);
10950 }
10951 
10952 static void
10953 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
10954 {
10955 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
10956 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
10957 	struct bwn_softc *sc = mac->mac_sc;
10958 	struct ieee80211com *ic = &sc->sc_ic;
10959 
10960 	bwn_phy_lp_set_txgain(mac,
10961 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
10962 	bwn_phy_lp_set_bbmult(mac, 150);
10963 }
10964 
10965 static void
10966 bwn_phy_lp_calib(struct bwn_mac *mac)
10967 {
10968 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10969 	struct bwn_softc *sc = mac->mac_sc;
10970 	struct ieee80211com *ic = &sc->sc_ic;
10971 	const struct bwn_rxcompco *rc = NULL;
10972 	struct bwn_txgain ogain;
10973 	int i, omode, oafeovr, orf, obbmult;
10974 	uint8_t mode, fc = 0;
10975 
10976 	if (plp->plp_chanfullcal != plp->plp_chan) {
10977 		plp->plp_chanfullcal = plp->plp_chan;
10978 		fc = 1;
10979 	}
10980 
10981 	bwn_mac_suspend(mac);
10982 
10983 	/* BlueTooth Coexistance Override */
10984 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
10985 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
10986 
10987 	if (mac->mac_phy.rev >= 2)
10988 		bwn_phy_lp_digflt_save(mac);
10989 	bwn_phy_lp_get_txpctlmode(mac);
10990 	mode = plp->plp_txpctlmode;
10991 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
10992 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
10993 		bwn_phy_lp_bugfix(mac);
10994 	if (mac->mac_phy.rev >= 2 && fc == 1) {
10995 		bwn_phy_lp_get_txpctlmode(mac);
10996 		omode = plp->plp_txpctlmode;
10997 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
10998 		if (oafeovr)
10999 			ogain = bwn_phy_lp_get_txgain(mac);
11000 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11001 		obbmult = bwn_phy_lp_get_bbmult(mac);
11002 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11003 		if (oafeovr)
11004 			bwn_phy_lp_set_txgain(mac, &ogain);
11005 		bwn_phy_lp_set_bbmult(mac, obbmult);
11006 		bwn_phy_lp_set_txpctlmode(mac, omode);
11007 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11008 	}
11009 	bwn_phy_lp_set_txpctlmode(mac, mode);
11010 	if (mac->mac_phy.rev >= 2)
11011 		bwn_phy_lp_digflt_restore(mac);
11012 
11013 	/* do RX IQ Calculation; assumes that noise is true. */
11014 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11015 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11016 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11017 				rc = &bwn_rxcompco_5354[i];
11018 		}
11019 	} else if (mac->mac_phy.rev >= 2)
11020 		rc = &bwn_rxcompco_r2;
11021 	else {
11022 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11023 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11024 				rc = &bwn_rxcompco_r12[i];
11025 		}
11026 	}
11027 	if (rc == NULL)
11028 		goto fail;
11029 
11030 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11031 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11032 
11033 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11034 
11035 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11036 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11037 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11038 	} else {
11039 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11040 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11041 	}
11042 
11043 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11044 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11045 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11046 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11047 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11048 	bwn_phy_lp_set_deaf(mac, 0);
11049 	/* XXX no checking return value? */
11050 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11051 	bwn_phy_lp_clear_deaf(mac, 0);
11052 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11053 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11054 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11055 
11056 	/* disable RX GAIN override. */
11057 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11058 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11059 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11060 	if (mac->mac_phy.rev >= 2) {
11061 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11062 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11063 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11064 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11065 		}
11066 	} else {
11067 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11068 	}
11069 
11070 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11071 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11072 fail:
11073 	bwn_mac_enable(mac);
11074 }
11075 
11076 static void
11077 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11078 {
11079 
11080 	if (on) {
11081 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11082 		return;
11083 	}
11084 
11085 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11086 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11087 }
11088 
11089 static int
11090 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11091 {
11092 	static const struct bwn_b206x_chan *bc = NULL;
11093 	struct bwn_softc *sc = mac->mac_sc;
11094 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11095 	    tmp[6];
11096 	uint16_t old, scale, tmp16;
11097 	int i, div;
11098 
11099 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11100 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11101 			bc = &bwn_b2063_chantable[i];
11102 			break;
11103 		}
11104 	}
11105 	if (bc == NULL)
11106 		return (EINVAL);
11107 
11108 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11109 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11110 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11111 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11112 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11113 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11114 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11115 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11116 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11117 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11118 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11119 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11120 
11121 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11122 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11123 
11124 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11125 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11126 	freqref = freqxtal * 3;
11127 	div = (freqxtal <= 26000000 ? 1 : 2);
11128 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11129 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11130 		999999) / 1000000) + 1;
11131 
11132 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11133 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11134 	    0xfff8, timeout >> 2);
11135 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11136 	    0xff9f,timeout << 5);
11137 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11138 
11139 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11140 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11141 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11142 
11143 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11144 	    (timeoutref + 1)) - 1;
11145 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11146 	    0xf0, count >> 8);
11147 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11148 
11149 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11150 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11151 	while (tmp[1] >= freqref) {
11152 		tmp[0]++;
11153 		tmp[1] -= freqref;
11154 	}
11155 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11156 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11157 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11158 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11159 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11160 
11161 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11162 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11163 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11164 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11165 
11166 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11167 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11168 
11169 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11170 		scale = 1;
11171 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11172 	} else {
11173 		scale = 0;
11174 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11175 	}
11176 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11177 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11178 
11179 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11180 	    (scale + 1);
11181 	if (tmp[5] > 150)
11182 		tmp[5] = 0;
11183 
11184 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11185 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11186 
11187 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11188 	if (freqxtal > 26000000)
11189 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11190 	else
11191 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11192 
11193 	if (val[0] == 45)
11194 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11195 	else
11196 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11197 
11198 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11199 	DELAY(1);
11200 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11201 
11202 	/* VCO Calibration */
11203 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11204 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11205 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11206 	DELAY(1);
11207 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11208 	DELAY(1);
11209 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11210 	DELAY(1);
11211 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11212 	DELAY(300);
11213 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11214 
11215 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11216 	return (0);
11217 }
11218 
11219 static int
11220 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11221 {
11222 	struct bwn_softc *sc = mac->mac_sc;
11223 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11224 	const struct bwn_b206x_chan *bc = NULL;
11225 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11226 	uint32_t tmp[9];
11227 	int i;
11228 
11229 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11230 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11231 			bc = &bwn_b2062_chantable[i];
11232 			break;
11233 		}
11234 	}
11235 
11236 	if (bc == NULL)
11237 		return (EINVAL);
11238 
11239 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11240 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11241 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11242 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11243 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11244 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11245 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11246 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11247 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11248 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11249 
11250 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11251 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11252 	bwn_phy_lp_b2062_reset_pllbias(mac);
11253 	tmp[0] = freqxtal / 1000;
11254 	tmp[1] = plp->plp_div * 1000;
11255 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11256 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11257 		tmp[2] *= 2;
11258 	tmp[3] = 48 * tmp[0];
11259 	tmp[5] = tmp[2] / tmp[3];
11260 	tmp[6] = tmp[2] % tmp[3];
11261 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11262 	tmp[4] = tmp[6] * 0x100;
11263 	tmp[5] = tmp[4] / tmp[3];
11264 	tmp[6] = tmp[4] % tmp[3];
11265 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11266 	tmp[4] = tmp[6] * 0x100;
11267 	tmp[5] = tmp[4] / tmp[3];
11268 	tmp[6] = tmp[4] % tmp[3];
11269 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11270 	tmp[4] = tmp[6] * 0x100;
11271 	tmp[5] = tmp[4] / tmp[3];
11272 	tmp[6] = tmp[4] % tmp[3];
11273 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11274 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11275 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11276 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11277 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11278 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11279 
11280 	bwn_phy_lp_b2062_vco_calib(mac);
11281 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11282 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11283 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11284 		bwn_phy_lp_b2062_reset_pllbias(mac);
11285 		bwn_phy_lp_b2062_vco_calib(mac);
11286 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11287 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11288 			return (EIO);
11289 		}
11290 	}
11291 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11292 	return (0);
11293 }
11294 
11295 static void
11296 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11297 {
11298 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11299 	uint16_t tmp = (channel == 14);
11300 
11301 	if (mac->mac_phy.rev < 2) {
11302 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11303 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11304 			bwn_phy_lp_set_rccap(mac);
11305 		return;
11306 	}
11307 
11308 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11309 }
11310 
11311 static void
11312 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11313 {
11314 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11315 	struct bwn_softc *sc = mac->mac_sc;
11316 	struct ieee80211com *ic = &sc->sc_ic;
11317 	uint16_t iso, tmp[3];
11318 
11319 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11320 
11321 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11322 		iso = plp->plp_txisoband_m;
11323 	else if (freq <= 5320)
11324 		iso = plp->plp_txisoband_l;
11325 	else if (freq <= 5700)
11326 		iso = plp->plp_txisoband_m;
11327 	else
11328 		iso = plp->plp_txisoband_h;
11329 
11330 	tmp[0] = ((iso - 26) / 12) << 12;
11331 	tmp[1] = tmp[0] + 0x1000;
11332 	tmp[2] = tmp[0] + 0x2000;
11333 
11334 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11335 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11336 }
11337 
11338 static void
11339 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11340 {
11341 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11342 	int i;
11343 	static const uint16_t addr[] = {
11344 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11345 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11346 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11347 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11348 		BWN_PHY_OFDM(0xcf),
11349 	};
11350 	static const uint16_t val[] = {
11351 		0xde5e, 0xe832, 0xe331, 0x4d26,
11352 		0x0026, 0x1420, 0x0020, 0xfe08,
11353 		0x0008,
11354 	};
11355 
11356 	for (i = 0; i < N(addr); i++) {
11357 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11358 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11359 	}
11360 }
11361 
11362 static void
11363 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11364 {
11365 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11366 	struct bwn_softc *sc = mac->mac_sc;
11367 	uint16_t ctl;
11368 
11369 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11370 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11371 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11372 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11373 		break;
11374 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11375 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11376 		break;
11377 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11378 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11379 		break;
11380 	default:
11381 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11382 		device_printf(sc->sc_dev, "unknown command mode\n");
11383 		break;
11384 	}
11385 }
11386 
11387 static void
11388 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11389 {
11390 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11391 	uint16_t ctl;
11392 	uint8_t old;
11393 
11394 	bwn_phy_lp_get_txpctlmode(mac);
11395 	old = plp->plp_txpctlmode;
11396 	if (old == mode)
11397 		return;
11398 	plp->plp_txpctlmode = mode;
11399 
11400 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11401 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11402 		    plp->plp_tssiidx);
11403 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11404 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11405 
11406 		/* disable TX GAIN override */
11407 		if (mac->mac_phy.rev < 2)
11408 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11409 		else {
11410 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11411 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11412 		}
11413 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11414 
11415 		plp->plp_txpwridx = -1;
11416 	}
11417 	if (mac->mac_phy.rev >= 2) {
11418 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11419 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11420 		else
11421 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11422 	}
11423 
11424 	/* writes TX Power Control mode */
11425 	switch (plp->plp_txpctlmode) {
11426 	case BWN_PHYLP_TXPCTL_OFF:
11427 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11428 		break;
11429 	case BWN_PHYLP_TXPCTL_ON_HW:
11430 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11431 		break;
11432 	case BWN_PHYLP_TXPCTL_ON_SW:
11433 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11434 		break;
11435 	default:
11436 		ctl = 0;
11437 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11438 	}
11439 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11440 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11441 }
11442 
11443 static void
11444 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11445 {
11446 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11447 	struct bwn_softc *sc = mac->mac_sc;
11448 	const unsigned int size = 256;
11449 	struct bwn_txgain tg;
11450 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11451 	uint16_t tssinpt, tssiidx, value[2];
11452 	uint8_t mode;
11453 	int8_t txpwridx;
11454 
11455 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11456 	    M_NOWAIT | M_ZERO);
11457 	if (tabs == NULL) {
11458 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11459 		return;
11460 	}
11461 
11462 	bwn_phy_lp_get_txpctlmode(mac);
11463 	mode = plp->plp_txpctlmode;
11464 	txpwridx = plp->plp_txpwridx;
11465 	tssinpt = plp->plp_tssinpt;
11466 	tssiidx = plp->plp_tssiidx;
11467 
11468 	bwn_tab_read_multi(mac,
11469 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11470 	    BWN_TAB_4(7, 0x140), size, tabs);
11471 
11472 	bwn_phy_lp_tblinit(mac);
11473 	bwn_phy_lp_bbinit(mac);
11474 	bwn_phy_lp_txpctl_init(mac);
11475 	bwn_phy_lp_rf_onoff(mac, 1);
11476 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11477 
11478 	bwn_tab_write_multi(mac,
11479 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11480 	    BWN_TAB_4(7, 0x140), size, tabs);
11481 
11482 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11483 	plp->plp_tssinpt = tssinpt;
11484 	plp->plp_tssiidx = tssiidx;
11485 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11486 	if (txpwridx != -1) {
11487 		/* set TX power by index */
11488 		plp->plp_txpwridx = txpwridx;
11489 		bwn_phy_lp_get_txpctlmode(mac);
11490 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11491 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11492 		if (mac->mac_phy.rev >= 2) {
11493 			rxcomp = bwn_tab_read(mac,
11494 			    BWN_TAB_4(7, txpwridx + 320));
11495 			txgain = bwn_tab_read(mac,
11496 			    BWN_TAB_4(7, txpwridx + 192));
11497 			tg.tg_pad = (txgain >> 16) & 0xff;
11498 			tg.tg_gm = txgain & 0xff;
11499 			tg.tg_pga = (txgain >> 8) & 0xff;
11500 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11501 			bwn_phy_lp_set_txgain(mac, &tg);
11502 		} else {
11503 			rxcomp = bwn_tab_read(mac,
11504 			    BWN_TAB_4(10, txpwridx + 320));
11505 			txgain = bwn_tab_read(mac,
11506 			    BWN_TAB_4(10, txpwridx + 192));
11507 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11508 			    0xf800, (txgain >> 4) & 0x7fff);
11509 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11510 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11511 		}
11512 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11513 
11514 		/* set TX IQCC */
11515 		value[0] = (rxcomp >> 10) & 0x3ff;
11516 		value[1] = rxcomp & 0x3ff;
11517 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11518 
11519 		coeff = bwn_tab_read(mac,
11520 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11521 		    BWN_TAB_4(10, txpwridx + 448));
11522 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11523 		if (mac->mac_phy.rev >= 2) {
11524 			rfpwr = bwn_tab_read(mac,
11525 			    BWN_TAB_4(7, txpwridx + 576));
11526 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11527 			    rfpwr & 0xffff);
11528 		}
11529 		bwn_phy_lp_set_txgain_override(mac);
11530 	}
11531 	if (plp->plp_rccap)
11532 		bwn_phy_lp_set_rccap(mac);
11533 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11534 	bwn_phy_lp_set_txpctlmode(mac, mode);
11535 	free(tabs, M_DEVBUF);
11536 }
11537 
11538 static void
11539 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11540 {
11541 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11542 	int i;
11543 	static const uint16_t addr[] = {
11544 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11545 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11546 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11547 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11548 		BWN_PHY_OFDM(0xcf),
11549 	};
11550 
11551 	for (i = 0; i < N(addr); i++)
11552 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11553 }
11554 
11555 static void
11556 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11557 {
11558 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11559 
11560 	if (mac->mac_phy.rev < 2) {
11561 		bwn_phy_lp_tblinit_r01(mac);
11562 		bwn_phy_lp_tblinit_txgain(mac);
11563 		bwn_phy_lp_set_gaintbl(mac, freq);
11564 		return;
11565 	}
11566 
11567 	bwn_phy_lp_tblinit_r2(mac);
11568 	bwn_phy_lp_tblinit_txgain(mac);
11569 }
11570 
11571 struct bwn_wpair {
11572 	uint16_t		reg;
11573 	uint16_t		value;
11574 };
11575 
11576 struct bwn_smpair {
11577 	uint16_t		offset;
11578 	uint16_t		mask;
11579 	uint16_t		set;
11580 };
11581 
11582 static void
11583 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11584 {
11585 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11586 	struct bwn_softc *sc = mac->mac_sc;
11587 	struct ieee80211com *ic = &sc->sc_ic;
11588 	static const struct bwn_wpair v1[] = {
11589 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11590 		{ BWN_PHY_AFE_CTL, 0x8800 },
11591 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11592 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11593 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11594 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11595 		{ BWN_PHY_OFDM(0xf9), 0 },
11596 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11597 	};
11598 	static const struct bwn_smpair v2[] = {
11599 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11600 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11601 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11602 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11603 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11604 	};
11605 	static const struct bwn_smpair v3[] = {
11606 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11607 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11608 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11609 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11610 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11611 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11612 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11613 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11614 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11615 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11616 
11617 	};
11618 	int i;
11619 
11620 	for (i = 0; i < N(v1); i++)
11621 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11622 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11623 	for (i = 0; i < N(v2); i++)
11624 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11625 
11626 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11627 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11628 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11629 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11630 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11631 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11632 	} else {
11633 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11634 	}
11635 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11636 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11637 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11638 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11639 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11640 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11641 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11642 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11643 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11644 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11645 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11646 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11647 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11648 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11649 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11650 	} else {
11651 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11652 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11653 	}
11654 	for (i = 0; i < N(v3); i++)
11655 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11656 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11657 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11658 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11659 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11660 	}
11661 
11662 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11663 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11664 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11665 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11666 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11667 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11668 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11669 	} else
11670 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11671 
11672 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11673 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11674 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11675 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11676 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11677 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11678 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11679 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11680 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11681 
11682 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11683 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11684 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11685 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11686 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11687 	}
11688 
11689 	bwn_phy_lp_digflt_save(mac);
11690 }
11691 
11692 static void
11693 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11694 {
11695 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11696 	struct bwn_softc *sc = mac->mac_sc;
11697 	struct ieee80211com *ic = &sc->sc_ic;
11698 	static const struct bwn_smpair v1[] = {
11699 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11700 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11701 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11702 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11703 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11704 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11705 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11706 	};
11707 	static const struct bwn_smpair v2[] = {
11708 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11709 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11710 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11711 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11712 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11713 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11714 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11715 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11716 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11717 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11718 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11719 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11720 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11721 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11722 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11723 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11724 	};
11725 	static const struct bwn_smpair v3[] = {
11726 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11727 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11728 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11729 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11730 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11731 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11732 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11733 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11734 	};
11735 	static const struct bwn_smpair v4[] = {
11736 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11737 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11738 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11739 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11740 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11741 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11742 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11743 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11744 	};
11745 	static const struct bwn_smpair v5[] = {
11746 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11747 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11748 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11749 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11750 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11751 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11752 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11753 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11754 	};
11755 	int i;
11756 	uint16_t tmp, tmp2;
11757 
11758 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11759 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11760 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11761 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11762 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11763 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11764 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11765 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11766 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11767 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11768 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11769 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11770 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11771 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11772 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11773 	for (i = 0; i < N(v1); i++)
11774 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11775 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11776 	    0xff00, plp->plp_rxpwroffset);
11777 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11778 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11779 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11780 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11781 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11782 		if (mac->mac_phy.rev == 0)
11783 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11784 			    0xffcf, 0x0010);
11785 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11786 	} else {
11787 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11788 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11789 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11790 	}
11791 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11792 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11793 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11794 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11795 	else
11796 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11797 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11798 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11799 	    0xfff9, (plp->plp_bxarch << 1));
11800 	if (mac->mac_phy.rev == 1 &&
11801 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11802 		for (i = 0; i < N(v2); i++)
11803 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11804 			    v2[i].set);
11805 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11806 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11807 	    ((mac->mac_phy.rev == 0) &&
11808 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11809 		for (i = 0; i < N(v3); i++)
11810 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11811 			    v3[i].set);
11812 	} else if (mac->mac_phy.rev == 1 ||
11813 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11814 		for (i = 0; i < N(v4); i++)
11815 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11816 			    v4[i].set);
11817 	} else {
11818 		for (i = 0; i < N(v5); i++)
11819 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11820 			    v5[i].set);
11821 	}
11822 	if (mac->mac_phy.rev == 1 &&
11823 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11824 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11825 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11826 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11827 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11828 	}
11829 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11830 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11831 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11832 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11833 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11834 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11835 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11836 	}
11837 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11838 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11839 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11840 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11841 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11842 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11843 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11844 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11845 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11846 	} else {
11847 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11848 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11849 	}
11850 	if (mac->mac_phy.rev == 1) {
11851 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11852 		tmp2 = (tmp & 0x03e0) >> 5;
11853 		tmp2 |= tmp2 << 5;
11854 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11855 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11856 		tmp2 = (tmp & 0x1f00) >> 8;
11857 		tmp2 |= tmp2 << 5;
11858 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11859 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11860 		tmp2 = tmp & 0x00ff;
11861 		tmp2 |= tmp << 8;
11862 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11863 	}
11864 }
11865 
11866 struct bwn_b2062_freq {
11867 	uint16_t		freq;
11868 	uint8_t			value[6];
11869 };
11870 
11871 static void
11872 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11873 {
11874 #define	CALC_CTL7(freq, div)						\
11875 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11876 #define	CALC_CTL18(freq, div)						\
11877 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11878 #define	CALC_CTL19(freq, div)						\
11879 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11880 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11881 	struct bwn_softc *sc = mac->mac_sc;
11882 	struct ieee80211com *ic = &sc->sc_ic;
11883 	static const struct bwn_b2062_freq freqdata_tab[] = {
11884 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11885 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11886 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11887 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11888 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11889 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11890 	};
11891 	static const struct bwn_wpair v1[] = {
11892 		{ BWN_B2062_N_TXCTL3, 0 },
11893 		{ BWN_B2062_N_TXCTL4, 0 },
11894 		{ BWN_B2062_N_TXCTL5, 0 },
11895 		{ BWN_B2062_N_TXCTL6, 0 },
11896 		{ BWN_B2062_N_PDNCTL0, 0x40 },
11897 		{ BWN_B2062_N_PDNCTL0, 0 },
11898 		{ BWN_B2062_N_CALIB_TS, 0x10 },
11899 		{ BWN_B2062_N_CALIB_TS, 0 }
11900 	};
11901 	const struct bwn_b2062_freq *f = NULL;
11902 	uint32_t xtalfreq, ref;
11903 	unsigned int i;
11904 
11905 	bwn_phy_lp_b2062_tblinit(mac);
11906 
11907 	for (i = 0; i < N(v1); i++)
11908 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11909 	if (mac->mac_phy.rev > 0)
11910 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11911 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11912 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11913 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11914 	else
11915 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11916 
11917 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11918 	    ("%s:%d: fail", __func__, __LINE__));
11919 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11920 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11921 
11922 	if (xtalfreq <= 30000000) {
11923 		plp->plp_div = 1;
11924 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11925 	} else {
11926 		plp->plp_div = 2;
11927 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11928 	}
11929 
11930 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11931 	    CALC_CTL7(xtalfreq, plp->plp_div));
11932 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11933 	    CALC_CTL18(xtalfreq, plp->plp_div));
11934 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11935 	    CALC_CTL19(xtalfreq, plp->plp_div));
11936 
11937 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11938 	ref &= 0xffff;
11939 	for (i = 0; i < N(freqdata_tab); i++) {
11940 		if (ref < freqdata_tab[i].freq) {
11941 			f = &freqdata_tab[i];
11942 			break;
11943 		}
11944 	}
11945 	if (f == NULL)
11946 		f = &freqdata_tab[N(freqdata_tab) - 1];
11947 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
11948 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
11949 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
11950 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
11951 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
11952 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
11953 #undef CALC_CTL7
11954 #undef CALC_CTL18
11955 #undef CALC_CTL19
11956 }
11957 
11958 static void
11959 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
11960 {
11961 
11962 	bwn_phy_lp_b2063_tblinit(mac);
11963 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
11964 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
11965 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
11966 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
11967 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
11968 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
11969 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
11970 	if (mac->mac_phy.rev == 2) {
11971 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
11972 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
11973 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
11974 	} else {
11975 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
11976 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
11977 	}
11978 }
11979 
11980 static void
11981 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
11982 {
11983 	struct bwn_softc *sc = mac->mac_sc;
11984 	static const struct bwn_wpair v1[] = {
11985 		{ BWN_B2063_RX_BB_SP8, 0x0 },
11986 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11987 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11988 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
11989 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
11990 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
11991 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
11992 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
11993 	};
11994 	static const struct bwn_wpair v2[] = {
11995 		{ BWN_B2063_TX_BB_SP3, 0x0 },
11996 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11997 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11998 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
11999 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12000 	};
12001 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12002 	int i;
12003 	uint8_t tmp;
12004 
12005 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12006 
12007 	for (i = 0; i < 2; i++)
12008 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12009 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12010 	for (i = 2; i < N(v1); i++)
12011 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12012 	for (i = 0; i < 10000; i++) {
12013 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12014 			break;
12015 		DELAY(1000);
12016 	}
12017 
12018 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12019 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12020 
12021 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12022 
12023 	for (i = 0; i < N(v2); i++)
12024 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12025 	if (freqxtal == 24000000) {
12026 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12027 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12028 	} else {
12029 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12030 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12031 	}
12032 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12033 	for (i = 0; i < 10000; i++) {
12034 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12035 			break;
12036 		DELAY(1000);
12037 	}
12038 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12039 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12040 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12041 }
12042 
12043 static void
12044 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12045 {
12046 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12047 	struct bwn_softc *sc = mac->mac_sc;
12048 	struct bwn_phy_lp_iq_est ie;
12049 	struct bwn_txgain tx_gains;
12050 	static const uint32_t pwrtbl[21] = {
12051 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12052 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12053 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12054 		0x0004c, 0x0002c, 0x0001a,
12055 	};
12056 	uint32_t npwr, ipwr, sqpwr, tmp;
12057 	int loopback, i, j, sum, error;
12058 	uint16_t save[7];
12059 	uint8_t txo, bbmult, txpctlmode;
12060 
12061 	error = bwn_phy_lp_switch_channel(mac, 7);
12062 	if (error)
12063 		device_printf(sc->sc_dev,
12064 		    "failed to change channel to 7 (%d)\n", error);
12065 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12066 	bbmult = bwn_phy_lp_get_bbmult(mac);
12067 	if (txo)
12068 		tx_gains = bwn_phy_lp_get_txgain(mac);
12069 
12070 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12071 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12072 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12073 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12074 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12075 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12076 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12077 
12078 	bwn_phy_lp_get_txpctlmode(mac);
12079 	txpctlmode = plp->plp_txpctlmode;
12080 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12081 
12082 	/* disable CRS */
12083 	bwn_phy_lp_set_deaf(mac, 1);
12084 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12085 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12086 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12087 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12088 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12089 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12090 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12091 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12092 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12093 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12094 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12095 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12096 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12097 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12098 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12099 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12100 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12101 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12102 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12103 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12104 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12105 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12106 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12107 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12108 
12109 	loopback = bwn_phy_lp_loopback(mac);
12110 	if (loopback == -1)
12111 		goto done;
12112 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12113 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12114 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12115 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12116 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12117 
12118 	tmp = 0;
12119 	memset(&ie, 0, sizeof(ie));
12120 	for (i = 128; i <= 159; i++) {
12121 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12122 		sum = 0;
12123 		for (j = 5; j <= 25; j++) {
12124 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12125 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12126 				goto done;
12127 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12128 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12129 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12130 			    12);
12131 			sum += ((ipwr - npwr) * (ipwr - npwr));
12132 			if ((i == 128) || (sum < tmp)) {
12133 				plp->plp_rccap = i;
12134 				tmp = sum;
12135 			}
12136 		}
12137 	}
12138 	bwn_phy_lp_ddfs_turnoff(mac);
12139 done:
12140 	/* restore CRS */
12141 	bwn_phy_lp_clear_deaf(mac, 1);
12142 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12143 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12144 
12145 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12146 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12147 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12148 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12149 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12150 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12151 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12152 
12153 	bwn_phy_lp_set_bbmult(mac, bbmult);
12154 	if (txo)
12155 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12156 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12157 	if (plp->plp_rccap)
12158 		bwn_phy_lp_set_rccap(mac);
12159 }
12160 
12161 static void
12162 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12163 {
12164 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12165 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12166 
12167 	if (mac->mac_phy.rev == 1)
12168 		rc_cap = MIN(rc_cap + 5, 15);
12169 
12170 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12171 	    MAX(plp->plp_rccap - 4, 0x80));
12172 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12173 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12174 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12175 }
12176 
12177 static uint32_t
12178 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12179 {
12180 	uint32_t i, q, r;
12181 
12182 	if (div == 0)
12183 		return (0);
12184 
12185 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12186 		q <<= 1;
12187 		if (r << 1 >= div) {
12188 			q++;
12189 			r = (r << 1) - div;
12190 		}
12191 	}
12192 	if (r << 1 >= div)
12193 		q++;
12194 	return (q);
12195 }
12196 
12197 static void
12198 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12199 {
12200 	struct bwn_softc *sc = mac->mac_sc;
12201 
12202 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12203 	DELAY(20);
12204 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12205 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12206 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12207 	} else {
12208 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12209 	}
12210 	DELAY(5);
12211 }
12212 
12213 static void
12214 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12215 {
12216 
12217 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12218 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12219 	DELAY(200);
12220 }
12221 
12222 static void
12223 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12224 {
12225 #define	FLAG_A	0x01
12226 #define	FLAG_G	0x02
12227 	struct bwn_softc *sc = mac->mac_sc;
12228 	struct ieee80211com *ic = &sc->sc_ic;
12229 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12230 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12231 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12232 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12233 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12234 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12235 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12236 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12237 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12238 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12239 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12240 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12241 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12242 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12243 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12244 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12245 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12246 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12247 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12248 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12249 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12250 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12251 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12252 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12253 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12254 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12255 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12256 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12257 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12258 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12259 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12260 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12261 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12262 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12263 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12264 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12265 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12266 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12267 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12268 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12269 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12270 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12271 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12272 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12273 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12274 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12275 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12276 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12277 	};
12278 	const struct bwn_b206x_rfinit_entry *br;
12279 	unsigned int i;
12280 
12281 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12282 		br = &bwn_b2062_init_tab[i];
12283 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12284 			if (br->br_flags & FLAG_G)
12285 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12286 		} else {
12287 			if (br->br_flags & FLAG_A)
12288 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12289 		}
12290 	}
12291 #undef FLAG_A
12292 #undef FLAG_B
12293 }
12294 
12295 static void
12296 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12297 {
12298 #define	FLAG_A	0x01
12299 #define	FLAG_G	0x02
12300 	struct bwn_softc *sc = mac->mac_sc;
12301 	struct ieee80211com *ic = &sc->sc_ic;
12302 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12303 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12304 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12305 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12306 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12307 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12308 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12309 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12310 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12311 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12312 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12313 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12314 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12315 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12316 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12317 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12318 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12319 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12320 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12321 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12322 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12323 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12324 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12325 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12326 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12327 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12328 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12329 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12330 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12331 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12332 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12333 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12334 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12335 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12336 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12337 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12338 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12339 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12340 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12341 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12342 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12343 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12344 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12345 	};
12346 	const struct bwn_b206x_rfinit_entry *br;
12347 	unsigned int i;
12348 
12349 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12350 		br = &bwn_b2063_init_tab[i];
12351 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12352 			if (br->br_flags & FLAG_G)
12353 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12354 		} else {
12355 			if (br->br_flags & FLAG_A)
12356 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12357 		}
12358 	}
12359 #undef FLAG_A
12360 #undef FLAG_B
12361 }
12362 
12363 static void
12364 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12365     int count, void *_data)
12366 {
12367 	unsigned int i;
12368 	uint32_t offset, type;
12369 	uint8_t *data = _data;
12370 
12371 	type = BWN_TAB_GETTYPE(typenoffset);
12372 	offset = BWN_TAB_GETOFFSET(typenoffset);
12373 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12374 
12375 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12376 
12377 	for (i = 0; i < count; i++) {
12378 		switch (type) {
12379 		case BWN_TAB_8BIT:
12380 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12381 			data++;
12382 			break;
12383 		case BWN_TAB_16BIT:
12384 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12385 			    BWN_PHY_TABLEDATALO);
12386 			data += 2;
12387 			break;
12388 		case BWN_TAB_32BIT:
12389 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12390 			    BWN_PHY_TABLEDATAHI);
12391 			*((uint32_t *)data) <<= 16;
12392 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12393 			    BWN_PHY_TABLEDATALO);
12394 			data += 4;
12395 			break;
12396 		default:
12397 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12398 		}
12399 	}
12400 }
12401 
12402 static void
12403 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12404     int count, const void *_data)
12405 {
12406 	uint32_t offset, type, value;
12407 	const uint8_t *data = _data;
12408 	unsigned int i;
12409 
12410 	type = BWN_TAB_GETTYPE(typenoffset);
12411 	offset = BWN_TAB_GETOFFSET(typenoffset);
12412 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12413 
12414 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12415 
12416 	for (i = 0; i < count; i++) {
12417 		switch (type) {
12418 		case BWN_TAB_8BIT:
12419 			value = *data;
12420 			data++;
12421 			KASSERT(!(value & ~0xff),
12422 			    ("%s:%d: fail", __func__, __LINE__));
12423 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12424 			break;
12425 		case BWN_TAB_16BIT:
12426 			value = *((const uint16_t *)data);
12427 			data += 2;
12428 			KASSERT(!(value & ~0xffff),
12429 			    ("%s:%d: fail", __func__, __LINE__));
12430 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12431 			break;
12432 		case BWN_TAB_32BIT:
12433 			value = *((const uint32_t *)data);
12434 			data += 4;
12435 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12436 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12437 			break;
12438 		default:
12439 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12440 		}
12441 	}
12442 }
12443 
12444 static struct bwn_txgain
12445 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12446 {
12447 	struct bwn_txgain tg;
12448 	uint16_t tmp;
12449 
12450 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12451 	if (mac->mac_phy.rev < 2) {
12452 		tmp = BWN_PHY_READ(mac,
12453 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12454 		tg.tg_gm = tmp & 0x0007;
12455 		tg.tg_pga = (tmp & 0x0078) >> 3;
12456 		tg.tg_pad = (tmp & 0x780) >> 7;
12457 		return (tg);
12458 	}
12459 
12460 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12461 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12462 	tg.tg_gm = tmp & 0xff;
12463 	tg.tg_pga = (tmp >> 8) & 0xff;
12464 	return (tg);
12465 }
12466 
12467 static uint8_t
12468 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12469 {
12470 
12471 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12472 }
12473 
12474 static void
12475 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12476 {
12477 	uint16_t pa;
12478 
12479 	if (mac->mac_phy.rev < 2) {
12480 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12481 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12482 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12483 		bwn_phy_lp_set_txgain_override(mac);
12484 		return;
12485 	}
12486 
12487 	pa = bwn_phy_lp_get_pa_gain(mac);
12488 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12489 	    (tg->tg_pga << 8) | tg->tg_gm);
12490 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12491 	    tg->tg_pad | (pa << 6));
12492 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12493 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12494 	    tg->tg_pad | (pa << 8));
12495 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12496 	bwn_phy_lp_set_txgain_override(mac);
12497 }
12498 
12499 static void
12500 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12501 {
12502 
12503 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12504 }
12505 
12506 static void
12507 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12508 {
12509 	uint16_t trsw = (tx << 1) | rx;
12510 
12511 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12512 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12513 }
12514 
12515 static void
12516 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12517 {
12518 	struct bwn_softc *sc = mac->mac_sc;
12519 	struct ieee80211com *ic = &sc->sc_ic;
12520 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12521 
12522 	if (mac->mac_phy.rev < 2) {
12523 		trsw = gain & 0x1;
12524 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12525 		ext_lna = (gain & 2) >> 1;
12526 
12527 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12528 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12529 		    0xfbff, ext_lna << 10);
12530 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12531 		    0xf7ff, ext_lna << 11);
12532 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12533 	} else {
12534 		low_gain = gain & 0xffff;
12535 		high_gain = (gain >> 16) & 0xf;
12536 		ext_lna = (gain >> 21) & 0x1;
12537 		trsw = ~(gain >> 20) & 0x1;
12538 
12539 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12540 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12541 		    0xfdff, ext_lna << 9);
12542 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12543 		    0xfbff, ext_lna << 10);
12544 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12545 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12546 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12547 			tmp = (gain >> 2) & 0x3;
12548 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12549 			    0xe7ff, tmp<<11);
12550 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12551 			    tmp << 3);
12552 		}
12553 	}
12554 
12555 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12556 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12557 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12558 	if (mac->mac_phy.rev >= 2) {
12559 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12560 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12561 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12562 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12563 		}
12564 		return;
12565 	}
12566 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12567 }
12568 
12569 static void
12570 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12571 {
12572 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12573 
12574 	if (user)
12575 		plp->plp_crsusr_off = 1;
12576 	else
12577 		plp->plp_crssys_off = 1;
12578 
12579 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12580 }
12581 
12582 static void
12583 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12584 {
12585 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12586 	struct bwn_softc *sc = mac->mac_sc;
12587 	struct ieee80211com *ic = &sc->sc_ic;
12588 
12589 	if (user)
12590 		plp->plp_crsusr_off = 0;
12591 	else
12592 		plp->plp_crssys_off = 0;
12593 
12594 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12595 		return;
12596 
12597 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12598 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12599 	else
12600 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12601 }
12602 
12603 static unsigned int
12604 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12605 {
12606 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12607 	static uint8_t sqrt_table[256] = {
12608 		10, 14, 17, 20, 22, 24, 26, 28,
12609 		30, 31, 33, 34, 36, 37, 38, 40,
12610 		41, 42, 43, 44, 45, 46, 47, 48,
12611 		50, 50, 51, 52, 53, 54, 55, 56,
12612 		57, 58, 59, 60, 60, 61, 62, 63,
12613 		64, 64, 65, 66, 67, 67, 68, 69,
12614 		70, 70, 71, 72, 72, 73, 74, 74,
12615 		75, 76, 76, 77, 78, 78, 79, 80,
12616 		80, 81, 81, 82, 83, 83, 84, 84,
12617 		85, 86, 86, 87, 87, 88, 88, 89,
12618 		90, 90, 91, 91, 92, 92, 93, 93,
12619 		94, 94, 95, 95, 96, 96, 97, 97,
12620 		98, 98, 99, 100, 100, 100, 101, 101,
12621 		102, 102, 103, 103, 104, 104, 105, 105,
12622 		106, 106, 107, 107, 108, 108, 109, 109,
12623 		110, 110, 110, 111, 111, 112, 112, 113,
12624 		113, 114, 114, 114, 115, 115, 116, 116,
12625 		117, 117, 117, 118, 118, 119, 119, 120,
12626 		120, 120, 121, 121, 122, 122, 122, 123,
12627 		123, 124, 124, 124, 125, 125, 126, 126,
12628 		126, 127, 127, 128, 128, 128, 129, 129,
12629 		130, 130, 130, 131, 131, 131, 132, 132,
12630 		133, 133, 133, 134, 134, 134, 135, 135,
12631 		136, 136, 136, 137, 137, 137, 138, 138,
12632 		138, 139, 139, 140, 140, 140, 141, 141,
12633 		141, 142, 142, 142, 143, 143, 143, 144,
12634 		144, 144, 145, 145, 145, 146, 146, 146,
12635 		147, 147, 147, 148, 148, 148, 149, 149,
12636 		150, 150, 150, 150, 151, 151, 151, 152,
12637 		152, 152, 153, 153, 153, 154, 154, 154,
12638 		155, 155, 155, 156, 156, 156, 157, 157,
12639 		157, 158, 158, 158, 159, 159, 159, 160
12640 	};
12641 
12642 	if (x == 0)
12643 		return (0);
12644 	if (x >= 256) {
12645 		unsigned int tmp;
12646 
12647 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12648 			/* do nothing */ ;
12649 		return (tmp);
12650 	}
12651 	return (sqrt_table[x - 1] / 10);
12652 }
12653 
12654 static int
12655 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12656 {
12657 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12658 	int _t;								\
12659 	_t = _x - 20;							\
12660 	if (_t >= 0) {							\
12661 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12662 	} else {							\
12663 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12664 	}								\
12665 } while (0)
12666 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12667 	int _t;								\
12668 	_t = _x - 11;							\
12669 	if (_t >= 0)							\
12670 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12671 	else								\
12672 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12673 } while (0)
12674 	struct bwn_phy_lp_iq_est ie;
12675 	uint16_t v0, v1;
12676 	int tmp[2], ret;
12677 
12678 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12679 	v0 = v1 >> 8;
12680 	v1 |= 0xff;
12681 
12682 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12683 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12684 
12685 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12686 	if (ret == 0)
12687 		goto done;
12688 
12689 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12690 		ret = 0;
12691 		goto done;
12692 	}
12693 
12694 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12695 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12696 
12697 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12698 	v0 = tmp[0] >> 3;
12699 	v1 = tmp[1] >> 4;
12700 done:
12701 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12702 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12703 	return ret;
12704 #undef CALC_COEFF
12705 #undef CALC_COEFF2
12706 }
12707 
12708 static void
12709 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12710 {
12711 	static const uint16_t noisescale[] = {
12712 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12713 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12714 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12715 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12716 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12717 	};
12718 	static const uint16_t crsgainnft[] = {
12719 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12720 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12721 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12722 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12723 		0x013d,
12724 	};
12725 	static const uint16_t filterctl[] = {
12726 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12727 		0xff53, 0x0127,
12728 	};
12729 	static const uint32_t psctl[] = {
12730 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12731 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12732 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12733 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12734 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12735 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12736 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12737 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12738 	};
12739 	static const uint16_t ofdmcckgain_r0[] = {
12740 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12741 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12742 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12743 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12744 		0x755d,
12745 	};
12746 	static const uint16_t ofdmcckgain_r1[] = {
12747 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12748 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12749 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12750 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12751 		0x755d,
12752 	};
12753 	static const uint16_t gaindelta[] = {
12754 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12755 		0x0000,
12756 	};
12757 	static const uint32_t txpwrctl[] = {
12758 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12759 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12760 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12761 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12762 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12763 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12764 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12765 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12766 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12767 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12768 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12769 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12770 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12771 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12772 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12773 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12774 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12775 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12776 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12777 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12778 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12779 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12780 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12781 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12782 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12783 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12784 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12785 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12786 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12787 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12788 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12789 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12790 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12791 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12792 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12793 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12794 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12795 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12796 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12797 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12798 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12799 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12800 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12801 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12802 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12803 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12804 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12805 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12806 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12807 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12808 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12809 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12810 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12811 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12812 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12813 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12814 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12815 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12816 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12817 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12818 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12819 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12820 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12821 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12822 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12823 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12824 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12825 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12826 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12827 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12828 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12829 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12830 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12831 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12832 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12833 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12834 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12835 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12836 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12837 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12838 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12839 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12840 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12841 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12842 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12843 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12844 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12845 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12846 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12847 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12848 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12849 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12850 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12851 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12852 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12853 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12854 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12855 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12856 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12857 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12858 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12859 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12860 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12861 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12862 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12863 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12864 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12865 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12866 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12867 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12868 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12869 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12870 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12871 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12872 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12873 		0x00000702,
12874 	};
12875 
12876 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12877 
12878 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12879 	    bwn_tab_sigsq_tbl);
12880 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12881 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12882 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12883 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12884 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12885 	    bwn_tab_pllfrac_tbl);
12886 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12887 	    bwn_tabl_iqlocal_tbl);
12888 	if (mac->mac_phy.rev == 0) {
12889 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12890 		    ofdmcckgain_r0);
12891 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12892 		    ofdmcckgain_r0);
12893 	} else {
12894 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12895 		    ofdmcckgain_r1);
12896 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12897 		    ofdmcckgain_r1);
12898 	}
12899 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12900 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12901 }
12902 
12903 static void
12904 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12905 {
12906 	struct bwn_softc *sc = mac->mac_sc;
12907 	int i;
12908 	static const uint16_t noisescale[] = {
12909 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12910 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12911 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12912 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12913 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12914 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12915 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12916 	};
12917 	static const uint32_t filterctl[] = {
12918 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12919 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12920 	};
12921 	static const uint32_t psctl[] = {
12922 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12923 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12924 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12925 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12926 	};
12927 	static const uint32_t gainidx[] = {
12928 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12932 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12933 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12934 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12935 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12936 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12937 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12938 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
12939 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
12940 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
12941 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
12942 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
12943 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
12947 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
12948 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
12949 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
12950 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
12951 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
12952 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
12953 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
12954 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
12955 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
12956 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
12957 		0x0000001a, 0x64ca55ad, 0x0000001a
12958 	};
12959 	static const uint16_t auxgainidx[] = {
12960 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12961 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
12962 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
12963 		0x0004, 0x0016
12964 	};
12965 	static const uint16_t swctl[] = {
12966 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12967 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12968 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12969 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
12970 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12971 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12972 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12973 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
12974 	};
12975 	static const uint8_t hf[] = {
12976 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
12977 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
12978 	};
12979 	static const uint32_t gainval[] = {
12980 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
12981 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
12982 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
12983 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
12984 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
12985 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
12986 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12988 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
12989 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
12990 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
12991 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
12992 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
12993 		0x000000f1, 0x00000000, 0x00000000
12994 	};
12995 	static const uint16_t gain[] = {
12996 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
12997 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
12998 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
12999 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13000 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13001 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13002 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13003 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13004 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13005 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13006 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13007 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13008 	};
13009 	static const uint32_t papdeps[] = {
13010 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13011 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13012 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13013 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13014 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13015 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13016 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13017 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13018 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13019 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13020 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13021 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13022 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13023 	};
13024 	static const uint32_t papdmult[] = {
13025 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13026 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13027 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13028 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13029 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13030 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13031 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13032 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13033 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13034 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13035 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13036 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13037 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13038 	};
13039 	static const uint32_t gainidx_a0[] = {
13040 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13041 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13042 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13043 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13044 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13045 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13046 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13047 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13048 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13049 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13050 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13051 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13052 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13053 	};
13054 	static const uint16_t auxgainidx_a0[] = {
13055 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13056 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13057 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13058 		0x0002, 0x0014
13059 	};
13060 	static const uint32_t gainval_a0[] = {
13061 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13062 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13063 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13064 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13065 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13066 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13067 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13068 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13069 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13070 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13071 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13072 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13073 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13074 		0x000000f7, 0x00000000, 0x00000000
13075 	};
13076 	static const uint16_t gain_a0[] = {
13077 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13078 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13079 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13080 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13081 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13082 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13083 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13084 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13085 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13086 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13087 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13088 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13089 	};
13090 
13091 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13092 
13093 	for (i = 0; i < 704; i++)
13094 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13095 
13096 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13097 	    bwn_tab_sigsq_tbl);
13098 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13099 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13100 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13101 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13102 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13103 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13104 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13105 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13106 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13107 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13108 	    bwn_tab_pllfrac_tbl);
13109 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13110 	    bwn_tabl_iqlocal_tbl);
13111 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13112 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13113 
13114 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13115 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13116 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13117 		    gainidx_a0);
13118 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13119 		    auxgainidx_a0);
13120 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13121 		    gainval_a0);
13122 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13123 	}
13124 }
13125 
13126 static void
13127 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13128 {
13129 	struct bwn_softc *sc = mac->mac_sc;
13130 	struct ieee80211com *ic = &sc->sc_ic;
13131 	static struct bwn_txgain_entry txgain_r2[] = {
13132 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13133 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13134 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13135 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13136 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13137 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13138 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13139 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13140 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13141 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13142 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13143 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13144 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13145 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13146 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13147 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13148 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13149 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13150 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13151 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13152 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13153 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13154 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13155 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13156 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13157 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13158 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13159 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13160 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13161 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13162 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13163 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13164 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13165 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13166 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13167 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13168 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13169 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13170 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13171 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13172 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13173 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13174 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13175 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13176 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13177 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13178 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13179 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13180 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13181 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13182 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13183 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13184 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13185 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13186 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13187 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13188 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13189 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13190 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13191 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13192 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13193 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13194 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13195 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13196 	};
13197 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13198 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13199 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13200 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13201 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13202 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13203 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13204 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13205 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13206 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13207 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13208 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13209 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13210 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13211 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13212 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13213 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13214 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13215 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13216 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13217 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13218 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13219 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13220 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13221 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13222 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13223 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13224 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13225 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13226 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13227 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13228 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13229 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13230 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13231 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13232 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13233 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13234 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13235 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13236 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13237 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13238 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13239 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13240 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13241 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13242 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13243 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13244 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13245 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13246 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13247 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13248 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13249 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13250 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13251 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13252 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13253 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13254 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13255 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13256 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13257 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13258 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13259 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13260 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13261 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13262 	};
13263 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13264 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13265 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13266 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13267 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13268 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13269 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13270 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13271 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13272 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13273 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13274 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13275 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13276 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13277 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13278 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13279 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13280 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13281 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13282 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13283 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13284 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13285 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13286 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13287 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13288 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13289 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13290 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13291 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13292 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13293 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13294 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13295 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13296 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13297 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13298 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13299 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13300 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13301 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13302 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13303 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13304 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13305 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13306 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13307 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13308 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13309 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13310 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13311 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13312 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13313 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13314 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13315 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13316 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13317 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13318 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13319 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13320 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13321 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13322 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13323 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13324 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13325 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13326 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13327 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13328 	};
13329 	static struct bwn_txgain_entry txgain_r0[] = {
13330 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13331 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13332 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13333 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13334 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13335 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13336 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13337 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13338 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13339 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13340 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13341 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13342 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13343 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13344 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13345 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13346 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13347 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13348 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13349 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13350 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13351 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13352 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13353 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13354 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13355 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13356 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13357 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13358 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13359 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13360 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13361 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13362 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13363 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13364 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13365 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13366 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13367 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13368 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13369 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13370 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13371 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13372 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13373 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13374 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13375 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13376 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13377 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13378 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13379 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13380 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13381 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13382 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13383 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13384 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13385 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13386 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13387 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13388 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13389 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13390 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13391 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13392 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13393 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13394 	};
13395 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13396 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13397 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13398 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13399 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13400 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13401 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13402 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13403 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13404 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13405 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13406 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13407 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13408 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13409 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13410 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13411 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13412 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13413 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13414 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13415 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13416 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13417 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13418 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13419 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13420 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13421 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13422 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13423 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13424 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13425 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13426 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13427 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13428 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13429 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13430 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13431 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13432 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13433 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13434 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13435 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13436 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13437 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13438 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13439 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13440 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13441 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13442 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13443 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13444 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13445 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13446 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13447 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13448 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13449 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13450 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13451 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13452 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13453 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13454 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13455 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13456 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13457 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13458 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13459 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13460 	};
13461 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13462 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13463 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13464 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13465 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13466 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13467 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13468 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13469 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13470 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13471 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13472 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13473 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13474 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13475 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13476 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13477 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13478 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13479 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13480 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13481 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13482 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13483 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13484 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13485 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13486 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13487 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13488 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13489 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13490 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13491 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13492 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13493 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13494 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13495 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13496 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13497 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13498 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13499 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13500 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13501 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13502 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13503 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13504 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13505 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13506 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13507 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13508 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13509 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13510 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13511 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13512 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13513 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13514 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13515 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13516 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13517 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13518 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13519 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13520 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13521 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13522 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13523 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13524 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13525 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13526 	};
13527 	static struct bwn_txgain_entry txgain_r1[] = {
13528 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13529 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13530 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13531 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13532 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13533 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13534 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13535 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13536 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13537 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13538 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13539 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13540 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13541 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13542 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13543 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13544 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13545 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13546 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13547 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13548 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13549 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13550 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13551 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13552 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13553 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13554 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13555 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13556 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13557 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13558 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13559 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13560 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13561 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13562 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13563 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13564 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13565 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13566 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13567 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13568 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13569 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13570 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13571 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13572 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13573 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13574 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13575 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13576 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13577 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13578 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13579 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13580 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13581 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13582 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13583 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13584 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13585 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13586 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13587 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13588 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13589 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13590 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13591 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13592 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13593 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13594 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13595 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13596 		{ 7, 11, 6, 0, 71 }
13597 	};
13598 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13599 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13600 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13601 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13602 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13603 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13604 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13605 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13606 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13607 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13608 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13609 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13610 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13611 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13612 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13613 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13614 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13615 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13616 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13617 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13618 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13619 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13620 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13621 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13622 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13623 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13624 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13625 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13626 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13627 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13628 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13629 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13630 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13631 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13632 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13633 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13634 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13635 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13636 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13637 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13638 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13639 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13640 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13641 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13642 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13643 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13644 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13645 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13646 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13647 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13648 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13649 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13650 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13651 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13652 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13653 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13654 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13655 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13656 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13657 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13658 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13659 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13660 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13661 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13662 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13663 	};
13664 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13665 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13666 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13667 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13668 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13669 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13670 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13671 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13672 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13673 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13674 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13675 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13676 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13677 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13678 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13679 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13680 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13681 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13682 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13683 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13684 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13685 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13686 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13687 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13688 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13689 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13690 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13691 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13692 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13693 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13694 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13695 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13696 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13697 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13698 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13699 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13700 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13701 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13702 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13703 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13704 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13705 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13706 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13707 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13708 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13709 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13710 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13711 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13712 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13713 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13714 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13715 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13716 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13717 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13718 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13719 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13720 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13721 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13722 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13723 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13724 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13725 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13726 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13727 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13728 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13729 	};
13730 
13731 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13732 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13733 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13734 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13735 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13736 			    txgain_2ghz_r2);
13737 		else
13738 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13739 			    txgain_5ghz_r2);
13740 		return;
13741 	}
13742 
13743 	if (mac->mac_phy.rev == 0) {
13744 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13745 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13746 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13747 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13748 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13749 			    txgain_2ghz_r0);
13750 		else
13751 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13752 			    txgain_5ghz_r0);
13753 		return;
13754 	}
13755 
13756 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13757 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13758 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13759 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13760 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13761 	else
13762 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13763 }
13764 
13765 static void
13766 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13767 {
13768 	uint32_t offset, type;
13769 
13770 	type = BWN_TAB_GETTYPE(typeoffset);
13771 	offset = BWN_TAB_GETOFFSET(typeoffset);
13772 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13773 
13774 	switch (type) {
13775 	case BWN_TAB_8BIT:
13776 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13777 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13778 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13779 		break;
13780 	case BWN_TAB_16BIT:
13781 		KASSERT(!(value & ~0xffff),
13782 		    ("%s:%d: fail", __func__, __LINE__));
13783 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13784 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13785 		break;
13786 	case BWN_TAB_32BIT:
13787 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13788 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13789 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13790 		break;
13791 	default:
13792 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13793 	}
13794 }
13795 
13796 static int
13797 bwn_phy_lp_loopback(struct bwn_mac *mac)
13798 {
13799 	struct bwn_phy_lp_iq_est ie;
13800 	int i, index = -1;
13801 	uint32_t tmp;
13802 
13803 	memset(&ie, 0, sizeof(ie));
13804 
13805 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13806 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13807 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13808 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13809 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13810 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13811 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13812 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13813 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13814 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13815 	for (i = 0; i < 32; i++) {
13816 		bwn_phy_lp_set_rxgain_idx(mac, i);
13817 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13818 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13819 			continue;
13820 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13821 		if ((tmp > 4000) && (tmp < 10000)) {
13822 			index = i;
13823 			break;
13824 		}
13825 	}
13826 	bwn_phy_lp_ddfs_turnoff(mac);
13827 	return (index);
13828 }
13829 
13830 static void
13831 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13832 {
13833 
13834 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13835 }
13836 
13837 static void
13838 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13839     int incr1, int incr2, int scale_idx)
13840 {
13841 
13842 	bwn_phy_lp_ddfs_turnoff(mac);
13843 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13844 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13845 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13846 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13847 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13848 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13849 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13850 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13851 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13852 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13853 }
13854 
13855 static uint8_t
13856 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13857     struct bwn_phy_lp_iq_est *ie)
13858 {
13859 	int i;
13860 
13861 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13862 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13863 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13864 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13865 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13866 
13867 	for (i = 0; i < 500; i++) {
13868 		if (!(BWN_PHY_READ(mac,
13869 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13870 			break;
13871 		DELAY(1000);
13872 	}
13873 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13874 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13875 		return 0;
13876 	}
13877 
13878 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13879 	ie->ie_iqprod <<= 16;
13880 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13881 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13882 	ie->ie_ipwr <<= 16;
13883 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13884 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13885 	ie->ie_qpwr <<= 16;
13886 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13887 
13888 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13889 	return 1;
13890 }
13891 
13892 static uint32_t
13893 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13894 {
13895 	uint32_t offset, type, value;
13896 
13897 	type = BWN_TAB_GETTYPE(typeoffset);
13898 	offset = BWN_TAB_GETOFFSET(typeoffset);
13899 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13900 
13901 	switch (type) {
13902 	case BWN_TAB_8BIT:
13903 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13904 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13905 		break;
13906 	case BWN_TAB_16BIT:
13907 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13908 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13909 		break;
13910 	case BWN_TAB_32BIT:
13911 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13912 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13913 		value <<= 16;
13914 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13915 		break;
13916 	default:
13917 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13918 		value = 0;
13919 	}
13920 
13921 	return (value);
13922 }
13923 
13924 static void
13925 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13926 {
13927 
13928 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13929 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13930 }
13931 
13932 static void
13933 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13934 {
13935 	uint16_t ctl;
13936 
13937 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
13938 	ctl |= dac << 7;
13939 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
13940 }
13941 
13942 static void
13943 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
13944 {
13945 
13946 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
13947 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
13948 }
13949 
13950 static void
13951 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
13952 {
13953 
13954 	if (mac->mac_phy.rev < 2)
13955 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
13956 	else {
13957 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
13958 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
13959 	}
13960 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
13961 }
13962 
13963 static uint16_t
13964 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
13965 {
13966 
13967 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
13968 }
13969 
13970 static uint8_t
13971 bwn_nbits(int32_t val)
13972 {
13973 	uint32_t tmp;
13974 	uint8_t nbits = 0;
13975 
13976 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
13977 		nbits++;
13978 	return (nbits);
13979 }
13980 
13981 static void
13982 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
13983     struct bwn_txgain_entry *table)
13984 {
13985 	int i;
13986 
13987 	for (i = offset; i < count; i++)
13988 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
13989 }
13990 
13991 static void
13992 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
13993     struct bwn_txgain_entry data)
13994 {
13995 
13996 	if (mac->mac_phy.rev >= 2)
13997 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
13998 	else
13999 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14000 }
14001 
14002 static void
14003 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14004     struct bwn_txgain_entry te)
14005 {
14006 	struct bwn_softc *sc = mac->mac_sc;
14007 	struct ieee80211com *ic = &sc->sc_ic;
14008 	uint32_t tmp;
14009 
14010 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14011 
14012 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14013 	if (mac->mac_phy.rev >= 3) {
14014 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14015 		    (0x10 << 24) : (0x70 << 24));
14016 	} else {
14017 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14018 		    (0x14 << 24) : (0x7f << 24));
14019 	}
14020 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14021 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14022 	    te.te_bbmult << 20 | te.te_dac << 28);
14023 }
14024 
14025 static void
14026 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14027     struct bwn_txgain_entry te)
14028 {
14029 
14030 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14031 
14032 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14033 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14034 	    te.te_dac);
14035 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14036 }
14037 
14038 static void
14039 bwn_sysctl_node(struct bwn_softc *sc)
14040 {
14041 	device_t dev = sc->sc_dev;
14042 	struct bwn_mac *mac;
14043 	struct bwn_stats *stats;
14044 
14045 	/* XXX assume that count of MAC is only 1. */
14046 
14047 	if ((mac = sc->sc_curmac) == NULL)
14048 		return;
14049 	stats = &mac->mac_stats;
14050 
14051 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14052 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14053 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14054 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14055 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14056 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14057 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14058 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14059 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14060 
14061 #ifdef BWN_DEBUG
14062 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14063 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14064 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14065 #endif
14066 }
14067 
14068 static device_method_t bwn_methods[] = {
14069 	/* Device interface */
14070 	DEVMETHOD(device_probe,		bwn_probe),
14071 	DEVMETHOD(device_attach,	bwn_attach),
14072 	DEVMETHOD(device_detach,	bwn_detach),
14073 	DEVMETHOD(device_suspend,	bwn_suspend),
14074 	DEVMETHOD(device_resume,	bwn_resume),
14075 	DEVMETHOD_END
14076 };
14077 static driver_t bwn_driver = {
14078 	"bwn",
14079 	bwn_methods,
14080 	sizeof(struct bwn_softc)
14081 };
14082 static devclass_t bwn_devclass;
14083 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14084 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14085 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14086 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14087 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14088