xref: /freebsd/sys/dev/bwn/if_bwn.c (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * The Broadcom Wireless LAN controller driver.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/module.h>
40 #include <sys/kernel.h>
41 #include <sys/endian.h>
42 #include <sys/errno.h>
43 #include <sys/firmware.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_var.h>
56 #include <net/if_arp.h>
57 #include <net/if_dl.h>
58 #include <net/if_llc.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 
62 #include <dev/pci/pcivar.h>
63 #include <dev/pci/pcireg.h>
64 #include <dev/siba/siba_ids.h>
65 #include <dev/siba/sibareg.h>
66 #include <dev/siba/sibavar.h>
67 
68 #include <net80211/ieee80211_var.h>
69 #include <net80211/ieee80211_radiotap.h>
70 #include <net80211/ieee80211_regdomain.h>
71 #include <net80211/ieee80211_phy.h>
72 #include <net80211/ieee80211_ratectl.h>
73 
74 #include <dev/bwn/if_bwnreg.h>
75 #include <dev/bwn/if_bwnvar.h>
76 
77 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
78     "Broadcom driver parameters");
79 
80 /*
81  * Tunable & sysctl variables.
82  */
83 
84 #ifdef BWN_DEBUG
85 static	int bwn_debug = 0;
86 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
87     "Broadcom debugging printfs");
88 enum {
89 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107 	BWN_DEBUG_ANY		= 0xffffffff
108 };
109 #define	DPRINTF(sc, m, fmt, ...) do {			\
110 	if (sc->sc_debug & (m))				\
111 		printf(fmt, __VA_ARGS__);		\
112 } while (0)
113 #else
114 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115 #endif
116 
117 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119     "uses Bad Frames Preemption");
120 static int	bwn_bluetooth = 1;
121 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122     "turns on Bluetooth Coexistence");
123 static int	bwn_hwpctl = 0;
124 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125     "uses H/W power control");
126 static int	bwn_msi_disable = 0;		/* MSI disabled  */
127 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128 static int	bwn_usedma = 1;
129 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130     "uses DMA");
131 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132 static int	bwn_wme = 1;
133 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134     "uses WME support");
135 
136 static int	bwn_attach_pre(struct bwn_softc *);
137 static int	bwn_attach_post(struct bwn_softc *);
138 static void	bwn_sprom_bugfixes(device_t);
139 static void	bwn_init(void *);
140 static int	bwn_init_locked(struct bwn_softc *);
141 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
142 static void	bwn_start(struct ifnet *);
143 static int	bwn_attach_core(struct bwn_mac *);
144 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145 static int	bwn_phy_getinfo(struct bwn_mac *, int);
146 static int	bwn_chiptest(struct bwn_mac *);
147 static int	bwn_setup_channels(struct bwn_mac *, int, int);
148 static int	bwn_phy_g_attach(struct bwn_mac *);
149 static void	bwn_phy_g_detach(struct bwn_mac *);
150 static void	bwn_phy_g_init_pre(struct bwn_mac *);
151 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152 static int	bwn_phy_g_init(struct bwn_mac *);
153 static void	bwn_phy_g_exit(struct bwn_mac *);
154 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156 		    uint16_t);
157 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159 		    uint16_t);
160 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165 static int	bwn_phy_g_im(struct bwn_mac *, int);
166 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168 static void	bwn_phy_g_task_15s(struct bwn_mac *);
169 static void	bwn_phy_g_task_60s(struct bwn_mac *);
170 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174 		    uint16_t);
175 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177 		    uint32_t);
178 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179 		    uint16_t);
180 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181 		    const struct bwn_channelinfo *, int);
182 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183 		    const struct ieee80211_bpf_params *);
184 static void	bwn_updateslot(struct ieee80211com *);
185 static void	bwn_update_promisc(struct ieee80211com *);
186 static void	bwn_wme_init(struct bwn_mac *);
187 static int	bwn_wme_update(struct ieee80211com *);
188 static void	bwn_wme_clear(struct bwn_softc *);
189 static void	bwn_wme_load(struct bwn_mac *);
190 static void	bwn_wme_loadparams(struct bwn_mac *,
191 		    const struct wmeParams *, uint16_t);
192 static void	bwn_scan_start(struct ieee80211com *);
193 static void	bwn_scan_end(struct ieee80211com *);
194 static void	bwn_set_channel(struct ieee80211com *);
195 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197 		    const uint8_t [IEEE80211_ADDR_LEN],
198 		    const uint8_t [IEEE80211_ADDR_LEN]);
199 static void	bwn_vap_delete(struct ieee80211vap *);
200 static void	bwn_stop(struct bwn_softc *, int);
201 static void	bwn_stop_locked(struct bwn_softc *, int);
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 void	bwn_start_locked(struct ifnet *);
413 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414 		    struct mbuf *);
415 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416 static int	bwn_set_txhdr(struct bwn_mac *,
417 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418 		    uint16_t);
419 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420 		    const uint8_t);
421 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422 static uint8_t	bwn_get_fbrate(uint8_t);
423 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425 static void	bwn_phy_lock(struct bwn_mac *);
426 static void	bwn_phy_unlock(struct bwn_mac *);
427 static void	bwn_rf_lock(struct bwn_mac *);
428 static void	bwn_rf_unlock(struct bwn_mac *);
429 static void	bwn_txpwr(void *, int);
430 static void	bwn_tasks(void *);
431 static void	bwn_task_15s(struct bwn_mac *);
432 static void	bwn_task_30s(struct bwn_mac *);
433 static void	bwn_task_60s(struct bwn_mac *);
434 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435 		    uint8_t);
436 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439 		    int, int);
440 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
441 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
443 static void	bwn_watchdog(void *);
444 static void	bwn_dma_stop(struct bwn_mac *);
445 static void	bwn_pio_stop(struct bwn_mac *);
446 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
447 static void	bwn_led_attach(struct bwn_mac *);
448 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449 static void	bwn_led_event(struct bwn_mac *, int);
450 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
451 static void	bwn_led_blink_next(void *);
452 static void	bwn_led_blink_end(void *);
453 static void	bwn_rfswitch(void *);
454 static void	bwn_rf_turnon(struct bwn_mac *);
455 static void	bwn_rf_turnoff(struct bwn_mac *);
456 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
457 static int	bwn_phy_lp_init(struct bwn_mac *);
458 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461 		    uint16_t);
462 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
467 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
469 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
470 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
471 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
472 static void	bwn_phy_lp_calib(struct bwn_mac *);
473 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
479 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
482 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
483 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
484 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
487 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
488 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
490 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
491 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495 		    const void *);
496 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497 static struct bwn_txgain
498 		bwn_phy_lp_get_txgain(struct bwn_mac *);
499 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
500 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513 static int	bwn_phy_lp_loopback(struct bwn_mac *);
514 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516 		    int);
517 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518 		    struct bwn_phy_lp_iq_est *);
519 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
521 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525 static uint8_t	bwn_nbits(int32_t);
526 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527 		    struct bwn_txgain_entry *);
528 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529 		    struct bwn_txgain_entry);
530 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531 		    struct bwn_txgain_entry);
532 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533 		    struct bwn_txgain_entry);
534 static void	bwn_sysctl_node(struct bwn_softc *);
535 
536 static struct resource_spec bwn_res_spec_legacy[] = {
537 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
538 	{ -1,			0,		0 }
539 };
540 
541 static struct resource_spec bwn_res_spec_msi[] = {
542 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
543 	{ -1,			0,		0 }
544 };
545 
546 static const struct bwn_channelinfo bwn_chantable_bg = {
547 	.channels = {
548 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
549 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
550 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
551 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
553 	.nchannels = 14
554 };
555 
556 static const struct bwn_channelinfo bwn_chantable_a = {
557 	.channels = {
558 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
559 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
560 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
561 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
562 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570 		{ 6080, 216, 30 } },
571 	.nchannels = 37
572 };
573 
574 static const struct bwn_channelinfo bwn_chantable_n = {
575 	.channels = {
576 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
577 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
578 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
579 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
580 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
581 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
582 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
583 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
584 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
585 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
586 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
587 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
613 	.nchannels = 110
614 };
615 
616 static const uint8_t bwn_b2063_chantable_data[33][12] = {
617 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650 };
651 
652 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653 	{ 1, 2412, bwn_b2063_chantable_data[0] },
654 	{ 2, 2417, bwn_b2063_chantable_data[0] },
655 	{ 3, 2422, bwn_b2063_chantable_data[0] },
656 	{ 4, 2427, bwn_b2063_chantable_data[1] },
657 	{ 5, 2432, bwn_b2063_chantable_data[1] },
658 	{ 6, 2437, bwn_b2063_chantable_data[1] },
659 	{ 7, 2442, bwn_b2063_chantable_data[1] },
660 	{ 8, 2447, bwn_b2063_chantable_data[1] },
661 	{ 9, 2452, bwn_b2063_chantable_data[2] },
662 	{ 10, 2457, bwn_b2063_chantable_data[2] },
663 	{ 11, 2462, bwn_b2063_chantable_data[3] },
664 	{ 12, 2467, bwn_b2063_chantable_data[3] },
665 	{ 13, 2472, bwn_b2063_chantable_data[3] },
666 	{ 14, 2484, bwn_b2063_chantable_data[4] },
667 	{ 34, 5170, bwn_b2063_chantable_data[5] },
668 	{ 36, 5180, bwn_b2063_chantable_data[6] },
669 	{ 38, 5190, bwn_b2063_chantable_data[7] },
670 	{ 40, 5200, bwn_b2063_chantable_data[8] },
671 	{ 42, 5210, bwn_b2063_chantable_data[9] },
672 	{ 44, 5220, bwn_b2063_chantable_data[10] },
673 	{ 46, 5230, bwn_b2063_chantable_data[11] },
674 	{ 48, 5240, bwn_b2063_chantable_data[12] },
675 	{ 52, 5260, bwn_b2063_chantable_data[13] },
676 	{ 56, 5280, bwn_b2063_chantable_data[14] },
677 	{ 60, 5300, bwn_b2063_chantable_data[14] },
678 	{ 64, 5320, bwn_b2063_chantable_data[15] },
679 	{ 100, 5500, bwn_b2063_chantable_data[16] },
680 	{ 104, 5520, bwn_b2063_chantable_data[17] },
681 	{ 108, 5540, bwn_b2063_chantable_data[18] },
682 	{ 112, 5560, bwn_b2063_chantable_data[19] },
683 	{ 116, 5580, bwn_b2063_chantable_data[20] },
684 	{ 120, 5600, bwn_b2063_chantable_data[21] },
685 	{ 124, 5620, bwn_b2063_chantable_data[21] },
686 	{ 128, 5640, bwn_b2063_chantable_data[22] },
687 	{ 132, 5660, bwn_b2063_chantable_data[22] },
688 	{ 136, 5680, bwn_b2063_chantable_data[22] },
689 	{ 140, 5700, bwn_b2063_chantable_data[23] },
690 	{ 149, 5745, bwn_b2063_chantable_data[23] },
691 	{ 153, 5765, bwn_b2063_chantable_data[23] },
692 	{ 157, 5785, bwn_b2063_chantable_data[23] },
693 	{ 161, 5805, bwn_b2063_chantable_data[23] },
694 	{ 165, 5825, bwn_b2063_chantable_data[23] },
695 	{ 184, 4920, bwn_b2063_chantable_data[24] },
696 	{ 188, 4940, bwn_b2063_chantable_data[25] },
697 	{ 192, 4960, bwn_b2063_chantable_data[26] },
698 	{ 196, 4980, bwn_b2063_chantable_data[27] },
699 	{ 200, 5000, bwn_b2063_chantable_data[28] },
700 	{ 204, 5020, bwn_b2063_chantable_data[29] },
701 	{ 208, 5040, bwn_b2063_chantable_data[30] },
702 	{ 212, 5060, bwn_b2063_chantable_data[31] },
703 	{ 216, 5080, bwn_b2063_chantable_data[32] }
704 };
705 
706 static const uint8_t bwn_b2062_chantable_data[22][12] = {
707 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729 };
730 
731 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732 	{ 1, 2412, bwn_b2062_chantable_data[0] },
733 	{ 2, 2417, bwn_b2062_chantable_data[0] },
734 	{ 3, 2422, bwn_b2062_chantable_data[0] },
735 	{ 4, 2427, bwn_b2062_chantable_data[0] },
736 	{ 5, 2432, bwn_b2062_chantable_data[0] },
737 	{ 6, 2437, bwn_b2062_chantable_data[0] },
738 	{ 7, 2442, bwn_b2062_chantable_data[0] },
739 	{ 8, 2447, bwn_b2062_chantable_data[0] },
740 	{ 9, 2452, bwn_b2062_chantable_data[0] },
741 	{ 10, 2457, bwn_b2062_chantable_data[0] },
742 	{ 11, 2462, bwn_b2062_chantable_data[0] },
743 	{ 12, 2467, bwn_b2062_chantable_data[0] },
744 	{ 13, 2472, bwn_b2062_chantable_data[0] },
745 	{ 14, 2484, bwn_b2062_chantable_data[0] },
746 	{ 34, 5170, bwn_b2062_chantable_data[1] },
747 	{ 38, 5190, bwn_b2062_chantable_data[2] },
748 	{ 42, 5210, bwn_b2062_chantable_data[2] },
749 	{ 46, 5230, bwn_b2062_chantable_data[3] },
750 	{ 36, 5180, bwn_b2062_chantable_data[4] },
751 	{ 40, 5200, bwn_b2062_chantable_data[5] },
752 	{ 44, 5220, bwn_b2062_chantable_data[6] },
753 	{ 48, 5240, bwn_b2062_chantable_data[3] },
754 	{ 52, 5260, bwn_b2062_chantable_data[3] },
755 	{ 56, 5280, bwn_b2062_chantable_data[3] },
756 	{ 60, 5300, bwn_b2062_chantable_data[7] },
757 	{ 64, 5320, bwn_b2062_chantable_data[8] },
758 	{ 100, 5500, bwn_b2062_chantable_data[9] },
759 	{ 104, 5520, bwn_b2062_chantable_data[10] },
760 	{ 108, 5540, bwn_b2062_chantable_data[10] },
761 	{ 112, 5560, bwn_b2062_chantable_data[10] },
762 	{ 116, 5580, bwn_b2062_chantable_data[11] },
763 	{ 120, 5600, bwn_b2062_chantable_data[12] },
764 	{ 124, 5620, bwn_b2062_chantable_data[12] },
765 	{ 128, 5640, bwn_b2062_chantable_data[12] },
766 	{ 132, 5660, bwn_b2062_chantable_data[12] },
767 	{ 136, 5680, bwn_b2062_chantable_data[12] },
768 	{ 140, 5700, bwn_b2062_chantable_data[12] },
769 	{ 149, 5745, bwn_b2062_chantable_data[12] },
770 	{ 153, 5765, bwn_b2062_chantable_data[12] },
771 	{ 157, 5785, bwn_b2062_chantable_data[12] },
772 	{ 161, 5805, bwn_b2062_chantable_data[12] },
773 	{ 165, 5825, bwn_b2062_chantable_data[12] },
774 	{ 184, 4920, bwn_b2062_chantable_data[13] },
775 	{ 188, 4940, bwn_b2062_chantable_data[14] },
776 	{ 192, 4960, bwn_b2062_chantable_data[15] },
777 	{ 196, 4980, bwn_b2062_chantable_data[16] },
778 	{ 200, 5000, bwn_b2062_chantable_data[17] },
779 	{ 204, 5020, bwn_b2062_chantable_data[18] },
780 	{ 208, 5040, bwn_b2062_chantable_data[19] },
781 	{ 212, 5060, bwn_b2062_chantable_data[20] },
782 	{ 216, 5080, bwn_b2062_chantable_data[21] }
783 };
784 
785 /* for LP PHY */
786 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
788 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
789 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790 	{ 13, -66, 13 }, { 14, -66, 13 },
791 };
792 
793 /* for LP PHY */
794 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
796 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
797 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
798 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
799 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
800 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
801 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
805 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
806 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808 };
809 
810 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811 
812 static const uint8_t bwn_tab_sigsq_tbl[] = {
813 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819 };
820 
821 static const uint8_t bwn_tab_pllfrac_tbl[] = {
822 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824 };
825 
826 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 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, 0x0000, 0x0000, 0x0000,
836 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839 };
840 
841 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847 
848 #define	VENDOR_LED_ACT(vendor)				\
849 {							\
850 	.vid = PCI_VENDOR_##vendor,			\
851 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
852 }
853 
854 static const struct {
855 	uint16_t	vid;
856 	uint8_t		led_act[BWN_LED_MAX];
857 } bwn_vendor_led_act[] = {
858 	VENDOR_LED_ACT(COMPAQ),
859 	VENDOR_LED_ACT(ASUSTEK)
860 };
861 
862 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863 	{ BWN_VENDOR_LED_ACT_DEFAULT };
864 
865 #undef VENDOR_LED_ACT
866 
867 static const struct {
868 	int		on_dur;
869 	int		off_dur;
870 } bwn_led_duration[109] = {
871 	[0]	= { 400, 100 },
872 	[2]	= { 150, 75 },
873 	[4]	= { 90, 45 },
874 	[11]	= { 66, 34 },
875 	[12]	= { 53, 26 },
876 	[18]	= { 42, 21 },
877 	[22]	= { 35, 17 },
878 	[24]	= { 32, 16 },
879 	[36]	= { 21, 10 },
880 	[48]	= { 16, 8 },
881 	[72]	= { 11, 5 },
882 	[96]	= { 9, 4 },
883 	[108]	= { 7, 3 }
884 };
885 
886 static const uint16_t bwn_wme_shm_offsets[] = {
887 	[0] = BWN_WME_BESTEFFORT,
888 	[1] = BWN_WME_BACKGROUND,
889 	[2] = BWN_WME_VOICE,
890 	[3] = BWN_WME_VIDEO,
891 };
892 
893 static const struct siba_devid bwn_devs[] = {
894 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903 };
904 
905 static int
906 bwn_probe(device_t dev)
907 {
908 	int i;
909 
910 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911 		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912 		    siba_get_device(dev) == bwn_devs[i].sd_device &&
913 		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
914 			return (BUS_PROBE_DEFAULT);
915 	}
916 
917 	return (ENXIO);
918 }
919 
920 static int
921 bwn_attach(device_t dev)
922 {
923 	struct bwn_mac *mac;
924 	struct bwn_softc *sc = device_get_softc(dev);
925 	int error, i, msic, reg;
926 
927 	sc->sc_dev = dev;
928 #ifdef BWN_DEBUG
929 	sc->sc_debug = bwn_debug;
930 #endif
931 
932 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933 		error = bwn_attach_pre(sc);
934 		if (error != 0)
935 			return (error);
936 		bwn_sprom_bugfixes(dev);
937 		sc->sc_flags |= BWN_FLAG_ATTACHED;
938 	}
939 
940 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941 		if (siba_get_pci_device(dev) != 0x4313 &&
942 		    siba_get_pci_device(dev) != 0x431a &&
943 		    siba_get_pci_device(dev) != 0x4321) {
944 			device_printf(sc->sc_dev,
945 			    "skip 802.11 cores\n");
946 			return (ENODEV);
947 		}
948 	}
949 
950 	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951 	    M_NOWAIT | M_ZERO);
952 	if (mac == NULL)
953 		return (ENOMEM);
954 	mac->mac_sc = sc;
955 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
956 	if (bwn_bfp != 0)
957 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958 
959 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962 
963 	error = bwn_attach_core(mac);
964 	if (error)
965 		goto fail0;
966 	bwn_led_attach(mac);
967 
968 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973 	    mac->mac_phy.rf_rev);
974 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
976 		    mac->mac_method.dma.dmatype);
977 	else
978 		device_printf(sc->sc_dev, "PIO\n");
979 
980 	/*
981 	 * setup PCI resources and interrupt.
982 	 */
983 	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
984 		msic = pci_msi_count(dev);
985 		if (bootverbose)
986 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987 	} else
988 		msic = 0;
989 
990 	mac->mac_intr_spec = bwn_res_spec_legacy;
991 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992 		if (pci_alloc_msi(dev, &msic) == 0) {
993 			device_printf(sc->sc_dev,
994 			    "Using %d MSI messages\n", msic);
995 			mac->mac_intr_spec = bwn_res_spec_msi;
996 			mac->mac_msi = 1;
997 		}
998 	}
999 
1000 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001 	    mac->mac_res_irq);
1002 	if (error) {
1003 		device_printf(sc->sc_dev,
1004 		    "couldn't allocate IRQ resources (%d)\n", error);
1005 		goto fail1;
1006 	}
1007 
1008 	if (mac->mac_msi == 0)
1009 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011 		    &mac->mac_intrhand[0]);
1012 	else {
1013 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016 			    &mac->mac_intrhand[i]);
1017 			if (error != 0) {
1018 				device_printf(sc->sc_dev,
1019 				    "couldn't setup interrupt (%d)\n", error);
1020 				break;
1021 			}
1022 		}
1023 	}
1024 
1025 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026 
1027 	/*
1028 	 * calls attach-post routine
1029 	 */
1030 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031 		bwn_attach_post(sc);
1032 
1033 	return (0);
1034 fail1:
1035 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036 		pci_release_msi(dev);
1037 fail0:
1038 	free(mac, M_DEVBUF);
1039 	return (error);
1040 }
1041 
1042 static int
1043 bwn_is_valid_ether_addr(uint8_t *addr)
1044 {
1045 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046 
1047 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048 		return (FALSE);
1049 
1050 	return (TRUE);
1051 }
1052 
1053 static int
1054 bwn_attach_post(struct bwn_softc *sc)
1055 {
1056 	struct ieee80211com *ic;
1057 	struct ifnet *ifp = sc->sc_ifp;
1058 
1059 	ic = ifp->if_l2com;
1060 	ic->ic_ifp = ifp;
1061 	ic->ic_softc = sc;
1062 	ic->ic_name = device_get_nameunit(sc->sc_dev);
1063 	/* XXX not right but it's not used anywhere important */
1064 	ic->ic_phytype = IEEE80211_T_OFDM;
1065 	ic->ic_opmode = IEEE80211_M_STA;
1066 	ic->ic_caps =
1067 		  IEEE80211_C_STA		/* station mode supported */
1068 		| IEEE80211_C_MONITOR		/* monitor mode */
1069 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1070 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1071 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1072 		| IEEE80211_C_WME		/* WME/WMM supported */
1073 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1074 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1075 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1076 		;
1077 
1078 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1079 
1080 	/* call MI attach routine. */
1081 	ieee80211_ifattach(ic,
1082 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1083 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1084 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1085 
1086 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1087 
1088 	/* override default methods */
1089 	ic->ic_raw_xmit = bwn_raw_xmit;
1090 	ic->ic_updateslot = bwn_updateslot;
1091 	ic->ic_update_promisc = bwn_update_promisc;
1092 	ic->ic_wme.wme_update = bwn_wme_update;
1093 
1094 	ic->ic_scan_start = bwn_scan_start;
1095 	ic->ic_scan_end = bwn_scan_end;
1096 	ic->ic_set_channel = bwn_set_channel;
1097 
1098 	ic->ic_vap_create = bwn_vap_create;
1099 	ic->ic_vap_delete = bwn_vap_delete;
1100 
1101 	ieee80211_radiotap_attach(ic,
1102 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1103 	    BWN_TX_RADIOTAP_PRESENT,
1104 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1105 	    BWN_RX_RADIOTAP_PRESENT);
1106 
1107 	bwn_sysctl_node(sc);
1108 
1109 	if (bootverbose)
1110 		ieee80211_announce(ic);
1111 	return (0);
1112 }
1113 
1114 static void
1115 bwn_phy_detach(struct bwn_mac *mac)
1116 {
1117 
1118 	if (mac->mac_phy.detach != NULL)
1119 		mac->mac_phy.detach(mac);
1120 }
1121 
1122 static int
1123 bwn_detach(device_t dev)
1124 {
1125 	struct bwn_softc *sc = device_get_softc(dev);
1126 	struct bwn_mac *mac = sc->sc_curmac;
1127 	struct ifnet *ifp = sc->sc_ifp;
1128 	struct ieee80211com *ic = ifp->if_l2com;
1129 	int i;
1130 
1131 	sc->sc_flags |= BWN_FLAG_INVALID;
1132 
1133 	if (device_is_attached(sc->sc_dev)) {
1134 		bwn_stop(sc, 1);
1135 		bwn_dma_free(mac);
1136 		callout_drain(&sc->sc_led_blink_ch);
1137 		callout_drain(&sc->sc_rfswitch_ch);
1138 		callout_drain(&sc->sc_task_ch);
1139 		callout_drain(&sc->sc_watchdog_ch);
1140 		bwn_phy_detach(mac);
1141 		if (ifp != NULL) {
1142 			ieee80211_draintask(ic, &mac->mac_hwreset);
1143 			ieee80211_draintask(ic, &mac->mac_txpower);
1144 			ieee80211_ifdetach(ic);
1145 			if_free(ifp);
1146 		}
1147 	}
1148 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1149 	taskqueue_free(sc->sc_tq);
1150 
1151 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1152 		if (mac->mac_intrhand[i] != NULL) {
1153 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1154 			    mac->mac_intrhand[i]);
1155 			mac->mac_intrhand[i] = NULL;
1156 		}
1157 	}
1158 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1159 	if (mac->mac_msi != 0)
1160 		pci_release_msi(dev);
1161 
1162 	BWN_LOCK_DESTROY(sc);
1163 	return (0);
1164 }
1165 
1166 static int
1167 bwn_attach_pre(struct bwn_softc *sc)
1168 {
1169 	struct ifnet *ifp;
1170 	int error = 0;
1171 
1172 	BWN_LOCK_INIT(sc);
1173 	TAILQ_INIT(&sc->sc_maclist);
1174 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1175 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1176 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1177 
1178 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1179 		taskqueue_thread_enqueue, &sc->sc_tq);
1180 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1181 		"%s taskq", device_get_nameunit(sc->sc_dev));
1182 
1183 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1184 	if (ifp == NULL) {
1185 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1186 		error = ENOSPC;
1187 		goto fail;
1188 	}
1189 
1190 	/* set these up early for if_printf use */
1191 	if_initname(ifp, device_get_name(sc->sc_dev),
1192 	    device_get_unit(sc->sc_dev));
1193 
1194 	ifp->if_softc = sc;
1195 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1196 	ifp->if_init = bwn_init;
1197 	ifp->if_ioctl = bwn_ioctl;
1198 	ifp->if_start = bwn_start;
1199 	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1200 	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1201 	IFQ_SET_READY(&ifp->if_snd);
1202 
1203 	return (0);
1204 
1205 fail:	BWN_LOCK_DESTROY(sc);
1206 	return (error);
1207 }
1208 
1209 static void
1210 bwn_sprom_bugfixes(device_t dev)
1211 {
1212 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1213 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1214 	 (siba_get_pci_device(dev) == _device) &&			\
1215 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1216 	 (siba_get_pci_subdevice(dev) == _subdevice))
1217 
1218 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1219 	    siba_get_pci_subdevice(dev) == 0x4e &&
1220 	    siba_get_pci_revid(dev) > 0x40)
1221 		siba_sprom_set_bf_lo(dev,
1222 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1223 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1224 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1225 		siba_sprom_set_bf_lo(dev,
1226 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1227 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1228 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1229 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1230 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1231 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1232 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1233 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1234 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1235 			siba_sprom_set_bf_lo(dev,
1236 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1237 	}
1238 #undef	BWN_ISDEV
1239 }
1240 
1241 static int
1242 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1243 {
1244 #define	IS_RUNNING(ifp) \
1245 	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1246 	struct bwn_softc *sc = ifp->if_softc;
1247 	struct ieee80211com *ic = ifp->if_l2com;
1248 	struct ifreq *ifr = (struct ifreq *)data;
1249 	int error = 0, startall;
1250 
1251 	switch (cmd) {
1252 	case SIOCSIFFLAGS:
1253 		startall = 0;
1254 		if (IS_RUNNING(ifp)) {
1255 			bwn_update_promisc(ic);
1256 		} else if (ifp->if_flags & IFF_UP) {
1257 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1258 				bwn_init(sc);
1259 				startall = 1;
1260 			}
1261 		} else
1262 			bwn_stop(sc, 1);
1263 		if (startall)
1264 			ieee80211_start_all(ic);
1265 		break;
1266 	case SIOCGIFMEDIA:
1267 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1268 		break;
1269 	case SIOCGIFADDR:
1270 		error = ether_ioctl(ifp, cmd, data);
1271 		break;
1272 	default:
1273 		error = EINVAL;
1274 		break;
1275 	}
1276 	return (error);
1277 }
1278 
1279 static void
1280 bwn_start(struct ifnet *ifp)
1281 {
1282 	struct bwn_softc *sc = ifp->if_softc;
1283 
1284 	BWN_LOCK(sc);
1285 	bwn_start_locked(ifp);
1286 	BWN_UNLOCK(sc);
1287 }
1288 
1289 static void
1290 bwn_start_locked(struct ifnet *ifp)
1291 {
1292 	struct bwn_softc *sc = ifp->if_softc;
1293 	struct bwn_mac *mac = sc->sc_curmac;
1294 	struct ieee80211_frame *wh;
1295 	struct ieee80211_node *ni;
1296 	struct ieee80211_key *k;
1297 	struct mbuf *m;
1298 
1299 	BWN_ASSERT_LOCKED(sc);
1300 
1301 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1302 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1303 		return;
1304 
1305 	for (;;) {
1306 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1307 		if (m == NULL)
1308 			break;
1309 
1310 		if (bwn_tx_isfull(sc, m))
1311 			break;
1312 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1313 		if (ni == NULL) {
1314 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1315 			m_freem(m);
1316 			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1317 			continue;
1318 		}
1319 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1320 		wh = mtod(m, struct ieee80211_frame *);
1321 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1322 			k = ieee80211_crypto_encap(ni, m);
1323 			if (k == NULL) {
1324 				ieee80211_free_node(ni);
1325 				m_freem(m);
1326 				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1327 				continue;
1328 			}
1329 		}
1330 		wh = NULL;	/* Catch any invalid use */
1331 
1332 		if (bwn_tx_start(sc, ni, m) != 0) {
1333 			if (ni != NULL)
1334 				ieee80211_free_node(ni);
1335 			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1336 			continue;
1337 		}
1338 
1339 		sc->sc_watchdog_timer = 5;
1340 	}
1341 }
1342 
1343 static int
1344 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1345 {
1346 	struct bwn_dma_ring *dr;
1347 	struct bwn_mac *mac = sc->sc_curmac;
1348 	struct bwn_pio_txqueue *tq;
1349 	struct ifnet *ifp = sc->sc_ifp;
1350 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1351 
1352 	BWN_ASSERT_LOCKED(sc);
1353 
1354 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1355 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1356 		if (dr->dr_stop == 1 ||
1357 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1358 			dr->dr_stop = 1;
1359 			goto full;
1360 		}
1361 	} else {
1362 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1363 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1364 		    pktlen > (tq->tq_size - tq->tq_used)) {
1365 			tq->tq_stop = 1;
1366 			goto full;
1367 		}
1368 	}
1369 	return (0);
1370 full:
1371 	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1372 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1373 	return (1);
1374 }
1375 
1376 static int
1377 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1378 {
1379 	struct bwn_mac *mac = sc->sc_curmac;
1380 	int error;
1381 
1382 	BWN_ASSERT_LOCKED(sc);
1383 
1384 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1385 		m_freem(m);
1386 		return (ENXIO);
1387 	}
1388 
1389 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1390 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1391 	if (error) {
1392 		m_freem(m);
1393 		return (error);
1394 	}
1395 	return (0);
1396 }
1397 
1398 static int
1399 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1400 {
1401 	struct bwn_pio_txpkt *tp;
1402 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1403 	struct bwn_softc *sc = mac->mac_sc;
1404 	struct bwn_txhdr txhdr;
1405 	struct mbuf *m_new;
1406 	uint32_t ctl32;
1407 	int error;
1408 	uint16_t ctl16;
1409 
1410 	BWN_ASSERT_LOCKED(sc);
1411 
1412 	/* XXX TODO send packets after DTIM */
1413 
1414 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1415 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1416 	tp->tp_ni = ni;
1417 	tp->tp_m = m;
1418 
1419 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1420 	if (error) {
1421 		device_printf(sc->sc_dev, "tx fail\n");
1422 		return (error);
1423 	}
1424 
1425 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1426 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1427 	tq->tq_free--;
1428 
1429 	if (siba_get_revid(sc->sc_dev) >= 8) {
1430 		/*
1431 		 * XXX please removes m_defrag(9)
1432 		 */
1433 		m_new = m_defrag(m, M_NOWAIT);
1434 		if (m_new == NULL) {
1435 			device_printf(sc->sc_dev,
1436 			    "%s: can't defrag TX buffer\n",
1437 			    __func__);
1438 			return (ENOBUFS);
1439 		}
1440 		if (m_new->m_next != NULL)
1441 			device_printf(sc->sc_dev,
1442 			    "TODO: fragmented packets for PIO\n");
1443 		tp->tp_m = m_new;
1444 
1445 		/* send HEADER */
1446 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1447 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1448 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1449 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1450 		/* send BODY */
1451 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1452 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1453 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1454 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1455 	} else {
1456 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1457 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1458 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1459 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1460 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1461 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1462 		    ctl16 | BWN_PIO_TXCTL_EOF);
1463 	}
1464 
1465 	return (0);
1466 }
1467 
1468 static struct bwn_pio_txqueue *
1469 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1470 {
1471 
1472 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1473 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1474 
1475 	switch (prio) {
1476 	case 0:
1477 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1478 	case 1:
1479 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1480 	case 2:
1481 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1482 	case 3:
1483 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1484 	}
1485 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1486 	return (NULL);
1487 }
1488 
1489 static int
1490 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1491 {
1492 #define	BWN_GET_TXHDRCACHE(slot)					\
1493 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1494 	struct bwn_dma *dma = &mac->mac_method.dma;
1495 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1496 	struct bwn_dmadesc_generic *desc;
1497 	struct bwn_dmadesc_meta *mt;
1498 	struct bwn_softc *sc = mac->mac_sc;
1499 	struct ifnet *ifp = sc->sc_ifp;
1500 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1501 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1502 
1503 	BWN_ASSERT_LOCKED(sc);
1504 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1505 
1506 	/* XXX send after DTIM */
1507 
1508 	slot = bwn_dma_getslot(dr);
1509 	dr->getdesc(dr, slot, &desc, &mt);
1510 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1511 	    ("%s:%d: fail", __func__, __LINE__));
1512 
1513 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1514 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1515 	    BWN_DMA_COOKIE(dr, slot));
1516 	if (error)
1517 		goto fail;
1518 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1519 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1520 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1521 	if (error) {
1522 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1523 		    __func__, error);
1524 		goto fail;
1525 	}
1526 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1527 	    BUS_DMASYNC_PREWRITE);
1528 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1529 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1530 	    BUS_DMASYNC_PREWRITE);
1531 
1532 	slot = bwn_dma_getslot(dr);
1533 	dr->getdesc(dr, slot, &desc, &mt);
1534 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1535 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1536 	mt->mt_m = m;
1537 	mt->mt_ni = ni;
1538 
1539 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1540 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1541 	if (error && error != EFBIG) {
1542 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1543 		    __func__, error);
1544 		goto fail;
1545 	}
1546 	if (error) {    /* error == EFBIG */
1547 		struct mbuf *m_new;
1548 
1549 		m_new = m_defrag(m, M_NOWAIT);
1550 		if (m_new == NULL) {
1551 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1552 			    __func__);
1553 			error = ENOBUFS;
1554 			goto fail;
1555 		} else {
1556 			m = m_new;
1557 		}
1558 
1559 		mt->mt_m = m;
1560 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1561 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1562 		if (error) {
1563 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1564 			    __func__, error);
1565 			goto fail;
1566 		}
1567 	}
1568 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1569 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1570 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1571 	    BUS_DMASYNC_PREWRITE);
1572 
1573 	/* XXX send after DTIM */
1574 
1575 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1576 	return (0);
1577 fail:
1578 	dr->dr_curslot = backup[0];
1579 	dr->dr_usedslot = backup[1];
1580 	return (error);
1581 #undef BWN_GET_TXHDRCACHE
1582 }
1583 
1584 static void
1585 bwn_watchdog(void *arg)
1586 {
1587 	struct bwn_softc *sc = arg;
1588 	struct ifnet *ifp = sc->sc_ifp;
1589 
1590 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1591 		if_printf(ifp, "device timeout\n");
1592 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1593 	}
1594 	callout_schedule(&sc->sc_watchdog_ch, hz);
1595 }
1596 
1597 static int
1598 bwn_attach_core(struct bwn_mac *mac)
1599 {
1600 	struct bwn_softc *sc = mac->mac_sc;
1601 	int error, have_bg = 0, have_a = 0;
1602 	uint32_t high;
1603 
1604 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1605 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1606 
1607 	siba_powerup(sc->sc_dev, 0);
1608 
1609 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1610 	bwn_reset_core(mac,
1611 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1612 	error = bwn_phy_getinfo(mac, high);
1613 	if (error)
1614 		goto fail;
1615 
1616 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1617 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1618 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1619 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1620 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1621 		have_a = have_bg = 0;
1622 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1623 			have_a = 1;
1624 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1625 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1626 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1627 			have_bg = 1;
1628 		else
1629 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1630 			    mac->mac_phy.type));
1631 	}
1632 	/* XXX turns off PHY A because it's not supported */
1633 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1634 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1635 		have_a = 0;
1636 		have_bg = 1;
1637 	}
1638 
1639 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1640 		mac->mac_phy.attach = bwn_phy_g_attach;
1641 		mac->mac_phy.detach = bwn_phy_g_detach;
1642 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1643 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1644 		mac->mac_phy.init = bwn_phy_g_init;
1645 		mac->mac_phy.exit = bwn_phy_g_exit;
1646 		mac->mac_phy.phy_read = bwn_phy_g_read;
1647 		mac->mac_phy.phy_write = bwn_phy_g_write;
1648 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1649 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1650 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1651 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1652 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1653 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1654 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1655 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1656 		mac->mac_phy.set_im = bwn_phy_g_im;
1657 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1658 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1659 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1660 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1661 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1662 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1663 		mac->mac_phy.init = bwn_phy_lp_init;
1664 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1665 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1666 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1667 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1668 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1669 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1670 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1671 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1672 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1673 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1674 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1675 	} else {
1676 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1677 		    mac->mac_phy.type);
1678 		error = ENXIO;
1679 		goto fail;
1680 	}
1681 
1682 	mac->mac_phy.gmode = have_bg;
1683 	if (mac->mac_phy.attach != NULL) {
1684 		error = mac->mac_phy.attach(mac);
1685 		if (error) {
1686 			device_printf(sc->sc_dev, "failed\n");
1687 			goto fail;
1688 		}
1689 	}
1690 
1691 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1692 
1693 	error = bwn_chiptest(mac);
1694 	if (error)
1695 		goto fail;
1696 	error = bwn_setup_channels(mac, have_bg, have_a);
1697 	if (error) {
1698 		device_printf(sc->sc_dev, "failed to setup channels\n");
1699 		goto fail;
1700 	}
1701 
1702 	if (sc->sc_curmac == NULL)
1703 		sc->sc_curmac = mac;
1704 
1705 	error = bwn_dma_attach(mac);
1706 	if (error != 0) {
1707 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1708 		goto fail;
1709 	}
1710 
1711 	mac->mac_phy.switch_analog(mac, 0);
1712 
1713 	siba_dev_down(sc->sc_dev, 0);
1714 fail:
1715 	siba_powerdown(sc->sc_dev);
1716 	return (error);
1717 }
1718 
1719 static void
1720 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1721 {
1722 	struct bwn_softc *sc = mac->mac_sc;
1723 	uint32_t low, ctl;
1724 
1725 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1726 
1727 	siba_dev_up(sc->sc_dev, flags);
1728 	DELAY(2000);
1729 
1730 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1731 	    ~BWN_TGSLOW_PHYRESET;
1732 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1733 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734 	DELAY(1000);
1735 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1736 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1737 	DELAY(1000);
1738 
1739 	if (mac->mac_phy.switch_analog != NULL)
1740 		mac->mac_phy.switch_analog(mac, 1);
1741 
1742 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1743 	if (flags & BWN_TGSLOW_SUPPORT_G)
1744 		ctl |= BWN_MACCTL_GMODE;
1745 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1746 }
1747 
1748 static int
1749 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1750 {
1751 	struct bwn_phy *phy = &mac->mac_phy;
1752 	struct bwn_softc *sc = mac->mac_sc;
1753 	uint32_t tmp;
1754 
1755 	/* PHY */
1756 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1757 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1758 	phy->rf_on = 1;
1759 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1760 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1761 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1762 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1763 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1764 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1765 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1766 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1767 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1768 		goto unsupphy;
1769 
1770 	/* RADIO */
1771 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1772 		if (siba_get_chiprev(sc->sc_dev) == 0)
1773 			tmp = 0x3205017f;
1774 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1775 			tmp = 0x4205017f;
1776 		else
1777 			tmp = 0x5205017f;
1778 	} else {
1779 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1781 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1782 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1783 	}
1784 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1785 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1786 	phy->rf_manuf = (tmp & 0x00000fff);
1787 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1788 		goto unsupradio;
1789 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1790 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1791 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1792 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1793 	    (phy->type == BWN_PHYTYPE_N &&
1794 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1795 	    (phy->type == BWN_PHYTYPE_LP &&
1796 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1797 		goto unsupradio;
1798 
1799 	return (0);
1800 unsupphy:
1801 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1802 	    "analog %#x)\n",
1803 	    phy->type, phy->rev, phy->analog);
1804 	return (ENXIO);
1805 unsupradio:
1806 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1807 	    "rev %#x)\n",
1808 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1809 	return (ENXIO);
1810 }
1811 
1812 static int
1813 bwn_chiptest(struct bwn_mac *mac)
1814 {
1815 #define	TESTVAL0	0x55aaaa55
1816 #define	TESTVAL1	0xaa5555aa
1817 	struct bwn_softc *sc = mac->mac_sc;
1818 	uint32_t v, backup;
1819 
1820 	BWN_LOCK(sc);
1821 
1822 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1823 
1824 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1825 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1826 		goto error;
1827 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1828 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1829 		goto error;
1830 
1831 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1832 
1833 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1834 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1835 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1836 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1837 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1838 			goto error;
1839 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1840 			goto error;
1841 	}
1842 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1843 
1844 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1845 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1846 		goto error;
1847 
1848 	BWN_UNLOCK(sc);
1849 	return (0);
1850 error:
1851 	BWN_UNLOCK(sc);
1852 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1853 	return (ENODEV);
1854 }
1855 
1856 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1857 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1858 
1859 static int
1860 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1861 {
1862 	struct bwn_softc *sc = mac->mac_sc;
1863 	struct ifnet *ifp = sc->sc_ifp;
1864 	struct ieee80211com *ic = ifp->if_l2com;
1865 
1866 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1867 	ic->ic_nchans = 0;
1868 
1869 	if (have_bg)
1870 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1871 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1872 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1873 		if (have_a)
1874 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1875 			    &ic->ic_nchans, &bwn_chantable_n,
1876 			    IEEE80211_CHAN_HTA);
1877 	} else {
1878 		if (have_a)
1879 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1880 			    &ic->ic_nchans, &bwn_chantable_a,
1881 			    IEEE80211_CHAN_A);
1882 	}
1883 
1884 	mac->mac_phy.supports_2ghz = have_bg;
1885 	mac->mac_phy.supports_5ghz = have_a;
1886 
1887 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1888 }
1889 
1890 static uint32_t
1891 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1892 {
1893 	uint32_t ret;
1894 
1895 	BWN_ASSERT_LOCKED(mac->mac_sc);
1896 
1897 	if (way == BWN_SHARED) {
1898 		KASSERT((offset & 0x0001) == 0,
1899 		    ("%s:%d warn", __func__, __LINE__));
1900 		if (offset & 0x0003) {
1901 			bwn_shm_ctlword(mac, way, offset >> 2);
1902 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1903 			ret <<= 16;
1904 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1905 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1906 			goto out;
1907 		}
1908 		offset >>= 2;
1909 	}
1910 	bwn_shm_ctlword(mac, way, offset);
1911 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1912 out:
1913 	return (ret);
1914 }
1915 
1916 static uint16_t
1917 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1918 {
1919 	uint16_t ret;
1920 
1921 	BWN_ASSERT_LOCKED(mac->mac_sc);
1922 
1923 	if (way == BWN_SHARED) {
1924 		KASSERT((offset & 0x0001) == 0,
1925 		    ("%s:%d warn", __func__, __LINE__));
1926 		if (offset & 0x0003) {
1927 			bwn_shm_ctlword(mac, way, offset >> 2);
1928 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1929 			goto out;
1930 		}
1931 		offset >>= 2;
1932 	}
1933 	bwn_shm_ctlword(mac, way, offset);
1934 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1935 out:
1936 
1937 	return (ret);
1938 }
1939 
1940 static void
1941 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1942     uint16_t offset)
1943 {
1944 	uint32_t control;
1945 
1946 	control = way;
1947 	control <<= 16;
1948 	control |= offset;
1949 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1950 }
1951 
1952 static void
1953 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1954     uint32_t value)
1955 {
1956 	BWN_ASSERT_LOCKED(mac->mac_sc);
1957 
1958 	if (way == BWN_SHARED) {
1959 		KASSERT((offset & 0x0001) == 0,
1960 		    ("%s:%d warn", __func__, __LINE__));
1961 		if (offset & 0x0003) {
1962 			bwn_shm_ctlword(mac, way, offset >> 2);
1963 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1964 				    (value >> 16) & 0xffff);
1965 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1966 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1967 			return;
1968 		}
1969 		offset >>= 2;
1970 	}
1971 	bwn_shm_ctlword(mac, way, offset);
1972 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1973 }
1974 
1975 static void
1976 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1977     uint16_t value)
1978 {
1979 	BWN_ASSERT_LOCKED(mac->mac_sc);
1980 
1981 	if (way == BWN_SHARED) {
1982 		KASSERT((offset & 0x0001) == 0,
1983 		    ("%s:%d warn", __func__, __LINE__));
1984 		if (offset & 0x0003) {
1985 			bwn_shm_ctlword(mac, way, offset >> 2);
1986 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1987 			return;
1988 		}
1989 		offset >>= 2;
1990 	}
1991 	bwn_shm_ctlword(mac, way, offset);
1992 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1993 }
1994 
1995 static void
1996 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1997     int txpow)
1998 {
1999 
2000 	c->ic_freq = freq;
2001 	c->ic_flags = flags;
2002 	c->ic_ieee = ieee;
2003 	c->ic_minpower = 0;
2004 	c->ic_maxpower = 2 * txpow;
2005 	c->ic_maxregpower = txpow;
2006 }
2007 
2008 static void
2009 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2010     const struct bwn_channelinfo *ci, int flags)
2011 {
2012 	struct ieee80211_channel *c;
2013 	int i;
2014 
2015 	c = &chans[*nchans];
2016 
2017 	for (i = 0; i < ci->nchannels; i++) {
2018 		const struct bwn_channel *hc;
2019 
2020 		hc = &ci->channels[i];
2021 		if (*nchans >= maxchans)
2022 			break;
2023 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2024 		c++, (*nchans)++;
2025 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2026 			/* g channel have a separate b-only entry */
2027 			if (*nchans >= maxchans)
2028 				break;
2029 			c[0] = c[-1];
2030 			c[-1].ic_flags = IEEE80211_CHAN_B;
2031 			c++, (*nchans)++;
2032 		}
2033 		if (flags == IEEE80211_CHAN_HTG) {
2034 			/* HT g channel have a separate g-only entry */
2035 			if (*nchans >= maxchans)
2036 				break;
2037 			c[-1].ic_flags = IEEE80211_CHAN_G;
2038 			c[0] = c[-1];
2039 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2040 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2041 			c++, (*nchans)++;
2042 		}
2043 		if (flags == IEEE80211_CHAN_HTA) {
2044 			/* HT a channel have a separate a-only entry */
2045 			if (*nchans >= maxchans)
2046 				break;
2047 			c[-1].ic_flags = IEEE80211_CHAN_A;
2048 			c[0] = c[-1];
2049 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2050 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2051 			c++, (*nchans)++;
2052 		}
2053 	}
2054 }
2055 
2056 static int
2057 bwn_phy_g_attach(struct bwn_mac *mac)
2058 {
2059 	struct bwn_softc *sc = mac->mac_sc;
2060 	struct bwn_phy *phy = &mac->mac_phy;
2061 	struct bwn_phy_g *pg = &phy->phy_g;
2062 	unsigned int i;
2063 	int16_t pab0, pab1, pab2;
2064 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2065 	int8_t bg;
2066 
2067 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2068 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2069 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2070 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2071 
2072 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2073 		device_printf(sc->sc_dev, "not supported anymore\n");
2074 
2075 	pg->pg_flags = 0;
2076 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2077 	    pab2 == -1) {
2078 		pg->pg_idletssi = 52;
2079 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2080 		return (0);
2081 	}
2082 
2083 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2084 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2085 	if (pg->pg_tssi2dbm == NULL) {
2086 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2087 		return (ENOMEM);
2088 	}
2089 	for (i = 0; i < 64; i++) {
2090 		int32_t m1, m2, f, q, delta;
2091 		int8_t j = 0;
2092 
2093 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2094 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2095 		f = 256;
2096 
2097 		do {
2098 			if (j > 15) {
2099 				device_printf(sc->sc_dev,
2100 				    "failed to generate tssi2dBm\n");
2101 				free(pg->pg_tssi2dbm, M_DEVBUF);
2102 				return (ENOMEM);
2103 			}
2104 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2105 			    f, 2048);
2106 			delta = abs(q - f);
2107 			f = q;
2108 			j++;
2109 		} while (delta >= 2);
2110 
2111 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2112 		    128);
2113 	}
2114 
2115 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2116 	return (0);
2117 }
2118 
2119 static void
2120 bwn_phy_g_detach(struct bwn_mac *mac)
2121 {
2122 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2123 
2124 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2125 		free(pg->pg_tssi2dbm, M_DEVBUF);
2126 		pg->pg_tssi2dbm = NULL;
2127 	}
2128 	pg->pg_flags = 0;
2129 }
2130 
2131 static void
2132 bwn_phy_g_init_pre(struct bwn_mac *mac)
2133 {
2134 	struct bwn_phy *phy = &mac->mac_phy;
2135 	struct bwn_phy_g *pg = &phy->phy_g;
2136 	void *tssi2dbm;
2137 	int idletssi;
2138 	unsigned int i;
2139 
2140 	tssi2dbm = pg->pg_tssi2dbm;
2141 	idletssi = pg->pg_idletssi;
2142 
2143 	memset(pg, 0, sizeof(*pg));
2144 
2145 	pg->pg_tssi2dbm = tssi2dbm;
2146 	pg->pg_idletssi = idletssi;
2147 
2148 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2149 
2150 	for (i = 0; i < N(pg->pg_nrssi); i++)
2151 		pg->pg_nrssi[i] = -1000;
2152 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2153 		pg->pg_nrssi_lt[i] = i;
2154 	pg->pg_lofcal = 0xffff;
2155 	pg->pg_initval = 0xffff;
2156 	pg->pg_immode = BWN_IMMODE_NONE;
2157 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2158 	pg->pg_avgtssi = 0xff;
2159 
2160 	pg->pg_loctl.tx_bias = 0xff;
2161 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2162 }
2163 
2164 static int
2165 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2166 {
2167 	struct bwn_phy *phy = &mac->mac_phy;
2168 	struct bwn_phy_g *pg = &phy->phy_g;
2169 	struct bwn_softc *sc = mac->mac_sc;
2170 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2171 	static const struct bwn_rfatt rfatt0[] = {
2172 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2173 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2174 		{ 3, 1 }, { 4, 1 }
2175 	};
2176 	static const struct bwn_rfatt rfatt1[] = {
2177 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2178 		{ 14, 1 }
2179 	};
2180 	static const struct bwn_rfatt rfatt2[] = {
2181 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2182 		{ 9, 1 }
2183 	};
2184 	static const struct bwn_bbatt bbatt_0[] = {
2185 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2186 	};
2187 
2188 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2189 
2190 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2191 		pg->pg_bbatt.att = 0;
2192 	else
2193 		pg->pg_bbatt.att = 2;
2194 
2195 	/* prepare Radio Attenuation */
2196 	pg->pg_rfatt.padmix = 0;
2197 
2198 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2199 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2200 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2201 			pg->pg_rfatt.att = 2;
2202 			goto done;
2203 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2204 			pg->pg_rfatt.att = 3;
2205 			goto done;
2206 		}
2207 	}
2208 
2209 	if (phy->type == BWN_PHYTYPE_A) {
2210 		pg->pg_rfatt.att = 0x60;
2211 		goto done;
2212 	}
2213 
2214 	switch (phy->rf_ver) {
2215 	case 0x2050:
2216 		switch (phy->rf_rev) {
2217 		case 0:
2218 			pg->pg_rfatt.att = 5;
2219 			goto done;
2220 		case 1:
2221 			if (phy->type == BWN_PHYTYPE_G) {
2222 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2223 				    SIBA_BOARDVENDOR_BCM &&
2224 				    siba_get_pci_subdevice(sc->sc_dev) ==
2225 				    SIBA_BOARD_BCM4309G &&
2226 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2227 					pg->pg_rfatt.att = 3;
2228 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2229 				    SIBA_BOARDVENDOR_BCM &&
2230 				    siba_get_pci_subdevice(sc->sc_dev) ==
2231 				    SIBA_BOARD_BU4306)
2232 					pg->pg_rfatt.att = 3;
2233 				else
2234 					pg->pg_rfatt.att = 1;
2235 			} else {
2236 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2237 				    SIBA_BOARDVENDOR_BCM &&
2238 				    siba_get_pci_subdevice(sc->sc_dev) ==
2239 				    SIBA_BOARD_BCM4309G &&
2240 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2241 					pg->pg_rfatt.att = 7;
2242 				else
2243 					pg->pg_rfatt.att = 6;
2244 			}
2245 			goto done;
2246 		case 2:
2247 			if (phy->type == BWN_PHYTYPE_G) {
2248 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2249 				    SIBA_BOARDVENDOR_BCM &&
2250 				    siba_get_pci_subdevice(sc->sc_dev) ==
2251 				    SIBA_BOARD_BCM4309G &&
2252 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2253 					pg->pg_rfatt.att = 3;
2254 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2255 				    SIBA_BOARDVENDOR_BCM &&
2256 				    siba_get_pci_subdevice(sc->sc_dev) ==
2257 				    SIBA_BOARD_BU4306)
2258 					pg->pg_rfatt.att = 5;
2259 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2260 					pg->pg_rfatt.att = 4;
2261 				else
2262 					pg->pg_rfatt.att = 3;
2263 			} else
2264 				pg->pg_rfatt.att = 6;
2265 			goto done;
2266 		case 3:
2267 			pg->pg_rfatt.att = 5;
2268 			goto done;
2269 		case 4:
2270 		case 5:
2271 			pg->pg_rfatt.att = 1;
2272 			goto done;
2273 		case 6:
2274 		case 7:
2275 			pg->pg_rfatt.att = 5;
2276 			goto done;
2277 		case 8:
2278 			pg->pg_rfatt.att = 0xa;
2279 			pg->pg_rfatt.padmix = 1;
2280 			goto done;
2281 		case 9:
2282 		default:
2283 			pg->pg_rfatt.att = 5;
2284 			goto done;
2285 		}
2286 		break;
2287 	case 0x2053:
2288 		switch (phy->rf_rev) {
2289 		case 1:
2290 			pg->pg_rfatt.att = 6;
2291 			goto done;
2292 		}
2293 		break;
2294 	}
2295 	pg->pg_rfatt.att = 5;
2296 done:
2297 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2298 
2299 	if (!bwn_has_hwpctl(mac)) {
2300 		lo->rfatt.array = rfatt0;
2301 		lo->rfatt.len = N(rfatt0);
2302 		lo->rfatt.min = 0;
2303 		lo->rfatt.max = 9;
2304 		goto genbbatt;
2305 	}
2306 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2307 		lo->rfatt.array = rfatt1;
2308 		lo->rfatt.len = N(rfatt1);
2309 		lo->rfatt.min = 0;
2310 		lo->rfatt.max = 14;
2311 		goto genbbatt;
2312 	}
2313 	lo->rfatt.array = rfatt2;
2314 	lo->rfatt.len = N(rfatt2);
2315 	lo->rfatt.min = 0;
2316 	lo->rfatt.max = 9;
2317 genbbatt:
2318 	lo->bbatt.array = bbatt_0;
2319 	lo->bbatt.len = N(bbatt_0);
2320 	lo->bbatt.min = 0;
2321 	lo->bbatt.max = 8;
2322 
2323 	BWN_READ_4(mac, BWN_MACCTL);
2324 	if (phy->rev == 1) {
2325 		phy->gmode = 0;
2326 		bwn_reset_core(mac, 0);
2327 		bwn_phy_g_init_sub(mac);
2328 		phy->gmode = 1;
2329 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2330 	}
2331 	return (0);
2332 }
2333 
2334 static uint16_t
2335 bwn_phy_g_txctl(struct bwn_mac *mac)
2336 {
2337 	struct bwn_phy *phy = &mac->mac_phy;
2338 
2339 	if (phy->rf_ver != 0x2050)
2340 		return (0);
2341 	if (phy->rf_rev == 1)
2342 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2343 	if (phy->rf_rev < 6)
2344 		return (BWN_TXCTL_PA2DB);
2345 	if (phy->rf_rev == 8)
2346 		return (BWN_TXCTL_TXMIX);
2347 	return (0);
2348 }
2349 
2350 static int
2351 bwn_phy_g_init(struct bwn_mac *mac)
2352 {
2353 
2354 	bwn_phy_g_init_sub(mac);
2355 	return (0);
2356 }
2357 
2358 static void
2359 bwn_phy_g_exit(struct bwn_mac *mac)
2360 {
2361 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2362 	struct bwn_lo_calib *cal, *tmp;
2363 
2364 	if (lo == NULL)
2365 		return;
2366 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2367 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2368 		free(cal, M_DEVBUF);
2369 	}
2370 }
2371 
2372 static uint16_t
2373 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2374 {
2375 
2376 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2377 	return (BWN_READ_2(mac, BWN_PHYDATA));
2378 }
2379 
2380 static void
2381 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2382 {
2383 
2384 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2385 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2386 }
2387 
2388 static uint16_t
2389 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2390 {
2391 
2392 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2393 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2394 	return (BWN_READ_2(mac, BWN_RFDATALO));
2395 }
2396 
2397 static void
2398 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2399 {
2400 
2401 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2402 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2403 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2404 }
2405 
2406 static int
2407 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2408 {
2409 
2410 	return (mac->mac_phy.rev >= 6);
2411 }
2412 
2413 static void
2414 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2415 {
2416 	struct bwn_phy *phy = &mac->mac_phy;
2417 	struct bwn_phy_g *pg = &phy->phy_g;
2418 	unsigned int channel;
2419 	uint16_t rfover, rfoverval;
2420 
2421 	if (on) {
2422 		if (phy->rf_on)
2423 			return;
2424 
2425 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2426 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2427 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2428 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2429 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2430 			    pg->pg_radioctx_over);
2431 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2432 			    pg->pg_radioctx_overval);
2433 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2434 		}
2435 		channel = phy->chan;
2436 		bwn_phy_g_switch_chan(mac, 6, 1);
2437 		bwn_phy_g_switch_chan(mac, channel, 0);
2438 		return;
2439 	}
2440 
2441 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2442 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2443 	pg->pg_radioctx_over = rfover;
2444 	pg->pg_radioctx_overval = rfoverval;
2445 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2446 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2447 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2448 }
2449 
2450 static int
2451 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2452 {
2453 
2454 	if ((newchan < 1) || (newchan > 14))
2455 		return (EINVAL);
2456 	bwn_phy_g_switch_chan(mac, newchan, 0);
2457 
2458 	return (0);
2459 }
2460 
2461 static uint32_t
2462 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2463 {
2464 
2465 	return (1);
2466 }
2467 
2468 static void
2469 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2470 {
2471 	struct bwn_phy *phy = &mac->mac_phy;
2472 	uint64_t hf;
2473 	int autodiv = 0;
2474 	uint16_t tmp;
2475 
2476 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2477 		autodiv = 1;
2478 
2479 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2480 	bwn_hf_write(mac, hf);
2481 
2482 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2483 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2484 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2485 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2486 
2487 	if (autodiv) {
2488 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2489 		if (antenna == BWN_ANTAUTO1)
2490 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2491 		else
2492 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2493 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2494 	}
2495 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2496 	if (autodiv)
2497 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2498 	else
2499 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2500 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2501 	if (phy->rev >= 2) {
2502 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2503 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2504 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2505 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2506 		    0x15);
2507 		if (phy->rev == 2)
2508 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2509 		else
2510 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2511 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2512 			    8);
2513 	}
2514 	if (phy->rev >= 6)
2515 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2516 
2517 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2518 	bwn_hf_write(mac, hf);
2519 }
2520 
2521 static int
2522 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2523 {
2524 	struct bwn_phy *phy = &mac->mac_phy;
2525 	struct bwn_phy_g *pg = &phy->phy_g;
2526 
2527 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2528 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2529 
2530 	if (phy->rev == 0 || !phy->gmode)
2531 		return (ENODEV);
2532 
2533 	pg->pg_aci_wlan_automatic = 0;
2534 	return (0);
2535 }
2536 
2537 static int
2538 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
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 	unsigned int tssi;
2544 	int cck, ofdm;
2545 	int power;
2546 	int rfatt, bbatt;
2547 	unsigned int max;
2548 
2549 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2550 
2551 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2552 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2553 	if (cck < 0 && ofdm < 0) {
2554 		if (ignore_tssi == 0)
2555 			return (BWN_TXPWR_RES_DONE);
2556 		cck = 0;
2557 		ofdm = 0;
2558 	}
2559 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2560 	if (pg->pg_avgtssi != 0xff)
2561 		tssi = (tssi + pg->pg_avgtssi) / 2;
2562 	pg->pg_avgtssi = tssi;
2563 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2564 
2565 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2566 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2567 		max -= 3;
2568 	if (max >= 120) {
2569 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2570 		max = 80;
2571 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2572 	}
2573 
2574 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2575 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2576 	     tssi, 0x00), 0x3f)]);
2577 	if (power == 0)
2578 		return (BWN_TXPWR_RES_DONE);
2579 
2580 	rfatt = -((power + 7) / 8);
2581 	bbatt = (-(power / 2)) - (4 * rfatt);
2582 	if ((rfatt == 0) && (bbatt == 0))
2583 		return (BWN_TXPWR_RES_DONE);
2584 	pg->pg_bbatt_delta = bbatt;
2585 	pg->pg_rfatt_delta = rfatt;
2586 	return (BWN_TXPWR_RES_NEED_ADJUST);
2587 }
2588 
2589 static void
2590 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2591 {
2592 	struct bwn_phy *phy = &mac->mac_phy;
2593 	struct bwn_phy_g *pg = &phy->phy_g;
2594 	struct bwn_softc *sc = mac->mac_sc;
2595 	int rfatt, bbatt;
2596 	uint8_t txctl;
2597 
2598 	bwn_mac_suspend(mac);
2599 
2600 	BWN_ASSERT_LOCKED(sc);
2601 
2602 	bbatt = pg->pg_bbatt.att;
2603 	bbatt += pg->pg_bbatt_delta;
2604 	rfatt = pg->pg_rfatt.att;
2605 	rfatt += pg->pg_rfatt_delta;
2606 
2607 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2608 	txctl = pg->pg_txctl;
2609 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2610 		if (rfatt <= 1) {
2611 			if (txctl == 0) {
2612 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2613 				rfatt += 2;
2614 				bbatt += 2;
2615 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2616 			    BWN_BFL_PACTRL) {
2617 				bbatt += 4 * (rfatt - 2);
2618 				rfatt = 2;
2619 			}
2620 		} else if (rfatt > 4 && txctl) {
2621 			txctl = 0;
2622 			if (bbatt < 3) {
2623 				rfatt -= 3;
2624 				bbatt += 2;
2625 			} else {
2626 				rfatt -= 2;
2627 				bbatt -= 2;
2628 			}
2629 		}
2630 	}
2631 	pg->pg_txctl = txctl;
2632 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2633 	pg->pg_rfatt.att = rfatt;
2634 	pg->pg_bbatt.att = bbatt;
2635 
2636 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2637 
2638 	bwn_phy_lock(mac);
2639 	bwn_rf_lock(mac);
2640 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2641 	    pg->pg_txctl);
2642 	bwn_rf_unlock(mac);
2643 	bwn_phy_unlock(mac);
2644 
2645 	bwn_mac_enable(mac);
2646 }
2647 
2648 static void
2649 bwn_phy_g_task_15s(struct bwn_mac *mac)
2650 {
2651 	struct bwn_phy *phy = &mac->mac_phy;
2652 	struct bwn_phy_g *pg = &phy->phy_g;
2653 	struct bwn_softc *sc = mac->mac_sc;
2654 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2655 	unsigned long expire, now;
2656 	struct bwn_lo_calib *cal, *tmp;
2657 	uint8_t expired = 0;
2658 
2659 	bwn_mac_suspend(mac);
2660 
2661 	if (lo == NULL)
2662 		goto fail;
2663 
2664 	BWN_GETTIME(now);
2665 	if (bwn_has_hwpctl(mac)) {
2666 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2667 		if (time_before(lo->pwr_vec_read_time, expire)) {
2668 			bwn_lo_get_powervector(mac);
2669 			bwn_phy_g_dc_lookup_init(mac, 0);
2670 		}
2671 		goto fail;
2672 	}
2673 
2674 	expire = now - BWN_LO_CALIB_EXPIRE;
2675 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2676 		if (!time_before(cal->calib_time, expire))
2677 			continue;
2678 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2679 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2680 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2681 			expired = 1;
2682 		}
2683 
2684 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2685 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2686 		    cal->ctl.i, cal->ctl.q);
2687 
2688 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2689 		free(cal, M_DEVBUF);
2690 	}
2691 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2692 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2693 		    &pg->pg_rfatt);
2694 		if (cal == NULL) {
2695 			device_printf(sc->sc_dev,
2696 			    "failed to recalibrate LO\n");
2697 			goto fail;
2698 		}
2699 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2700 		bwn_lo_write(mac, &cal->ctl);
2701 	}
2702 
2703 fail:
2704 	bwn_mac_enable(mac);
2705 }
2706 
2707 static void
2708 bwn_phy_g_task_60s(struct bwn_mac *mac)
2709 {
2710 	struct bwn_phy *phy = &mac->mac_phy;
2711 	struct bwn_softc *sc = mac->mac_sc;
2712 	uint8_t old = phy->chan;
2713 
2714 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2715 		return;
2716 
2717 	bwn_mac_suspend(mac);
2718 	bwn_nrssi_slope_11g(mac);
2719 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2720 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2721 		bwn_switch_channel(mac, old);
2722 	}
2723 	bwn_mac_enable(mac);
2724 }
2725 
2726 static void
2727 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2728 {
2729 
2730 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2731 }
2732 
2733 static int
2734 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2735 	const struct ieee80211_bpf_params *params)
2736 {
2737 	struct ieee80211com *ic = ni->ni_ic;
2738 	struct ifnet *ifp = ic->ic_ifp;
2739 	struct bwn_softc *sc = ifp->if_softc;
2740 	struct bwn_mac *mac = sc->sc_curmac;
2741 
2742 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2743 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2744 		ieee80211_free_node(ni);
2745 		m_freem(m);
2746 		return (ENETDOWN);
2747 	}
2748 
2749 	BWN_LOCK(sc);
2750 	if (bwn_tx_isfull(sc, m)) {
2751 		ieee80211_free_node(ni);
2752 		m_freem(m);
2753 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2754 		BWN_UNLOCK(sc);
2755 		return (ENOBUFS);
2756 	}
2757 
2758 	if (bwn_tx_start(sc, ni, m) != 0) {
2759 		if (ni != NULL)
2760 			ieee80211_free_node(ni);
2761 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2762 	}
2763 	sc->sc_watchdog_timer = 5;
2764 	BWN_UNLOCK(sc);
2765 	return (0);
2766 }
2767 
2768 /*
2769  * Callback from the 802.11 layer to update the slot time
2770  * based on the current setting.  We use it to notify the
2771  * firmware of ERP changes and the f/w takes care of things
2772  * like slot time and preamble.
2773  */
2774 static void
2775 bwn_updateslot(struct ieee80211com *ic)
2776 {
2777 	struct bwn_softc *sc = ic->ic_softc;
2778 	struct bwn_mac *mac;
2779 
2780 	BWN_LOCK(sc);
2781 	if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
2782 		mac = (struct bwn_mac *)sc->sc_curmac;
2783 		bwn_set_slot_time(mac,
2784 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2785 	}
2786 	BWN_UNLOCK(sc);
2787 }
2788 
2789 /*
2790  * Callback from the 802.11 layer after a promiscuous mode change.
2791  * Note this interface does not check the operating mode as this
2792  * is an internal callback and we are expected to honor the current
2793  * state (e.g. this is used for setting the interface in promiscuous
2794  * mode when operating in hostap mode to do ACS).
2795  */
2796 static void
2797 bwn_update_promisc(struct ieee80211com *ic)
2798 {
2799 	struct bwn_softc *sc = ic->ic_softc;
2800 	struct bwn_mac *mac = sc->sc_curmac;
2801 
2802 	BWN_LOCK(sc);
2803 	mac = sc->sc_curmac;
2804 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2805 		if (ic->ic_ifp->if_flags & IFF_PROMISC)
2806 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2807 		else
2808 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2809 		bwn_set_opmode(mac);
2810 	}
2811 	BWN_UNLOCK(sc);
2812 }
2813 
2814 /*
2815  * Callback from the 802.11 layer to update WME parameters.
2816  */
2817 static int
2818 bwn_wme_update(struct ieee80211com *ic)
2819 {
2820 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2821 	struct bwn_mac *mac = sc->sc_curmac;
2822 	struct wmeParams *wmep;
2823 	int i;
2824 
2825 	BWN_LOCK(sc);
2826 	mac = sc->sc_curmac;
2827 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2828 		bwn_mac_suspend(mac);
2829 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2830 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2831 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2832 		}
2833 		bwn_mac_enable(mac);
2834 	}
2835 	BWN_UNLOCK(sc);
2836 	return (0);
2837 }
2838 
2839 static void
2840 bwn_scan_start(struct ieee80211com *ic)
2841 {
2842 	struct ifnet *ifp = ic->ic_ifp;
2843 	struct bwn_softc *sc = ifp->if_softc;
2844 	struct bwn_mac *mac;
2845 
2846 	BWN_LOCK(sc);
2847 	mac = sc->sc_curmac;
2848 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2849 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2850 		bwn_set_opmode(mac);
2851 		/* disable CFP update during scan */
2852 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2853 	}
2854 	BWN_UNLOCK(sc);
2855 }
2856 
2857 static void
2858 bwn_scan_end(struct ieee80211com *ic)
2859 {
2860 	struct ifnet *ifp = ic->ic_ifp;
2861 	struct bwn_softc *sc = ifp->if_softc;
2862 	struct bwn_mac *mac;
2863 
2864 	BWN_LOCK(sc);
2865 	mac = sc->sc_curmac;
2866 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2867 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2868 		bwn_set_opmode(mac);
2869 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2870 	}
2871 	BWN_UNLOCK(sc);
2872 }
2873 
2874 static void
2875 bwn_set_channel(struct ieee80211com *ic)
2876 {
2877 	struct ifnet *ifp = ic->ic_ifp;
2878 	struct bwn_softc *sc = ifp->if_softc;
2879 	struct bwn_mac *mac = sc->sc_curmac;
2880 	struct bwn_phy *phy = &mac->mac_phy;
2881 	int chan, error;
2882 
2883 	BWN_LOCK(sc);
2884 
2885 	error = bwn_switch_band(sc, ic->ic_curchan);
2886 	if (error)
2887 		goto fail;
2888 	bwn_mac_suspend(mac);
2889 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2890 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2891 	if (chan != phy->chan)
2892 		bwn_switch_channel(mac, chan);
2893 
2894 	/* TX power level */
2895 	if (ic->ic_curchan->ic_maxpower != 0 &&
2896 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2897 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2898 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2899 		    BWN_TXPWR_IGNORE_TSSI);
2900 	}
2901 
2902 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2903 	if (phy->set_antenna)
2904 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2905 
2906 	if (sc->sc_rf_enabled != phy->rf_on) {
2907 		if (sc->sc_rf_enabled) {
2908 			bwn_rf_turnon(mac);
2909 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2910 				device_printf(sc->sc_dev,
2911 				    "please turn on the RF switch\n");
2912 		} else
2913 			bwn_rf_turnoff(mac);
2914 	}
2915 
2916 	bwn_mac_enable(mac);
2917 
2918 fail:
2919 	/*
2920 	 * Setup radio tap channel freq and flags
2921 	 */
2922 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2923 		htole16(ic->ic_curchan->ic_freq);
2924 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2925 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2926 
2927 	BWN_UNLOCK(sc);
2928 }
2929 
2930 static struct ieee80211vap *
2931 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2932     enum ieee80211_opmode opmode, int flags,
2933     const uint8_t bssid[IEEE80211_ADDR_LEN],
2934     const uint8_t mac0[IEEE80211_ADDR_LEN])
2935 {
2936 	struct ifnet *ifp = ic->ic_ifp;
2937 	struct bwn_softc *sc = ifp->if_softc;
2938 	struct ieee80211vap *vap;
2939 	struct bwn_vap *bvp;
2940 	uint8_t mac[IEEE80211_ADDR_LEN];
2941 
2942 	IEEE80211_ADDR_COPY(mac, mac0);
2943 	switch (opmode) {
2944 	case IEEE80211_M_HOSTAP:
2945 	case IEEE80211_M_MBSS:
2946 	case IEEE80211_M_STA:
2947 	case IEEE80211_M_WDS:
2948 	case IEEE80211_M_MONITOR:
2949 	case IEEE80211_M_IBSS:
2950 	case IEEE80211_M_AHDEMO:
2951 		break;
2952 	default:
2953 		return (NULL);
2954 	}
2955 
2956 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2957 
2958 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2959 	    M_80211_VAP, M_NOWAIT | M_ZERO);
2960 	if (bvp == NULL) {
2961 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2962 		return (NULL);
2963 	}
2964 	vap = &bvp->bv_vap;
2965 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2966 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2967 	/* override with driver methods */
2968 	bvp->bv_newstate = vap->iv_newstate;
2969 	vap->iv_newstate = bwn_newstate;
2970 
2971 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2972 	vap->iv_max_aid = BWN_STAID_MAX;
2973 
2974 	ieee80211_ratectl_init(vap);
2975 
2976 	/* complete setup */
2977 	ieee80211_vap_attach(vap, ieee80211_media_change,
2978 	    ieee80211_media_status);
2979 	return (vap);
2980 }
2981 
2982 static void
2983 bwn_vap_delete(struct ieee80211vap *vap)
2984 {
2985 	struct bwn_vap *bvp = BWN_VAP(vap);
2986 
2987 	ieee80211_ratectl_deinit(vap);
2988 	ieee80211_vap_detach(vap);
2989 	free(bvp, M_80211_VAP);
2990 }
2991 
2992 static void
2993 bwn_init(void *arg)
2994 {
2995 	struct bwn_softc *sc = arg;
2996 	struct ifnet *ifp = sc->sc_ifp;
2997 	struct ieee80211com *ic = ifp->if_l2com;
2998 	int error = 0;
2999 
3000 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3001 		__func__, ifp->if_flags);
3002 
3003 	BWN_LOCK(sc);
3004 	error = bwn_init_locked(sc);
3005 	BWN_UNLOCK(sc);
3006 
3007 	if (error == 0)
3008 		ieee80211_start_all(ic);	/* start all vap's */
3009 }
3010 
3011 static int
3012 bwn_init_locked(struct bwn_softc *sc)
3013 {
3014 	struct bwn_mac *mac;
3015 	struct ifnet *ifp = sc->sc_ifp;
3016 	int error;
3017 
3018 	BWN_ASSERT_LOCKED(sc);
3019 
3020 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3021 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3022 	sc->sc_filters = 0;
3023 	bwn_wme_clear(sc);
3024 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3025 	sc->sc_rf_enabled = 1;
3026 
3027 	mac = sc->sc_curmac;
3028 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3029 		error = bwn_core_init(mac);
3030 		if (error != 0)
3031 			return (error);
3032 	}
3033 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3034 		bwn_core_start(mac);
3035 
3036 	bwn_set_opmode(mac);
3037 	bwn_set_pretbtt(mac);
3038 	bwn_spu_setdelay(mac, 0);
3039 	bwn_set_macaddr(mac);
3040 
3041 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3042 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3043 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3044 
3045 	return (0);
3046 }
3047 
3048 static void
3049 bwn_stop(struct bwn_softc *sc, int statechg)
3050 {
3051 
3052 	BWN_LOCK(sc);
3053 	bwn_stop_locked(sc, statechg);
3054 	BWN_UNLOCK(sc);
3055 }
3056 
3057 static void
3058 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3059 {
3060 	struct bwn_mac *mac = sc->sc_curmac;
3061 	struct ifnet *ifp = sc->sc_ifp;
3062 
3063 	BWN_ASSERT_LOCKED(sc);
3064 
3065 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3066 		/* XXX FIXME opmode not based on VAP */
3067 		bwn_set_opmode(mac);
3068 		bwn_set_macaddr(mac);
3069 	}
3070 
3071 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3072 		bwn_core_stop(mac);
3073 
3074 	callout_stop(&sc->sc_led_blink_ch);
3075 	sc->sc_led_blinking = 0;
3076 
3077 	bwn_core_exit(mac);
3078 	sc->sc_rf_enabled = 0;
3079 
3080 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3081 }
3082 
3083 static void
3084 bwn_wme_clear(struct bwn_softc *sc)
3085 {
3086 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3087 	struct wmeParams *p;
3088 	unsigned int i;
3089 
3090 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3091 	    ("%s:%d: fail", __func__, __LINE__));
3092 
3093 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3094 		p = &(sc->sc_wmeParams[i]);
3095 
3096 		switch (bwn_wme_shm_offsets[i]) {
3097 		case BWN_WME_VOICE:
3098 			p->wmep_txopLimit = 0;
3099 			p->wmep_aifsn = 2;
3100 			/* XXX FIXME: log2(cwmin) */
3101 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3102 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3103 			break;
3104 		case BWN_WME_VIDEO:
3105 			p->wmep_txopLimit = 0;
3106 			p->wmep_aifsn = 2;
3107 			/* XXX FIXME: log2(cwmin) */
3108 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3109 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3110 			break;
3111 		case BWN_WME_BESTEFFORT:
3112 			p->wmep_txopLimit = 0;
3113 			p->wmep_aifsn = 3;
3114 			/* XXX FIXME: log2(cwmin) */
3115 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3116 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3117 			break;
3118 		case BWN_WME_BACKGROUND:
3119 			p->wmep_txopLimit = 0;
3120 			p->wmep_aifsn = 7;
3121 			/* XXX FIXME: log2(cwmin) */
3122 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3123 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3124 			break;
3125 		default:
3126 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3127 		}
3128 	}
3129 }
3130 
3131 static int
3132 bwn_core_init(struct bwn_mac *mac)
3133 {
3134 	struct bwn_softc *sc = mac->mac_sc;
3135 	uint64_t hf;
3136 	int error;
3137 
3138 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3139 	    ("%s:%d: fail", __func__, __LINE__));
3140 
3141 	siba_powerup(sc->sc_dev, 0);
3142 	if (!siba_dev_isup(sc->sc_dev))
3143 		bwn_reset_core(mac,
3144 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3145 
3146 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3147 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3148 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3149 	BWN_GETTIME(mac->mac_phy.nexttime);
3150 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3151 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3152 	mac->mac_stats.link_noise = -95;
3153 	mac->mac_reason_intr = 0;
3154 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3155 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3156 #ifdef BWN_DEBUG
3157 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3158 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3159 #endif
3160 	mac->mac_suspended = 1;
3161 	mac->mac_task_state = 0;
3162 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3163 
3164 	mac->mac_phy.init_pre(mac);
3165 
3166 	siba_pcicore_intr(sc->sc_dev);
3167 
3168 	siba_fix_imcfglobug(sc->sc_dev);
3169 	bwn_bt_disable(mac);
3170 	if (mac->mac_phy.prepare_hw) {
3171 		error = mac->mac_phy.prepare_hw(mac);
3172 		if (error)
3173 			goto fail0;
3174 	}
3175 	error = bwn_chip_init(mac);
3176 	if (error)
3177 		goto fail0;
3178 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3179 	    siba_get_revid(sc->sc_dev));
3180 	hf = bwn_hf_read(mac);
3181 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3182 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3183 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3184 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3185 		if (mac->mac_phy.rev == 1)
3186 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3187 	}
3188 	if (mac->mac_phy.rf_ver == 0x2050) {
3189 		if (mac->mac_phy.rf_rev < 6)
3190 			hf |= BWN_HF_FORCE_VCO_RECALC;
3191 		if (mac->mac_phy.rf_rev == 6)
3192 			hf |= BWN_HF_4318_TSSI;
3193 	}
3194 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3195 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3196 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3197 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3198 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3199 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3200 	bwn_hf_write(mac, hf);
3201 
3202 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3203 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3204 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3205 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3206 
3207 	bwn_rate_init(mac);
3208 	bwn_set_phytxctl(mac);
3209 
3210 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3211 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3212 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3213 
3214 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3215 		bwn_pio_init(mac);
3216 	else
3217 		bwn_dma_init(mac);
3218 	bwn_wme_init(mac);
3219 	bwn_spu_setdelay(mac, 1);
3220 	bwn_bt_enable(mac);
3221 
3222 	siba_powerup(sc->sc_dev,
3223 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3224 	bwn_set_macaddr(mac);
3225 	bwn_crypt_init(mac);
3226 
3227 	/* XXX LED initializatin */
3228 
3229 	mac->mac_status = BWN_MAC_STATUS_INITED;
3230 
3231 	return (error);
3232 
3233 fail0:
3234 	siba_powerdown(sc->sc_dev);
3235 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3236 	    ("%s:%d: fail", __func__, __LINE__));
3237 	return (error);
3238 }
3239 
3240 static void
3241 bwn_core_start(struct bwn_mac *mac)
3242 {
3243 	struct bwn_softc *sc = mac->mac_sc;
3244 	uint32_t tmp;
3245 
3246 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3247 	    ("%s:%d: fail", __func__, __LINE__));
3248 
3249 	if (siba_get_revid(sc->sc_dev) < 5)
3250 		return;
3251 
3252 	while (1) {
3253 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3254 		if (!(tmp & 0x00000001))
3255 			break;
3256 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3257 	}
3258 
3259 	bwn_mac_enable(mac);
3260 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3261 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3262 
3263 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3264 }
3265 
3266 static void
3267 bwn_core_exit(struct bwn_mac *mac)
3268 {
3269 	struct bwn_softc *sc = mac->mac_sc;
3270 	uint32_t macctl;
3271 
3272 	BWN_ASSERT_LOCKED(mac->mac_sc);
3273 
3274 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3275 	    ("%s:%d: fail", __func__, __LINE__));
3276 
3277 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3278 		return;
3279 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3280 
3281 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3282 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3283 	macctl |= BWN_MACCTL_MCODE_JMP0;
3284 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3285 
3286 	bwn_dma_stop(mac);
3287 	bwn_pio_stop(mac);
3288 	bwn_chip_exit(mac);
3289 	mac->mac_phy.switch_analog(mac, 0);
3290 	siba_dev_down(sc->sc_dev, 0);
3291 	siba_powerdown(sc->sc_dev);
3292 }
3293 
3294 static void
3295 bwn_bt_disable(struct bwn_mac *mac)
3296 {
3297 	struct bwn_softc *sc = mac->mac_sc;
3298 
3299 	(void)sc;
3300 	/* XXX do nothing yet */
3301 }
3302 
3303 static int
3304 bwn_chip_init(struct bwn_mac *mac)
3305 {
3306 	struct bwn_softc *sc = mac->mac_sc;
3307 	struct bwn_phy *phy = &mac->mac_phy;
3308 	uint32_t macctl;
3309 	int error;
3310 
3311 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3312 	if (phy->gmode)
3313 		macctl |= BWN_MACCTL_GMODE;
3314 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3315 
3316 	error = bwn_fw_fillinfo(mac);
3317 	if (error)
3318 		return (error);
3319 	error = bwn_fw_loaducode(mac);
3320 	if (error)
3321 		return (error);
3322 
3323 	error = bwn_gpio_init(mac);
3324 	if (error)
3325 		return (error);
3326 
3327 	error = bwn_fw_loadinitvals(mac);
3328 	if (error) {
3329 		siba_gpio_set(sc->sc_dev, 0);
3330 		return (error);
3331 	}
3332 	phy->switch_analog(mac, 1);
3333 	error = bwn_phy_init(mac);
3334 	if (error) {
3335 		siba_gpio_set(sc->sc_dev, 0);
3336 		return (error);
3337 	}
3338 	if (phy->set_im)
3339 		phy->set_im(mac, BWN_IMMODE_NONE);
3340 	if (phy->set_antenna)
3341 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3342 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3343 
3344 	if (phy->type == BWN_PHYTYPE_B)
3345 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3346 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3347 	if (siba_get_revid(sc->sc_dev) < 5)
3348 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3349 
3350 	BWN_WRITE_4(mac, BWN_MACCTL,
3351 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3352 	BWN_WRITE_4(mac, BWN_MACCTL,
3353 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3354 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3355 
3356 	bwn_set_opmode(mac);
3357 	if (siba_get_revid(sc->sc_dev) < 3) {
3358 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3359 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3360 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3361 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3362 	} else {
3363 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3364 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3365 	}
3366 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3367 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3368 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3369 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3370 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3371 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3372 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3373 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3374 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3375 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3376 	return (error);
3377 }
3378 
3379 /* read hostflags */
3380 static uint64_t
3381 bwn_hf_read(struct bwn_mac *mac)
3382 {
3383 	uint64_t ret;
3384 
3385 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3386 	ret <<= 16;
3387 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3388 	ret <<= 16;
3389 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3390 	return (ret);
3391 }
3392 
3393 static void
3394 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3395 {
3396 
3397 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3398 	    (value & 0x00000000ffffull));
3399 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3400 	    (value & 0x0000ffff0000ull) >> 16);
3401 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3402 	    (value & 0xffff00000000ULL) >> 32);
3403 }
3404 
3405 static void
3406 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3407 {
3408 
3409 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3410 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3411 }
3412 
3413 static void
3414 bwn_rate_init(struct bwn_mac *mac)
3415 {
3416 
3417 	switch (mac->mac_phy.type) {
3418 	case BWN_PHYTYPE_A:
3419 	case BWN_PHYTYPE_G:
3420 	case BWN_PHYTYPE_LP:
3421 	case BWN_PHYTYPE_N:
3422 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3423 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3424 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3425 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3426 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3427 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3428 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3429 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3430 			break;
3431 		/* FALLTHROUGH */
3432 	case BWN_PHYTYPE_B:
3433 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3434 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3435 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3436 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3437 		break;
3438 	default:
3439 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3440 	}
3441 }
3442 
3443 static void
3444 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3445 {
3446 	uint16_t offset;
3447 
3448 	if (ofdm) {
3449 		offset = 0x480;
3450 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3451 	} else {
3452 		offset = 0x4c0;
3453 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3454 	}
3455 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3456 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3457 }
3458 
3459 static uint8_t
3460 bwn_plcp_getcck(const uint8_t bitrate)
3461 {
3462 
3463 	switch (bitrate) {
3464 	case BWN_CCK_RATE_1MB:
3465 		return (0x0a);
3466 	case BWN_CCK_RATE_2MB:
3467 		return (0x14);
3468 	case BWN_CCK_RATE_5MB:
3469 		return (0x37);
3470 	case BWN_CCK_RATE_11MB:
3471 		return (0x6e);
3472 	}
3473 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3474 	return (0);
3475 }
3476 
3477 static uint8_t
3478 bwn_plcp_getofdm(const uint8_t bitrate)
3479 {
3480 
3481 	switch (bitrate) {
3482 	case BWN_OFDM_RATE_6MB:
3483 		return (0xb);
3484 	case BWN_OFDM_RATE_9MB:
3485 		return (0xf);
3486 	case BWN_OFDM_RATE_12MB:
3487 		return (0xa);
3488 	case BWN_OFDM_RATE_18MB:
3489 		return (0xe);
3490 	case BWN_OFDM_RATE_24MB:
3491 		return (0x9);
3492 	case BWN_OFDM_RATE_36MB:
3493 		return (0xd);
3494 	case BWN_OFDM_RATE_48MB:
3495 		return (0x8);
3496 	case BWN_OFDM_RATE_54MB:
3497 		return (0xc);
3498 	}
3499 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3500 	return (0);
3501 }
3502 
3503 static void
3504 bwn_set_phytxctl(struct bwn_mac *mac)
3505 {
3506 	uint16_t ctl;
3507 
3508 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3509 	    BWN_TX_PHY_TXPWR);
3510 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3511 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3512 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3513 }
3514 
3515 static void
3516 bwn_pio_init(struct bwn_mac *mac)
3517 {
3518 	struct bwn_pio *pio = &mac->mac_method.pio;
3519 
3520 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3521 	    & ~BWN_MACCTL_BIGENDIAN);
3522 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3523 
3524 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3525 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3526 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3527 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3528 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3529 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3530 }
3531 
3532 static void
3533 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3534     int index)
3535 {
3536 	struct bwn_pio_txpkt *tp;
3537 	struct bwn_softc *sc = mac->mac_sc;
3538 	unsigned int i;
3539 
3540 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3541 	tq->tq_index = index;
3542 
3543 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3544 	if (siba_get_revid(sc->sc_dev) >= 8)
3545 		tq->tq_size = 1920;
3546 	else {
3547 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3548 		tq->tq_size -= 80;
3549 	}
3550 
3551 	TAILQ_INIT(&tq->tq_pktlist);
3552 	for (i = 0; i < N(tq->tq_pkts); i++) {
3553 		tp = &(tq->tq_pkts[i]);
3554 		tp->tp_index = i;
3555 		tp->tp_queue = tq;
3556 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3557 	}
3558 }
3559 
3560 static uint16_t
3561 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3562 {
3563 	struct bwn_softc *sc = mac->mac_sc;
3564 	static const uint16_t bases[] = {
3565 		BWN_PIO_BASE0,
3566 		BWN_PIO_BASE1,
3567 		BWN_PIO_BASE2,
3568 		BWN_PIO_BASE3,
3569 		BWN_PIO_BASE4,
3570 		BWN_PIO_BASE5,
3571 		BWN_PIO_BASE6,
3572 		BWN_PIO_BASE7,
3573 	};
3574 	static const uint16_t bases_rev11[] = {
3575 		BWN_PIO11_BASE0,
3576 		BWN_PIO11_BASE1,
3577 		BWN_PIO11_BASE2,
3578 		BWN_PIO11_BASE3,
3579 		BWN_PIO11_BASE4,
3580 		BWN_PIO11_BASE5,
3581 	};
3582 
3583 	if (siba_get_revid(sc->sc_dev) >= 11) {
3584 		if (index >= N(bases_rev11))
3585 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3586 		return (bases_rev11[index]);
3587 	}
3588 	if (index >= N(bases))
3589 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3590 	return (bases[index]);
3591 }
3592 
3593 static void
3594 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3595     int index)
3596 {
3597 	struct bwn_softc *sc = mac->mac_sc;
3598 
3599 	prq->prq_mac = mac;
3600 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3601 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3602 	bwn_dma_rxdirectfifo(mac, index, 1);
3603 }
3604 
3605 static void
3606 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3607 {
3608 	if (tq == NULL)
3609 		return;
3610 	bwn_pio_cancel_tx_packets(tq);
3611 }
3612 
3613 static void
3614 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3615 {
3616 
3617 	bwn_destroy_pioqueue_tx(pio);
3618 }
3619 
3620 static uint16_t
3621 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3622     uint16_t offset)
3623 {
3624 
3625 	return (BWN_READ_2(mac, tq->tq_base + offset));
3626 }
3627 
3628 static void
3629 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3630 {
3631 	uint32_t ctl;
3632 	int type;
3633 	uint16_t base;
3634 
3635 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3636 	base = bwn_dma_base(type, idx);
3637 	if (type == BWN_DMA_64BIT) {
3638 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3639 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3640 		if (enable)
3641 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3642 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3643 	} else {
3644 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3645 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3646 		if (enable)
3647 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3648 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3649 	}
3650 }
3651 
3652 static uint64_t
3653 bwn_dma_mask(struct bwn_mac *mac)
3654 {
3655 	uint32_t tmp;
3656 	uint16_t base;
3657 
3658 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3659 	if (tmp & SIBA_TGSHIGH_DMA64)
3660 		return (BWN_DMA_BIT_MASK(64));
3661 	base = bwn_dma_base(0, 0);
3662 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3663 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3664 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3665 		return (BWN_DMA_BIT_MASK(32));
3666 
3667 	return (BWN_DMA_BIT_MASK(30));
3668 }
3669 
3670 static int
3671 bwn_dma_mask2type(uint64_t dmamask)
3672 {
3673 
3674 	if (dmamask == BWN_DMA_BIT_MASK(30))
3675 		return (BWN_DMA_30BIT);
3676 	if (dmamask == BWN_DMA_BIT_MASK(32))
3677 		return (BWN_DMA_32BIT);
3678 	if (dmamask == BWN_DMA_BIT_MASK(64))
3679 		return (BWN_DMA_64BIT);
3680 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3681 	return (BWN_DMA_30BIT);
3682 }
3683 
3684 static void
3685 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3686 {
3687 	struct bwn_pio_txpkt *tp;
3688 	unsigned int i;
3689 
3690 	for (i = 0; i < N(tq->tq_pkts); i++) {
3691 		tp = &(tq->tq_pkts[i]);
3692 		if (tp->tp_m) {
3693 			m_freem(tp->tp_m);
3694 			tp->tp_m = NULL;
3695 		}
3696 	}
3697 }
3698 
3699 static uint16_t
3700 bwn_dma_base(int type, int controller_idx)
3701 {
3702 	static const uint16_t map64[] = {
3703 		BWN_DMA64_BASE0,
3704 		BWN_DMA64_BASE1,
3705 		BWN_DMA64_BASE2,
3706 		BWN_DMA64_BASE3,
3707 		BWN_DMA64_BASE4,
3708 		BWN_DMA64_BASE5,
3709 	};
3710 	static const uint16_t map32[] = {
3711 		BWN_DMA32_BASE0,
3712 		BWN_DMA32_BASE1,
3713 		BWN_DMA32_BASE2,
3714 		BWN_DMA32_BASE3,
3715 		BWN_DMA32_BASE4,
3716 		BWN_DMA32_BASE5,
3717 	};
3718 
3719 	if (type == BWN_DMA_64BIT) {
3720 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3721 		    ("%s:%d: fail", __func__, __LINE__));
3722 		return (map64[controller_idx]);
3723 	}
3724 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3725 	    ("%s:%d: fail", __func__, __LINE__));
3726 	return (map32[controller_idx]);
3727 }
3728 
3729 static void
3730 bwn_dma_init(struct bwn_mac *mac)
3731 {
3732 	struct bwn_dma *dma = &mac->mac_method.dma;
3733 
3734 	/* setup TX DMA channels. */
3735 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3736 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3737 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3738 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3739 	bwn_dma_setup(dma->mcast);
3740 	/* setup RX DMA channel. */
3741 	bwn_dma_setup(dma->rx);
3742 }
3743 
3744 static struct bwn_dma_ring *
3745 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3746     int for_tx, int type)
3747 {
3748 	struct bwn_dma *dma = &mac->mac_method.dma;
3749 	struct bwn_dma_ring *dr;
3750 	struct bwn_dmadesc_generic *desc;
3751 	struct bwn_dmadesc_meta *mt;
3752 	struct bwn_softc *sc = mac->mac_sc;
3753 	int error, i;
3754 
3755 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3756 	if (dr == NULL)
3757 		goto out;
3758 	dr->dr_numslots = BWN_RXRING_SLOTS;
3759 	if (for_tx)
3760 		dr->dr_numslots = BWN_TXRING_SLOTS;
3761 
3762 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3763 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3764 	if (dr->dr_meta == NULL)
3765 		goto fail0;
3766 
3767 	dr->dr_type = type;
3768 	dr->dr_mac = mac;
3769 	dr->dr_base = bwn_dma_base(type, controller_index);
3770 	dr->dr_index = controller_index;
3771 	if (type == BWN_DMA_64BIT) {
3772 		dr->getdesc = bwn_dma_64_getdesc;
3773 		dr->setdesc = bwn_dma_64_setdesc;
3774 		dr->start_transfer = bwn_dma_64_start_transfer;
3775 		dr->suspend = bwn_dma_64_suspend;
3776 		dr->resume = bwn_dma_64_resume;
3777 		dr->get_curslot = bwn_dma_64_get_curslot;
3778 		dr->set_curslot = bwn_dma_64_set_curslot;
3779 	} else {
3780 		dr->getdesc = bwn_dma_32_getdesc;
3781 		dr->setdesc = bwn_dma_32_setdesc;
3782 		dr->start_transfer = bwn_dma_32_start_transfer;
3783 		dr->suspend = bwn_dma_32_suspend;
3784 		dr->resume = bwn_dma_32_resume;
3785 		dr->get_curslot = bwn_dma_32_get_curslot;
3786 		dr->set_curslot = bwn_dma_32_set_curslot;
3787 	}
3788 	if (for_tx) {
3789 		dr->dr_tx = 1;
3790 		dr->dr_curslot = -1;
3791 	} else {
3792 		if (dr->dr_index == 0) {
3793 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3794 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3795 		} else
3796 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3797 	}
3798 
3799 	error = bwn_dma_allocringmemory(dr);
3800 	if (error)
3801 		goto fail2;
3802 
3803 	if (for_tx) {
3804 		/*
3805 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3806 		 * BWN_TX_SLOTS_PER_FRAME
3807 		 */
3808 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3809 		    ("%s:%d: fail", __func__, __LINE__));
3810 
3811 		dr->dr_txhdr_cache =
3812 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3813 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3814 		KASSERT(dr->dr_txhdr_cache != NULL,
3815 		    ("%s:%d: fail", __func__, __LINE__));
3816 
3817 		/*
3818 		 * Create TX ring DMA stuffs
3819 		 */
3820 		error = bus_dma_tag_create(dma->parent_dtag,
3821 				    BWN_ALIGN, 0,
3822 				    BUS_SPACE_MAXADDR,
3823 				    BUS_SPACE_MAXADDR,
3824 				    NULL, NULL,
3825 				    BWN_HDRSIZE(mac),
3826 				    1,
3827 				    BUS_SPACE_MAXSIZE_32BIT,
3828 				    0,
3829 				    NULL, NULL,
3830 				    &dr->dr_txring_dtag);
3831 		if (error) {
3832 			device_printf(sc->sc_dev,
3833 			    "can't create TX ring DMA tag: TODO frees\n");
3834 			goto fail1;
3835 		}
3836 
3837 		for (i = 0; i < dr->dr_numslots; i += 2) {
3838 			dr->getdesc(dr, i, &desc, &mt);
3839 
3840 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3841 			mt->mt_m = NULL;
3842 			mt->mt_ni = NULL;
3843 			mt->mt_islast = 0;
3844 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3845 			    &mt->mt_dmap);
3846 			if (error) {
3847 				device_printf(sc->sc_dev,
3848 				     "can't create RX buf DMA map\n");
3849 				goto fail1;
3850 			}
3851 
3852 			dr->getdesc(dr, i + 1, &desc, &mt);
3853 
3854 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3855 			mt->mt_m = NULL;
3856 			mt->mt_ni = NULL;
3857 			mt->mt_islast = 1;
3858 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3859 			    &mt->mt_dmap);
3860 			if (error) {
3861 				device_printf(sc->sc_dev,
3862 				     "can't create RX buf DMA map\n");
3863 				goto fail1;
3864 			}
3865 		}
3866 	} else {
3867 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3868 		    &dr->dr_spare_dmap);
3869 		if (error) {
3870 			device_printf(sc->sc_dev,
3871 			    "can't create RX buf DMA map\n");
3872 			goto out;		/* XXX wrong! */
3873 		}
3874 
3875 		for (i = 0; i < dr->dr_numslots; i++) {
3876 			dr->getdesc(dr, i, &desc, &mt);
3877 
3878 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3879 			    &mt->mt_dmap);
3880 			if (error) {
3881 				device_printf(sc->sc_dev,
3882 				    "can't create RX buf DMA map\n");
3883 				goto out;	/* XXX wrong! */
3884 			}
3885 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3886 			if (error) {
3887 				device_printf(sc->sc_dev,
3888 				    "failed to allocate RX buf\n");
3889 				goto out;	/* XXX wrong! */
3890 			}
3891 		}
3892 
3893 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3894 		    BUS_DMASYNC_PREWRITE);
3895 
3896 		dr->dr_usedslot = dr->dr_numslots;
3897 	}
3898 
3899       out:
3900 	return (dr);
3901 
3902 fail2:
3903 	free(dr->dr_txhdr_cache, M_DEVBUF);
3904 fail1:
3905 	free(dr->dr_meta, M_DEVBUF);
3906 fail0:
3907 	free(dr, M_DEVBUF);
3908 	return (NULL);
3909 }
3910 
3911 static void
3912 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3913 {
3914 
3915 	if (dr == NULL)
3916 		return;
3917 
3918 	bwn_dma_free_descbufs(*dr);
3919 	bwn_dma_free_ringmemory(*dr);
3920 
3921 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3922 	free((*dr)->dr_meta, M_DEVBUF);
3923 	free(*dr, M_DEVBUF);
3924 
3925 	*dr = NULL;
3926 }
3927 
3928 static void
3929 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3930     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3931 {
3932 	struct bwn_dmadesc32 *desc;
3933 
3934 	*meta = &(dr->dr_meta[slot]);
3935 	desc = dr->dr_ring_descbase;
3936 	desc = &(desc[slot]);
3937 
3938 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3939 }
3940 
3941 static void
3942 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3943     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3944     int start, int end, int irq)
3945 {
3946 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3947 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3948 	uint32_t addr, addrext, ctl;
3949 	int slot;
3950 
3951 	slot = (int)(&(desc->dma.dma32) - descbase);
3952 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3953 	    ("%s:%d: fail", __func__, __LINE__));
3954 
3955 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3956 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3957 	addr |= siba_dma_translation(sc->sc_dev);
3958 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3959 	if (slot == dr->dr_numslots - 1)
3960 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3961 	if (start)
3962 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3963 	if (end)
3964 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3965 	if (irq)
3966 		ctl |= BWN_DMA32_DCTL_IRQ;
3967 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3968 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3969 
3970 	desc->dma.dma32.control = htole32(ctl);
3971 	desc->dma.dma32.address = htole32(addr);
3972 }
3973 
3974 static void
3975 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3976 {
3977 
3978 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3979 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3980 }
3981 
3982 static void
3983 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3984 {
3985 
3986 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3987 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3988 }
3989 
3990 static void
3991 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3992 {
3993 
3994 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3995 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3996 }
3997 
3998 static int
3999 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4000 {
4001 	uint32_t val;
4002 
4003 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4004 	val &= BWN_DMA32_RXDPTR;
4005 
4006 	return (val / sizeof(struct bwn_dmadesc32));
4007 }
4008 
4009 static void
4010 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4011 {
4012 
4013 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4014 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4015 }
4016 
4017 static void
4018 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4019     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4020 {
4021 	struct bwn_dmadesc64 *desc;
4022 
4023 	*meta = &(dr->dr_meta[slot]);
4024 	desc = dr->dr_ring_descbase;
4025 	desc = &(desc[slot]);
4026 
4027 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4028 }
4029 
4030 static void
4031 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4032     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4033     int start, int end, int irq)
4034 {
4035 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4036 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4037 	int slot;
4038 	uint32_t ctl0 = 0, ctl1 = 0;
4039 	uint32_t addrlo, addrhi;
4040 	uint32_t addrext;
4041 
4042 	slot = (int)(&(desc->dma.dma64) - descbase);
4043 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4044 	    ("%s:%d: fail", __func__, __LINE__));
4045 
4046 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4047 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4048 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4049 	    30;
4050 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4051 	if (slot == dr->dr_numslots - 1)
4052 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4053 	if (start)
4054 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4055 	if (end)
4056 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4057 	if (irq)
4058 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4059 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4060 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4061 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4062 
4063 	desc->dma.dma64.control0 = htole32(ctl0);
4064 	desc->dma.dma64.control1 = htole32(ctl1);
4065 	desc->dma.dma64.address_low = htole32(addrlo);
4066 	desc->dma.dma64.address_high = htole32(addrhi);
4067 }
4068 
4069 static void
4070 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4071 {
4072 
4073 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4074 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4075 }
4076 
4077 static void
4078 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4079 {
4080 
4081 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4082 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4083 }
4084 
4085 static void
4086 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4087 {
4088 
4089 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4090 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4091 }
4092 
4093 static int
4094 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4095 {
4096 	uint32_t val;
4097 
4098 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4099 	val &= BWN_DMA64_RXSTATDPTR;
4100 
4101 	return (val / sizeof(struct bwn_dmadesc64));
4102 }
4103 
4104 static void
4105 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4106 {
4107 
4108 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4109 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4110 }
4111 
4112 static int
4113 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4114 {
4115 	struct bwn_mac *mac = dr->dr_mac;
4116 	struct bwn_dma *dma = &mac->mac_method.dma;
4117 	struct bwn_softc *sc = mac->mac_sc;
4118 	int error;
4119 
4120 	error = bus_dma_tag_create(dma->parent_dtag,
4121 			    BWN_ALIGN, 0,
4122 			    BUS_SPACE_MAXADDR,
4123 			    BUS_SPACE_MAXADDR,
4124 			    NULL, NULL,
4125 			    BWN_DMA_RINGMEMSIZE,
4126 			    1,
4127 			    BUS_SPACE_MAXSIZE_32BIT,
4128 			    0,
4129 			    NULL, NULL,
4130 			    &dr->dr_ring_dtag);
4131 	if (error) {
4132 		device_printf(sc->sc_dev,
4133 		    "can't create TX ring DMA tag: TODO frees\n");
4134 		return (-1);
4135 	}
4136 
4137 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4138 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4139 	    &dr->dr_ring_dmap);
4140 	if (error) {
4141 		device_printf(sc->sc_dev,
4142 		    "can't allocate DMA mem: TODO frees\n");
4143 		return (-1);
4144 	}
4145 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4146 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4147 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4148 	if (error) {
4149 		device_printf(sc->sc_dev,
4150 		    "can't load DMA mem: TODO free\n");
4151 		return (-1);
4152 	}
4153 
4154 	return (0);
4155 }
4156 
4157 static void
4158 bwn_dma_setup(struct bwn_dma_ring *dr)
4159 {
4160 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4161 	uint64_t ring64;
4162 	uint32_t addrext, ring32, value;
4163 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4164 
4165 	if (dr->dr_tx) {
4166 		dr->dr_curslot = -1;
4167 
4168 		if (dr->dr_type == BWN_DMA_64BIT) {
4169 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4170 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4171 			    >> 30;
4172 			value = BWN_DMA64_TXENABLE;
4173 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4174 			    & BWN_DMA64_TXADDREXT_MASK;
4175 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4176 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4177 			    (ring64 & 0xffffffff));
4178 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4179 			    ((ring64 >> 32) &
4180 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4181 		} else {
4182 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4183 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4184 			value = BWN_DMA32_TXENABLE;
4185 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4186 			    & BWN_DMA32_TXADDREXT_MASK;
4187 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4188 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4189 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4190 		}
4191 		return;
4192 	}
4193 
4194 	/*
4195 	 * set for RX
4196 	 */
4197 	dr->dr_usedslot = dr->dr_numslots;
4198 
4199 	if (dr->dr_type == BWN_DMA_64BIT) {
4200 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4201 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4202 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4203 		value |= BWN_DMA64_RXENABLE;
4204 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4205 		    & BWN_DMA64_RXADDREXT_MASK;
4206 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4207 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4208 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4209 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4210 		    | (trans << 1));
4211 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4212 		    sizeof(struct bwn_dmadesc64));
4213 	} else {
4214 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4215 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4216 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4217 		value |= BWN_DMA32_RXENABLE;
4218 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4219 		    & BWN_DMA32_RXADDREXT_MASK;
4220 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4221 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4222 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4223 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4224 		    sizeof(struct bwn_dmadesc32));
4225 	}
4226 }
4227 
4228 static void
4229 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4230 {
4231 
4232 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4233 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4234 	    dr->dr_ring_dmap);
4235 }
4236 
4237 static void
4238 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4239 {
4240 
4241 	if (dr->dr_tx) {
4242 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4243 		if (dr->dr_type == BWN_DMA_64BIT) {
4244 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4245 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4246 		} else
4247 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4248 	} else {
4249 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4250 		if (dr->dr_type == BWN_DMA_64BIT) {
4251 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4252 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4253 		} else
4254 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4255 	}
4256 }
4257 
4258 static void
4259 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4260 {
4261 	struct bwn_dmadesc_generic *desc;
4262 	struct bwn_dmadesc_meta *meta;
4263 	struct bwn_mac *mac = dr->dr_mac;
4264 	struct bwn_dma *dma = &mac->mac_method.dma;
4265 	struct bwn_softc *sc = mac->mac_sc;
4266 	int i;
4267 
4268 	if (!dr->dr_usedslot)
4269 		return;
4270 	for (i = 0; i < dr->dr_numslots; i++) {
4271 		dr->getdesc(dr, i, &desc, &meta);
4272 
4273 		if (meta->mt_m == NULL) {
4274 			if (!dr->dr_tx)
4275 				device_printf(sc->sc_dev, "%s: not TX?\n",
4276 				    __func__);
4277 			continue;
4278 		}
4279 		if (dr->dr_tx) {
4280 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4281 				bus_dmamap_unload(dr->dr_txring_dtag,
4282 				    meta->mt_dmap);
4283 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4284 				bus_dmamap_unload(dma->txbuf_dtag,
4285 				    meta->mt_dmap);
4286 		} else
4287 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4288 		bwn_dma_free_descbuf(dr, meta);
4289 	}
4290 }
4291 
4292 static int
4293 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4294     int type)
4295 {
4296 	struct bwn_softc *sc = mac->mac_sc;
4297 	uint32_t value;
4298 	int i;
4299 	uint16_t offset;
4300 
4301 	for (i = 0; i < 10; i++) {
4302 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4303 		    BWN_DMA32_TXSTATUS;
4304 		value = BWN_READ_4(mac, base + offset);
4305 		if (type == BWN_DMA_64BIT) {
4306 			value &= BWN_DMA64_TXSTAT;
4307 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4308 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4309 			    value == BWN_DMA64_TXSTAT_STOPPED)
4310 				break;
4311 		} else {
4312 			value &= BWN_DMA32_TXSTATE;
4313 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4314 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4315 			    value == BWN_DMA32_TXSTAT_STOPPED)
4316 				break;
4317 		}
4318 		DELAY(1000);
4319 	}
4320 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4321 	BWN_WRITE_4(mac, base + offset, 0);
4322 	for (i = 0; i < 10; i++) {
4323 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4324 						   BWN_DMA32_TXSTATUS;
4325 		value = BWN_READ_4(mac, base + offset);
4326 		if (type == BWN_DMA_64BIT) {
4327 			value &= BWN_DMA64_TXSTAT;
4328 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4329 				i = -1;
4330 				break;
4331 			}
4332 		} else {
4333 			value &= BWN_DMA32_TXSTATE;
4334 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4335 				i = -1;
4336 				break;
4337 			}
4338 		}
4339 		DELAY(1000);
4340 	}
4341 	if (i != -1) {
4342 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4343 		return (ENODEV);
4344 	}
4345 	DELAY(1000);
4346 
4347 	return (0);
4348 }
4349 
4350 static int
4351 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4352     int type)
4353 {
4354 	struct bwn_softc *sc = mac->mac_sc;
4355 	uint32_t value;
4356 	int i;
4357 	uint16_t offset;
4358 
4359 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4360 	BWN_WRITE_4(mac, base + offset, 0);
4361 	for (i = 0; i < 10; i++) {
4362 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4363 		    BWN_DMA32_RXSTATUS;
4364 		value = BWN_READ_4(mac, base + offset);
4365 		if (type == BWN_DMA_64BIT) {
4366 			value &= BWN_DMA64_RXSTAT;
4367 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4368 				i = -1;
4369 				break;
4370 			}
4371 		} else {
4372 			value &= BWN_DMA32_RXSTATE;
4373 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4374 				i = -1;
4375 				break;
4376 			}
4377 		}
4378 		DELAY(1000);
4379 	}
4380 	if (i != -1) {
4381 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4382 		return (ENODEV);
4383 	}
4384 
4385 	return (0);
4386 }
4387 
4388 static void
4389 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4390     struct bwn_dmadesc_meta *meta)
4391 {
4392 
4393 	if (meta->mt_m != NULL) {
4394 		m_freem(meta->mt_m);
4395 		meta->mt_m = NULL;
4396 	}
4397 	if (meta->mt_ni != NULL) {
4398 		ieee80211_free_node(meta->mt_ni);
4399 		meta->mt_ni = NULL;
4400 	}
4401 }
4402 
4403 static void
4404 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4405 {
4406 	struct bwn_rxhdr4 *rxhdr;
4407 	unsigned char *frame;
4408 
4409 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4410 	rxhdr->frame_len = 0;
4411 
4412 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4413 	    sizeof(struct bwn_plcp6) + 2,
4414 	    ("%s:%d: fail", __func__, __LINE__));
4415 	frame = mtod(m, char *) + dr->dr_frameoffset;
4416 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4417 }
4418 
4419 static uint8_t
4420 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4421 {
4422 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4423 
4424 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4425 	    == 0xff);
4426 }
4427 
4428 static void
4429 bwn_wme_init(struct bwn_mac *mac)
4430 {
4431 
4432 	bwn_wme_load(mac);
4433 
4434 	/* enable WME support. */
4435 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4436 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4437 	    BWN_IFSCTL_USE_EDCF);
4438 }
4439 
4440 static void
4441 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4442 {
4443 	struct bwn_softc *sc = mac->mac_sc;
4444 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4445 	uint16_t delay;	/* microsec */
4446 
4447 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4448 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4449 		delay = 500;
4450 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4451 		delay = max(delay, (uint16_t)2400);
4452 
4453 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4454 }
4455 
4456 static void
4457 bwn_bt_enable(struct bwn_mac *mac)
4458 {
4459 	struct bwn_softc *sc = mac->mac_sc;
4460 	uint64_t hf;
4461 
4462 	if (bwn_bluetooth == 0)
4463 		return;
4464 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4465 		return;
4466 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4467 		return;
4468 
4469 	hf = bwn_hf_read(mac);
4470 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4471 		hf |= BWN_HF_BT_COEXISTALT;
4472 	else
4473 		hf |= BWN_HF_BT_COEXIST;
4474 	bwn_hf_write(mac, hf);
4475 }
4476 
4477 static void
4478 bwn_set_macaddr(struct bwn_mac *mac)
4479 {
4480 
4481 	bwn_mac_write_bssid(mac);
4482 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4483 }
4484 
4485 static void
4486 bwn_clear_keys(struct bwn_mac *mac)
4487 {
4488 	int i;
4489 
4490 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4491 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4492 		    ("%s:%d: fail", __func__, __LINE__));
4493 
4494 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4495 		    NULL, BWN_SEC_KEYSIZE, NULL);
4496 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4497 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4498 			    NULL, BWN_SEC_KEYSIZE, NULL);
4499 		}
4500 		mac->mac_key[i].keyconf = NULL;
4501 	}
4502 }
4503 
4504 static void
4505 bwn_crypt_init(struct bwn_mac *mac)
4506 {
4507 	struct bwn_softc *sc = mac->mac_sc;
4508 
4509 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4510 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4511 	    ("%s:%d: fail", __func__, __LINE__));
4512 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4513 	mac->mac_ktp *= 2;
4514 	if (siba_get_revid(sc->sc_dev) >= 5)
4515 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4516 	bwn_clear_keys(mac);
4517 }
4518 
4519 static void
4520 bwn_chip_exit(struct bwn_mac *mac)
4521 {
4522 	struct bwn_softc *sc = mac->mac_sc;
4523 
4524 	bwn_phy_exit(mac);
4525 	siba_gpio_set(sc->sc_dev, 0);
4526 }
4527 
4528 static int
4529 bwn_fw_fillinfo(struct bwn_mac *mac)
4530 {
4531 	int error;
4532 
4533 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4534 	if (error == 0)
4535 		return (0);
4536 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4537 	if (error == 0)
4538 		return (0);
4539 	return (error);
4540 }
4541 
4542 static int
4543 bwn_gpio_init(struct bwn_mac *mac)
4544 {
4545 	struct bwn_softc *sc = mac->mac_sc;
4546 	uint32_t mask = 0x1f, set = 0xf, value;
4547 
4548 	BWN_WRITE_4(mac, BWN_MACCTL,
4549 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4550 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4551 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4552 
4553 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4554 		mask |= 0x0060;
4555 		set |= 0x0060;
4556 	}
4557 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4558 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4559 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4560 		mask |= 0x0200;
4561 		set |= 0x0200;
4562 	}
4563 	if (siba_get_revid(sc->sc_dev) >= 2)
4564 		mask |= 0x0010;
4565 
4566 	value = siba_gpio_get(sc->sc_dev);
4567 	if (value == -1)
4568 		return (0);
4569 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4570 
4571 	return (0);
4572 }
4573 
4574 static int
4575 bwn_fw_loadinitvals(struct bwn_mac *mac)
4576 {
4577 #define	GETFWOFFSET(fwp, offset)				\
4578 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4579 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4580 	const struct bwn_fwhdr *hdr;
4581 	struct bwn_fw *fw = &mac->mac_fw;
4582 	int error;
4583 
4584 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4585 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4586 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4587 	if (error)
4588 		return (error);
4589 	if (fw->initvals_band.fw) {
4590 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4591 		error = bwn_fwinitvals_write(mac,
4592 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4593 		    be32toh(hdr->size),
4594 		    fw->initvals_band.fw->datasize - hdr_len);
4595 	}
4596 	return (error);
4597 #undef GETFWOFFSET
4598 }
4599 
4600 static int
4601 bwn_phy_init(struct bwn_mac *mac)
4602 {
4603 	struct bwn_softc *sc = mac->mac_sc;
4604 	int error;
4605 
4606 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4607 	mac->mac_phy.rf_onoff(mac, 1);
4608 	error = mac->mac_phy.init(mac);
4609 	if (error) {
4610 		device_printf(sc->sc_dev, "PHY init failed\n");
4611 		goto fail0;
4612 	}
4613 	error = bwn_switch_channel(mac,
4614 	    mac->mac_phy.get_default_chan(mac));
4615 	if (error) {
4616 		device_printf(sc->sc_dev,
4617 		    "failed to switch default channel\n");
4618 		goto fail1;
4619 	}
4620 	return (0);
4621 fail1:
4622 	if (mac->mac_phy.exit)
4623 		mac->mac_phy.exit(mac);
4624 fail0:
4625 	mac->mac_phy.rf_onoff(mac, 0);
4626 
4627 	return (error);
4628 }
4629 
4630 static void
4631 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4632 {
4633 	uint16_t ant;
4634 	uint16_t tmp;
4635 
4636 	ant = bwn_ant2phy(antenna);
4637 
4638 	/* For ACK/CTS */
4639 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4640 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4641 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4642 	/* For Probe Resposes */
4643 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4644 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4645 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4646 }
4647 
4648 static void
4649 bwn_set_opmode(struct bwn_mac *mac)
4650 {
4651 	struct bwn_softc *sc = mac->mac_sc;
4652 	struct ifnet *ifp = sc->sc_ifp;
4653 	struct ieee80211com *ic = ifp->if_l2com;
4654 	uint32_t ctl;
4655 	uint16_t cfp_pretbtt;
4656 
4657 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4658 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4659 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4660 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4661 	ctl |= BWN_MACCTL_STA;
4662 
4663 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4664 	    ic->ic_opmode == IEEE80211_M_MBSS)
4665 		ctl |= BWN_MACCTL_HOSTAP;
4666 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4667 		ctl &= ~BWN_MACCTL_STA;
4668 	ctl |= sc->sc_filters;
4669 
4670 	if (siba_get_revid(sc->sc_dev) <= 4)
4671 		ctl |= BWN_MACCTL_PROMISC;
4672 
4673 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4674 
4675 	cfp_pretbtt = 2;
4676 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4677 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4678 		    siba_get_chiprev(sc->sc_dev) == 3)
4679 			cfp_pretbtt = 100;
4680 		else
4681 			cfp_pretbtt = 50;
4682 	}
4683 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4684 }
4685 
4686 static int
4687 bwn_dma_gettype(struct bwn_mac *mac)
4688 {
4689 	uint32_t tmp;
4690 	uint16_t base;
4691 
4692 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4693 	if (tmp & SIBA_TGSHIGH_DMA64)
4694 		return (BWN_DMA_64BIT);
4695 	base = bwn_dma_base(0, 0);
4696 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4697 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4698 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4699 		return (BWN_DMA_32BIT);
4700 
4701 	return (BWN_DMA_30BIT);
4702 }
4703 
4704 static void
4705 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4706 {
4707 	if (!error) {
4708 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4709 		*((bus_addr_t *)arg) = seg->ds_addr;
4710 	}
4711 }
4712 
4713 static void
4714 bwn_phy_g_init_sub(struct bwn_mac *mac)
4715 {
4716 	struct bwn_phy *phy = &mac->mac_phy;
4717 	struct bwn_phy_g *pg = &phy->phy_g;
4718 	struct bwn_softc *sc = mac->mac_sc;
4719 	uint16_t i, tmp;
4720 
4721 	if (phy->rev == 1)
4722 		bwn_phy_init_b5(mac);
4723 	else
4724 		bwn_phy_init_b6(mac);
4725 
4726 	if (phy->rev >= 2 || phy->gmode)
4727 		bwn_phy_init_a(mac);
4728 
4729 	if (phy->rev >= 2) {
4730 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4731 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4732 	}
4733 	if (phy->rev == 2) {
4734 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4735 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4736 	}
4737 	if (phy->rev > 5) {
4738 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4739 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4740 	}
4741 	if (phy->gmode || phy->rev >= 2) {
4742 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4743 		tmp &= BWN_PHYVER_VERSION;
4744 		if (tmp == 3 || tmp == 5) {
4745 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4746 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4747 		}
4748 		if (tmp == 5) {
4749 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4750 			    0x1f00);
4751 		}
4752 	}
4753 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4754 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4755 	if (phy->rf_rev == 8) {
4756 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4757 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4758 	}
4759 	if (BWN_HAS_LOOPBACK(phy))
4760 		bwn_loopback_calcgain(mac);
4761 
4762 	if (phy->rf_rev != 8) {
4763 		if (pg->pg_initval == 0xffff)
4764 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4765 		else
4766 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4767 	}
4768 	bwn_lo_g_init(mac);
4769 	if (BWN_HAS_TXMAG(phy)) {
4770 		BWN_RF_WRITE(mac, 0x52,
4771 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4772 		    | pg->pg_loctl.tx_bias |
4773 		    pg->pg_loctl.tx_magn);
4774 	} else {
4775 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4776 	}
4777 	if (phy->rev >= 6) {
4778 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4779 		    (pg->pg_loctl.tx_bias << 12));
4780 	}
4781 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4782 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4783 	else
4784 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4785 	if (phy->rev < 2)
4786 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4787 	else
4788 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4789 	if (phy->gmode || phy->rev >= 2) {
4790 		bwn_lo_g_adjust(mac);
4791 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4792 	}
4793 
4794 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4795 		for (i = 0; i < 64; i++) {
4796 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4797 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4798 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4799 			    -32), 31));
4800 		}
4801 		bwn_nrssi_threshold(mac);
4802 	} else if (phy->gmode || phy->rev >= 2) {
4803 		if (pg->pg_nrssi[0] == -1000) {
4804 			KASSERT(pg->pg_nrssi[1] == -1000,
4805 			    ("%s:%d: fail", __func__, __LINE__));
4806 			bwn_nrssi_slope_11g(mac);
4807 		} else
4808 			bwn_nrssi_threshold(mac);
4809 	}
4810 	if (phy->rf_rev == 8)
4811 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4812 	bwn_phy_hwpctl_init(mac);
4813 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4814 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4815 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4816 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4817 	}
4818 }
4819 
4820 static uint8_t
4821 bwn_has_hwpctl(struct bwn_mac *mac)
4822 {
4823 
4824 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4825 		return (0);
4826 	return (mac->mac_phy.use_hwpctl(mac));
4827 }
4828 
4829 static void
4830 bwn_phy_init_b5(struct bwn_mac *mac)
4831 {
4832 	struct bwn_phy *phy = &mac->mac_phy;
4833 	struct bwn_phy_g *pg = &phy->phy_g;
4834 	struct bwn_softc *sc = mac->mac_sc;
4835 	uint16_t offset, value;
4836 	uint8_t old_channel;
4837 
4838 	if (phy->analog == 1)
4839 		BWN_RF_SET(mac, 0x007a, 0x0050);
4840 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4841 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4842 		value = 0x2120;
4843 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4844 			BWN_PHY_WRITE(mac, offset, value);
4845 			value += 0x202;
4846 		}
4847 	}
4848 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4849 	if (phy->rf_ver == 0x2050)
4850 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4851 
4852 	if (phy->gmode || phy->rev >= 2) {
4853 		if (phy->rf_ver == 0x2050) {
4854 			BWN_RF_SET(mac, 0x007a, 0x0020);
4855 			BWN_RF_SET(mac, 0x0051, 0x0004);
4856 		}
4857 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4858 
4859 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4860 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4861 
4862 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4863 
4864 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4865 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4866 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4867 	}
4868 
4869 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4870 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4871 
4872 	if (phy->analog == 1) {
4873 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4874 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4875 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4876 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4877 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4878 	} else
4879 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4880 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4881 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4882 
4883 	if (phy->analog == 1)
4884 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4885 	else
4886 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4887 
4888 	if (phy->analog == 0)
4889 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4890 
4891 	old_channel = phy->chan;
4892 	bwn_phy_g_switch_chan(mac, 7, 0);
4893 
4894 	if (phy->rf_ver != 0x2050) {
4895 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4896 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4897 	}
4898 
4899 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4900 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4901 
4902 	if (phy->rf_ver == 0x2050) {
4903 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4904 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4905 	}
4906 
4907 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4908 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4909 	BWN_RF_SET(mac, 0x007a, 0x0007);
4910 
4911 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4912 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4913 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4914 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4915 
4916 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4917 	    pg->pg_txctl);
4918 
4919 	if (phy->rf_ver == 0x2050)
4920 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4921 
4922 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4923 }
4924 
4925 static void
4926 bwn_loopback_calcgain(struct bwn_mac *mac)
4927 {
4928 	struct bwn_phy *phy = &mac->mac_phy;
4929 	struct bwn_phy_g *pg = &phy->phy_g;
4930 	struct bwn_softc *sc = mac->mac_sc;
4931 	uint16_t backup_phy[16] = { 0 };
4932 	uint16_t backup_radio[3];
4933 	uint16_t backup_bband;
4934 	uint16_t i, j, loop_i_max;
4935 	uint16_t trsw_rx;
4936 	uint16_t loop1_outer_done, loop1_inner_done;
4937 
4938 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4939 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4940 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4941 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4942 	if (phy->rev != 1) {
4943 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4944 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4945 	}
4946 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4947 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4948 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4949 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4950 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4951 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4952 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4953 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4954 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4955 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4956 	backup_bband = pg->pg_bbatt.att;
4957 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4958 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4959 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4960 
4961 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4962 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4963 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4964 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4965 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4966 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4967 	if (phy->rev != 1) {
4968 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4969 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4970 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4971 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4972 	}
4973 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4974 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4975 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4976 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4977 
4978 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4979 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4980 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4981 
4982 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4983 	if (phy->rev != 1) {
4984 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4985 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4986 	}
4987 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4988 
4989 	if (phy->rf_rev == 8)
4990 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4991 	else {
4992 		BWN_RF_WRITE(mac, 0x52, 0);
4993 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4994 	}
4995 	bwn_phy_g_set_bbatt(mac, 11);
4996 
4997 	if (phy->rev >= 3)
4998 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4999 	else
5000 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5001 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5002 
5003 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5004 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5005 
5006 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5007 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5008 
5009 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5010 		if (phy->rev >= 7) {
5011 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5012 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5013 		}
5014 	}
5015 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5016 
5017 	j = 0;
5018 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5019 	for (i = 0; i < loop_i_max; i++) {
5020 		for (j = 0; j < 16; j++) {
5021 			BWN_RF_WRITE(mac, 0x43, i);
5022 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5023 			    (j << 8));
5024 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5025 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5026 			DELAY(20);
5027 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5028 				goto done0;
5029 		}
5030 	}
5031 done0:
5032 	loop1_outer_done = i;
5033 	loop1_inner_done = j;
5034 	if (j >= 8) {
5035 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5036 		trsw_rx = 0x1b;
5037 		for (j = j - 8; j < 16; j++) {
5038 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5039 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5040 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5041 			DELAY(20);
5042 			trsw_rx -= 3;
5043 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5044 				goto done1;
5045 		}
5046 	} else
5047 		trsw_rx = 0x18;
5048 done1:
5049 
5050 	if (phy->rev != 1) {
5051 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5052 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5053 	}
5054 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5055 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5056 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5057 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5058 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5059 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5060 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5061 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5062 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5063 
5064 	bwn_phy_g_set_bbatt(mac, backup_bband);
5065 
5066 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5067 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5068 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5069 
5070 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5071 	DELAY(10);
5072 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5073 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5074 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5075 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5076 
5077 	pg->pg_max_lb_gain =
5078 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5079 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5080 }
5081 
5082 static uint16_t
5083 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5084 {
5085 	struct bwn_phy *phy = &mac->mac_phy;
5086 	uint32_t tmp1 = 0, tmp2 = 0;
5087 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5088 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5089 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5090 	static const uint8_t rcc_table[] = {
5091 		0x02, 0x03, 0x01, 0x0f,
5092 		0x06, 0x07, 0x05, 0x0f,
5093 		0x0a, 0x0b, 0x09, 0x0f,
5094 		0x0e, 0x0f, 0x0d, 0x0f,
5095 	};
5096 
5097 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5098 	    rfoverval = rfover = cck3 = 0;
5099 	radio0 = BWN_RF_READ(mac, 0x43);
5100 	radio1 = BWN_RF_READ(mac, 0x51);
5101 	radio2 = BWN_RF_READ(mac, 0x52);
5102 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5103 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5104 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5105 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5106 
5107 	if (phy->type == BWN_PHYTYPE_B) {
5108 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5109 		reg0 = BWN_READ_2(mac, 0x3ec);
5110 
5111 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5112 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5113 	} else if (phy->gmode || phy->rev >= 2) {
5114 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5115 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5116 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5117 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5118 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5119 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5120 
5121 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5122 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5123 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5124 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5125 		if (BWN_HAS_LOOPBACK(phy)) {
5126 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5127 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5128 			if (phy->rev >= 3)
5129 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5130 			else
5131 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5132 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5133 		}
5134 
5135 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5136 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5137 			BWN_LPD(0, 1, 1)));
5138 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5139 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5140 	}
5141 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5142 
5143 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5144 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5145 	reg1 = BWN_READ_2(mac, 0x3e6);
5146 	reg2 = BWN_READ_2(mac, 0x3f4);
5147 
5148 	if (phy->analog == 0)
5149 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5150 	else {
5151 		if (phy->analog >= 2)
5152 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5153 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5154 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5155 	}
5156 
5157 	reg = BWN_RF_READ(mac, 0x60);
5158 	index = (reg & 0x001e) >> 1;
5159 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5160 
5161 	if (phy->type == BWN_PHYTYPE_B)
5162 		BWN_RF_WRITE(mac, 0x78, 0x26);
5163 	if (phy->gmode || phy->rev >= 2) {
5164 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5165 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5166 			BWN_LPD(0, 1, 1)));
5167 	}
5168 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5169 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5170 	if (phy->gmode || phy->rev >= 2) {
5171 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5172 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5173 			BWN_LPD(0, 0, 1)));
5174 	}
5175 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5176 	BWN_RF_SET(mac, 0x51, 0x0004);
5177 	if (phy->rf_rev == 8)
5178 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5179 	else {
5180 		BWN_RF_WRITE(mac, 0x52, 0);
5181 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5182 	}
5183 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5184 
5185 	for (i = 0; i < 16; i++) {
5186 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5187 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5188 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5189 		if (phy->gmode || phy->rev >= 2) {
5190 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5191 			    bwn_rf_2050_rfoverval(mac,
5192 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5193 		}
5194 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5195 		DELAY(10);
5196 		if (phy->gmode || phy->rev >= 2) {
5197 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5198 			    bwn_rf_2050_rfoverval(mac,
5199 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5200 		}
5201 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5202 		DELAY(10);
5203 		if (phy->gmode || phy->rev >= 2) {
5204 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5205 			    bwn_rf_2050_rfoverval(mac,
5206 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5207 		}
5208 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5209 		DELAY(20);
5210 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5211 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5212 		if (phy->gmode || phy->rev >= 2) {
5213 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5214 			    bwn_rf_2050_rfoverval(mac,
5215 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5216 		}
5217 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5218 	}
5219 	DELAY(10);
5220 
5221 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5222 	tmp1++;
5223 	tmp1 >>= 9;
5224 
5225 	for (i = 0; i < 16; i++) {
5226 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5227 		BWN_RF_WRITE(mac, 0x78, radio78);
5228 		DELAY(10);
5229 		for (j = 0; j < 16; j++) {
5230 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5231 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5232 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5233 			if (phy->gmode || phy->rev >= 2) {
5234 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5235 				    bwn_rf_2050_rfoverval(mac,
5236 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5237 			}
5238 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5239 			DELAY(10);
5240 			if (phy->gmode || phy->rev >= 2) {
5241 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5242 				    bwn_rf_2050_rfoverval(mac,
5243 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5244 			}
5245 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5246 			DELAY(10);
5247 			if (phy->gmode || phy->rev >= 2) {
5248 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5249 				    bwn_rf_2050_rfoverval(mac,
5250 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5251 			}
5252 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5253 			DELAY(10);
5254 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5255 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5256 			if (phy->gmode || phy->rev >= 2) {
5257 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5258 				    bwn_rf_2050_rfoverval(mac,
5259 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5260 			}
5261 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5262 		}
5263 		tmp2++;
5264 		tmp2 >>= 8;
5265 		if (tmp1 < tmp2)
5266 			break;
5267 	}
5268 
5269 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5270 	BWN_RF_WRITE(mac, 0x51, radio1);
5271 	BWN_RF_WRITE(mac, 0x52, radio2);
5272 	BWN_RF_WRITE(mac, 0x43, radio0);
5273 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5274 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5275 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5276 	BWN_WRITE_2(mac, 0x3e6, reg1);
5277 	if (phy->analog != 0)
5278 		BWN_WRITE_2(mac, 0x3f4, reg2);
5279 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5280 	bwn_spu_workaround(mac, phy->chan);
5281 	if (phy->type == BWN_PHYTYPE_B) {
5282 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5283 		BWN_WRITE_2(mac, 0x3ec, reg0);
5284 	} else if (phy->gmode) {
5285 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5286 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5287 			    & 0x7fff);
5288 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5289 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5290 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5291 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5292 			      analogoverval);
5293 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5294 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5295 		if (BWN_HAS_LOOPBACK(phy)) {
5296 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5297 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5298 		}
5299 	}
5300 
5301 	return ((i > 15) ? radio78 : rcc);
5302 }
5303 
5304 static void
5305 bwn_phy_init_b6(struct bwn_mac *mac)
5306 {
5307 	struct bwn_phy *phy = &mac->mac_phy;
5308 	struct bwn_phy_g *pg = &phy->phy_g;
5309 	struct bwn_softc *sc = mac->mac_sc;
5310 	uint16_t offset, val;
5311 	uint8_t old_channel;
5312 
5313 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5314 	    ("%s:%d: fail", __func__, __LINE__));
5315 
5316 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5317 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5318 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5319 		BWN_RF_WRITE(mac, 0x51, 0x37);
5320 		BWN_RF_WRITE(mac, 0x52, 0x70);
5321 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5322 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5323 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5324 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5325 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5326 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5327 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5328 		bwn_hf_write(mac,
5329 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5330 	}
5331 	if (phy->rf_rev == 8) {
5332 		BWN_RF_WRITE(mac, 0x51, 0);
5333 		BWN_RF_WRITE(mac, 0x52, 0x40);
5334 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5335 		BWN_RF_WRITE(mac, 0x54, 0x98);
5336 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5337 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5338 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5339 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5340 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5341 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5342 		} else {
5343 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5344 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5345 		}
5346 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5347 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5348 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5349 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5350 	}
5351 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5352 		BWN_PHY_WRITE(mac, offset, val);
5353 		val -= 0x0202;
5354 	}
5355 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5356 		BWN_PHY_WRITE(mac, offset, val);
5357 		val -= 0x0202;
5358 	}
5359 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5360 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5361 		val += 0x0202;
5362 	}
5363 	if (phy->type == BWN_PHYTYPE_G) {
5364 		BWN_RF_SET(mac, 0x007a, 0x0020);
5365 		BWN_RF_SET(mac, 0x0051, 0x0004);
5366 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5367 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5368 		BWN_PHY_WRITE(mac, 0x5b, 0);
5369 		BWN_PHY_WRITE(mac, 0x5c, 0);
5370 	}
5371 
5372 	old_channel = phy->chan;
5373 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5374 
5375 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5376 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5377 	DELAY(40);
5378 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5379 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5380 		BWN_RF_WRITE(mac, 0x50, 0x20);
5381 	}
5382 	if (phy->rf_rev <= 2) {
5383 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5384 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5385 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5386 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5387 	}
5388 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5389 
5390 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5391 
5392 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5393 	if (phy->rf_rev >= 6)
5394 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5395 	else
5396 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5397 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5398 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5399 	    pg->pg_txctl);
5400 	if (phy->rf_rev <= 5)
5401 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5402 	if (phy->rf_rev <= 2)
5403 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5404 
5405 	if (phy->analog == 4) {
5406 		BWN_WRITE_2(mac, 0x3e4, 9);
5407 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5408 	} else
5409 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5410 	if (phy->type == BWN_PHYTYPE_B)
5411 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5412 	else if (phy->type == BWN_PHYTYPE_G)
5413 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5414 }
5415 
5416 static void
5417 bwn_phy_init_a(struct bwn_mac *mac)
5418 {
5419 	struct bwn_phy *phy = &mac->mac_phy;
5420 	struct bwn_softc *sc = mac->mac_sc;
5421 
5422 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5423 	    ("%s:%d: fail", __func__, __LINE__));
5424 
5425 	if (phy->rev >= 6) {
5426 		if (phy->type == BWN_PHYTYPE_A)
5427 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5428 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5429 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5430 		else
5431 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5432 	}
5433 
5434 	bwn_wa_init(mac);
5435 
5436 	if (phy->type == BWN_PHYTYPE_G &&
5437 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5438 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5439 }
5440 
5441 static void
5442 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5443 {
5444 	int i;
5445 
5446 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5447 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5448 }
5449 
5450 static void
5451 bwn_wa_agc(struct bwn_mac *mac)
5452 {
5453 	struct bwn_phy *phy = &mac->mac_phy;
5454 
5455 	if (phy->rev == 1) {
5456 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5457 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5458 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5459 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5460 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5461 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5462 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5463 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5464 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5465 	} else {
5466 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5467 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5468 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5469 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5470 	}
5471 
5472 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5473 	    0x5700);
5474 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5475 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5476 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5477 	BWN_RF_SET(mac, 0x7a, 0x0008);
5478 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5479 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5480 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5481 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5482 	if (phy->rev == 1)
5483 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5484 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5485 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5486 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5487 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5488 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5489 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5490 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5491 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5492 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5493 	if (phy->rev == 1) {
5494 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5495 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5496 	} else {
5497 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5498 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5499 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5500 		if (phy->rev >= 6) {
5501 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5502 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5503 			    (uint16_t)~0xf000, 0x3000);
5504 		}
5505 	}
5506 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5507 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5508 	if (phy->rev == 1) {
5509 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5510 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5511 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5512 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5513 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5514 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5515 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5516 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5517 	} else {
5518 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5519 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5520 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5521 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5522 	}
5523 	if (phy->rev >= 6) {
5524 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5525 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5526 	}
5527 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5528 }
5529 
5530 static void
5531 bwn_wa_grev1(struct bwn_mac *mac)
5532 {
5533 	struct bwn_phy *phy = &mac->mac_phy;
5534 	int i;
5535 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5536 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5537 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5538 
5539 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5540 
5541 	/* init CRSTHRES and ANTDWELL */
5542 	if (phy->rev == 1) {
5543 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5544 	} else if (phy->rev == 2) {
5545 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5546 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5547 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5548 	} else {
5549 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5550 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5551 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5552 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5553 	}
5554 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5555 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5556 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5557 
5558 	/* XXX support PHY-A??? */
5559 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5560 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5561 		    bwn_tab_finefreqg[i]);
5562 
5563 	/* XXX support PHY-A??? */
5564 	if (phy->rev == 1)
5565 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5566 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5567 			    bwn_tab_noise_g1[i]);
5568 	else
5569 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5570 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5571 			    bwn_tab_noise_g2[i]);
5572 
5573 
5574 	for (i = 0; i < N(bwn_tab_rotor); i++)
5575 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5576 		    bwn_tab_rotor[i]);
5577 
5578 	/* XXX support PHY-A??? */
5579 	if (phy->rev >= 6) {
5580 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5581 		    BWN_PHY_ENCORE_EN)
5582 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5583 		else
5584 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5585 	} else
5586 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5587 
5588 	for (i = 0; i < N(bwn_tab_retard); i++)
5589 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5590 		    bwn_tab_retard[i]);
5591 
5592 	if (phy->rev == 1) {
5593 		for (i = 0; i < 16; i++)
5594 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5595 			    i, 0x0020);
5596 	} else {
5597 		for (i = 0; i < 32; i++)
5598 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5599 	}
5600 
5601 	bwn_wa_agc(mac);
5602 }
5603 
5604 static void
5605 bwn_wa_grev26789(struct bwn_mac *mac)
5606 {
5607 	struct bwn_phy *phy = &mac->mac_phy;
5608 	int i;
5609 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5610 	uint16_t ofdmrev;
5611 
5612 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5613 
5614 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5615 
5616 	/* init CRSTHRES and ANTDWELL */
5617 	if (phy->rev == 1)
5618 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5619 	else if (phy->rev == 2) {
5620 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5621 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5622 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5623 	} else {
5624 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5625 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5626 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5627 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5628 	}
5629 
5630 	for (i = 0; i < 64; i++)
5631 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5632 
5633 	/* XXX support PHY-A??? */
5634 	if (phy->rev == 1)
5635 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5636 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5637 			    bwn_tab_noise_g1[i]);
5638 	else
5639 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5640 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5641 			    bwn_tab_noise_g2[i]);
5642 
5643 	/* XXX support PHY-A??? */
5644 	if (phy->rev >= 6) {
5645 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5646 		    BWN_PHY_ENCORE_EN)
5647 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5648 		else
5649 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5650 	} else
5651 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5652 
5653 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5654 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5655 		    bwn_tab_sigmasqr2[i]);
5656 
5657 	if (phy->rev == 1) {
5658 		for (i = 0; i < 16; i++)
5659 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5660 			    0x0020);
5661 	} else {
5662 		for (i = 0; i < 32; i++)
5663 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5664 	}
5665 
5666 	bwn_wa_agc(mac);
5667 
5668 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5669 	if (ofdmrev > 2) {
5670 		if (phy->type == BWN_PHYTYPE_A)
5671 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5672 		else
5673 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5674 	} else {
5675 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5676 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5677 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5678 	}
5679 
5680 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5681 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5682 }
5683 
5684 static void
5685 bwn_wa_init(struct bwn_mac *mac)
5686 {
5687 	struct bwn_phy *phy = &mac->mac_phy;
5688 	struct bwn_softc *sc = mac->mac_sc;
5689 
5690 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5691 
5692 	switch (phy->rev) {
5693 	case 1:
5694 		bwn_wa_grev1(mac);
5695 		break;
5696 	case 2:
5697 	case 6:
5698 	case 7:
5699 	case 8:
5700 	case 9:
5701 		bwn_wa_grev26789(mac);
5702 		break;
5703 	default:
5704 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5705 	}
5706 
5707 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5708 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5709 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5710 		if (phy->rev < 2) {
5711 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5712 			    0x0002);
5713 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5714 			    0x0001);
5715 		} else {
5716 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5717 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5718 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5719 			     BWN_BFL_EXTLNA) &&
5720 			    (phy->rev >= 7)) {
5721 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5722 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723 				    0x0020, 0x0001);
5724 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725 				    0x0021, 0x0001);
5726 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727 				    0x0022, 0x0001);
5728 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729 				    0x0023, 0x0000);
5730 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5731 				    0x0000, 0x0000);
5732 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5733 				    0x0003, 0x0002);
5734 			}
5735 		}
5736 	}
5737 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5738 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5739 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5740 	}
5741 
5742 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5743 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5744 }
5745 
5746 static void
5747 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5748     uint16_t value)
5749 {
5750 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5751 	uint16_t addr;
5752 
5753 	addr = table + offset;
5754 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5755 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5756 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5757 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5758 	}
5759 	pg->pg_ofdmtab_addr = addr;
5760 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5761 }
5762 
5763 static void
5764 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5765     uint32_t value)
5766 {
5767 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5768 	uint16_t addr;
5769 
5770 	addr = table + offset;
5771 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5772 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5773 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5774 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5775 	}
5776 	pg->pg_ofdmtab_addr = addr;
5777 
5778 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5779 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5780 }
5781 
5782 static void
5783 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5784     uint16_t value)
5785 {
5786 
5787 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5788 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5789 }
5790 
5791 static void
5792 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5793 {
5794 	struct bwn_phy *phy = &mac->mac_phy;
5795 	struct bwn_softc *sc = mac->mac_sc;
5796 	unsigned int i, max_loop;
5797 	uint16_t value;
5798 	uint32_t buffer[5] = {
5799 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5800 	};
5801 
5802 	if (ofdm) {
5803 		max_loop = 0x1e;
5804 		buffer[0] = 0x000201cc;
5805 	} else {
5806 		max_loop = 0xfa;
5807 		buffer[0] = 0x000b846e;
5808 	}
5809 
5810 	BWN_ASSERT_LOCKED(mac->mac_sc);
5811 
5812 	for (i = 0; i < 5; i++)
5813 		bwn_ram_write(mac, i * 4, buffer[i]);
5814 
5815 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5816 	BWN_WRITE_2(mac, 0x07c0,
5817 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5818 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5819 	BWN_WRITE_2(mac, 0x050c, value);
5820 	if (phy->type == BWN_PHYTYPE_LP)
5821 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5822 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5823 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5824 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5825 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5826 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5827 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5828 	if (phy->type == BWN_PHYTYPE_LP)
5829 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5830 	else
5831 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5832 
5833 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5834 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5835 	for (i = 0x00; i < max_loop; i++) {
5836 		value = BWN_READ_2(mac, 0x050e);
5837 		if (value & 0x0080)
5838 			break;
5839 		DELAY(10);
5840 	}
5841 	for (i = 0x00; i < 0x0a; i++) {
5842 		value = BWN_READ_2(mac, 0x050e);
5843 		if (value & 0x0400)
5844 			break;
5845 		DELAY(10);
5846 	}
5847 	for (i = 0x00; i < 0x19; i++) {
5848 		value = BWN_READ_2(mac, 0x0690);
5849 		if (!(value & 0x0100))
5850 			break;
5851 		DELAY(10);
5852 	}
5853 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5854 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5855 }
5856 
5857 static void
5858 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5859 {
5860 	uint32_t macctl;
5861 
5862 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5863 
5864 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5865 	if (macctl & BWN_MACCTL_BIGENDIAN)
5866 		printf("TODO: need swap\n");
5867 
5868 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5869 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5870 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5871 }
5872 
5873 static void
5874 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5875 {
5876 	uint16_t value;
5877 
5878 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5879 	    ("%s:%d: fail", __func__, __LINE__));
5880 
5881 	value = (uint8_t) (ctl->q);
5882 	value |= ((uint8_t) (ctl->i)) << 8;
5883 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5884 }
5885 
5886 static uint16_t
5887 bwn_lo_calcfeed(struct bwn_mac *mac,
5888     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5889 {
5890 	struct bwn_phy *phy = &mac->mac_phy;
5891 	struct bwn_softc *sc = mac->mac_sc;
5892 	uint16_t rfover;
5893 	uint16_t feedthrough;
5894 
5895 	if (phy->gmode) {
5896 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5897 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5898 
5899 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5900 		    ("%s:%d: fail", __func__, __LINE__));
5901 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5902 		    ("%s:%d: fail", __func__, __LINE__));
5903 
5904 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5905 
5906 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5907 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5908 		    phy->rev > 6)
5909 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5910 
5911 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5912 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5913 		DELAY(10);
5914 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5915 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5916 		DELAY(10);
5917 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5918 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5919 		DELAY(10);
5920 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5921 	} else {
5922 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5923 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5924 		DELAY(10);
5925 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5926 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5927 		DELAY(10);
5928 		pga |= BWN_PHY_PGACTL_LPF;
5929 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5930 	}
5931 	DELAY(21);
5932 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5933 
5934 	return (feedthrough);
5935 }
5936 
5937 static uint16_t
5938 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5939     uint16_t *value, uint16_t *pad_mix_gain)
5940 {
5941 	struct bwn_phy *phy = &mac->mac_phy;
5942 	uint16_t reg, v, padmix;
5943 
5944 	if (phy->type == BWN_PHYTYPE_B) {
5945 		v = 0x30;
5946 		if (phy->rf_rev <= 5) {
5947 			reg = 0x43;
5948 			padmix = 0;
5949 		} else {
5950 			reg = 0x52;
5951 			padmix = 5;
5952 		}
5953 	} else {
5954 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5955 			reg = 0x43;
5956 			v = 0x10;
5957 			padmix = 2;
5958 		} else {
5959 			reg = 0x52;
5960 			v = 0x30;
5961 			padmix = 5;
5962 		}
5963 	}
5964 	if (value)
5965 		*value = v;
5966 	if (pad_mix_gain)
5967 		*pad_mix_gain = padmix;
5968 
5969 	return (reg);
5970 }
5971 
5972 static void
5973 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5974 {
5975 	struct bwn_phy *phy = &mac->mac_phy;
5976 	struct bwn_phy_g *pg = &phy->phy_g;
5977 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5978 	uint16_t reg, mask;
5979 	uint16_t trsw_rx, pga;
5980 	uint16_t rf_pctl_reg;
5981 
5982 	static const uint8_t tx_bias_values[] = {
5983 		0x09, 0x08, 0x0a, 0x01, 0x00,
5984 		0x02, 0x05, 0x04, 0x06,
5985 	};
5986 	static const uint8_t tx_magn_values[] = {
5987 		0x70, 0x40,
5988 	};
5989 
5990 	if (!BWN_HAS_LOOPBACK(phy)) {
5991 		rf_pctl_reg = 6;
5992 		trsw_rx = 2;
5993 		pga = 0;
5994 	} else {
5995 		int lb_gain;
5996 
5997 		trsw_rx = 0;
5998 		lb_gain = pg->pg_max_lb_gain / 2;
5999 		if (lb_gain > 10) {
6000 			rf_pctl_reg = 0;
6001 			pga = abs(10 - lb_gain) / 6;
6002 			pga = MIN(MAX(pga, 0), 15);
6003 		} else {
6004 			int cmp_val;
6005 			int tmp;
6006 
6007 			pga = 0;
6008 			cmp_val = 0x24;
6009 			if ((phy->rev >= 2) &&
6010 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6011 				cmp_val = 0x3c;
6012 			tmp = lb_gain;
6013 			if ((10 - lb_gain) < cmp_val)
6014 				tmp = (10 - lb_gain);
6015 			if (tmp < 0)
6016 				tmp += 6;
6017 			else
6018 				tmp += 3;
6019 			cmp_val /= 4;
6020 			tmp /= 4;
6021 			if (tmp >= cmp_val)
6022 				rf_pctl_reg = cmp_val;
6023 			else
6024 				rf_pctl_reg = tmp;
6025 		}
6026 	}
6027 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6028 	bwn_phy_g_set_bbatt(mac, 2);
6029 
6030 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6031 	mask = ~mask;
6032 	BWN_RF_MASK(mac, reg, mask);
6033 
6034 	if (BWN_HAS_TXMAG(phy)) {
6035 		int i, j;
6036 		int feedthrough;
6037 		int min_feedth = 0xffff;
6038 		uint8_t tx_magn, tx_bias;
6039 
6040 		for (i = 0; i < N(tx_magn_values); i++) {
6041 			tx_magn = tx_magn_values[i];
6042 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6043 			for (j = 0; j < N(tx_bias_values); j++) {
6044 				tx_bias = tx_bias_values[j];
6045 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6046 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6047 				    trsw_rx);
6048 				if (feedthrough < min_feedth) {
6049 					lo->tx_bias = tx_bias;
6050 					lo->tx_magn = tx_magn;
6051 					min_feedth = feedthrough;
6052 				}
6053 				if (lo->tx_bias == 0)
6054 					break;
6055 			}
6056 			BWN_RF_WRITE(mac, 0x52,
6057 					  (BWN_RF_READ(mac, 0x52)
6058 					   & 0xff00) | lo->tx_bias | lo->
6059 					  tx_magn);
6060 		}
6061 	} else {
6062 		lo->tx_magn = 0;
6063 		lo->tx_bias = 0;
6064 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6065 	}
6066 
6067 	BWN_GETTIME(lo->txctl_measured_time);
6068 }
6069 
6070 static void
6071 bwn_lo_get_powervector(struct bwn_mac *mac)
6072 {
6073 	struct bwn_phy *phy = &mac->mac_phy;
6074 	struct bwn_phy_g *pg = &phy->phy_g;
6075 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6076 	int i;
6077 	uint64_t tmp;
6078 	uint64_t power_vector = 0;
6079 
6080 	for (i = 0; i < 8; i += 2) {
6081 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6082 		power_vector |= (tmp << (i * 8));
6083 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6084 	}
6085 	if (power_vector)
6086 		lo->power_vector = power_vector;
6087 
6088 	BWN_GETTIME(lo->pwr_vec_read_time);
6089 }
6090 
6091 static void
6092 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6093     int use_trsw_rx)
6094 {
6095 	struct bwn_phy *phy = &mac->mac_phy;
6096 	struct bwn_phy_g *pg = &phy->phy_g;
6097 	uint16_t tmp;
6098 
6099 	if (max_rx_gain < 0)
6100 		max_rx_gain = 0;
6101 
6102 	if (BWN_HAS_LOOPBACK(phy)) {
6103 		int trsw_rx = 0;
6104 		int trsw_rx_gain;
6105 
6106 		if (use_trsw_rx) {
6107 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6108 			if (max_rx_gain >= trsw_rx_gain) {
6109 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6110 				trsw_rx = 0x20;
6111 			}
6112 		} else
6113 			trsw_rx_gain = max_rx_gain;
6114 		if (trsw_rx_gain < 9) {
6115 			pg->pg_lna_lod_gain = 0;
6116 		} else {
6117 			pg->pg_lna_lod_gain = 1;
6118 			trsw_rx_gain -= 8;
6119 		}
6120 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6121 		pg->pg_pga_gain = trsw_rx_gain / 3;
6122 		if (pg->pg_pga_gain >= 5) {
6123 			pg->pg_pga_gain -= 5;
6124 			pg->pg_lna_gain = 2;
6125 		} else
6126 			pg->pg_lna_gain = 0;
6127 	} else {
6128 		pg->pg_lna_gain = 0;
6129 		pg->pg_trsw_rx_gain = 0x20;
6130 		if (max_rx_gain >= 0x14) {
6131 			pg->pg_lna_lod_gain = 1;
6132 			pg->pg_pga_gain = 2;
6133 		} else if (max_rx_gain >= 0x12) {
6134 			pg->pg_lna_lod_gain = 1;
6135 			pg->pg_pga_gain = 1;
6136 		} else if (max_rx_gain >= 0xf) {
6137 			pg->pg_lna_lod_gain = 1;
6138 			pg->pg_pga_gain = 0;
6139 		} else {
6140 			pg->pg_lna_lod_gain = 0;
6141 			pg->pg_pga_gain = 0;
6142 		}
6143 	}
6144 
6145 	tmp = BWN_RF_READ(mac, 0x7a);
6146 	if (pg->pg_lna_lod_gain == 0)
6147 		tmp &= ~0x0008;
6148 	else
6149 		tmp |= 0x0008;
6150 	BWN_RF_WRITE(mac, 0x7a, tmp);
6151 }
6152 
6153 static void
6154 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6155 {
6156 	struct bwn_phy *phy = &mac->mac_phy;
6157 	struct bwn_phy_g *pg = &phy->phy_g;
6158 	struct bwn_softc *sc = mac->mac_sc;
6159 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6160 	struct timespec ts;
6161 	uint16_t tmp;
6162 
6163 	if (bwn_has_hwpctl(mac)) {
6164 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6165 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6166 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6167 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6168 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6169 
6170 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6171 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6172 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6173 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6174 	}
6175 	if (phy->type == BWN_PHYTYPE_B &&
6176 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6177 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6178 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6179 	}
6180 	if (phy->rev >= 2) {
6181 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6182 		sav->phy_analogoverval =
6183 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6184 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6185 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6186 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6187 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6188 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6189 
6190 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6191 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6192 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6193 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6194 		if (phy->type == BWN_PHYTYPE_G) {
6195 			if ((phy->rev >= 7) &&
6196 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6197 			     BWN_BFL_EXTLNA)) {
6198 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6199 			} else {
6200 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6201 			}
6202 		} else {
6203 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6204 		}
6205 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6206 	}
6207 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6208 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6209 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6210 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6211 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6212 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6213 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6214 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6215 
6216 	if (!BWN_HAS_TXMAG(phy)) {
6217 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6218 		sav->rf2 &= 0x00f0;
6219 	}
6220 	if (phy->type == BWN_PHYTYPE_B) {
6221 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6222 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6223 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6224 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6225 	} else {
6226 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6227 			    | 0x8000);
6228 	}
6229 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6230 		    & 0xf000);
6231 
6232 	tmp =
6233 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6234 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6235 
6236 	tmp = sav->phy_syncctl;
6237 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6238 	tmp = sav->rf1;
6239 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6240 
6241 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6242 	if (phy->type == BWN_PHYTYPE_G ||
6243 	    (phy->type == BWN_PHYTYPE_B &&
6244 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6245 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6246 	} else
6247 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6248 	if (phy->rev >= 2)
6249 		bwn_dummy_transmission(mac, 0, 1);
6250 	bwn_phy_g_switch_chan(mac, 6, 0);
6251 	BWN_RF_READ(mac, 0x51);
6252 	if (phy->type == BWN_PHYTYPE_G)
6253 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6254 
6255 	nanouptime(&ts);
6256 	if (time_before(lo->txctl_measured_time,
6257 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6258 		bwn_lo_measure_txctl_values(mac);
6259 
6260 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6261 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6262 	else {
6263 		if (phy->type == BWN_PHYTYPE_B)
6264 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6265 		else
6266 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6267 	}
6268 }
6269 
6270 static void
6271 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6272 {
6273 	struct bwn_phy *phy = &mac->mac_phy;
6274 	struct bwn_phy_g *pg = &phy->phy_g;
6275 	uint16_t tmp;
6276 
6277 	if (phy->rev >= 2) {
6278 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6279 		tmp = (pg->pg_pga_gain << 8);
6280 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6281 		DELAY(5);
6282 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6283 		DELAY(2);
6284 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6285 	} else {
6286 		tmp = (pg->pg_pga_gain | 0xefa0);
6287 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6288 	}
6289 	if (phy->type == BWN_PHYTYPE_G) {
6290 		if (phy->rev >= 3)
6291 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6292 		else
6293 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6294 		if (phy->rev >= 2)
6295 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6296 		else
6297 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6298 	}
6299 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6300 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6301 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6302 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6303 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6304 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6305 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6306 	if (!BWN_HAS_TXMAG(phy)) {
6307 		tmp = sav->rf2;
6308 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6309 	}
6310 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6311 	if (phy->type == BWN_PHYTYPE_B &&
6312 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6313 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6314 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6315 	}
6316 	if (phy->rev >= 2) {
6317 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6318 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6319 			      sav->phy_analogoverval);
6320 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6321 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6322 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6323 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6324 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6325 	}
6326 	if (bwn_has_hwpctl(mac)) {
6327 		tmp = (sav->phy_lomask & 0xbfff);
6328 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6329 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6330 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6331 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6332 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6333 	}
6334 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6335 }
6336 
6337 static int
6338 bwn_lo_probe_loctl(struct bwn_mac *mac,
6339     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6340 {
6341 	struct bwn_phy *phy = &mac->mac_phy;
6342 	struct bwn_phy_g *pg = &phy->phy_g;
6343 	struct bwn_loctl orig, test;
6344 	struct bwn_loctl prev = { -100, -100 };
6345 	static const struct bwn_loctl modifiers[] = {
6346 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6347 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6348 	};
6349 	int begin, end, lower = 0, i;
6350 	uint16_t feedth;
6351 
6352 	if (d->curstate == 0) {
6353 		begin = 1;
6354 		end = 8;
6355 	} else if (d->curstate % 2 == 0) {
6356 		begin = d->curstate - 1;
6357 		end = d->curstate + 1;
6358 	} else {
6359 		begin = d->curstate - 2;
6360 		end = d->curstate + 2;
6361 	}
6362 	if (begin < 1)
6363 		begin += 8;
6364 	if (end > 8)
6365 		end -= 8;
6366 
6367 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6368 	i = begin;
6369 	d->curstate = i;
6370 	while (1) {
6371 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6372 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6373 		test.i += modifiers[i - 1].i * d->multipler;
6374 		test.q += modifiers[i - 1].q * d->multipler;
6375 		if ((test.i != prev.i || test.q != prev.q) &&
6376 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6377 			bwn_lo_write(mac, &test);
6378 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6379 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6380 			if (feedth < d->feedth) {
6381 				memcpy(probe, &test,
6382 				    sizeof(struct bwn_loctl));
6383 				lower = 1;
6384 				d->feedth = feedth;
6385 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6386 					break;
6387 			}
6388 		}
6389 		memcpy(&prev, &test, sizeof(prev));
6390 		if (i == end)
6391 			break;
6392 		if (i == 8)
6393 			i = 1;
6394 		else
6395 			i++;
6396 		d->curstate = i;
6397 	}
6398 
6399 	return (lower);
6400 }
6401 
6402 static void
6403 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6404 {
6405 	struct bwn_phy *phy = &mac->mac_phy;
6406 	struct bwn_phy_g *pg = &phy->phy_g;
6407 	struct bwn_lo_g_sm d;
6408 	struct bwn_loctl probe;
6409 	int lower, repeat, cnt = 0;
6410 	uint16_t feedth;
6411 
6412 	d.nmeasure = 0;
6413 	d.multipler = 1;
6414 	if (BWN_HAS_LOOPBACK(phy))
6415 		d.multipler = 3;
6416 
6417 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6418 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6419 
6420 	do {
6421 		bwn_lo_write(mac, &d.loctl);
6422 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6423 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6424 		if (feedth < 0x258) {
6425 			if (feedth >= 0x12c)
6426 				*rxgain += 6;
6427 			else
6428 				*rxgain += 3;
6429 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6430 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6431 		}
6432 		d.feedth = feedth;
6433 		d.curstate = 0;
6434 		do {
6435 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6436 			    ("%s:%d: fail", __func__, __LINE__));
6437 			memcpy(&probe, &d.loctl,
6438 			       sizeof(struct bwn_loctl));
6439 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6440 			if (!lower)
6441 				break;
6442 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6443 				break;
6444 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6445 			d.nmeasure++;
6446 		} while (d.nmeasure < 24);
6447 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6448 
6449 		if (BWN_HAS_LOOPBACK(phy)) {
6450 			if (d.feedth > 0x1194)
6451 				*rxgain -= 6;
6452 			else if (d.feedth < 0x5dc)
6453 				*rxgain += 3;
6454 			if (cnt == 0) {
6455 				if (d.feedth <= 0x5dc) {
6456 					d.multipler = 1;
6457 					cnt++;
6458 				} else
6459 					d.multipler = 2;
6460 			} else if (cnt == 2)
6461 				d.multipler = 1;
6462 		}
6463 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6464 	} while (++cnt < repeat);
6465 }
6466 
6467 static struct bwn_lo_calib *
6468 bwn_lo_calibset(struct bwn_mac *mac,
6469     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6470 {
6471 	struct bwn_phy *phy = &mac->mac_phy;
6472 	struct bwn_phy_g *pg = &phy->phy_g;
6473 	struct bwn_loctl loctl = { 0, 0 };
6474 	struct bwn_lo_calib *cal;
6475 	struct bwn_lo_g_value sval = { 0 };
6476 	int rxgain;
6477 	uint16_t pad, reg, value;
6478 
6479 	sval.old_channel = phy->chan;
6480 	bwn_mac_suspend(mac);
6481 	bwn_lo_save(mac, &sval);
6482 
6483 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6484 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6485 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6486 
6487 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6488 	if (rfatt->padmix)
6489 		rxgain -= pad;
6490 	if (BWN_HAS_LOOPBACK(phy))
6491 		rxgain += pg->pg_max_lb_gain;
6492 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6493 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6494 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6495 
6496 	bwn_lo_restore(mac, &sval);
6497 	bwn_mac_enable(mac);
6498 
6499 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6500 	if (!cal) {
6501 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6502 		return (NULL);
6503 	}
6504 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6505 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6506 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6507 
6508 	BWN_GETTIME(cal->calib_time);
6509 
6510 	return (cal);
6511 }
6512 
6513 static struct bwn_lo_calib *
6514 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6515     const struct bwn_rfatt *rfatt)
6516 {
6517 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6518 	struct bwn_lo_calib *c;
6519 
6520 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6521 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6522 			continue;
6523 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6524 			continue;
6525 		return (c);
6526 	}
6527 
6528 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6529 	if (!c)
6530 		return (NULL);
6531 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6532 
6533 	return (c);
6534 }
6535 
6536 static void
6537 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6538 {
6539 	struct bwn_phy *phy = &mac->mac_phy;
6540 	struct bwn_phy_g *pg = &phy->phy_g;
6541 	struct bwn_softc *sc = mac->mac_sc;
6542 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6543 	const struct bwn_rfatt *rfatt;
6544 	const struct bwn_bbatt *bbatt;
6545 	uint64_t pvector;
6546 	int i;
6547 	int rf_offset, bb_offset;
6548 	uint8_t changed = 0;
6549 
6550 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6551 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6552 	    ("%s:%d: fail", __func__, __LINE__));
6553 
6554 	pvector = lo->power_vector;
6555 	if (!update && !pvector)
6556 		return;
6557 
6558 	bwn_mac_suspend(mac);
6559 
6560 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6561 		struct bwn_lo_calib *cal;
6562 		int idx;
6563 		uint16_t val;
6564 
6565 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6566 			continue;
6567 		bb_offset = i / lo->rfatt.len;
6568 		rf_offset = i % lo->rfatt.len;
6569 		bbatt = &(lo->bbatt.array[bb_offset]);
6570 		rfatt = &(lo->rfatt.array[rf_offset]);
6571 
6572 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6573 		if (!cal) {
6574 			device_printf(sc->sc_dev, "LO: Could not "
6575 			    "calibrate DC table entry\n");
6576 			continue;
6577 		}
6578 		val = (uint8_t)(cal->ctl.q);
6579 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6580 		free(cal, M_DEVBUF);
6581 
6582 		idx = i / 2;
6583 		if (i % 2)
6584 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6585 			    | ((val & 0x00ff) << 8);
6586 		else
6587 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6588 			    | (val & 0x00ff);
6589 		changed = 1;
6590 	}
6591 	if (changed) {
6592 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6593 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6594 	}
6595 	bwn_mac_enable(mac);
6596 }
6597 
6598 static void
6599 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6600 {
6601 
6602 	if (!rf->padmix)
6603 		return;
6604 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6605 		rf->att = 4;
6606 }
6607 
6608 static void
6609 bwn_lo_g_adjust(struct bwn_mac *mac)
6610 {
6611 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6612 	struct bwn_lo_calib *cal;
6613 	struct bwn_rfatt rf;
6614 
6615 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6616 	bwn_lo_fixup_rfatt(&rf);
6617 
6618 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6619 	if (!cal)
6620 		return;
6621 	bwn_lo_write(mac, &cal->ctl);
6622 }
6623 
6624 static void
6625 bwn_lo_g_init(struct bwn_mac *mac)
6626 {
6627 
6628 	if (!bwn_has_hwpctl(mac))
6629 		return;
6630 
6631 	bwn_lo_get_powervector(mac);
6632 	bwn_phy_g_dc_lookup_init(mac, 1);
6633 }
6634 
6635 static void
6636 bwn_mac_suspend(struct bwn_mac *mac)
6637 {
6638 	struct bwn_softc *sc = mac->mac_sc;
6639 	int i;
6640 	uint32_t tmp;
6641 
6642 	KASSERT(mac->mac_suspended >= 0,
6643 	    ("%s:%d: fail", __func__, __LINE__));
6644 
6645 	if (mac->mac_suspended == 0) {
6646 		bwn_psctl(mac, BWN_PS_AWAKE);
6647 		BWN_WRITE_4(mac, BWN_MACCTL,
6648 			    BWN_READ_4(mac, BWN_MACCTL)
6649 			    & ~BWN_MACCTL_ON);
6650 		BWN_READ_4(mac, BWN_MACCTL);
6651 		for (i = 35; i; i--) {
6652 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6653 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6654 				goto out;
6655 			DELAY(10);
6656 		}
6657 		for (i = 40; i; i--) {
6658 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6659 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6660 				goto out;
6661 			DELAY(1000);
6662 		}
6663 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6664 	}
6665 out:
6666 	mac->mac_suspended++;
6667 }
6668 
6669 static void
6670 bwn_mac_enable(struct bwn_mac *mac)
6671 {
6672 	struct bwn_softc *sc = mac->mac_sc;
6673 	uint16_t state;
6674 
6675 	state = bwn_shm_read_2(mac, BWN_SHARED,
6676 	    BWN_SHARED_UCODESTAT);
6677 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6678 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6679 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6680 
6681 	mac->mac_suspended--;
6682 	KASSERT(mac->mac_suspended >= 0,
6683 	    ("%s:%d: fail", __func__, __LINE__));
6684 	if (mac->mac_suspended == 0) {
6685 		BWN_WRITE_4(mac, BWN_MACCTL,
6686 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6687 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6688 		BWN_READ_4(mac, BWN_MACCTL);
6689 		BWN_READ_4(mac, BWN_INTR_REASON);
6690 		bwn_psctl(mac, 0);
6691 	}
6692 }
6693 
6694 static void
6695 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6696 {
6697 	struct bwn_softc *sc = mac->mac_sc;
6698 	int i;
6699 	uint16_t ucstat;
6700 
6701 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6702 	    ("%s:%d: fail", __func__, __LINE__));
6703 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6704 	    ("%s:%d: fail", __func__, __LINE__));
6705 
6706 	/* XXX forcibly awake and hwps-off */
6707 
6708 	BWN_WRITE_4(mac, BWN_MACCTL,
6709 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6710 	    ~BWN_MACCTL_HWPS);
6711 	BWN_READ_4(mac, BWN_MACCTL);
6712 	if (siba_get_revid(sc->sc_dev) >= 5) {
6713 		for (i = 0; i < 100; i++) {
6714 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6715 			    BWN_SHARED_UCODESTAT);
6716 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6717 				break;
6718 			DELAY(10);
6719 		}
6720 	}
6721 }
6722 
6723 static int16_t
6724 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6725 {
6726 
6727 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6728 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6729 }
6730 
6731 static void
6732 bwn_nrssi_threshold(struct bwn_mac *mac)
6733 {
6734 	struct bwn_phy *phy = &mac->mac_phy;
6735 	struct bwn_phy_g *pg = &phy->phy_g;
6736 	struct bwn_softc *sc = mac->mac_sc;
6737 	int32_t a, b;
6738 	int16_t tmp16;
6739 	uint16_t tmpu16;
6740 
6741 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6742 
6743 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6744 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6745 			a = 0x13;
6746 			b = 0x12;
6747 		} else {
6748 			a = 0xe;
6749 			b = 0x11;
6750 		}
6751 
6752 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6753 		a += (pg->pg_nrssi[0] << 6);
6754 		a += (a < 32) ? 31 : 32;
6755 		a = a >> 6;
6756 		a = MIN(MAX(a, -31), 31);
6757 
6758 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6759 		b += (pg->pg_nrssi[0] << 6);
6760 		if (b < 32)
6761 			b += 31;
6762 		else
6763 			b += 32;
6764 		b = b >> 6;
6765 		b = MIN(MAX(b, -31), 31);
6766 
6767 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6768 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6769 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6770 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6771 		return;
6772 	}
6773 
6774 	tmp16 = bwn_nrssi_read(mac, 0x20);
6775 	if (tmp16 >= 0x20)
6776 		tmp16 -= 0x40;
6777 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6778 }
6779 
6780 static void
6781 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6782 {
6783 #define	SAVE_RF_MAX		3
6784 #define	SAVE_PHY_COMM_MAX	4
6785 #define	SAVE_PHY3_MAX		8
6786 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6787 		{ 0x7a, 0x52, 0x43 };
6788 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6789 		{ 0x15, 0x5a, 0x59, 0x58 };
6790 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6791 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6792 		0x0801, 0x0060, 0x0014, 0x0478
6793 	};
6794 	struct bwn_phy *phy = &mac->mac_phy;
6795 	struct bwn_phy_g *pg = &phy->phy_g;
6796 	int32_t i, tmp32, phy3_idx = 0;
6797 	uint16_t delta, tmp;
6798 	uint16_t save_rf[SAVE_RF_MAX];
6799 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6800 	uint16_t save_phy3[SAVE_PHY3_MAX];
6801 	uint16_t ant_div, phy0, chan_ex;
6802 	int16_t nrssi0, nrssi1;
6803 
6804 	KASSERT(phy->type == BWN_PHYTYPE_G,
6805 	    ("%s:%d: fail", __func__, __LINE__));
6806 
6807 	if (phy->rf_rev >= 9)
6808 		return;
6809 	if (phy->rf_rev == 8)
6810 		bwn_nrssi_offset(mac);
6811 
6812 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6813 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6814 
6815 	/*
6816 	 * Save RF/PHY registers for later restoration
6817 	 */
6818 	ant_div = BWN_READ_2(mac, 0x03e2);
6819 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6820 	for (i = 0; i < SAVE_RF_MAX; ++i)
6821 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6822 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6823 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6824 
6825 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6826 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6827 	if (phy->rev >= 3) {
6828 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6829 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6830 		BWN_PHY_WRITE(mac, 0x002e, 0);
6831 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6832 		switch (phy->rev) {
6833 		case 4:
6834 		case 6:
6835 		case 7:
6836 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6837 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6838 			break;
6839 		case 3:
6840 		case 5:
6841 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6842 			break;
6843 		}
6844 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6845 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6846 	}
6847 	/*
6848 	 * Calculate nrssi0
6849 	 */
6850 	BWN_RF_SET(mac, 0x007a, 0x0070);
6851 	bwn_set_all_gains(mac, 0, 8, 0);
6852 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6853 	if (phy->rev >= 2) {
6854 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6855 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6856 	}
6857 	BWN_RF_SET(mac, 0x007a, 0x0080);
6858 	DELAY(20);
6859 
6860 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6861 	if (nrssi0 >= 0x0020)
6862 		nrssi0 -= 0x0040;
6863 
6864 	/*
6865 	 * Calculate nrssi1
6866 	 */
6867 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6868 	if (phy->rev >= 2)
6869 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6870 
6871 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6872 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6873 	BWN_RF_SET(mac, 0x007a, 0x000f);
6874 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6875 	if (phy->rev >= 2) {
6876 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6877 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6878 	}
6879 
6880 	bwn_set_all_gains(mac, 3, 0, 1);
6881 	if (phy->rf_rev == 8) {
6882 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6883 	} else {
6884 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6885 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6886 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6887 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6888 	}
6889 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6890 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6891 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6892 	DELAY(20);
6893 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6894 
6895 	/*
6896 	 * Install calculated narrow RSSI values
6897 	 */
6898 	if (nrssi1 >= 0x0020)
6899 		nrssi1 -= 0x0040;
6900 	if (nrssi0 == nrssi1)
6901 		pg->pg_nrssi_slope = 0x00010000;
6902 	else
6903 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6904 	if (nrssi0 >= -4) {
6905 		pg->pg_nrssi[0] = nrssi1;
6906 		pg->pg_nrssi[1] = nrssi0;
6907 	}
6908 
6909 	/*
6910 	 * Restore saved RF/PHY registers
6911 	 */
6912 	if (phy->rev >= 3) {
6913 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6914 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6915 			    save_phy3[phy3_idx]);
6916 		}
6917 	}
6918 	if (phy->rev >= 2) {
6919 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6920 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6921 	}
6922 
6923 	for (i = 0; i < SAVE_RF_MAX; ++i)
6924 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6925 
6926 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6927 	BWN_WRITE_2(mac, 0x03e6, phy0);
6928 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6929 
6930 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6931 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6932 
6933 	bwn_spu_workaround(mac, phy->chan);
6934 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6935 	bwn_set_original_gains(mac);
6936 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6937 	if (phy->rev >= 3) {
6938 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6939 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6940 			    save_phy3[phy3_idx]);
6941 		}
6942 	}
6943 
6944 	delta = 0x1f - pg->pg_nrssi[0];
6945 	for (i = 0; i < 64; i++) {
6946 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6947 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6948 		pg->pg_nrssi_lt[i] = tmp32;
6949 	}
6950 
6951 	bwn_nrssi_threshold(mac);
6952 #undef SAVE_RF_MAX
6953 #undef SAVE_PHY_COMM_MAX
6954 #undef SAVE_PHY3_MAX
6955 }
6956 
6957 static void
6958 bwn_nrssi_offset(struct bwn_mac *mac)
6959 {
6960 #define	SAVE_RF_MAX		2
6961 #define	SAVE_PHY_COMM_MAX	10
6962 #define	SAVE_PHY6_MAX		8
6963 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6964 		{ 0x7a, 0x43 };
6965 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6966 		0x0001, 0x0811, 0x0812, 0x0814,
6967 		0x0815, 0x005a, 0x0059, 0x0058,
6968 		0x000a, 0x0003
6969 	};
6970 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6971 		0x002e, 0x002f, 0x080f, 0x0810,
6972 		0x0801, 0x0060, 0x0014, 0x0478
6973 	};
6974 	struct bwn_phy *phy = &mac->mac_phy;
6975 	int i, phy6_idx = 0;
6976 	uint16_t save_rf[SAVE_RF_MAX];
6977 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6978 	uint16_t save_phy6[SAVE_PHY6_MAX];
6979 	int16_t nrssi;
6980 	uint16_t saved = 0xffff;
6981 
6982 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6983 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6984 	for (i = 0; i < SAVE_RF_MAX; ++i)
6985 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6986 
6987 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6988 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6989 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6990 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6991 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6992 	if (phy->rev >= 6) {
6993 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6994 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6995 
6996 		BWN_PHY_WRITE(mac, 0x002e, 0);
6997 		BWN_PHY_WRITE(mac, 0x002f, 0);
6998 		BWN_PHY_WRITE(mac, 0x080f, 0);
6999 		BWN_PHY_WRITE(mac, 0x0810, 0);
7000 		BWN_PHY_SET(mac, 0x0478, 0x0100);
7001 		BWN_PHY_SET(mac, 0x0801, 0x0040);
7002 		BWN_PHY_SET(mac, 0x0060, 0x0040);
7003 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7004 	}
7005 	BWN_RF_SET(mac, 0x007a, 0x0070);
7006 	BWN_RF_SET(mac, 0x007a, 0x0080);
7007 	DELAY(30);
7008 
7009 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7010 	if (nrssi >= 0x20)
7011 		nrssi -= 0x40;
7012 	if (nrssi == 31) {
7013 		for (i = 7; i >= 4; i--) {
7014 			BWN_RF_WRITE(mac, 0x007b, i);
7015 			DELAY(20);
7016 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7017 			    0x003f);
7018 			if (nrssi >= 0x20)
7019 				nrssi -= 0x40;
7020 			if (nrssi < 31 && saved == 0xffff)
7021 				saved = i;
7022 		}
7023 		if (saved == 0xffff)
7024 			saved = 4;
7025 	} else {
7026 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7027 		if (phy->rev != 1) {
7028 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7029 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7030 		}
7031 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7032 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7033 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7034 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7035 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7036 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7037 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7038 		if (phy->rev == 0)
7039 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7040 		else
7041 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7042 		if (phy->rev != 1) {
7043 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7044 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7045 		}
7046 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7047 		BWN_RF_SET(mac, 0x007a, 0x000f);
7048 		bwn_set_all_gains(mac, 3, 0, 1);
7049 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7050 		DELAY(30);
7051 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7052 		if (nrssi >= 0x20)
7053 			nrssi -= 0x40;
7054 		if (nrssi == -32) {
7055 			for (i = 0; i < 4; i++) {
7056 				BWN_RF_WRITE(mac, 0x007b, i);
7057 				DELAY(20);
7058 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7059 				    0x047f) >> 8) & 0x003f);
7060 				if (nrssi >= 0x20)
7061 					nrssi -= 0x40;
7062 				if (nrssi > -31 && saved == 0xffff)
7063 					saved = i;
7064 			}
7065 			if (saved == 0xffff)
7066 				saved = 3;
7067 		} else
7068 			saved = 0;
7069 	}
7070 	BWN_RF_WRITE(mac, 0x007b, saved);
7071 
7072 	/*
7073 	 * Restore saved RF/PHY registers
7074 	 */
7075 	if (phy->rev >= 6) {
7076 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7077 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7078 			    save_phy6[phy6_idx]);
7079 		}
7080 	}
7081 	if (phy->rev != 1) {
7082 		for (i = 3; i < 5; i++)
7083 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7084 			    save_phy_comm[i]);
7085 	}
7086 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7087 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7088 
7089 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7090 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7091 
7092 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7093 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7094 	bwn_set_original_gains(mac);
7095 	if (phy->rev >= 6) {
7096 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7097 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7098 			    save_phy6[phy6_idx]);
7099 		}
7100 	}
7101 
7102 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7103 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7104 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7105 }
7106 
7107 static void
7108 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7109     int16_t third)
7110 {
7111 	struct bwn_phy *phy = &mac->mac_phy;
7112 	uint16_t i;
7113 	uint16_t start = 0x08, end = 0x18;
7114 	uint16_t tmp;
7115 	uint16_t table;
7116 
7117 	if (phy->rev <= 1) {
7118 		start = 0x10;
7119 		end = 0x20;
7120 	}
7121 
7122 	table = BWN_OFDMTAB_GAINX;
7123 	if (phy->rev <= 1)
7124 		table = BWN_OFDMTAB_GAINX_R1;
7125 	for (i = 0; i < 4; i++)
7126 		bwn_ofdmtab_write_2(mac, table, i, first);
7127 
7128 	for (i = start; i < end; i++)
7129 		bwn_ofdmtab_write_2(mac, table, i, second);
7130 
7131 	if (third != -1) {
7132 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7133 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7134 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7135 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7136 	}
7137 	bwn_dummy_transmission(mac, 0, 1);
7138 }
7139 
7140 static void
7141 bwn_set_original_gains(struct bwn_mac *mac)
7142 {
7143 	struct bwn_phy *phy = &mac->mac_phy;
7144 	uint16_t i, tmp;
7145 	uint16_t table;
7146 	uint16_t start = 0x0008, end = 0x0018;
7147 
7148 	if (phy->rev <= 1) {
7149 		start = 0x0010;
7150 		end = 0x0020;
7151 	}
7152 
7153 	table = BWN_OFDMTAB_GAINX;
7154 	if (phy->rev <= 1)
7155 		table = BWN_OFDMTAB_GAINX_R1;
7156 	for (i = 0; i < 4; i++) {
7157 		tmp = (i & 0xfffc);
7158 		tmp |= (i & 0x0001) << 1;
7159 		tmp |= (i & 0x0002) >> 1;
7160 
7161 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7162 	}
7163 
7164 	for (i = start; i < end; i++)
7165 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7166 
7167 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7168 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7169 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7170 	bwn_dummy_transmission(mac, 0, 1);
7171 }
7172 
7173 static void
7174 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7175 {
7176 	struct bwn_phy *phy = &mac->mac_phy;
7177 	struct bwn_phy_g *pg = &phy->phy_g;
7178 	struct bwn_rfatt old_rfatt, rfatt;
7179 	struct bwn_bbatt old_bbatt, bbatt;
7180 	struct bwn_softc *sc = mac->mac_sc;
7181 	uint8_t old_txctl = 0;
7182 
7183 	KASSERT(phy->type == BWN_PHYTYPE_G,
7184 	    ("%s:%d: fail", __func__, __LINE__));
7185 
7186 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7187 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7188 		return;
7189 
7190 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7191 
7192 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7193 
7194 	if (!phy->gmode)
7195 		return;
7196 	bwn_hwpctl_early_init(mac);
7197 	if (pg->pg_curtssi == 0) {
7198 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7199 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7200 		} else {
7201 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7202 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7203 			old_txctl = pg->pg_txctl;
7204 
7205 			bbatt.att = 11;
7206 			if (phy->rf_rev == 8) {
7207 				rfatt.att = 15;
7208 				rfatt.padmix = 1;
7209 			} else {
7210 				rfatt.att = 9;
7211 				rfatt.padmix = 0;
7212 			}
7213 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7214 		}
7215 		bwn_dummy_transmission(mac, 0, 1);
7216 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7217 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7218 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7219 		else
7220 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7221 			    &old_rfatt, old_txctl);
7222 	}
7223 	bwn_hwpctl_init_gphy(mac);
7224 
7225 	/* clear TSSI */
7226 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7227 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7228 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7229 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7230 }
7231 
7232 static void
7233 bwn_hwpctl_early_init(struct bwn_mac *mac)
7234 {
7235 	struct bwn_phy *phy = &mac->mac_phy;
7236 
7237 	if (!bwn_has_hwpctl(mac)) {
7238 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7239 		return;
7240 	}
7241 
7242 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7243 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7244 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7245 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7246 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7247 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7248 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7249 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7250 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7251 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7252 	} else {
7253 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7254 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7255 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7256 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7257 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7258 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7259 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7260 	}
7261 }
7262 
7263 static void
7264 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7265 {
7266 	struct bwn_phy *phy = &mac->mac_phy;
7267 	struct bwn_phy_g *pg = &phy->phy_g;
7268 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7269 	int i;
7270 	uint16_t nr_written = 0, tmp, value;
7271 	uint8_t rf, bb;
7272 
7273 	if (!bwn_has_hwpctl(mac)) {
7274 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7275 		return;
7276 	}
7277 
7278 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7279 	    (pg->pg_idletssi - pg->pg_curtssi));
7280 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7281 	    (pg->pg_idletssi - pg->pg_curtssi));
7282 
7283 	for (i = 0; i < 32; i++)
7284 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7285 	for (i = 32; i < 64; i++)
7286 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7287 	for (i = 0; i < 64; i += 2) {
7288 		value = (uint16_t) pg->pg_tssi2dbm[i];
7289 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7290 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7291 	}
7292 
7293 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7294 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7295 			if (nr_written >= 0x40)
7296 				return;
7297 			tmp = lo->bbatt.array[bb].att;
7298 			tmp <<= 8;
7299 			if (phy->rf_rev == 8)
7300 				tmp |= 0x50;
7301 			else
7302 				tmp |= 0x40;
7303 			tmp |= lo->rfatt.array[rf].att;
7304 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7305 			nr_written++;
7306 		}
7307 	}
7308 
7309 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7310 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7311 
7312 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7313 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7314 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7315 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7316 
7317 	bwn_phy_g_dc_lookup_init(mac, 1);
7318 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7319 }
7320 
7321 static void
7322 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7323 {
7324 	struct bwn_softc *sc = mac->mac_sc;
7325 
7326 	if (spu != 0)
7327 		bwn_spu_workaround(mac, channel);
7328 
7329 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7330 
7331 	if (channel == 14) {
7332 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7333 			bwn_hf_write(mac,
7334 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7335 		else
7336 			bwn_hf_write(mac,
7337 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7338 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7339 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7340 		return;
7341 	}
7342 
7343 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7344 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7345 }
7346 
7347 static uint16_t
7348 bwn_phy_g_chan2freq(uint8_t channel)
7349 {
7350 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7351 
7352 	KASSERT(channel >= 1 && channel <= 14,
7353 	    ("%s:%d: fail", __func__, __LINE__));
7354 
7355 	return (bwn_phy_g_rf_channels[channel - 1]);
7356 }
7357 
7358 static void
7359 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7360     const struct bwn_rfatt *rfatt, uint8_t txctl)
7361 {
7362 	struct bwn_phy *phy = &mac->mac_phy;
7363 	struct bwn_phy_g *pg = &phy->phy_g;
7364 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7365 	uint16_t bb, rf;
7366 	uint16_t tx_bias, tx_magn;
7367 
7368 	bb = bbatt->att;
7369 	rf = rfatt->att;
7370 	tx_bias = lo->tx_bias;
7371 	tx_magn = lo->tx_magn;
7372 	if (tx_bias == 0xff)
7373 		tx_bias = 0;
7374 
7375 	pg->pg_txctl = txctl;
7376 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7377 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7378 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7379 	bwn_phy_g_set_bbatt(mac, bb);
7380 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7381 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7382 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7383 	else {
7384 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7385 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7386 	}
7387 	if (BWN_HAS_TXMAG(phy))
7388 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7389 	else
7390 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7391 	bwn_lo_g_adjust(mac);
7392 }
7393 
7394 static void
7395 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7396     uint16_t bbatt)
7397 {
7398 	struct bwn_phy *phy = &mac->mac_phy;
7399 
7400 	if (phy->analog == 0) {
7401 		BWN_WRITE_2(mac, BWN_PHY0,
7402 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7403 		return;
7404 	}
7405 	if (phy->analog > 1) {
7406 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7407 		return;
7408 	}
7409 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7410 }
7411 
7412 static uint16_t
7413 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7414 {
7415 	struct bwn_phy *phy = &mac->mac_phy;
7416 	struct bwn_phy_g *pg = &phy->phy_g;
7417 	struct bwn_softc *sc = mac->mac_sc;
7418 	int max_lb_gain;
7419 	uint16_t extlna;
7420 	uint16_t i;
7421 
7422 	if (phy->gmode == 0)
7423 		return (0);
7424 
7425 	if (BWN_HAS_LOOPBACK(phy)) {
7426 		max_lb_gain = pg->pg_max_lb_gain;
7427 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7428 		if (max_lb_gain >= 0x46) {
7429 			extlna = 0x3000;
7430 			max_lb_gain -= 0x46;
7431 		} else if (max_lb_gain >= 0x3a) {
7432 			extlna = 0x1000;
7433 			max_lb_gain -= 0x3a;
7434 		} else if (max_lb_gain >= 0x2e) {
7435 			extlna = 0x2000;
7436 			max_lb_gain -= 0x2e;
7437 		} else {
7438 			extlna = 0;
7439 			max_lb_gain -= 0x10;
7440 		}
7441 
7442 		for (i = 0; i < 16; i++) {
7443 			max_lb_gain -= (i * 6);
7444 			if (max_lb_gain < 6)
7445 				break;
7446 		}
7447 
7448 		if ((phy->rev < 7) ||
7449 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7450 			if (reg == BWN_PHY_RFOVER) {
7451 				return (0x1b3);
7452 			} else if (reg == BWN_PHY_RFOVERVAL) {
7453 				extlna |= (i << 8);
7454 				switch (lpd) {
7455 				case BWN_LPD(0, 1, 1):
7456 					return (0x0f92);
7457 				case BWN_LPD(0, 0, 1):
7458 				case BWN_LPD(1, 0, 1):
7459 					return (0x0092 | extlna);
7460 				case BWN_LPD(1, 0, 0):
7461 					return (0x0093 | extlna);
7462 				}
7463 				KASSERT(0 == 1,
7464 				    ("%s:%d: fail", __func__, __LINE__));
7465 			}
7466 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7467 		} else {
7468 			if (reg == BWN_PHY_RFOVER)
7469 				return (0x9b3);
7470 			if (reg == BWN_PHY_RFOVERVAL) {
7471 				if (extlna)
7472 					extlna |= 0x8000;
7473 				extlna |= (i << 8);
7474 				switch (lpd) {
7475 				case BWN_LPD(0, 1, 1):
7476 					return (0x8f92);
7477 				case BWN_LPD(0, 0, 1):
7478 					return (0x8092 | extlna);
7479 				case BWN_LPD(1, 0, 1):
7480 					return (0x2092 | extlna);
7481 				case BWN_LPD(1, 0, 0):
7482 					return (0x2093 | extlna);
7483 				}
7484 				KASSERT(0 == 1,
7485 				    ("%s:%d: fail", __func__, __LINE__));
7486 			}
7487 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7488 		}
7489 		return (0);
7490 	}
7491 
7492 	if ((phy->rev < 7) ||
7493 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7494 		if (reg == BWN_PHY_RFOVER) {
7495 			return (0x1b3);
7496 		} else if (reg == BWN_PHY_RFOVERVAL) {
7497 			switch (lpd) {
7498 			case BWN_LPD(0, 1, 1):
7499 				return (0x0fb2);
7500 			case BWN_LPD(0, 0, 1):
7501 				return (0x00b2);
7502 			case BWN_LPD(1, 0, 1):
7503 				return (0x30b2);
7504 			case BWN_LPD(1, 0, 0):
7505 				return (0x30b3);
7506 			}
7507 			KASSERT(0 == 1,
7508 			    ("%s:%d: fail", __func__, __LINE__));
7509 		}
7510 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7511 	} else {
7512 		if (reg == BWN_PHY_RFOVER) {
7513 			return (0x9b3);
7514 		} else if (reg == BWN_PHY_RFOVERVAL) {
7515 			switch (lpd) {
7516 			case BWN_LPD(0, 1, 1):
7517 				return (0x8fb2);
7518 			case BWN_LPD(0, 0, 1):
7519 				return (0x80b2);
7520 			case BWN_LPD(1, 0, 1):
7521 				return (0x20b2);
7522 			case BWN_LPD(1, 0, 0):
7523 				return (0x20b3);
7524 			}
7525 			KASSERT(0 == 1,
7526 			    ("%s:%d: fail", __func__, __LINE__));
7527 		}
7528 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7529 	}
7530 	return (0);
7531 }
7532 
7533 static void
7534 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7535 {
7536 
7537 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7538 		return;
7539 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7540 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7541 	DELAY(1000);
7542 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7543 }
7544 
7545 static int
7546 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7547 {
7548 	struct bwn_softc *sc = mac->mac_sc;
7549 	struct bwn_fw *fw = &mac->mac_fw;
7550 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7551 	const char *filename;
7552 	uint32_t high;
7553 	int error;
7554 
7555 	/* microcode */
7556 	if (rev >= 5 && rev <= 10)
7557 		filename = "ucode5";
7558 	else if (rev >= 11 && rev <= 12)
7559 		filename = "ucode11";
7560 	else if (rev == 13)
7561 		filename = "ucode13";
7562 	else if (rev == 14)
7563 		filename = "ucode14";
7564 	else if (rev >= 15)
7565 		filename = "ucode15";
7566 	else {
7567 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7568 		bwn_release_firmware(mac);
7569 		return (EOPNOTSUPP);
7570 	}
7571 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7572 	if (error) {
7573 		bwn_release_firmware(mac);
7574 		return (error);
7575 	}
7576 
7577 	/* PCM */
7578 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7579 	if (rev >= 5 && rev <= 10) {
7580 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7581 		if (error == ENOENT)
7582 			fw->no_pcmfile = 1;
7583 		else if (error) {
7584 			bwn_release_firmware(mac);
7585 			return (error);
7586 		}
7587 	} else if (rev < 11) {
7588 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7589 		return (EOPNOTSUPP);
7590 	}
7591 
7592 	/* initvals */
7593 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7594 	switch (mac->mac_phy.type) {
7595 	case BWN_PHYTYPE_A:
7596 		if (rev < 5 || rev > 10)
7597 			goto fail1;
7598 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7599 			filename = "a0g1initvals5";
7600 		else
7601 			filename = "a0g0initvals5";
7602 		break;
7603 	case BWN_PHYTYPE_G:
7604 		if (rev >= 5 && rev <= 10)
7605 			filename = "b0g0initvals5";
7606 		else if (rev >= 13)
7607 			filename = "b0g0initvals13";
7608 		else
7609 			goto fail1;
7610 		break;
7611 	case BWN_PHYTYPE_LP:
7612 		if (rev == 13)
7613 			filename = "lp0initvals13";
7614 		else if (rev == 14)
7615 			filename = "lp0initvals14";
7616 		else if (rev >= 15)
7617 			filename = "lp0initvals15";
7618 		else
7619 			goto fail1;
7620 		break;
7621 	case BWN_PHYTYPE_N:
7622 		if (rev >= 11 && rev <= 12)
7623 			filename = "n0initvals11";
7624 		else
7625 			goto fail1;
7626 		break;
7627 	default:
7628 		goto fail1;
7629 	}
7630 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7631 	if (error) {
7632 		bwn_release_firmware(mac);
7633 		return (error);
7634 	}
7635 
7636 	/* bandswitch initvals */
7637 	switch (mac->mac_phy.type) {
7638 	case BWN_PHYTYPE_A:
7639 		if (rev >= 5 && rev <= 10) {
7640 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7641 				filename = "a0g1bsinitvals5";
7642 			else
7643 				filename = "a0g0bsinitvals5";
7644 		} else if (rev >= 11)
7645 			filename = NULL;
7646 		else
7647 			goto fail1;
7648 		break;
7649 	case BWN_PHYTYPE_G:
7650 		if (rev >= 5 && rev <= 10)
7651 			filename = "b0g0bsinitvals5";
7652 		else if (rev >= 11)
7653 			filename = NULL;
7654 		else
7655 			goto fail1;
7656 		break;
7657 	case BWN_PHYTYPE_LP:
7658 		if (rev == 13)
7659 			filename = "lp0bsinitvals13";
7660 		else if (rev == 14)
7661 			filename = "lp0bsinitvals14";
7662 		else if (rev >= 15)
7663 			filename = "lp0bsinitvals15";
7664 		else
7665 			goto fail1;
7666 		break;
7667 	case BWN_PHYTYPE_N:
7668 		if (rev >= 11 && rev <= 12)
7669 			filename = "n0bsinitvals11";
7670 		else
7671 			goto fail1;
7672 		break;
7673 	default:
7674 		goto fail1;
7675 	}
7676 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7677 	if (error) {
7678 		bwn_release_firmware(mac);
7679 		return (error);
7680 	}
7681 	return (0);
7682 fail1:
7683 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7684 	bwn_release_firmware(mac);
7685 	return (EOPNOTSUPP);
7686 }
7687 
7688 static int
7689 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7690     const char *name, struct bwn_fwfile *bfw)
7691 {
7692 	const struct bwn_fwhdr *hdr;
7693 	struct bwn_softc *sc = mac->mac_sc;
7694 	const struct firmware *fw;
7695 	char namebuf[64];
7696 
7697 	if (name == NULL) {
7698 		bwn_do_release_fw(bfw);
7699 		return (0);
7700 	}
7701 	if (bfw->filename != NULL) {
7702 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7703 			return (0);
7704 		bwn_do_release_fw(bfw);
7705 	}
7706 
7707 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7708 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7709 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7710 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7711 	fw = firmware_get(namebuf);
7712 	if (fw == NULL) {
7713 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7714 		    namebuf);
7715 		return (ENOENT);
7716 	}
7717 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7718 		goto fail;
7719 	hdr = (const struct bwn_fwhdr *)(fw->data);
7720 	switch (hdr->type) {
7721 	case BWN_FWTYPE_UCODE:
7722 	case BWN_FWTYPE_PCM:
7723 		if (be32toh(hdr->size) !=
7724 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7725 			goto fail;
7726 		/* FALLTHROUGH */
7727 	case BWN_FWTYPE_IV:
7728 		if (hdr->ver != 1)
7729 			goto fail;
7730 		break;
7731 	default:
7732 		goto fail;
7733 	}
7734 	bfw->filename = name;
7735 	bfw->fw = fw;
7736 	bfw->type = type;
7737 	return (0);
7738 fail:
7739 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7740 	if (fw != NULL)
7741 		firmware_put(fw, FIRMWARE_UNLOAD);
7742 	return (EPROTO);
7743 }
7744 
7745 static void
7746 bwn_release_firmware(struct bwn_mac *mac)
7747 {
7748 
7749 	bwn_do_release_fw(&mac->mac_fw.ucode);
7750 	bwn_do_release_fw(&mac->mac_fw.pcm);
7751 	bwn_do_release_fw(&mac->mac_fw.initvals);
7752 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7753 }
7754 
7755 static void
7756 bwn_do_release_fw(struct bwn_fwfile *bfw)
7757 {
7758 
7759 	if (bfw->fw != NULL)
7760 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7761 	bfw->fw = NULL;
7762 	bfw->filename = NULL;
7763 }
7764 
7765 static int
7766 bwn_fw_loaducode(struct bwn_mac *mac)
7767 {
7768 #define	GETFWOFFSET(fwp, offset)	\
7769 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7770 #define	GETFWSIZE(fwp, offset)	\
7771 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7772 	struct bwn_softc *sc = mac->mac_sc;
7773 	const uint32_t *data;
7774 	unsigned int i;
7775 	uint32_t ctl;
7776 	uint16_t date, fwcaps, time;
7777 	int error = 0;
7778 
7779 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7780 	ctl |= BWN_MACCTL_MCODE_JMP0;
7781 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7782 	    __LINE__));
7783 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7784 	for (i = 0; i < 64; i++)
7785 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7786 	for (i = 0; i < 4096; i += 2)
7787 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7788 
7789 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7790 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7791 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7792 	     i++) {
7793 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7794 		DELAY(10);
7795 	}
7796 
7797 	if (mac->mac_fw.pcm.fw) {
7798 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7799 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7800 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7801 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7802 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7803 		    sizeof(struct bwn_fwhdr)); i++) {
7804 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7805 			DELAY(10);
7806 		}
7807 	}
7808 
7809 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7810 	BWN_WRITE_4(mac, BWN_MACCTL,
7811 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7812 	    BWN_MACCTL_MCODE_RUN);
7813 
7814 	for (i = 0; i < 21; i++) {
7815 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7816 			break;
7817 		if (i >= 20) {
7818 			device_printf(sc->sc_dev, "ucode timeout\n");
7819 			error = ENXIO;
7820 			goto error;
7821 		}
7822 		DELAY(50000);
7823 	}
7824 	BWN_READ_4(mac, BWN_INTR_REASON);
7825 
7826 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7827 	if (mac->mac_fw.rev <= 0x128) {
7828 		device_printf(sc->sc_dev, "the firmware is too old\n");
7829 		error = EOPNOTSUPP;
7830 		goto error;
7831 	}
7832 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7833 	    BWN_SHARED_UCODE_PATCH);
7834 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7835 	mac->mac_fw.opensource = (date == 0xffff);
7836 	if (bwn_wme != 0)
7837 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7838 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7839 
7840 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7841 	if (mac->mac_fw.opensource == 0) {
7842 		device_printf(sc->sc_dev,
7843 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7844 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7845 		if (mac->mac_fw.no_pcmfile)
7846 			device_printf(sc->sc_dev,
7847 			    "no HW crypto acceleration due to pcm5\n");
7848 	} else {
7849 		mac->mac_fw.patch = time;
7850 		fwcaps = bwn_fwcaps_read(mac);
7851 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7852 			device_printf(sc->sc_dev,
7853 			    "disabling HW crypto acceleration\n");
7854 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7855 		}
7856 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7857 			device_printf(sc->sc_dev, "disabling WME support\n");
7858 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7859 		}
7860 	}
7861 
7862 	if (BWN_ISOLDFMT(mac))
7863 		device_printf(sc->sc_dev, "using old firmware image\n");
7864 
7865 	return (0);
7866 
7867 error:
7868 	BWN_WRITE_4(mac, BWN_MACCTL,
7869 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7870 	    BWN_MACCTL_MCODE_JMP0);
7871 
7872 	return (error);
7873 #undef GETFWSIZE
7874 #undef GETFWOFFSET
7875 }
7876 
7877 /* OpenFirmware only */
7878 static uint16_t
7879 bwn_fwcaps_read(struct bwn_mac *mac)
7880 {
7881 
7882 	KASSERT(mac->mac_fw.opensource == 1,
7883 	    ("%s:%d: fail", __func__, __LINE__));
7884 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7885 }
7886 
7887 static int
7888 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7889     size_t count, size_t array_size)
7890 {
7891 #define	GET_NEXTIV16(iv)						\
7892 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7893 	    sizeof(uint16_t) + sizeof(uint16_t)))
7894 #define	GET_NEXTIV32(iv)						\
7895 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7896 	    sizeof(uint16_t) + sizeof(uint32_t)))
7897 	struct bwn_softc *sc = mac->mac_sc;
7898 	const struct bwn_fwinitvals *iv;
7899 	uint16_t offset;
7900 	size_t i;
7901 	uint8_t bit32;
7902 
7903 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7904 	    ("%s:%d: fail", __func__, __LINE__));
7905 	iv = ivals;
7906 	for (i = 0; i < count; i++) {
7907 		if (array_size < sizeof(iv->offset_size))
7908 			goto fail;
7909 		array_size -= sizeof(iv->offset_size);
7910 		offset = be16toh(iv->offset_size);
7911 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7912 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7913 		if (offset >= 0x1000)
7914 			goto fail;
7915 		if (bit32) {
7916 			if (array_size < sizeof(iv->data.d32))
7917 				goto fail;
7918 			array_size -= sizeof(iv->data.d32);
7919 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7920 			iv = GET_NEXTIV32(iv);
7921 		} else {
7922 
7923 			if (array_size < sizeof(iv->data.d16))
7924 				goto fail;
7925 			array_size -= sizeof(iv->data.d16);
7926 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7927 
7928 			iv = GET_NEXTIV16(iv);
7929 		}
7930 	}
7931 	if (array_size != 0)
7932 		goto fail;
7933 	return (0);
7934 fail:
7935 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7936 	return (EPROTO);
7937 #undef GET_NEXTIV16
7938 #undef GET_NEXTIV32
7939 }
7940 
7941 static int
7942 bwn_switch_channel(struct bwn_mac *mac, int chan)
7943 {
7944 	struct bwn_phy *phy = &(mac->mac_phy);
7945 	struct bwn_softc *sc = mac->mac_sc;
7946 	struct ifnet *ifp = sc->sc_ifp;
7947 	struct ieee80211com *ic = ifp->if_l2com;
7948 	uint16_t channelcookie, savedcookie;
7949 	int error;
7950 
7951 	if (chan == 0xffff)
7952 		chan = phy->get_default_chan(mac);
7953 
7954 	channelcookie = chan;
7955 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7956 		channelcookie |= 0x100;
7957 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7958 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7959 	error = phy->switch_channel(mac, chan);
7960 	if (error)
7961 		goto fail;
7962 
7963 	mac->mac_phy.chan = chan;
7964 	DELAY(8000);
7965 	return (0);
7966 fail:
7967 	device_printf(sc->sc_dev, "failed to switch channel\n");
7968 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7969 	return (error);
7970 }
7971 
7972 static uint16_t
7973 bwn_ant2phy(int antenna)
7974 {
7975 
7976 	switch (antenna) {
7977 	case BWN_ANT0:
7978 		return (BWN_TX_PHY_ANT0);
7979 	case BWN_ANT1:
7980 		return (BWN_TX_PHY_ANT1);
7981 	case BWN_ANT2:
7982 		return (BWN_TX_PHY_ANT2);
7983 	case BWN_ANT3:
7984 		return (BWN_TX_PHY_ANT3);
7985 	case BWN_ANTAUTO:
7986 		return (BWN_TX_PHY_ANT01AUTO);
7987 	}
7988 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7989 	return (0);
7990 }
7991 
7992 static void
7993 bwn_wme_load(struct bwn_mac *mac)
7994 {
7995 	struct bwn_softc *sc = mac->mac_sc;
7996 	int i;
7997 
7998 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7999 	    ("%s:%d: fail", __func__, __LINE__));
8000 
8001 	bwn_mac_suspend(mac);
8002 	for (i = 0; i < N(sc->sc_wmeParams); i++)
8003 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8004 		    bwn_wme_shm_offsets[i]);
8005 	bwn_mac_enable(mac);
8006 }
8007 
8008 static void
8009 bwn_wme_loadparams(struct bwn_mac *mac,
8010     const struct wmeParams *p, uint16_t shm_offset)
8011 {
8012 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8013 	struct bwn_softc *sc = mac->mac_sc;
8014 	uint16_t params[BWN_NR_WMEPARAMS];
8015 	int slot, tmp;
8016 	unsigned int i;
8017 
8018 	slot = BWN_READ_2(mac, BWN_RNG) &
8019 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8020 
8021 	memset(&params, 0, sizeof(params));
8022 
8023 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8024 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8025 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8026 
8027 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8028 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8029 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8030 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8031 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8032 	params[BWN_WMEPARAM_BSLOTS] = slot;
8033 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8034 
8035 	for (i = 0; i < N(params); i++) {
8036 		if (i == BWN_WMEPARAM_STATUS) {
8037 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8038 			    shm_offset + (i * 2));
8039 			tmp |= 0x100;
8040 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8041 			    tmp);
8042 		} else {
8043 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8044 			    params[i]);
8045 		}
8046 	}
8047 }
8048 
8049 static void
8050 bwn_mac_write_bssid(struct bwn_mac *mac)
8051 {
8052 	struct bwn_softc *sc = mac->mac_sc;
8053 	uint32_t tmp;
8054 	int i;
8055 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8056 
8057 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8058 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8059 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8060 	    IEEE80211_ADDR_LEN);
8061 
8062 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8063 		tmp = (uint32_t) (mac_bssid[i + 0]);
8064 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8065 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8066 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8067 		bwn_ram_write(mac, 0x20 + i, tmp);
8068 	}
8069 }
8070 
8071 static void
8072 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8073     const uint8_t *macaddr)
8074 {
8075 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8076 	uint16_t data;
8077 
8078 	if (!mac)
8079 		macaddr = zero;
8080 
8081 	offset |= 0x0020;
8082 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8083 
8084 	data = macaddr[0];
8085 	data |= macaddr[1] << 8;
8086 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8087 	data = macaddr[2];
8088 	data |= macaddr[3] << 8;
8089 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8090 	data = macaddr[4];
8091 	data |= macaddr[5] << 8;
8092 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8093 }
8094 
8095 static void
8096 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8097     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8098 {
8099 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8100 	uint8_t per_sta_keys_start = 8;
8101 
8102 	if (BWN_SEC_NEWAPI(mac))
8103 		per_sta_keys_start = 4;
8104 
8105 	KASSERT(index < mac->mac_max_nr_keys,
8106 	    ("%s:%d: fail", __func__, __LINE__));
8107 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8108 	    ("%s:%d: fail", __func__, __LINE__));
8109 
8110 	if (index >= per_sta_keys_start)
8111 		bwn_key_macwrite(mac, index, NULL);
8112 	if (key)
8113 		memcpy(buf, key, key_len);
8114 	bwn_key_write(mac, index, algorithm, buf);
8115 	if (index >= per_sta_keys_start)
8116 		bwn_key_macwrite(mac, index, mac_addr);
8117 
8118 	mac->mac_key[index].algorithm = algorithm;
8119 }
8120 
8121 static void
8122 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8123 {
8124 	struct bwn_softc *sc = mac->mac_sc;
8125 	uint32_t addrtmp[2] = { 0, 0 };
8126 	uint8_t start = 8;
8127 
8128 	if (BWN_SEC_NEWAPI(mac))
8129 		start = 4;
8130 
8131 	KASSERT(index >= start,
8132 	    ("%s:%d: fail", __func__, __LINE__));
8133 	index -= start;
8134 
8135 	if (addr) {
8136 		addrtmp[0] = addr[0];
8137 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8138 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8139 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8140 		addrtmp[1] = addr[4];
8141 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8142 	}
8143 
8144 	if (siba_get_revid(sc->sc_dev) >= 5) {
8145 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8146 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8147 	} else {
8148 		if (index >= 8) {
8149 			bwn_shm_write_4(mac, BWN_SHARED,
8150 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8151 			bwn_shm_write_2(mac, BWN_SHARED,
8152 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8153 		}
8154 	}
8155 }
8156 
8157 static void
8158 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8159     const uint8_t *key)
8160 {
8161 	unsigned int i;
8162 	uint32_t offset;
8163 	uint16_t kidx, value;
8164 
8165 	kidx = BWN_SEC_KEY2FW(mac, index);
8166 	bwn_shm_write_2(mac, BWN_SHARED,
8167 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8168 
8169 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8170 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8171 		value = key[i];
8172 		value |= (uint16_t)(key[i + 1]) << 8;
8173 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8174 	}
8175 }
8176 
8177 static void
8178 bwn_phy_exit(struct bwn_mac *mac)
8179 {
8180 
8181 	mac->mac_phy.rf_onoff(mac, 0);
8182 	if (mac->mac_phy.exit != NULL)
8183 		mac->mac_phy.exit(mac);
8184 }
8185 
8186 static void
8187 bwn_dma_free(struct bwn_mac *mac)
8188 {
8189 	struct bwn_dma *dma;
8190 
8191 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8192 		return;
8193 	dma = &mac->mac_method.dma;
8194 
8195 	bwn_dma_ringfree(&dma->rx);
8196 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8197 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8198 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8199 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8200 	bwn_dma_ringfree(&dma->mcast);
8201 }
8202 
8203 static void
8204 bwn_core_stop(struct bwn_mac *mac)
8205 {
8206 	struct bwn_softc *sc = mac->mac_sc;
8207 
8208 	BWN_ASSERT_LOCKED(sc);
8209 
8210 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8211 		return;
8212 
8213 	callout_stop(&sc->sc_rfswitch_ch);
8214 	callout_stop(&sc->sc_task_ch);
8215 	callout_stop(&sc->sc_watchdog_ch);
8216 	sc->sc_watchdog_timer = 0;
8217 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8218 	BWN_READ_4(mac, BWN_INTR_MASK);
8219 	bwn_mac_suspend(mac);
8220 
8221 	mac->mac_status = BWN_MAC_STATUS_INITED;
8222 }
8223 
8224 static int
8225 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8226 {
8227 	struct bwn_mac *up_dev = NULL;
8228 	struct bwn_mac *down_dev;
8229 	struct bwn_mac *mac;
8230 	int err, status;
8231 	uint8_t gmode;
8232 
8233 	BWN_ASSERT_LOCKED(sc);
8234 
8235 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8236 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8237 		    mac->mac_phy.supports_2ghz) {
8238 			up_dev = mac;
8239 			gmode = 1;
8240 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8241 		    mac->mac_phy.supports_5ghz) {
8242 			up_dev = mac;
8243 			gmode = 0;
8244 		} else {
8245 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8246 			return (EINVAL);
8247 		}
8248 		if (up_dev != NULL)
8249 			break;
8250 	}
8251 	if (up_dev == NULL) {
8252 		device_printf(sc->sc_dev, "Could not find a device\n");
8253 		return (ENODEV);
8254 	}
8255 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8256 		return (0);
8257 
8258 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8259 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8260 
8261 	down_dev = sc->sc_curmac;
8262 	status = down_dev->mac_status;
8263 	if (status >= BWN_MAC_STATUS_STARTED)
8264 		bwn_core_stop(down_dev);
8265 	if (status >= BWN_MAC_STATUS_INITED)
8266 		bwn_core_exit(down_dev);
8267 
8268 	if (down_dev != up_dev)
8269 		bwn_phy_reset(down_dev);
8270 
8271 	up_dev->mac_phy.gmode = gmode;
8272 	if (status >= BWN_MAC_STATUS_INITED) {
8273 		err = bwn_core_init(up_dev);
8274 		if (err) {
8275 			device_printf(sc->sc_dev,
8276 			    "fatal: failed to initialize for %s-GHz\n",
8277 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8278 			goto fail;
8279 		}
8280 	}
8281 	if (status >= BWN_MAC_STATUS_STARTED)
8282 		bwn_core_start(up_dev);
8283 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8284 	sc->sc_curmac = up_dev;
8285 
8286 	return (0);
8287 fail:
8288 	sc->sc_curmac = NULL;
8289 	return (err);
8290 }
8291 
8292 static void
8293 bwn_rf_turnon(struct bwn_mac *mac)
8294 {
8295 
8296 	bwn_mac_suspend(mac);
8297 	mac->mac_phy.rf_onoff(mac, 1);
8298 	mac->mac_phy.rf_on = 1;
8299 	bwn_mac_enable(mac);
8300 }
8301 
8302 static void
8303 bwn_rf_turnoff(struct bwn_mac *mac)
8304 {
8305 
8306 	bwn_mac_suspend(mac);
8307 	mac->mac_phy.rf_onoff(mac, 0);
8308 	mac->mac_phy.rf_on = 0;
8309 	bwn_mac_enable(mac);
8310 }
8311 
8312 static void
8313 bwn_phy_reset(struct bwn_mac *mac)
8314 {
8315 	struct bwn_softc *sc = mac->mac_sc;
8316 
8317 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8318 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8319 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8320 	DELAY(1000);
8321 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8322 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8323 	    BWN_TGSLOW_PHYRESET);
8324 	DELAY(1000);
8325 }
8326 
8327 static int
8328 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8329 {
8330 	struct bwn_vap *bvp = BWN_VAP(vap);
8331 	struct ieee80211com *ic= vap->iv_ic;
8332 	struct ifnet *ifp = ic->ic_ifp;
8333 	enum ieee80211_state ostate = vap->iv_state;
8334 	struct bwn_softc *sc = ifp->if_softc;
8335 	struct bwn_mac *mac = sc->sc_curmac;
8336 	int error;
8337 
8338 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8339 	    ieee80211_state_name[vap->iv_state],
8340 	    ieee80211_state_name[nstate]);
8341 
8342 	error = bvp->bv_newstate(vap, nstate, arg);
8343 	if (error != 0)
8344 		return (error);
8345 
8346 	BWN_LOCK(sc);
8347 
8348 	bwn_led_newstate(mac, nstate);
8349 
8350 	/*
8351 	 * Clear the BSSID when we stop a STA
8352 	 */
8353 	if (vap->iv_opmode == IEEE80211_M_STA) {
8354 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8355 			/*
8356 			 * Clear out the BSSID.  If we reassociate to
8357 			 * the same AP, this will reinialize things
8358 			 * correctly...
8359 			 */
8360 			if (ic->ic_opmode == IEEE80211_M_STA &&
8361 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8362 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8363 				bwn_set_macaddr(mac);
8364 			}
8365 		}
8366 	}
8367 
8368 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8369 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8370 		/* XXX nothing to do? */
8371 	} else if (nstate == IEEE80211_S_RUN) {
8372 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8373 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8374 		bwn_set_opmode(mac);
8375 		bwn_set_pretbtt(mac);
8376 		bwn_spu_setdelay(mac, 0);
8377 		bwn_set_macaddr(mac);
8378 	}
8379 
8380 	BWN_UNLOCK(sc);
8381 
8382 	return (error);
8383 }
8384 
8385 static void
8386 bwn_set_pretbtt(struct bwn_mac *mac)
8387 {
8388 	struct bwn_softc *sc = mac->mac_sc;
8389 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8390 	uint16_t pretbtt;
8391 
8392 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8393 		pretbtt = 2;
8394 	else
8395 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8396 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8397 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8398 }
8399 
8400 static int
8401 bwn_intr(void *arg)
8402 {
8403 	struct bwn_mac *mac = arg;
8404 	struct bwn_softc *sc = mac->mac_sc;
8405 	uint32_t reason;
8406 
8407 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8408 	    (sc->sc_flags & BWN_FLAG_INVALID))
8409 		return (FILTER_STRAY);
8410 
8411 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8412 	if (reason == 0xffffffff)	/* shared IRQ */
8413 		return (FILTER_STRAY);
8414 	reason &= mac->mac_intr_mask;
8415 	if (reason == 0)
8416 		return (FILTER_HANDLED);
8417 
8418 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8419 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8420 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8421 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8422 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8423 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8424 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8425 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8426 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8427 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8428 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8429 
8430 	/* Disable interrupts. */
8431 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8432 
8433 	mac->mac_reason_intr = reason;
8434 
8435 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8436 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8437 
8438 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8439 	return (FILTER_HANDLED);
8440 }
8441 
8442 static void
8443 bwn_intrtask(void *arg, int npending)
8444 {
8445 	struct bwn_mac *mac = arg;
8446 	struct bwn_softc *sc = mac->mac_sc;
8447 	struct ifnet *ifp = sc->sc_ifp;
8448 	uint32_t merged = 0;
8449 	int i, tx = 0, rx = 0;
8450 
8451 	BWN_LOCK(sc);
8452 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8453 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8454 		BWN_UNLOCK(sc);
8455 		return;
8456 	}
8457 
8458 	for (i = 0; i < N(mac->mac_reason); i++)
8459 		merged |= mac->mac_reason[i];
8460 
8461 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8462 		device_printf(sc->sc_dev, "MAC trans error\n");
8463 
8464 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8465 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8466 		mac->mac_phy.txerrors--;
8467 		if (mac->mac_phy.txerrors == 0) {
8468 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8469 			bwn_restart(mac, "PHY TX errors");
8470 		}
8471 	}
8472 
8473 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8474 		if (merged & BWN_DMAINTR_FATALMASK) {
8475 			device_printf(sc->sc_dev,
8476 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8477 			    mac->mac_reason[0], mac->mac_reason[1],
8478 			    mac->mac_reason[2], mac->mac_reason[3],
8479 			    mac->mac_reason[4], mac->mac_reason[5]);
8480 			bwn_restart(mac, "DMA error");
8481 			BWN_UNLOCK(sc);
8482 			return;
8483 		}
8484 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8485 			device_printf(sc->sc_dev,
8486 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8487 			    mac->mac_reason[0], mac->mac_reason[1],
8488 			    mac->mac_reason[2], mac->mac_reason[3],
8489 			    mac->mac_reason[4], mac->mac_reason[5]);
8490 		}
8491 	}
8492 
8493 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8494 		bwn_intr_ucode_debug(mac);
8495 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8496 		bwn_intr_tbtt_indication(mac);
8497 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8498 		bwn_intr_atim_end(mac);
8499 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8500 		bwn_intr_beacon(mac);
8501 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8502 		bwn_intr_pmq(mac);
8503 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8504 		bwn_intr_noise(mac);
8505 
8506 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8507 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8508 			bwn_dma_rx(mac->mac_method.dma.rx);
8509 			rx = 1;
8510 		}
8511 	} else
8512 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8513 
8514 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8519 
8520 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8521 		bwn_intr_txeof(mac);
8522 		tx = 1;
8523 	}
8524 
8525 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8526 
8527 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8528 		int evt = BWN_LED_EVENT_NONE;
8529 
8530 		if (tx && rx) {
8531 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8532 				evt = BWN_LED_EVENT_RX;
8533 			else
8534 				evt = BWN_LED_EVENT_TX;
8535 		} else if (tx) {
8536 			evt = BWN_LED_EVENT_TX;
8537 		} else if (rx) {
8538 			evt = BWN_LED_EVENT_RX;
8539 		} else if (rx == 0) {
8540 			evt = BWN_LED_EVENT_POLL;
8541 		}
8542 
8543 		if (evt != BWN_LED_EVENT_NONE)
8544 			bwn_led_event(mac, evt);
8545        }
8546 
8547 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8548 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8549 			bwn_start_locked(ifp);
8550 	}
8551 
8552 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8553 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8554 
8555 	BWN_UNLOCK(sc);
8556 }
8557 
8558 static void
8559 bwn_restart(struct bwn_mac *mac, const char *msg)
8560 {
8561 	struct bwn_softc *sc = mac->mac_sc;
8562 	struct ifnet *ifp = sc->sc_ifp;
8563 	struct ieee80211com *ic = ifp->if_l2com;
8564 
8565 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8566 		return;
8567 
8568 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8569 	ieee80211_runtask(ic, &mac->mac_hwreset);
8570 }
8571 
8572 static void
8573 bwn_intr_ucode_debug(struct bwn_mac *mac)
8574 {
8575 	struct bwn_softc *sc = mac->mac_sc;
8576 	uint16_t reason;
8577 
8578 	if (mac->mac_fw.opensource == 0)
8579 		return;
8580 
8581 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8582 	switch (reason) {
8583 	case BWN_DEBUGINTR_PANIC:
8584 		bwn_handle_fwpanic(mac);
8585 		break;
8586 	case BWN_DEBUGINTR_DUMP_SHM:
8587 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8588 		break;
8589 	case BWN_DEBUGINTR_DUMP_REGS:
8590 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8591 		break;
8592 	case BWN_DEBUGINTR_MARKER:
8593 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8594 		break;
8595 	default:
8596 		device_printf(sc->sc_dev,
8597 		    "ucode debug unknown reason: %#x\n", reason);
8598 	}
8599 
8600 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8601 	    BWN_DEBUGINTR_ACK);
8602 }
8603 
8604 static void
8605 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8606 {
8607 	struct bwn_softc *sc = mac->mac_sc;
8608 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8609 
8610 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8611 		bwn_psctl(mac, 0);
8612 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8613 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8614 }
8615 
8616 static void
8617 bwn_intr_atim_end(struct bwn_mac *mac)
8618 {
8619 
8620 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8621 		BWN_WRITE_4(mac, BWN_MACCMD,
8622 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8623 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8624 	}
8625 }
8626 
8627 static void
8628 bwn_intr_beacon(struct bwn_mac *mac)
8629 {
8630 	struct bwn_softc *sc = mac->mac_sc;
8631 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8632 	uint32_t cmd, beacon0, beacon1;
8633 
8634 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8635 	    ic->ic_opmode == IEEE80211_M_MBSS)
8636 		return;
8637 
8638 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8639 
8640 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8641 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8642 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8643 
8644 	if (beacon0 && beacon1) {
8645 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8646 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8647 		return;
8648 	}
8649 
8650 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8651 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8652 		bwn_load_beacon0(mac);
8653 		bwn_load_beacon1(mac);
8654 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8655 		cmd |= BWN_MACCMD_BEACON0_VALID;
8656 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8657 	} else {
8658 		if (!beacon0) {
8659 			bwn_load_beacon0(mac);
8660 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8661 			cmd |= BWN_MACCMD_BEACON0_VALID;
8662 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8663 		} else if (!beacon1) {
8664 			bwn_load_beacon1(mac);
8665 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8666 			cmd |= BWN_MACCMD_BEACON1_VALID;
8667 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8668 		}
8669 	}
8670 }
8671 
8672 static void
8673 bwn_intr_pmq(struct bwn_mac *mac)
8674 {
8675 	uint32_t tmp;
8676 
8677 	while (1) {
8678 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8679 		if (!(tmp & 0x00000008))
8680 			break;
8681 	}
8682 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8683 }
8684 
8685 static void
8686 bwn_intr_noise(struct bwn_mac *mac)
8687 {
8688 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8689 	uint16_t tmp;
8690 	uint8_t noise[4];
8691 	uint8_t i, j;
8692 	int32_t average;
8693 
8694 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8695 		return;
8696 
8697 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8698 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8699 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8700 	    noise[3] == 0x7f)
8701 		goto new;
8702 
8703 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8704 	    ("%s:%d: fail", __func__, __LINE__));
8705 	i = mac->mac_noise.noi_nsamples;
8706 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8707 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8708 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8709 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8710 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8711 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8712 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8713 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8714 	mac->mac_noise.noi_nsamples++;
8715 	if (mac->mac_noise.noi_nsamples == 8) {
8716 		average = 0;
8717 		for (i = 0; i < 8; i++) {
8718 			for (j = 0; j < 4; j++)
8719 				average += mac->mac_noise.noi_samples[i][j];
8720 		}
8721 		average = (((average / 32) * 125) + 64) / 128;
8722 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8723 		if (tmp >= 8)
8724 			average += 2;
8725 		else
8726 			average -= 25;
8727 		average -= (tmp == 8) ? 72 : 48;
8728 
8729 		mac->mac_stats.link_noise = average;
8730 		mac->mac_noise.noi_running = 0;
8731 		return;
8732 	}
8733 new:
8734 	bwn_noise_gensample(mac);
8735 }
8736 
8737 static int
8738 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8739 {
8740 	struct bwn_mac *mac = prq->prq_mac;
8741 	struct bwn_softc *sc = mac->mac_sc;
8742 	unsigned int i;
8743 
8744 	BWN_ASSERT_LOCKED(sc);
8745 
8746 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8747 		return (0);
8748 
8749 	for (i = 0; i < 5000; i++) {
8750 		if (bwn_pio_rxeof(prq) == 0)
8751 			break;
8752 	}
8753 	if (i >= 5000)
8754 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8755 	return ((i > 0) ? 1 : 0);
8756 }
8757 
8758 static void
8759 bwn_dma_rx(struct bwn_dma_ring *dr)
8760 {
8761 	int slot, curslot;
8762 
8763 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8764 	curslot = dr->get_curslot(dr);
8765 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8766 	    ("%s:%d: fail", __func__, __LINE__));
8767 
8768 	slot = dr->dr_curslot;
8769 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8770 		bwn_dma_rxeof(dr, &slot);
8771 
8772 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8773 	    BUS_DMASYNC_PREWRITE);
8774 
8775 	dr->set_curslot(dr, slot);
8776 	dr->dr_curslot = slot;
8777 }
8778 
8779 static void
8780 bwn_intr_txeof(struct bwn_mac *mac)
8781 {
8782 	struct bwn_txstatus stat;
8783 	uint32_t stat0, stat1;
8784 	uint16_t tmp;
8785 
8786 	BWN_ASSERT_LOCKED(mac->mac_sc);
8787 
8788 	while (1) {
8789 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8790 		if (!(stat0 & 0x00000001))
8791 			break;
8792 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8793 
8794 		stat.cookie = (stat0 >> 16);
8795 		stat.seq = (stat1 & 0x0000ffff);
8796 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8797 		tmp = (stat0 & 0x0000ffff);
8798 		stat.framecnt = ((tmp & 0xf000) >> 12);
8799 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8800 		stat.sreason = ((tmp & 0x001c) >> 2);
8801 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8802 		stat.im = (tmp & 0x0040) ? 1 : 0;
8803 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8804 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8805 
8806 		bwn_handle_txeof(mac, &stat);
8807 	}
8808 }
8809 
8810 static void
8811 bwn_hwreset(void *arg, int npending)
8812 {
8813 	struct bwn_mac *mac = arg;
8814 	struct bwn_softc *sc = mac->mac_sc;
8815 	int error = 0;
8816 	int prev_status;
8817 
8818 	BWN_LOCK(sc);
8819 
8820 	prev_status = mac->mac_status;
8821 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8822 		bwn_core_stop(mac);
8823 	if (prev_status >= BWN_MAC_STATUS_INITED)
8824 		bwn_core_exit(mac);
8825 
8826 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8827 		error = bwn_core_init(mac);
8828 		if (error)
8829 			goto out;
8830 	}
8831 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8832 		bwn_core_start(mac);
8833 out:
8834 	if (error) {
8835 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8836 		sc->sc_curmac = NULL;
8837 	}
8838 	BWN_UNLOCK(sc);
8839 }
8840 
8841 static void
8842 bwn_handle_fwpanic(struct bwn_mac *mac)
8843 {
8844 	struct bwn_softc *sc = mac->mac_sc;
8845 	uint16_t reason;
8846 
8847 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8848 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8849 
8850 	if (reason == BWN_FWPANIC_RESTART)
8851 		bwn_restart(mac, "ucode panic");
8852 }
8853 
8854 static void
8855 bwn_load_beacon0(struct bwn_mac *mac)
8856 {
8857 
8858 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8859 }
8860 
8861 static void
8862 bwn_load_beacon1(struct bwn_mac *mac)
8863 {
8864 
8865 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8866 }
8867 
8868 static uint32_t
8869 bwn_jssi_read(struct bwn_mac *mac)
8870 {
8871 	uint32_t val = 0;
8872 
8873 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8874 	val <<= 16;
8875 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8876 
8877 	return (val);
8878 }
8879 
8880 static void
8881 bwn_noise_gensample(struct bwn_mac *mac)
8882 {
8883 	uint32_t jssi = 0x7f7f7f7f;
8884 
8885 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8886 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8887 	BWN_WRITE_4(mac, BWN_MACCMD,
8888 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8889 }
8890 
8891 static int
8892 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8893 {
8894 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8895 
8896 	return (dr->dr_numslots - dr->dr_usedslot);
8897 }
8898 
8899 static int
8900 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8901 {
8902 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8903 
8904 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8905 	    ("%s:%d: fail", __func__, __LINE__));
8906 	if (slot == dr->dr_numslots - 1)
8907 		return (0);
8908 	return (slot + 1);
8909 }
8910 
8911 static void
8912 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8913 {
8914 	struct bwn_mac *mac = dr->dr_mac;
8915 	struct bwn_softc *sc = mac->mac_sc;
8916 	struct bwn_dma *dma = &mac->mac_method.dma;
8917 	struct bwn_dmadesc_generic *desc;
8918 	struct bwn_dmadesc_meta *meta;
8919 	struct bwn_rxhdr4 *rxhdr;
8920 	struct ifnet *ifp = sc->sc_ifp;
8921 	struct mbuf *m;
8922 	uint32_t macstat;
8923 	int32_t tmp;
8924 	int cnt = 0;
8925 	uint16_t len;
8926 
8927 	dr->getdesc(dr, *slot, &desc, &meta);
8928 
8929 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8930 	m = meta->mt_m;
8931 
8932 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8933 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8934 		return;
8935 	}
8936 
8937 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8938 	len = le16toh(rxhdr->frame_len);
8939 	if (len <= 0) {
8940 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8941 		return;
8942 	}
8943 	if (bwn_dma_check_redzone(dr, m)) {
8944 		device_printf(sc->sc_dev, "redzone error.\n");
8945 		bwn_dma_set_redzone(dr, m);
8946 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8947 		    BUS_DMASYNC_PREWRITE);
8948 		return;
8949 	}
8950 	if (len > dr->dr_rx_bufsize) {
8951 		tmp = len;
8952 		while (1) {
8953 			dr->getdesc(dr, *slot, &desc, &meta);
8954 			bwn_dma_set_redzone(dr, meta->mt_m);
8955 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8956 			    BUS_DMASYNC_PREWRITE);
8957 			*slot = bwn_dma_nextslot(dr, *slot);
8958 			cnt++;
8959 			tmp -= dr->dr_rx_bufsize;
8960 			if (tmp <= 0)
8961 				break;
8962 		}
8963 		device_printf(sc->sc_dev, "too small buffer "
8964 		       "(len %u buffer %u dropped %d)\n",
8965 		       len, dr->dr_rx_bufsize, cnt);
8966 		return;
8967 	}
8968 	macstat = le32toh(rxhdr->mac_status);
8969 	if (macstat & BWN_RX_MAC_FCSERR) {
8970 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8971 			device_printf(sc->sc_dev, "RX drop\n");
8972 			return;
8973 		}
8974 	}
8975 
8976 	m->m_pkthdr.rcvif = ifp;
8977 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8978 	m_adj(m, dr->dr_frameoffset);
8979 
8980 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8981 }
8982 
8983 static void
8984 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8985 {
8986 	struct bwn_dma_ring *dr;
8987 	struct bwn_dmadesc_generic *desc;
8988 	struct bwn_dmadesc_meta *meta;
8989 	struct bwn_pio_txqueue *tq;
8990 	struct bwn_pio_txpkt *tp = NULL;
8991 	struct bwn_softc *sc = mac->mac_sc;
8992 	struct bwn_stats *stats = &mac->mac_stats;
8993 	struct ieee80211_node *ni;
8994 	struct ieee80211vap *vap;
8995 	int retrycnt = 0, slot;
8996 
8997 	BWN_ASSERT_LOCKED(mac->mac_sc);
8998 
8999 	if (status->im)
9000 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9001 	if (status->ampdu)
9002 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9003 	if (status->rtscnt) {
9004 		if (status->rtscnt == 0xf)
9005 			stats->rtsfail++;
9006 		else
9007 			stats->rts++;
9008 	}
9009 
9010 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9011 		if (status->ack) {
9012 			dr = bwn_dma_parse_cookie(mac, status,
9013 			    status->cookie, &slot);
9014 			if (dr == NULL) {
9015 				device_printf(sc->sc_dev,
9016 				    "failed to parse cookie\n");
9017 				return;
9018 			}
9019 			while (1) {
9020 				dr->getdesc(dr, slot, &desc, &meta);
9021 				if (meta->mt_islast) {
9022 					ni = meta->mt_ni;
9023 					vap = ni->ni_vap;
9024 					ieee80211_ratectl_tx_complete(vap, ni,
9025 					    status->ack ?
9026 					      IEEE80211_RATECTL_TX_SUCCESS :
9027 					      IEEE80211_RATECTL_TX_FAILURE,
9028 					    &retrycnt, 0);
9029 					break;
9030 				}
9031 				slot = bwn_dma_nextslot(dr, slot);
9032 			}
9033 		}
9034 		bwn_dma_handle_txeof(mac, status);
9035 	} else {
9036 		if (status->ack) {
9037 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9038 			if (tq == NULL) {
9039 				device_printf(sc->sc_dev,
9040 				    "failed to parse cookie\n");
9041 				return;
9042 			}
9043 			ni = tp->tp_ni;
9044 			vap = ni->ni_vap;
9045 			ieee80211_ratectl_tx_complete(vap, ni,
9046 			    status->ack ?
9047 			      IEEE80211_RATECTL_TX_SUCCESS :
9048 			      IEEE80211_RATECTL_TX_FAILURE,
9049 			    &retrycnt, 0);
9050 		}
9051 		bwn_pio_handle_txeof(mac, status);
9052 	}
9053 
9054 	bwn_phy_txpower_check(mac, 0);
9055 }
9056 
9057 static uint8_t
9058 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9059 {
9060 	struct bwn_mac *mac = prq->prq_mac;
9061 	struct bwn_softc *sc = mac->mac_sc;
9062 	struct bwn_rxhdr4 rxhdr;
9063 	struct ifnet *ifp = sc->sc_ifp;
9064 	struct mbuf *m;
9065 	uint32_t ctl32, macstat, v32;
9066 	unsigned int i, padding;
9067 	uint16_t ctl16, len, totlen, v16;
9068 	unsigned char *mp;
9069 	char *data;
9070 
9071 	memset(&rxhdr, 0, sizeof(rxhdr));
9072 
9073 	if (prq->prq_rev >= 8) {
9074 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9075 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9076 			return (0);
9077 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9078 		    BWN_PIO8_RXCTL_FRAMEREADY);
9079 		for (i = 0; i < 10; i++) {
9080 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9081 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9082 				goto ready;
9083 			DELAY(10);
9084 		}
9085 	} else {
9086 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9087 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9088 			return (0);
9089 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9090 		    BWN_PIO_RXCTL_FRAMEREADY);
9091 		for (i = 0; i < 10; i++) {
9092 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9093 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9094 				goto ready;
9095 			DELAY(10);
9096 		}
9097 	}
9098 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9099 	return (1);
9100 ready:
9101 	if (prq->prq_rev >= 8)
9102 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9103 		    prq->prq_base + BWN_PIO8_RXDATA);
9104 	else
9105 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9106 		    prq->prq_base + BWN_PIO_RXDATA);
9107 	len = le16toh(rxhdr.frame_len);
9108 	if (len > 0x700) {
9109 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9110 		goto error;
9111 	}
9112 	if (len == 0) {
9113 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9114 		goto error;
9115 	}
9116 
9117 	macstat = le32toh(rxhdr.mac_status);
9118 	if (macstat & BWN_RX_MAC_FCSERR) {
9119 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9120 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9121 			goto error;
9122 		}
9123 	}
9124 
9125 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9126 	totlen = len + padding;
9127 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9128 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9129 	if (m == NULL) {
9130 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9131 		goto error;
9132 	}
9133 	mp = mtod(m, unsigned char *);
9134 	if (prq->prq_rev >= 8) {
9135 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9136 		    prq->prq_base + BWN_PIO8_RXDATA);
9137 		if (totlen & 3) {
9138 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9139 			data = &(mp[totlen - 1]);
9140 			switch (totlen & 3) {
9141 			case 3:
9142 				*data = (v32 >> 16);
9143 				data--;
9144 			case 2:
9145 				*data = (v32 >> 8);
9146 				data--;
9147 			case 1:
9148 				*data = v32;
9149 			}
9150 		}
9151 	} else {
9152 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9153 		    prq->prq_base + BWN_PIO_RXDATA);
9154 		if (totlen & 1) {
9155 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9156 			mp[totlen - 1] = v16;
9157 		}
9158 	}
9159 
9160 	m->m_pkthdr.rcvif = ifp;
9161 	m->m_len = m->m_pkthdr.len = totlen;
9162 
9163 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9164 
9165 	return (1);
9166 error:
9167 	if (prq->prq_rev >= 8)
9168 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9169 		    BWN_PIO8_RXCTL_DATAREADY);
9170 	else
9171 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9172 	return (1);
9173 }
9174 
9175 static int
9176 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9177     struct bwn_dmadesc_meta *meta, int init)
9178 {
9179 	struct bwn_mac *mac = dr->dr_mac;
9180 	struct bwn_dma *dma = &mac->mac_method.dma;
9181 	struct bwn_rxhdr4 *hdr;
9182 	bus_dmamap_t map;
9183 	bus_addr_t paddr;
9184 	struct mbuf *m;
9185 	int error;
9186 
9187 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9188 	if (m == NULL) {
9189 		error = ENOBUFS;
9190 
9191 		/*
9192 		 * If the NIC is up and running, we need to:
9193 		 * - Clear RX buffer's header.
9194 		 * - Restore RX descriptor settings.
9195 		 */
9196 		if (init)
9197 			return (error);
9198 		else
9199 			goto back;
9200 	}
9201 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9202 
9203 	bwn_dma_set_redzone(dr, m);
9204 
9205 	/*
9206 	 * Try to load RX buf into temporary DMA map
9207 	 */
9208 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9209 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9210 	if (error) {
9211 		m_freem(m);
9212 
9213 		/*
9214 		 * See the comment above
9215 		 */
9216 		if (init)
9217 			return (error);
9218 		else
9219 			goto back;
9220 	}
9221 
9222 	if (!init)
9223 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9224 	meta->mt_m = m;
9225 	meta->mt_paddr = paddr;
9226 
9227 	/*
9228 	 * Swap RX buf's DMA map with the loaded temporary one
9229 	 */
9230 	map = meta->mt_dmap;
9231 	meta->mt_dmap = dr->dr_spare_dmap;
9232 	dr->dr_spare_dmap = map;
9233 
9234 back:
9235 	/*
9236 	 * Clear RX buf header
9237 	 */
9238 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9239 	bzero(hdr, sizeof(*hdr));
9240 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9241 	    BUS_DMASYNC_PREWRITE);
9242 
9243 	/*
9244 	 * Setup RX buf descriptor
9245 	 */
9246 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9247 	    sizeof(*hdr), 0, 0, 0);
9248 	return (error);
9249 }
9250 
9251 static void
9252 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9253 		 bus_size_t mapsz __unused, int error)
9254 {
9255 
9256 	if (!error) {
9257 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9258 		*((bus_addr_t *)arg) = seg->ds_addr;
9259 	}
9260 }
9261 
9262 static int
9263 bwn_hwrate2ieeerate(int rate)
9264 {
9265 
9266 	switch (rate) {
9267 	case BWN_CCK_RATE_1MB:
9268 		return (2);
9269 	case BWN_CCK_RATE_2MB:
9270 		return (4);
9271 	case BWN_CCK_RATE_5MB:
9272 		return (11);
9273 	case BWN_CCK_RATE_11MB:
9274 		return (22);
9275 	case BWN_OFDM_RATE_6MB:
9276 		return (12);
9277 	case BWN_OFDM_RATE_9MB:
9278 		return (18);
9279 	case BWN_OFDM_RATE_12MB:
9280 		return (24);
9281 	case BWN_OFDM_RATE_18MB:
9282 		return (36);
9283 	case BWN_OFDM_RATE_24MB:
9284 		return (48);
9285 	case BWN_OFDM_RATE_36MB:
9286 		return (72);
9287 	case BWN_OFDM_RATE_48MB:
9288 		return (96);
9289 	case BWN_OFDM_RATE_54MB:
9290 		return (108);
9291 	default:
9292 		printf("Ooops\n");
9293 		return (0);
9294 	}
9295 }
9296 
9297 static void
9298 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9299 {
9300 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9301 	struct bwn_plcp6 *plcp;
9302 	struct bwn_softc *sc = mac->mac_sc;
9303 	struct ieee80211_frame_min *wh;
9304 	struct ieee80211_node *ni;
9305 	struct ifnet *ifp = sc->sc_ifp;
9306 	struct ieee80211com *ic = ifp->if_l2com;
9307 	uint32_t macstat;
9308 	int padding, rate, rssi = 0, noise = 0, type;
9309 	uint16_t phytype, phystat0, phystat3, chanstat;
9310 	unsigned char *mp = mtod(m, unsigned char *);
9311 	static int rx_mac_dec_rpt = 0;
9312 
9313 	BWN_ASSERT_LOCKED(sc);
9314 
9315 	phystat0 = le16toh(rxhdr->phy_status0);
9316 	phystat3 = le16toh(rxhdr->phy_status3);
9317 	macstat = le32toh(rxhdr->mac_status);
9318 	chanstat = le16toh(rxhdr->channel);
9319 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9320 
9321 	if (macstat & BWN_RX_MAC_FCSERR)
9322 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9323 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9324 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9325 	if (macstat & BWN_RX_MAC_DECERR)
9326 		goto drop;
9327 
9328 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9329 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9330 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9331 		    m->m_pkthdr.len);
9332 		goto drop;
9333 	}
9334 	plcp = (struct bwn_plcp6 *)(mp + padding);
9335 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9336 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9337 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9338 		    m->m_pkthdr.len);
9339 		goto drop;
9340 	}
9341 	wh = mtod(m, struct ieee80211_frame_min *);
9342 
9343 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9344 		device_printf(sc->sc_dev,
9345 		    "RX decryption attempted (old %d keyidx %#x)\n",
9346 		    BWN_ISOLDFMT(mac),
9347 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9348 
9349 	/* XXX calculating RSSI & noise & antenna */
9350 
9351 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9352 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9353 		    phytype == BWN_PHYTYPE_A);
9354 	else
9355 		rate = bwn_plcp_get_cckrate(mac, plcp);
9356 	if (rate == -1) {
9357 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9358 			goto drop;
9359 	}
9360 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9361 
9362 	/* RX radio tap */
9363 	if (ieee80211_radiotap_active(ic))
9364 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9365 	m_adj(m, -IEEE80211_CRC_LEN);
9366 
9367 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9368 	noise = mac->mac_stats.link_noise;
9369 
9370 	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
9371 
9372 	BWN_UNLOCK(sc);
9373 
9374 	ni = ieee80211_find_rxnode(ic, wh);
9375 	if (ni != NULL) {
9376 		type = ieee80211_input(ni, m, rssi, noise);
9377 		ieee80211_free_node(ni);
9378 	} else
9379 		type = ieee80211_input_all(ic, m, rssi, noise);
9380 
9381 	BWN_LOCK(sc);
9382 	return;
9383 drop:
9384 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9385 }
9386 
9387 static void
9388 bwn_dma_handle_txeof(struct bwn_mac *mac,
9389     const struct bwn_txstatus *status)
9390 {
9391 	struct bwn_dma *dma = &mac->mac_method.dma;
9392 	struct bwn_dma_ring *dr;
9393 	struct bwn_dmadesc_generic *desc;
9394 	struct bwn_dmadesc_meta *meta;
9395 	struct bwn_softc *sc = mac->mac_sc;
9396 	struct ieee80211_node *ni;
9397 	struct ifnet *ifp = sc->sc_ifp;
9398 	struct mbuf *m;
9399 	int slot;
9400 
9401 	BWN_ASSERT_LOCKED(sc);
9402 
9403 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9404 	if (dr == NULL) {
9405 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9406 		return;
9407 	}
9408 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9409 
9410 	while (1) {
9411 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9412 		    ("%s:%d: fail", __func__, __LINE__));
9413 		dr->getdesc(dr, slot, &desc, &meta);
9414 
9415 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9416 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9417 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9418 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9419 
9420 		if (meta->mt_islast) {
9421 			KASSERT(meta->mt_m != NULL,
9422 			    ("%s:%d: fail", __func__, __LINE__));
9423 
9424 			ni = meta->mt_ni;
9425 			m = meta->mt_m;
9426 			if (ni != NULL) {
9427 				/*
9428 				 * Do any tx complete callback. Note this must
9429 				 * be done before releasing the node reference.
9430 				 */
9431 				if (m->m_flags & M_TXCB)
9432 					ieee80211_process_callback(ni, m, 0);
9433 				ieee80211_free_node(ni);
9434 				meta->mt_ni = NULL;
9435 			}
9436 			m_freem(m);
9437 			meta->mt_m = NULL;
9438 		} else {
9439 			KASSERT(meta->mt_m == NULL,
9440 			    ("%s:%d: fail", __func__, __LINE__));
9441 		}
9442 
9443 		dr->dr_usedslot--;
9444 		if (meta->mt_islast) {
9445 			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9446 			break;
9447 		}
9448 		slot = bwn_dma_nextslot(dr, slot);
9449 	}
9450 	sc->sc_watchdog_timer = 0;
9451 	if (dr->dr_stop) {
9452 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9453 		    ("%s:%d: fail", __func__, __LINE__));
9454 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9455 		dr->dr_stop = 0;
9456 	}
9457 }
9458 
9459 static void
9460 bwn_pio_handle_txeof(struct bwn_mac *mac,
9461     const struct bwn_txstatus *status)
9462 {
9463 	struct bwn_pio_txqueue *tq;
9464 	struct bwn_pio_txpkt *tp = NULL;
9465 	struct bwn_softc *sc = mac->mac_sc;
9466 	struct ifnet *ifp = sc->sc_ifp;
9467 
9468 	BWN_ASSERT_LOCKED(sc);
9469 
9470 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9471 	if (tq == NULL)
9472 		return;
9473 
9474 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9475 	tq->tq_free++;
9476 
9477 	if (tp->tp_ni != NULL) {
9478 		/*
9479 		 * Do any tx complete callback.  Note this must
9480 		 * be done before releasing the node reference.
9481 		 */
9482 		if (tp->tp_m->m_flags & M_TXCB)
9483 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9484 		ieee80211_free_node(tp->tp_ni);
9485 		tp->tp_ni = NULL;
9486 	}
9487 	m_freem(tp->tp_m);
9488 	tp->tp_m = NULL;
9489 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9490 
9491 	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9492 
9493 	sc->sc_watchdog_timer = 0;
9494 	if (tq->tq_stop) {
9495 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9496 		tq->tq_stop = 0;
9497 	}
9498 }
9499 
9500 static void
9501 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9502 {
9503 	struct bwn_softc *sc = mac->mac_sc;
9504 	struct bwn_phy *phy = &mac->mac_phy;
9505 	struct ifnet *ifp = sc->sc_ifp;
9506 	struct ieee80211com *ic = ifp->if_l2com;
9507 	unsigned long now;
9508 	int result;
9509 
9510 	BWN_GETTIME(now);
9511 
9512 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9513 		return;
9514 	phy->nexttime = now + 2 * 1000;
9515 
9516 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9517 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9518 		return;
9519 
9520 	if (phy->recalc_txpwr != NULL) {
9521 		result = phy->recalc_txpwr(mac,
9522 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9523 		if (result == BWN_TXPWR_RES_DONE)
9524 			return;
9525 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9526 		    ("%s: fail", __func__));
9527 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9528 
9529 		ieee80211_runtask(ic, &mac->mac_txpower);
9530 	}
9531 }
9532 
9533 static uint16_t
9534 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9535 {
9536 
9537 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9538 }
9539 
9540 static uint32_t
9541 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9542 {
9543 
9544 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9545 }
9546 
9547 static void
9548 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9549 {
9550 
9551 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9552 }
9553 
9554 static void
9555 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9556 {
9557 
9558 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9559 }
9560 
9561 static int
9562 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9563 {
9564 
9565 	switch (rate) {
9566 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9567 	case 12:
9568 		return (BWN_OFDM_RATE_6MB);
9569 	case 18:
9570 		return (BWN_OFDM_RATE_9MB);
9571 	case 24:
9572 		return (BWN_OFDM_RATE_12MB);
9573 	case 36:
9574 		return (BWN_OFDM_RATE_18MB);
9575 	case 48:
9576 		return (BWN_OFDM_RATE_24MB);
9577 	case 72:
9578 		return (BWN_OFDM_RATE_36MB);
9579 	case 96:
9580 		return (BWN_OFDM_RATE_48MB);
9581 	case 108:
9582 		return (BWN_OFDM_RATE_54MB);
9583 	/* CCK rates (NB: not IEEE std, device-specific) */
9584 	case 2:
9585 		return (BWN_CCK_RATE_1MB);
9586 	case 4:
9587 		return (BWN_CCK_RATE_2MB);
9588 	case 11:
9589 		return (BWN_CCK_RATE_5MB);
9590 	case 22:
9591 		return (BWN_CCK_RATE_11MB);
9592 	}
9593 
9594 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9595 	return (BWN_CCK_RATE_1MB);
9596 }
9597 
9598 static int
9599 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9600     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9601 {
9602 	const struct bwn_phy *phy = &mac->mac_phy;
9603 	struct bwn_softc *sc = mac->mac_sc;
9604 	struct ieee80211_frame *wh;
9605 	struct ieee80211_frame *protwh;
9606 	struct ieee80211_frame_cts *cts;
9607 	struct ieee80211_frame_rts *rts;
9608 	const struct ieee80211_txparam *tp;
9609 	struct ieee80211vap *vap = ni->ni_vap;
9610 	struct ifnet *ifp = sc->sc_ifp;
9611 	struct ieee80211com *ic = ifp->if_l2com;
9612 	struct mbuf *mprot;
9613 	unsigned int len;
9614 	uint32_t macctl = 0;
9615 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9616 	uint16_t phyctl = 0;
9617 	uint8_t rate, rate_fb;
9618 
9619 	wh = mtod(m, struct ieee80211_frame *);
9620 	memset(txhdr, 0, sizeof(*txhdr));
9621 
9622 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9623 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9624 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9625 
9626 	/*
9627 	 * Find TX rate
9628 	 */
9629 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9630 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9631 		rate = rate_fb = tp->mgmtrate;
9632 	else if (ismcast)
9633 		rate = rate_fb = tp->mcastrate;
9634 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9635 		rate = rate_fb = tp->ucastrate;
9636 	else {
9637 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9638 		rate = ni->ni_txrate;
9639 
9640 		if (rix > 0)
9641 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9642 			    IEEE80211_RATE_VAL;
9643 		else
9644 			rate_fb = rate;
9645 	}
9646 
9647 	sc->sc_tx_rate = rate;
9648 
9649 	rate = bwn_ieeerate2hwrate(sc, rate);
9650 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9651 
9652 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9653 	    bwn_plcp_getcck(rate);
9654 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9655 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9656 
9657 	if ((rate_fb == rate) ||
9658 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9659 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9660 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9661 	else
9662 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9663 		    m->m_pkthdr.len, rate, isshort);
9664 
9665 	/* XXX TX encryption */
9666 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9667 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9668 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9669 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9670 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9671 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9672 
9673 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9674 	    BWN_TX_EFT_FB_CCK;
9675 	txhdr->chan = phy->chan;
9676 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9677 	    BWN_TX_PHY_ENC_CCK;
9678 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9679 	     rate == BWN_CCK_RATE_11MB))
9680 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9681 
9682 	/* XXX TX antenna selection */
9683 
9684 	switch (bwn_antenna_sanitize(mac, 0)) {
9685 	case 0:
9686 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9687 		break;
9688 	case 1:
9689 		phyctl |= BWN_TX_PHY_ANT0;
9690 		break;
9691 	case 2:
9692 		phyctl |= BWN_TX_PHY_ANT1;
9693 		break;
9694 	case 3:
9695 		phyctl |= BWN_TX_PHY_ANT2;
9696 		break;
9697 	case 4:
9698 		phyctl |= BWN_TX_PHY_ANT3;
9699 		break;
9700 	default:
9701 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9702 	}
9703 
9704 	if (!ismcast)
9705 		macctl |= BWN_TX_MAC_ACK;
9706 
9707 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9708 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9709 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9710 		macctl |= BWN_TX_MAC_LONGFRAME;
9711 
9712 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9713 		/* XXX RTS rate is always 1MB??? */
9714 		rts_rate = BWN_CCK_RATE_1MB;
9715 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9716 
9717 		protdur = ieee80211_compute_duration(ic->ic_rt,
9718 		    m->m_pkthdr.len, rate, isshort) +
9719 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9720 
9721 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9722 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9723 			    (txhdr->body.old.rts_frame) :
9724 			    (txhdr->body.new.rts_frame));
9725 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9726 			    protdur);
9727 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9728 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9729 			    mprot->m_pkthdr.len);
9730 			m_freem(mprot);
9731 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9732 			len = sizeof(struct ieee80211_frame_cts);
9733 		} else {
9734 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9735 			    (txhdr->body.old.rts_frame) :
9736 			    (txhdr->body.new.rts_frame));
9737 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9738 			    isshort);
9739 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9740 			    wh->i_addr2, protdur);
9741 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9742 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9743 			    mprot->m_pkthdr.len);
9744 			m_freem(mprot);
9745 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9746 			len = sizeof(struct ieee80211_frame_rts);
9747 		}
9748 		len += IEEE80211_CRC_LEN;
9749 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9750 		    &txhdr->body.old.rts_plcp :
9751 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9752 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9753 		    rts_rate_fb);
9754 
9755 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9756 		    (&txhdr->body.old.rts_frame) :
9757 		    (&txhdr->body.new.rts_frame));
9758 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9759 
9760 		if (BWN_ISOFDMRATE(rts_rate)) {
9761 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9762 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9763 		} else {
9764 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9765 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9766 		}
9767 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9768 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9769 	}
9770 
9771 	if (BWN_ISOLDFMT(mac))
9772 		txhdr->body.old.cookie = htole16(cookie);
9773 	else
9774 		txhdr->body.new.cookie = htole16(cookie);
9775 
9776 	txhdr->macctl = htole32(macctl);
9777 	txhdr->phyctl = htole16(phyctl);
9778 
9779 	/*
9780 	 * TX radio tap
9781 	 */
9782 	if (ieee80211_radiotap_active_vap(vap)) {
9783 		sc->sc_tx_th.wt_flags = 0;
9784 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9785 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9786 		if (isshort &&
9787 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9788 		     rate == BWN_CCK_RATE_11MB))
9789 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9790 		sc->sc_tx_th.wt_rate = rate;
9791 
9792 		ieee80211_radiotap_tx(vap, m);
9793 	}
9794 
9795 	return (0);
9796 }
9797 
9798 static void
9799 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9800     const uint8_t rate)
9801 {
9802 	uint32_t d, plen;
9803 	uint8_t *raw = plcp->o.raw;
9804 
9805 	if (BWN_ISOFDMRATE(rate)) {
9806 		d = bwn_plcp_getofdm(rate);
9807 		KASSERT(!(octets & 0xf000),
9808 		    ("%s:%d: fail", __func__, __LINE__));
9809 		d |= (octets << 5);
9810 		plcp->o.data = htole32(d);
9811 	} else {
9812 		plen = octets * 16 / rate;
9813 		if ((octets * 16 % rate) > 0) {
9814 			plen++;
9815 			if ((rate == BWN_CCK_RATE_11MB)
9816 			    && ((octets * 8 % 11) < 4)) {
9817 				raw[1] = 0x84;
9818 			} else
9819 				raw[1] = 0x04;
9820 		} else
9821 			raw[1] = 0x04;
9822 		plcp->o.data |= htole32(plen << 16);
9823 		raw[0] = bwn_plcp_getcck(rate);
9824 	}
9825 }
9826 
9827 static uint8_t
9828 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9829 {
9830 	struct bwn_softc *sc = mac->mac_sc;
9831 	uint8_t mask;
9832 
9833 	if (n == 0)
9834 		return (0);
9835 	if (mac->mac_phy.gmode)
9836 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9837 	else
9838 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9839 	if (!(mask & (1 << (n - 1))))
9840 		return (0);
9841 	return (n);
9842 }
9843 
9844 static uint8_t
9845 bwn_get_fbrate(uint8_t bitrate)
9846 {
9847 	switch (bitrate) {
9848 	case BWN_CCK_RATE_1MB:
9849 		return (BWN_CCK_RATE_1MB);
9850 	case BWN_CCK_RATE_2MB:
9851 		return (BWN_CCK_RATE_1MB);
9852 	case BWN_CCK_RATE_5MB:
9853 		return (BWN_CCK_RATE_2MB);
9854 	case BWN_CCK_RATE_11MB:
9855 		return (BWN_CCK_RATE_5MB);
9856 	case BWN_OFDM_RATE_6MB:
9857 		return (BWN_CCK_RATE_5MB);
9858 	case BWN_OFDM_RATE_9MB:
9859 		return (BWN_OFDM_RATE_6MB);
9860 	case BWN_OFDM_RATE_12MB:
9861 		return (BWN_OFDM_RATE_9MB);
9862 	case BWN_OFDM_RATE_18MB:
9863 		return (BWN_OFDM_RATE_12MB);
9864 	case BWN_OFDM_RATE_24MB:
9865 		return (BWN_OFDM_RATE_18MB);
9866 	case BWN_OFDM_RATE_36MB:
9867 		return (BWN_OFDM_RATE_24MB);
9868 	case BWN_OFDM_RATE_48MB:
9869 		return (BWN_OFDM_RATE_36MB);
9870 	case BWN_OFDM_RATE_54MB:
9871 		return (BWN_OFDM_RATE_48MB);
9872 	}
9873 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9874 	return (0);
9875 }
9876 
9877 static uint32_t
9878 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9879     uint32_t ctl, const void *_data, int len)
9880 {
9881 	struct bwn_softc *sc = mac->mac_sc;
9882 	uint32_t value = 0;
9883 	const uint8_t *data = _data;
9884 
9885 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9886 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9887 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9888 
9889 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9890 	    tq->tq_base + BWN_PIO8_TXDATA);
9891 	if (len & 3) {
9892 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9893 		    BWN_PIO8_TXCTL_24_31);
9894 		data = &(data[len - 1]);
9895 		switch (len & 3) {
9896 		case 3:
9897 			ctl |= BWN_PIO8_TXCTL_16_23;
9898 			value |= (uint32_t)(*data) << 16;
9899 			data--;
9900 		case 2:
9901 			ctl |= BWN_PIO8_TXCTL_8_15;
9902 			value |= (uint32_t)(*data) << 8;
9903 			data--;
9904 		case 1:
9905 			value |= (uint32_t)(*data);
9906 		}
9907 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9908 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9909 	}
9910 
9911 	return (ctl);
9912 }
9913 
9914 static void
9915 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9916     uint16_t offset, uint32_t value)
9917 {
9918 
9919 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9920 }
9921 
9922 static uint16_t
9923 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9924     uint16_t ctl, const void *_data, int len)
9925 {
9926 	struct bwn_softc *sc = mac->mac_sc;
9927 	const uint8_t *data = _data;
9928 
9929 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9930 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9931 
9932 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9933 	    tq->tq_base + BWN_PIO_TXDATA);
9934 	if (len & 1) {
9935 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9936 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9937 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9938 	}
9939 
9940 	return (ctl);
9941 }
9942 
9943 static uint16_t
9944 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9945     uint16_t ctl, struct mbuf *m0)
9946 {
9947 	int i, j = 0;
9948 	uint16_t data = 0;
9949 	const uint8_t *buf;
9950 	struct mbuf *m = m0;
9951 
9952 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9953 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9954 
9955 	for (; m != NULL; m = m->m_next) {
9956 		buf = mtod(m, const uint8_t *);
9957 		for (i = 0; i < m->m_len; i++) {
9958 			if (!((j++) % 2))
9959 				data |= buf[i];
9960 			else {
9961 				data |= (buf[i] << 8);
9962 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9963 				data = 0;
9964 			}
9965 		}
9966 	}
9967 	if (m0->m_pkthdr.len % 2) {
9968 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9969 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9970 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9971 	}
9972 
9973 	return (ctl);
9974 }
9975 
9976 static void
9977 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9978 {
9979 
9980 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9981 		return;
9982 	BWN_WRITE_2(mac, 0x684, 510 + time);
9983 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9984 }
9985 
9986 static struct bwn_dma_ring *
9987 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9988 {
9989 
9990 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9991 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9992 
9993 	switch (prio) {
9994 	case 3:
9995 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9996 	case 2:
9997 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9998 	case 0:
9999 		return (mac->mac_method.dma.wme[WME_AC_BE]);
10000 	case 1:
10001 		return (mac->mac_method.dma.wme[WME_AC_BK]);
10002 	}
10003 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10004 	return (NULL);
10005 }
10006 
10007 static int
10008 bwn_dma_getslot(struct bwn_dma_ring *dr)
10009 {
10010 	int slot;
10011 
10012 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10013 
10014 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10015 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10016 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10017 
10018 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10019 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10020 	dr->dr_curslot = slot;
10021 	dr->dr_usedslot++;
10022 
10023 	return (slot);
10024 }
10025 
10026 static int
10027 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10028 {
10029 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10030 	unsigned int a, b, c, d;
10031 	unsigned int avg;
10032 	uint32_t tmp;
10033 
10034 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10035 	a = tmp & 0xff;
10036 	b = (tmp >> 8) & 0xff;
10037 	c = (tmp >> 16) & 0xff;
10038 	d = (tmp >> 24) & 0xff;
10039 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10040 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10041 		return (ENOENT);
10042 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10043 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10044 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10045 
10046 	if (ofdm) {
10047 		a = (a + 32) & 0x3f;
10048 		b = (b + 32) & 0x3f;
10049 		c = (c + 32) & 0x3f;
10050 		d = (d + 32) & 0x3f;
10051 	}
10052 
10053 	avg = (a + b + c + d + 2) / 4;
10054 	if (ofdm) {
10055 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10056 		    & BWN_HF_4DB_CCK_POWERBOOST)
10057 			avg = (avg >= 13) ? (avg - 13) : 0;
10058 	}
10059 	return (avg);
10060 }
10061 
10062 static void
10063 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10064 {
10065 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10066 	int rfatt = *rfattp;
10067 	int bbatt = *bbattp;
10068 
10069 	while (1) {
10070 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10071 			break;
10072 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10073 			break;
10074 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10075 			break;
10076 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10077 			break;
10078 		if (bbatt > lo->bbatt.max) {
10079 			bbatt -= 4;
10080 			rfatt += 1;
10081 			continue;
10082 		}
10083 		if (bbatt < lo->bbatt.min) {
10084 			bbatt += 4;
10085 			rfatt -= 1;
10086 			continue;
10087 		}
10088 		if (rfatt > lo->rfatt.max) {
10089 			rfatt -= 1;
10090 			bbatt += 4;
10091 			continue;
10092 		}
10093 		if (rfatt < lo->rfatt.min) {
10094 			rfatt += 1;
10095 			bbatt -= 4;
10096 			continue;
10097 		}
10098 		break;
10099 	}
10100 
10101 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10102 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10103 }
10104 
10105 static void
10106 bwn_phy_lock(struct bwn_mac *mac)
10107 {
10108 	struct bwn_softc *sc = mac->mac_sc;
10109 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10110 
10111 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10112 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10113 
10114 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10115 		bwn_psctl(mac, BWN_PS_AWAKE);
10116 }
10117 
10118 static void
10119 bwn_phy_unlock(struct bwn_mac *mac)
10120 {
10121 	struct bwn_softc *sc = mac->mac_sc;
10122 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10123 
10124 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10125 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10126 
10127 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10128 		bwn_psctl(mac, 0);
10129 }
10130 
10131 static void
10132 bwn_rf_lock(struct bwn_mac *mac)
10133 {
10134 
10135 	BWN_WRITE_4(mac, BWN_MACCTL,
10136 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10137 	BWN_READ_4(mac, BWN_MACCTL);
10138 	DELAY(10);
10139 }
10140 
10141 static void
10142 bwn_rf_unlock(struct bwn_mac *mac)
10143 {
10144 
10145 	BWN_READ_2(mac, BWN_PHYVER);
10146 	BWN_WRITE_4(mac, BWN_MACCTL,
10147 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10148 }
10149 
10150 static struct bwn_pio_txqueue *
10151 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10152     struct bwn_pio_txpkt **pack)
10153 {
10154 	struct bwn_pio *pio = &mac->mac_method.pio;
10155 	struct bwn_pio_txqueue *tq = NULL;
10156 	unsigned int index;
10157 
10158 	switch (cookie & 0xf000) {
10159 	case 0x1000:
10160 		tq = &pio->wme[WME_AC_BK];
10161 		break;
10162 	case 0x2000:
10163 		tq = &pio->wme[WME_AC_BE];
10164 		break;
10165 	case 0x3000:
10166 		tq = &pio->wme[WME_AC_VI];
10167 		break;
10168 	case 0x4000:
10169 		tq = &pio->wme[WME_AC_VO];
10170 		break;
10171 	case 0x5000:
10172 		tq = &pio->mcast;
10173 		break;
10174 	}
10175 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10176 	if (tq == NULL)
10177 		return (NULL);
10178 	index = (cookie & 0x0fff);
10179 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10180 	if (index >= N(tq->tq_pkts))
10181 		return (NULL);
10182 	*pack = &tq->tq_pkts[index];
10183 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10184 	return (tq);
10185 }
10186 
10187 static void
10188 bwn_txpwr(void *arg, int npending)
10189 {
10190 	struct bwn_mac *mac = arg;
10191 	struct bwn_softc *sc = mac->mac_sc;
10192 
10193 	BWN_LOCK(sc);
10194 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10195 	    mac->mac_phy.set_txpwr != NULL)
10196 		mac->mac_phy.set_txpwr(mac);
10197 	BWN_UNLOCK(sc);
10198 }
10199 
10200 static void
10201 bwn_task_15s(struct bwn_mac *mac)
10202 {
10203 	uint16_t reg;
10204 
10205 	if (mac->mac_fw.opensource) {
10206 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10207 		if (reg) {
10208 			bwn_restart(mac, "fw watchdog");
10209 			return;
10210 		}
10211 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10212 	}
10213 	if (mac->mac_phy.task_15s)
10214 		mac->mac_phy.task_15s(mac);
10215 
10216 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10217 }
10218 
10219 static void
10220 bwn_task_30s(struct bwn_mac *mac)
10221 {
10222 
10223 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10224 		return;
10225 	mac->mac_noise.noi_running = 1;
10226 	mac->mac_noise.noi_nsamples = 0;
10227 
10228 	bwn_noise_gensample(mac);
10229 }
10230 
10231 static void
10232 bwn_task_60s(struct bwn_mac *mac)
10233 {
10234 
10235 	if (mac->mac_phy.task_60s)
10236 		mac->mac_phy.task_60s(mac);
10237 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10238 }
10239 
10240 static void
10241 bwn_tasks(void *arg)
10242 {
10243 	struct bwn_mac *mac = arg;
10244 	struct bwn_softc *sc = mac->mac_sc;
10245 
10246 	BWN_ASSERT_LOCKED(sc);
10247 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10248 		return;
10249 
10250 	if (mac->mac_task_state % 4 == 0)
10251 		bwn_task_60s(mac);
10252 	if (mac->mac_task_state % 2 == 0)
10253 		bwn_task_30s(mac);
10254 	bwn_task_15s(mac);
10255 
10256 	mac->mac_task_state++;
10257 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10258 }
10259 
10260 static int
10261 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10262 {
10263 	struct bwn_softc *sc = mac->mac_sc;
10264 
10265 	KASSERT(a == 0, ("not support APHY\n"));
10266 
10267 	switch (plcp->o.raw[0] & 0xf) {
10268 	case 0xb:
10269 		return (BWN_OFDM_RATE_6MB);
10270 	case 0xf:
10271 		return (BWN_OFDM_RATE_9MB);
10272 	case 0xa:
10273 		return (BWN_OFDM_RATE_12MB);
10274 	case 0xe:
10275 		return (BWN_OFDM_RATE_18MB);
10276 	case 0x9:
10277 		return (BWN_OFDM_RATE_24MB);
10278 	case 0xd:
10279 		return (BWN_OFDM_RATE_36MB);
10280 	case 0x8:
10281 		return (BWN_OFDM_RATE_48MB);
10282 	case 0xc:
10283 		return (BWN_OFDM_RATE_54MB);
10284 	}
10285 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10286 	    plcp->o.raw[0] & 0xf);
10287 	return (-1);
10288 }
10289 
10290 static int
10291 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10292 {
10293 	struct bwn_softc *sc = mac->mac_sc;
10294 
10295 	switch (plcp->o.raw[0]) {
10296 	case 0x0a:
10297 		return (BWN_CCK_RATE_1MB);
10298 	case 0x14:
10299 		return (BWN_CCK_RATE_2MB);
10300 	case 0x37:
10301 		return (BWN_CCK_RATE_5MB);
10302 	case 0x6e:
10303 		return (BWN_CCK_RATE_11MB);
10304 	}
10305 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10306 	return (-1);
10307 }
10308 
10309 static void
10310 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10311     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10312     int rssi, int noise)
10313 {
10314 	struct bwn_softc *sc = mac->mac_sc;
10315 	const struct ieee80211_frame_min *wh;
10316 	uint64_t tsf;
10317 	uint16_t low_mactime_now;
10318 
10319 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10320 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10321 
10322 	wh = mtod(m, const struct ieee80211_frame_min *);
10323 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10324 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10325 
10326 	bwn_tsf_read(mac, &tsf);
10327 	low_mactime_now = tsf;
10328 	tsf = tsf & ~0xffffULL;
10329 	tsf += le16toh(rxhdr->mac_time);
10330 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10331 		tsf -= 0x10000;
10332 
10333 	sc->sc_rx_th.wr_tsf = tsf;
10334 	sc->sc_rx_th.wr_rate = rate;
10335 	sc->sc_rx_th.wr_antsignal = rssi;
10336 	sc->sc_rx_th.wr_antnoise = noise;
10337 }
10338 
10339 static void
10340 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10341 {
10342 	uint32_t low, high;
10343 
10344 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10345 	    ("%s:%d: fail", __func__, __LINE__));
10346 
10347 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10348 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10349 	*tsf = high;
10350 	*tsf <<= 32;
10351 	*tsf |= low;
10352 }
10353 
10354 static int
10355 bwn_dma_attach(struct bwn_mac *mac)
10356 {
10357 	struct bwn_dma *dma = &mac->mac_method.dma;
10358 	struct bwn_softc *sc = mac->mac_sc;
10359 	bus_addr_t lowaddr = 0;
10360 	int error;
10361 
10362 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10363 		return (0);
10364 
10365 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10366 
10367 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10368 
10369 	dma->dmatype = bwn_dma_gettype(mac);
10370 	if (dma->dmatype == BWN_DMA_30BIT)
10371 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10372 	else if (dma->dmatype == BWN_DMA_32BIT)
10373 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10374 	else
10375 		lowaddr = BUS_SPACE_MAXADDR;
10376 
10377 	/*
10378 	 * Create top level DMA tag
10379 	 */
10380 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10381 			       BWN_ALIGN, 0,		/* alignment, bounds */
10382 			       lowaddr,			/* lowaddr */
10383 			       BUS_SPACE_MAXADDR,	/* highaddr */
10384 			       NULL, NULL,		/* filter, filterarg */
10385 			       BUS_SPACE_MAXSIZE,	/* maxsize */
10386 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10387 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10388 			       0,			/* flags */
10389 			       NULL, NULL,		/* lockfunc, lockarg */
10390 			       &dma->parent_dtag);
10391 	if (error) {
10392 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10393 		return (error);
10394 	}
10395 
10396 	/*
10397 	 * Create TX/RX mbuf DMA tag
10398 	 */
10399 	error = bus_dma_tag_create(dma->parent_dtag,
10400 				1,
10401 				0,
10402 				BUS_SPACE_MAXADDR,
10403 				BUS_SPACE_MAXADDR,
10404 				NULL, NULL,
10405 				MCLBYTES,
10406 				1,
10407 				BUS_SPACE_MAXSIZE_32BIT,
10408 				0,
10409 				NULL, NULL,
10410 				&dma->rxbuf_dtag);
10411 	if (error) {
10412 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10413 		goto fail0;
10414 	}
10415 	error = bus_dma_tag_create(dma->parent_dtag,
10416 				1,
10417 				0,
10418 				BUS_SPACE_MAXADDR,
10419 				BUS_SPACE_MAXADDR,
10420 				NULL, NULL,
10421 				MCLBYTES,
10422 				1,
10423 				BUS_SPACE_MAXSIZE_32BIT,
10424 				0,
10425 				NULL, NULL,
10426 				&dma->txbuf_dtag);
10427 	if (error) {
10428 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10429 		goto fail1;
10430 	}
10431 
10432 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10433 	if (!dma->wme[WME_AC_BK])
10434 		goto fail2;
10435 
10436 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10437 	if (!dma->wme[WME_AC_BE])
10438 		goto fail3;
10439 
10440 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10441 	if (!dma->wme[WME_AC_VI])
10442 		goto fail4;
10443 
10444 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10445 	if (!dma->wme[WME_AC_VO])
10446 		goto fail5;
10447 
10448 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10449 	if (!dma->mcast)
10450 		goto fail6;
10451 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10452 	if (!dma->rx)
10453 		goto fail7;
10454 
10455 	return (error);
10456 
10457 fail7:	bwn_dma_ringfree(&dma->mcast);
10458 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10459 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10460 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10461 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10462 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10463 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10464 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10465 	return (error);
10466 }
10467 
10468 static struct bwn_dma_ring *
10469 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10470     uint16_t cookie, int *slot)
10471 {
10472 	struct bwn_dma *dma = &mac->mac_method.dma;
10473 	struct bwn_dma_ring *dr;
10474 	struct bwn_softc *sc = mac->mac_sc;
10475 
10476 	BWN_ASSERT_LOCKED(mac->mac_sc);
10477 
10478 	switch (cookie & 0xf000) {
10479 	case 0x1000:
10480 		dr = dma->wme[WME_AC_BK];
10481 		break;
10482 	case 0x2000:
10483 		dr = dma->wme[WME_AC_BE];
10484 		break;
10485 	case 0x3000:
10486 		dr = dma->wme[WME_AC_VI];
10487 		break;
10488 	case 0x4000:
10489 		dr = dma->wme[WME_AC_VO];
10490 		break;
10491 	case 0x5000:
10492 		dr = dma->mcast;
10493 		break;
10494 	default:
10495 		dr = NULL;
10496 		KASSERT(0 == 1,
10497 		    ("invalid cookie value %d", cookie & 0xf000));
10498 	}
10499 	*slot = (cookie & 0x0fff);
10500 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10501 		/*
10502 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10503 		 * that it occurs events which have same H/W sequence numbers.
10504 		 * When it's occurred just prints a WARNING msgs and ignores.
10505 		 */
10506 		KASSERT(status->seq == dma->lastseq,
10507 		    ("%s:%d: fail", __func__, __LINE__));
10508 		device_printf(sc->sc_dev,
10509 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10510 		    dr->dr_numslots);
10511 		return (NULL);
10512 	}
10513 	dma->lastseq = status->seq;
10514 	return (dr);
10515 }
10516 
10517 static void
10518 bwn_dma_stop(struct bwn_mac *mac)
10519 {
10520 	struct bwn_dma *dma;
10521 
10522 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10523 		return;
10524 	dma = &mac->mac_method.dma;
10525 
10526 	bwn_dma_ringstop(&dma->rx);
10527 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10528 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10529 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10530 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10531 	bwn_dma_ringstop(&dma->mcast);
10532 }
10533 
10534 static void
10535 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10536 {
10537 
10538 	if (dr == NULL)
10539 		return;
10540 
10541 	bwn_dma_cleanup(*dr);
10542 }
10543 
10544 static void
10545 bwn_pio_stop(struct bwn_mac *mac)
10546 {
10547 	struct bwn_pio *pio;
10548 
10549 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10550 		return;
10551 	pio = &mac->mac_method.pio;
10552 
10553 	bwn_destroy_queue_tx(&pio->mcast);
10554 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10555 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10556 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10557 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10558 }
10559 
10560 static void
10561 bwn_led_attach(struct bwn_mac *mac)
10562 {
10563 	struct bwn_softc *sc = mac->mac_sc;
10564 	const uint8_t *led_act = NULL;
10565 	uint16_t val[BWN_LED_MAX];
10566 	int i;
10567 
10568 	sc->sc_led_idle = (2350 * hz) / 1000;
10569 	sc->sc_led_blink = 1;
10570 
10571 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10572 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10573 		    bwn_vendor_led_act[i].vid) {
10574 			led_act = bwn_vendor_led_act[i].led_act;
10575 			break;
10576 		}
10577 	}
10578 	if (led_act == NULL)
10579 		led_act = bwn_default_led_act;
10580 
10581 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10582 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10583 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10584 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10585 
10586 	for (i = 0; i < BWN_LED_MAX; ++i) {
10587 		struct bwn_led *led = &sc->sc_leds[i];
10588 
10589 		if (val[i] == 0xff) {
10590 			led->led_act = led_act[i];
10591 		} else {
10592 			if (val[i] & BWN_LED_ACT_LOW)
10593 				led->led_flags |= BWN_LED_F_ACTLOW;
10594 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10595 		}
10596 		led->led_mask = (1 << i);
10597 
10598 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10599 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10600 		    led->led_act == BWN_LED_ACT_BLINK) {
10601 			led->led_flags |= BWN_LED_F_BLINK;
10602 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10603 				led->led_flags |= BWN_LED_F_POLLABLE;
10604 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10605 				led->led_flags |= BWN_LED_F_SLOW;
10606 
10607 			if (sc->sc_blink_led == NULL) {
10608 				sc->sc_blink_led = led;
10609 				if (led->led_flags & BWN_LED_F_SLOW)
10610 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10611 			}
10612 		}
10613 
10614 		DPRINTF(sc, BWN_DEBUG_LED,
10615 		    "%dth led, act %d, lowact %d\n", i,
10616 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10617 	}
10618 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10619 }
10620 
10621 static __inline uint16_t
10622 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10623 {
10624 
10625 	if (led->led_flags & BWN_LED_F_ACTLOW)
10626 		on = !on;
10627 	if (on)
10628 		val |= led->led_mask;
10629 	else
10630 		val &= ~led->led_mask;
10631 	return val;
10632 }
10633 
10634 static void
10635 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10636 {
10637 	struct bwn_softc *sc = mac->mac_sc;
10638 	struct ifnet *ifp = sc->sc_ifp;
10639 	struct ieee80211com *ic = ifp->if_l2com;
10640 	uint16_t val;
10641 	int i;
10642 
10643 	if (nstate == IEEE80211_S_INIT) {
10644 		callout_stop(&sc->sc_led_blink_ch);
10645 		sc->sc_led_blinking = 0;
10646 	}
10647 
10648 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10649 		return;
10650 
10651 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10652 	for (i = 0; i < BWN_LED_MAX; ++i) {
10653 		struct bwn_led *led = &sc->sc_leds[i];
10654 		int on;
10655 
10656 		if (led->led_act == BWN_LED_ACT_UNKN ||
10657 		    led->led_act == BWN_LED_ACT_NULL)
10658 			continue;
10659 
10660 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10661 		    nstate != IEEE80211_S_INIT)
10662 			continue;
10663 
10664 		switch (led->led_act) {
10665 		case BWN_LED_ACT_ON:    /* Always on */
10666 			on = 1;
10667 			break;
10668 		case BWN_LED_ACT_OFF:   /* Always off */
10669 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10670 			on = 0;
10671 			break;
10672 		default:
10673 			on = 1;
10674 			switch (nstate) {
10675 			case IEEE80211_S_INIT:
10676 				on = 0;
10677 				break;
10678 			case IEEE80211_S_RUN:
10679 				if (led->led_act == BWN_LED_ACT_11G &&
10680 				    ic->ic_curmode != IEEE80211_MODE_11G)
10681 					on = 0;
10682 				break;
10683 			default:
10684 				if (led->led_act == BWN_LED_ACT_ASSOC)
10685 					on = 0;
10686 				break;
10687 			}
10688 			break;
10689 		}
10690 
10691 		val = bwn_led_onoff(led, val, on);
10692 	}
10693 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10694 }
10695 
10696 static void
10697 bwn_led_event(struct bwn_mac *mac, int event)
10698 {
10699 	struct bwn_softc *sc = mac->mac_sc;
10700 	struct bwn_led *led = sc->sc_blink_led;
10701 	int rate;
10702 
10703 	if (event == BWN_LED_EVENT_POLL) {
10704 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10705 			return;
10706 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10707 			return;
10708 	}
10709 
10710 	sc->sc_led_ticks = ticks;
10711 	if (sc->sc_led_blinking)
10712 		return;
10713 
10714 	switch (event) {
10715 	case BWN_LED_EVENT_RX:
10716 		rate = sc->sc_rx_rate;
10717 		break;
10718 	case BWN_LED_EVENT_TX:
10719 		rate = sc->sc_tx_rate;
10720 		break;
10721 	case BWN_LED_EVENT_POLL:
10722 		rate = 0;
10723 		break;
10724 	default:
10725 		panic("unknown LED event %d\n", event);
10726 		break;
10727 	}
10728 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10729 	    bwn_led_duration[rate].off_dur);
10730 }
10731 
10732 static void
10733 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10734 {
10735 	struct bwn_softc *sc = mac->mac_sc;
10736 	struct bwn_led *led = sc->sc_blink_led;
10737 	uint16_t val;
10738 
10739 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10740 	val = bwn_led_onoff(led, val, 1);
10741 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10742 
10743 	if (led->led_flags & BWN_LED_F_SLOW) {
10744 		BWN_LED_SLOWDOWN(on_dur);
10745 		BWN_LED_SLOWDOWN(off_dur);
10746 	}
10747 
10748 	sc->sc_led_blinking = 1;
10749 	sc->sc_led_blink_offdur = off_dur;
10750 
10751 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10752 }
10753 
10754 static void
10755 bwn_led_blink_next(void *arg)
10756 {
10757 	struct bwn_mac *mac = arg;
10758 	struct bwn_softc *sc = mac->mac_sc;
10759 	uint16_t val;
10760 
10761 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10762 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10763 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10764 
10765 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10766 	    bwn_led_blink_end, mac);
10767 }
10768 
10769 static void
10770 bwn_led_blink_end(void *arg)
10771 {
10772 	struct bwn_mac *mac = arg;
10773 	struct bwn_softc *sc = mac->mac_sc;
10774 
10775 	sc->sc_led_blinking = 0;
10776 }
10777 
10778 static int
10779 bwn_suspend(device_t dev)
10780 {
10781 	struct bwn_softc *sc = device_get_softc(dev);
10782 
10783 	bwn_stop(sc, 1);
10784 	return (0);
10785 }
10786 
10787 static int
10788 bwn_resume(device_t dev)
10789 {
10790 	struct bwn_softc *sc = device_get_softc(dev);
10791 	struct ifnet *ifp = sc->sc_ifp;
10792 
10793 	if (ifp->if_flags & IFF_UP)
10794 		bwn_init(sc);
10795 	return (0);
10796 }
10797 
10798 static void
10799 bwn_rfswitch(void *arg)
10800 {
10801 	struct bwn_softc *sc = arg;
10802 	struct bwn_mac *mac = sc->sc_curmac;
10803 	int cur = 0, prev = 0;
10804 
10805 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10806 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10807 
10808 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10809 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10810 			& BWN_RF_HWENABLED_HI_MASK))
10811 			cur = 1;
10812 	} else {
10813 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10814 		    & BWN_RF_HWENABLED_LO_MASK)
10815 			cur = 1;
10816 	}
10817 
10818 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10819 		prev = 1;
10820 
10821 	if (cur != prev) {
10822 		if (cur)
10823 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10824 		else
10825 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10826 
10827 		device_printf(sc->sc_dev,
10828 		    "status of RF switch is changed to %s\n",
10829 		    cur ? "ON" : "OFF");
10830 		if (cur != mac->mac_phy.rf_on) {
10831 			if (cur)
10832 				bwn_rf_turnon(mac);
10833 			else
10834 				bwn_rf_turnoff(mac);
10835 		}
10836 	}
10837 
10838 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10839 }
10840 
10841 static void
10842 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10843 {
10844 	struct bwn_phy *phy = &mac->mac_phy;
10845 	struct bwn_phy_lp *plp = &phy->phy_lp;
10846 
10847 	plp->plp_antenna = BWN_ANT_DEFAULT;
10848 }
10849 
10850 static int
10851 bwn_phy_lp_init(struct bwn_mac *mac)
10852 {
10853 	static const struct bwn_stxtable tables[] = {
10854 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10855 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10856 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10857 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10858 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10859 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10860 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10861 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10862 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10863 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10864 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10865 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10866 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10867 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10868 		{ 2, 11, 0x40, 0, 0x0f }
10869 	};
10870 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10871 	struct bwn_softc *sc = mac->mac_sc;
10872 	const struct bwn_stxtable *st;
10873 	struct ifnet *ifp = sc->sc_ifp;
10874 	struct ieee80211com *ic = ifp->if_l2com;
10875 	int i, error;
10876 	uint16_t tmp;
10877 
10878 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10879 	bwn_phy_lp_bbinit(mac);
10880 
10881 	/* initialize RF */
10882 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10883 	DELAY(1);
10884 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10885 	DELAY(1);
10886 
10887 	if (mac->mac_phy.rf_ver == 0x2062)
10888 		bwn_phy_lp_b2062_init(mac);
10889 	else {
10890 		bwn_phy_lp_b2063_init(mac);
10891 
10892 		/* synchronize stx table. */
10893 		for (i = 0; i < N(tables); i++) {
10894 			st = &tables[i];
10895 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10896 			tmp >>= st->st_rfshift;
10897 			tmp <<= st->st_physhift;
10898 			BWN_PHY_SETMASK(mac,
10899 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10900 			    ~(st->st_mask << st->st_physhift), tmp);
10901 		}
10902 
10903 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10904 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10905 	}
10906 
10907 	/* calibrate RC */
10908 	if (mac->mac_phy.rev >= 2)
10909 		bwn_phy_lp_rxcal_r2(mac);
10910 	else if (!plp->plp_rccap) {
10911 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10912 			bwn_phy_lp_rccal_r12(mac);
10913 	} else
10914 		bwn_phy_lp_set_rccap(mac);
10915 
10916 	error = bwn_phy_lp_switch_channel(mac, 7);
10917 	if (error)
10918 		device_printf(sc->sc_dev,
10919 		    "failed to change channel 7 (%d)\n", error);
10920 	bwn_phy_lp_txpctl_init(mac);
10921 	bwn_phy_lp_calib(mac);
10922 	return (0);
10923 }
10924 
10925 static uint16_t
10926 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10927 {
10928 
10929 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10930 	return (BWN_READ_2(mac, BWN_PHYDATA));
10931 }
10932 
10933 static void
10934 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10935 {
10936 
10937 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10938 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10939 }
10940 
10941 static void
10942 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10943     uint16_t set)
10944 {
10945 
10946 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10947 	BWN_WRITE_2(mac, BWN_PHYDATA,
10948 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10949 }
10950 
10951 static uint16_t
10952 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10953 {
10954 
10955 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10956 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10957 		reg |= 0x100;
10958 	if (mac->mac_phy.rev >= 2)
10959 		reg |= 0x200;
10960 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10961 	return BWN_READ_2(mac, BWN_RFDATALO);
10962 }
10963 
10964 static void
10965 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10966 {
10967 
10968 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10969 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10970 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10971 }
10972 
10973 static void
10974 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10975 {
10976 
10977 	if (on) {
10978 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10979 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10980 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10981 		return;
10982 	}
10983 
10984 	if (mac->mac_phy.rev >= 2) {
10985 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10986 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10987 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10988 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10989 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10990 		return;
10991 	}
10992 
10993 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10994 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10995 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10996 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10997 }
10998 
10999 static int
11000 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11001 {
11002 	struct bwn_phy *phy = &mac->mac_phy;
11003 	struct bwn_phy_lp *plp = &phy->phy_lp;
11004 	int error;
11005 
11006 	if (phy->rf_ver == 0x2063) {
11007 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11008 		if (error)
11009 			return (error);
11010 	} else {
11011 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11012 		if (error)
11013 			return (error);
11014 		bwn_phy_lp_set_anafilter(mac, chan);
11015 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11016 	}
11017 
11018 	plp->plp_chan = chan;
11019 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11020 	return (0);
11021 }
11022 
11023 static uint32_t
11024 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11025 {
11026 	struct bwn_softc *sc = mac->mac_sc;
11027 	struct ifnet *ifp = sc->sc_ifp;
11028 	struct ieee80211com *ic = ifp->if_l2com;
11029 
11030 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11031 }
11032 
11033 static void
11034 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11035 {
11036 	struct bwn_phy *phy = &mac->mac_phy;
11037 	struct bwn_phy_lp *plp = &phy->phy_lp;
11038 
11039 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11040 		return;
11041 
11042 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11043 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11044 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11045 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11046 	plp->plp_antenna = antenna;
11047 }
11048 
11049 static void
11050 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11051 {
11052 
11053 	bwn_phy_lp_calib(mac);
11054 }
11055 
11056 static void
11057 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11058 {
11059 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11060 	struct bwn_softc *sc = mac->mac_sc;
11061 	struct ifnet *ifp = sc->sc_ifp;
11062 	struct ieee80211com *ic = ifp->if_l2com;
11063 
11064 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11065 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11066 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11067 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11068 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11069 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11070 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11071 		return;
11072 	}
11073 
11074 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11075 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11076 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11077 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11078 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11079 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11080 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11081 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11082 }
11083 
11084 static void
11085 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11086 {
11087 
11088 	bwn_phy_lp_tblinit(mac);
11089 	if (mac->mac_phy.rev >= 2)
11090 		bwn_phy_lp_bbinit_r2(mac);
11091 	else
11092 		bwn_phy_lp_bbinit_r01(mac);
11093 }
11094 
11095 static void
11096 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11097 {
11098 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11099 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11100 	struct bwn_softc *sc = mac->mac_sc;
11101 	struct ifnet *ifp = sc->sc_ifp;
11102 	struct ieee80211com *ic = ifp->if_l2com;
11103 
11104 	bwn_phy_lp_set_txgain(mac,
11105 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11106 	bwn_phy_lp_set_bbmult(mac, 150);
11107 }
11108 
11109 static void
11110 bwn_phy_lp_calib(struct bwn_mac *mac)
11111 {
11112 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11113 	struct bwn_softc *sc = mac->mac_sc;
11114 	struct ifnet *ifp = sc->sc_ifp;
11115 	struct ieee80211com *ic = ifp->if_l2com;
11116 	const struct bwn_rxcompco *rc = NULL;
11117 	struct bwn_txgain ogain;
11118 	int i, omode, oafeovr, orf, obbmult;
11119 	uint8_t mode, fc = 0;
11120 
11121 	if (plp->plp_chanfullcal != plp->plp_chan) {
11122 		plp->plp_chanfullcal = plp->plp_chan;
11123 		fc = 1;
11124 	}
11125 
11126 	bwn_mac_suspend(mac);
11127 
11128 	/* BlueTooth Coexistance Override */
11129 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11130 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11131 
11132 	if (mac->mac_phy.rev >= 2)
11133 		bwn_phy_lp_digflt_save(mac);
11134 	bwn_phy_lp_get_txpctlmode(mac);
11135 	mode = plp->plp_txpctlmode;
11136 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11137 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11138 		bwn_phy_lp_bugfix(mac);
11139 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11140 		bwn_phy_lp_get_txpctlmode(mac);
11141 		omode = plp->plp_txpctlmode;
11142 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11143 		if (oafeovr)
11144 			ogain = bwn_phy_lp_get_txgain(mac);
11145 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11146 		obbmult = bwn_phy_lp_get_bbmult(mac);
11147 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11148 		if (oafeovr)
11149 			bwn_phy_lp_set_txgain(mac, &ogain);
11150 		bwn_phy_lp_set_bbmult(mac, obbmult);
11151 		bwn_phy_lp_set_txpctlmode(mac, omode);
11152 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11153 	}
11154 	bwn_phy_lp_set_txpctlmode(mac, mode);
11155 	if (mac->mac_phy.rev >= 2)
11156 		bwn_phy_lp_digflt_restore(mac);
11157 
11158 	/* do RX IQ Calculation; assumes that noise is true. */
11159 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11160 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11161 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11162 				rc = &bwn_rxcompco_5354[i];
11163 		}
11164 	} else if (mac->mac_phy.rev >= 2)
11165 		rc = &bwn_rxcompco_r2;
11166 	else {
11167 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11168 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11169 				rc = &bwn_rxcompco_r12[i];
11170 		}
11171 	}
11172 	if (rc == NULL)
11173 		goto fail;
11174 
11175 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11176 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11177 
11178 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11179 
11180 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11181 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11182 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11183 	} else {
11184 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11185 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11186 	}
11187 
11188 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11189 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11190 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11191 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11192 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11193 	bwn_phy_lp_set_deaf(mac, 0);
11194 	/* XXX no checking return value? */
11195 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11196 	bwn_phy_lp_clear_deaf(mac, 0);
11197 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11198 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11199 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11200 
11201 	/* disable RX GAIN override. */
11202 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11203 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11204 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11205 	if (mac->mac_phy.rev >= 2) {
11206 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11207 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11208 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11209 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11210 		}
11211 	} else {
11212 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11213 	}
11214 
11215 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11216 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11217 fail:
11218 	bwn_mac_enable(mac);
11219 }
11220 
11221 static void
11222 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11223 {
11224 
11225 	if (on) {
11226 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11227 		return;
11228 	}
11229 
11230 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11231 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11232 }
11233 
11234 static int
11235 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11236 {
11237 	static const struct bwn_b206x_chan *bc = NULL;
11238 	struct bwn_softc *sc = mac->mac_sc;
11239 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11240 	    tmp[6];
11241 	uint16_t old, scale, tmp16;
11242 	int i, div;
11243 
11244 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11245 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11246 			bc = &bwn_b2063_chantable[i];
11247 			break;
11248 		}
11249 	}
11250 	if (bc == NULL)
11251 		return (EINVAL);
11252 
11253 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11254 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11255 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11256 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11257 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11258 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11259 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11260 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11261 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11262 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11263 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11264 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11265 
11266 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11267 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11268 
11269 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11270 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11271 	freqref = freqxtal * 3;
11272 	div = (freqxtal <= 26000000 ? 1 : 2);
11273 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11274 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11275 		999999) / 1000000) + 1;
11276 
11277 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11278 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11279 	    0xfff8, timeout >> 2);
11280 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11281 	    0xff9f,timeout << 5);
11282 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11283 
11284 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11285 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11286 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11287 
11288 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11289 	    (timeoutref + 1)) - 1;
11290 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11291 	    0xf0, count >> 8);
11292 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11293 
11294 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11295 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11296 	while (tmp[1] >= freqref) {
11297 		tmp[0]++;
11298 		tmp[1] -= freqref;
11299 	}
11300 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11301 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11302 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11303 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11304 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11305 
11306 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11307 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11308 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11309 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11310 
11311 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11312 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11313 
11314 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11315 		scale = 1;
11316 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11317 	} else {
11318 		scale = 0;
11319 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11320 	}
11321 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11322 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11323 
11324 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11325 	    (scale + 1);
11326 	if (tmp[5] > 150)
11327 		tmp[5] = 0;
11328 
11329 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11330 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11331 
11332 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11333 	if (freqxtal > 26000000)
11334 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11335 	else
11336 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11337 
11338 	if (val[0] == 45)
11339 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11340 	else
11341 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11342 
11343 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11344 	DELAY(1);
11345 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11346 
11347 	/* VCO Calibration */
11348 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11349 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11350 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11351 	DELAY(1);
11352 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11353 	DELAY(1);
11354 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11355 	DELAY(1);
11356 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11357 	DELAY(300);
11358 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11359 
11360 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11361 	return (0);
11362 }
11363 
11364 static int
11365 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11366 {
11367 	struct bwn_softc *sc = mac->mac_sc;
11368 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11369 	const struct bwn_b206x_chan *bc = NULL;
11370 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11371 	uint32_t tmp[9];
11372 	int i;
11373 
11374 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11375 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11376 			bc = &bwn_b2062_chantable[i];
11377 			break;
11378 		}
11379 	}
11380 
11381 	if (bc == NULL)
11382 		return (EINVAL);
11383 
11384 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11385 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11386 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11387 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11388 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11389 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11390 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11391 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11392 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11393 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11394 
11395 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11396 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11397 	bwn_phy_lp_b2062_reset_pllbias(mac);
11398 	tmp[0] = freqxtal / 1000;
11399 	tmp[1] = plp->plp_div * 1000;
11400 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11401 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11402 		tmp[2] *= 2;
11403 	tmp[3] = 48 * tmp[0];
11404 	tmp[5] = tmp[2] / tmp[3];
11405 	tmp[6] = tmp[2] % tmp[3];
11406 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11407 	tmp[4] = tmp[6] * 0x100;
11408 	tmp[5] = tmp[4] / tmp[3];
11409 	tmp[6] = tmp[4] % tmp[3];
11410 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11411 	tmp[4] = tmp[6] * 0x100;
11412 	tmp[5] = tmp[4] / tmp[3];
11413 	tmp[6] = tmp[4] % tmp[3];
11414 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11415 	tmp[4] = tmp[6] * 0x100;
11416 	tmp[5] = tmp[4] / tmp[3];
11417 	tmp[6] = tmp[4] % tmp[3];
11418 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11419 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11420 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11421 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11422 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11423 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11424 
11425 	bwn_phy_lp_b2062_vco_calib(mac);
11426 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11427 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11428 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11429 		bwn_phy_lp_b2062_reset_pllbias(mac);
11430 		bwn_phy_lp_b2062_vco_calib(mac);
11431 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11432 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11433 			return (EIO);
11434 		}
11435 	}
11436 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11437 	return (0);
11438 }
11439 
11440 static void
11441 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11442 {
11443 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11444 	uint16_t tmp = (channel == 14);
11445 
11446 	if (mac->mac_phy.rev < 2) {
11447 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11448 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11449 			bwn_phy_lp_set_rccap(mac);
11450 		return;
11451 	}
11452 
11453 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11454 }
11455 
11456 static void
11457 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11458 {
11459 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11460 	struct bwn_softc *sc = mac->mac_sc;
11461 	struct ifnet *ifp = sc->sc_ifp;
11462 	struct ieee80211com *ic = ifp->if_l2com;
11463 	uint16_t iso, tmp[3];
11464 
11465 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11466 
11467 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11468 		iso = plp->plp_txisoband_m;
11469 	else if (freq <= 5320)
11470 		iso = plp->plp_txisoband_l;
11471 	else if (freq <= 5700)
11472 		iso = plp->plp_txisoband_m;
11473 	else
11474 		iso = plp->plp_txisoband_h;
11475 
11476 	tmp[0] = ((iso - 26) / 12) << 12;
11477 	tmp[1] = tmp[0] + 0x1000;
11478 	tmp[2] = tmp[0] + 0x2000;
11479 
11480 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11481 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11482 }
11483 
11484 static void
11485 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11486 {
11487 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11488 	int i;
11489 	static const uint16_t addr[] = {
11490 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11491 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11492 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11493 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11494 		BWN_PHY_OFDM(0xcf),
11495 	};
11496 	static const uint16_t val[] = {
11497 		0xde5e, 0xe832, 0xe331, 0x4d26,
11498 		0x0026, 0x1420, 0x0020, 0xfe08,
11499 		0x0008,
11500 	};
11501 
11502 	for (i = 0; i < N(addr); i++) {
11503 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11504 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11505 	}
11506 }
11507 
11508 static void
11509 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11510 {
11511 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11512 	struct bwn_softc *sc = mac->mac_sc;
11513 	uint16_t ctl;
11514 
11515 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11516 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11517 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11518 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11519 		break;
11520 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11521 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11522 		break;
11523 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11524 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11525 		break;
11526 	default:
11527 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11528 		device_printf(sc->sc_dev, "unknown command mode\n");
11529 		break;
11530 	}
11531 }
11532 
11533 static void
11534 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11535 {
11536 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11537 	uint16_t ctl;
11538 	uint8_t old;
11539 
11540 	bwn_phy_lp_get_txpctlmode(mac);
11541 	old = plp->plp_txpctlmode;
11542 	if (old == mode)
11543 		return;
11544 	plp->plp_txpctlmode = mode;
11545 
11546 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11547 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11548 		    plp->plp_tssiidx);
11549 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11550 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11551 
11552 		/* disable TX GAIN override */
11553 		if (mac->mac_phy.rev < 2)
11554 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11555 		else {
11556 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11557 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11558 		}
11559 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11560 
11561 		plp->plp_txpwridx = -1;
11562 	}
11563 	if (mac->mac_phy.rev >= 2) {
11564 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11565 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11566 		else
11567 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11568 	}
11569 
11570 	/* writes TX Power Control mode */
11571 	switch (plp->plp_txpctlmode) {
11572 	case BWN_PHYLP_TXPCTL_OFF:
11573 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11574 		break;
11575 	case BWN_PHYLP_TXPCTL_ON_HW:
11576 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11577 		break;
11578 	case BWN_PHYLP_TXPCTL_ON_SW:
11579 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11580 		break;
11581 	default:
11582 		ctl = 0;
11583 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11584 	}
11585 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11586 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11587 }
11588 
11589 static void
11590 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11591 {
11592 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11593 	struct bwn_softc *sc = mac->mac_sc;
11594 	const unsigned int size = 256;
11595 	struct bwn_txgain tg;
11596 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11597 	uint16_t tssinpt, tssiidx, value[2];
11598 	uint8_t mode;
11599 	int8_t txpwridx;
11600 
11601 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11602 	    M_NOWAIT | M_ZERO);
11603 	if (tabs == NULL) {
11604 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11605 		return;
11606 	}
11607 
11608 	bwn_phy_lp_get_txpctlmode(mac);
11609 	mode = plp->plp_txpctlmode;
11610 	txpwridx = plp->plp_txpwridx;
11611 	tssinpt = plp->plp_tssinpt;
11612 	tssiidx = plp->plp_tssiidx;
11613 
11614 	bwn_tab_read_multi(mac,
11615 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11616 	    BWN_TAB_4(7, 0x140), size, tabs);
11617 
11618 	bwn_phy_lp_tblinit(mac);
11619 	bwn_phy_lp_bbinit(mac);
11620 	bwn_phy_lp_txpctl_init(mac);
11621 	bwn_phy_lp_rf_onoff(mac, 1);
11622 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11623 
11624 	bwn_tab_write_multi(mac,
11625 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11626 	    BWN_TAB_4(7, 0x140), size, tabs);
11627 
11628 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11629 	plp->plp_tssinpt = tssinpt;
11630 	plp->plp_tssiidx = tssiidx;
11631 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11632 	if (txpwridx != -1) {
11633 		/* set TX power by index */
11634 		plp->plp_txpwridx = txpwridx;
11635 		bwn_phy_lp_get_txpctlmode(mac);
11636 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11637 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11638 		if (mac->mac_phy.rev >= 2) {
11639 			rxcomp = bwn_tab_read(mac,
11640 			    BWN_TAB_4(7, txpwridx + 320));
11641 			txgain = bwn_tab_read(mac,
11642 			    BWN_TAB_4(7, txpwridx + 192));
11643 			tg.tg_pad = (txgain >> 16) & 0xff;
11644 			tg.tg_gm = txgain & 0xff;
11645 			tg.tg_pga = (txgain >> 8) & 0xff;
11646 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11647 			bwn_phy_lp_set_txgain(mac, &tg);
11648 		} else {
11649 			rxcomp = bwn_tab_read(mac,
11650 			    BWN_TAB_4(10, txpwridx + 320));
11651 			txgain = bwn_tab_read(mac,
11652 			    BWN_TAB_4(10, txpwridx + 192));
11653 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11654 			    0xf800, (txgain >> 4) & 0x7fff);
11655 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11656 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11657 		}
11658 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11659 
11660 		/* set TX IQCC */
11661 		value[0] = (rxcomp >> 10) & 0x3ff;
11662 		value[1] = rxcomp & 0x3ff;
11663 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11664 
11665 		coeff = bwn_tab_read(mac,
11666 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11667 		    BWN_TAB_4(10, txpwridx + 448));
11668 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11669 		if (mac->mac_phy.rev >= 2) {
11670 			rfpwr = bwn_tab_read(mac,
11671 			    BWN_TAB_4(7, txpwridx + 576));
11672 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11673 			    rfpwr & 0xffff);
11674 		}
11675 		bwn_phy_lp_set_txgain_override(mac);
11676 	}
11677 	if (plp->plp_rccap)
11678 		bwn_phy_lp_set_rccap(mac);
11679 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11680 	bwn_phy_lp_set_txpctlmode(mac, mode);
11681 	free(tabs, M_DEVBUF);
11682 }
11683 
11684 static void
11685 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11686 {
11687 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11688 	int i;
11689 	static const uint16_t addr[] = {
11690 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11691 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11692 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11693 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11694 		BWN_PHY_OFDM(0xcf),
11695 	};
11696 
11697 	for (i = 0; i < N(addr); i++)
11698 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11699 }
11700 
11701 static void
11702 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11703 {
11704 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11705 
11706 	if (mac->mac_phy.rev < 2) {
11707 		bwn_phy_lp_tblinit_r01(mac);
11708 		bwn_phy_lp_tblinit_txgain(mac);
11709 		bwn_phy_lp_set_gaintbl(mac, freq);
11710 		return;
11711 	}
11712 
11713 	bwn_phy_lp_tblinit_r2(mac);
11714 	bwn_phy_lp_tblinit_txgain(mac);
11715 }
11716 
11717 struct bwn_wpair {
11718 	uint16_t		reg;
11719 	uint16_t		value;
11720 };
11721 
11722 struct bwn_smpair {
11723 	uint16_t		offset;
11724 	uint16_t		mask;
11725 	uint16_t		set;
11726 };
11727 
11728 static void
11729 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11730 {
11731 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11732 	struct bwn_softc *sc = mac->mac_sc;
11733 	struct ifnet *ifp = sc->sc_ifp;
11734 	struct ieee80211com *ic = ifp->if_l2com;
11735 	static const struct bwn_wpair v1[] = {
11736 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11737 		{ BWN_PHY_AFE_CTL, 0x8800 },
11738 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11739 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11740 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11741 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11742 		{ BWN_PHY_OFDM(0xf9), 0 },
11743 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11744 	};
11745 	static const struct bwn_smpair v2[] = {
11746 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11747 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11748 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11749 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11750 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11751 	};
11752 	static const struct bwn_smpair v3[] = {
11753 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11754 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11755 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11756 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11757 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11758 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11759 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11760 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11761 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11762 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11763 
11764 	};
11765 	int i;
11766 
11767 	for (i = 0; i < N(v1); i++)
11768 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11769 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11770 	for (i = 0; i < N(v2); i++)
11771 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11772 
11773 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11774 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11775 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11776 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11777 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11778 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11779 	} else {
11780 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11781 	}
11782 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11783 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11784 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11785 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11786 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11787 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11788 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11789 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11790 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11791 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11792 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11793 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11794 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11795 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11796 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11797 	} else {
11798 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11799 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11800 	}
11801 	for (i = 0; i < N(v3); i++)
11802 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11803 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11804 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11805 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11806 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11807 	}
11808 
11809 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11810 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11811 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11812 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11813 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11814 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11815 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11816 	} else
11817 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11818 
11819 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11820 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11821 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11822 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11823 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11824 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11825 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11826 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11827 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11828 
11829 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11830 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11831 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11832 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11833 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11834 	}
11835 
11836 	bwn_phy_lp_digflt_save(mac);
11837 }
11838 
11839 static void
11840 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11841 {
11842 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11843 	struct bwn_softc *sc = mac->mac_sc;
11844 	struct ifnet *ifp = sc->sc_ifp;
11845 	struct ieee80211com *ic = ifp->if_l2com;
11846 	static const struct bwn_smpair v1[] = {
11847 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11848 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11849 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11850 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11851 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11852 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11853 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11854 	};
11855 	static const struct bwn_smpair v2[] = {
11856 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11857 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11858 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11859 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11860 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11861 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11862 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11863 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11864 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11865 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11866 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11867 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11868 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11869 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11870 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11871 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11872 	};
11873 	static const struct bwn_smpair v3[] = {
11874 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11875 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11876 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11877 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11878 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11879 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11880 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11881 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11882 	};
11883 	static const struct bwn_smpair v4[] = {
11884 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11885 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11886 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11887 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11888 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11889 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11890 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11891 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11892 	};
11893 	static const struct bwn_smpair v5[] = {
11894 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11895 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11896 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11897 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11898 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11899 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11900 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11901 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11902 	};
11903 	int i;
11904 	uint16_t tmp, tmp2;
11905 
11906 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11907 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11908 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11909 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11910 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11911 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11912 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11913 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11914 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11915 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11916 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11917 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11918 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11919 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11920 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11921 	for (i = 0; i < N(v1); i++)
11922 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11923 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11924 	    0xff00, plp->plp_rxpwroffset);
11925 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11926 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11927 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11928 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11929 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11930 		if (mac->mac_phy.rev == 0)
11931 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11932 			    0xffcf, 0x0010);
11933 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11934 	} else {
11935 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11936 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11937 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11938 	}
11939 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11940 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11941 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11942 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11943 	else
11944 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11945 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11946 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11947 	    0xfff9, (plp->plp_bxarch << 1));
11948 	if (mac->mac_phy.rev == 1 &&
11949 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11950 		for (i = 0; i < N(v2); i++)
11951 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11952 			    v2[i].set);
11953 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11954 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11955 	    ((mac->mac_phy.rev == 0) &&
11956 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11957 		for (i = 0; i < N(v3); i++)
11958 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11959 			    v3[i].set);
11960 	} else if (mac->mac_phy.rev == 1 ||
11961 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11962 		for (i = 0; i < N(v4); i++)
11963 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11964 			    v4[i].set);
11965 	} else {
11966 		for (i = 0; i < N(v5); i++)
11967 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11968 			    v5[i].set);
11969 	}
11970 	if (mac->mac_phy.rev == 1 &&
11971 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11972 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11973 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11974 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11975 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11976 	}
11977 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11978 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11979 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11980 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11981 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11982 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11983 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11984 	}
11985 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11986 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11987 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11988 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11989 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11990 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11991 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11992 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11993 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11994 	} else {
11995 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11996 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11997 	}
11998 	if (mac->mac_phy.rev == 1) {
11999 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12000 		tmp2 = (tmp & 0x03e0) >> 5;
12001 		tmp2 |= tmp2 << 5;
12002 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12003 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12004 		tmp2 = (tmp & 0x1f00) >> 8;
12005 		tmp2 |= tmp2 << 5;
12006 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12007 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12008 		tmp2 = tmp & 0x00ff;
12009 		tmp2 |= tmp << 8;
12010 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12011 	}
12012 }
12013 
12014 struct bwn_b2062_freq {
12015 	uint16_t		freq;
12016 	uint8_t			value[6];
12017 };
12018 
12019 static void
12020 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12021 {
12022 #define	CALC_CTL7(freq, div)						\
12023 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12024 #define	CALC_CTL18(freq, div)						\
12025 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12026 #define	CALC_CTL19(freq, div)						\
12027 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12028 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12029 	struct bwn_softc *sc = mac->mac_sc;
12030 	struct ifnet *ifp = sc->sc_ifp;
12031 	struct ieee80211com *ic = ifp->if_l2com;
12032 	static const struct bwn_b2062_freq freqdata_tab[] = {
12033 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12034 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12035 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12036 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12037 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12038 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12039 	};
12040 	static const struct bwn_wpair v1[] = {
12041 		{ BWN_B2062_N_TXCTL3, 0 },
12042 		{ BWN_B2062_N_TXCTL4, 0 },
12043 		{ BWN_B2062_N_TXCTL5, 0 },
12044 		{ BWN_B2062_N_TXCTL6, 0 },
12045 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12046 		{ BWN_B2062_N_PDNCTL0, 0 },
12047 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12048 		{ BWN_B2062_N_CALIB_TS, 0 }
12049 	};
12050 	const struct bwn_b2062_freq *f = NULL;
12051 	uint32_t xtalfreq, ref;
12052 	unsigned int i;
12053 
12054 	bwn_phy_lp_b2062_tblinit(mac);
12055 
12056 	for (i = 0; i < N(v1); i++)
12057 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12058 	if (mac->mac_phy.rev > 0)
12059 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12060 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12061 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12062 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12063 	else
12064 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12065 
12066 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12067 	    ("%s:%d: fail", __func__, __LINE__));
12068 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12069 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12070 
12071 	if (xtalfreq <= 30000000) {
12072 		plp->plp_div = 1;
12073 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12074 	} else {
12075 		plp->plp_div = 2;
12076 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12077 	}
12078 
12079 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12080 	    CALC_CTL7(xtalfreq, plp->plp_div));
12081 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12082 	    CALC_CTL18(xtalfreq, plp->plp_div));
12083 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12084 	    CALC_CTL19(xtalfreq, plp->plp_div));
12085 
12086 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12087 	ref &= 0xffff;
12088 	for (i = 0; i < N(freqdata_tab); i++) {
12089 		if (ref < freqdata_tab[i].freq) {
12090 			f = &freqdata_tab[i];
12091 			break;
12092 		}
12093 	}
12094 	if (f == NULL)
12095 		f = &freqdata_tab[N(freqdata_tab) - 1];
12096 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12097 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12098 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12099 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12100 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12101 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12102 #undef CALC_CTL7
12103 #undef CALC_CTL18
12104 #undef CALC_CTL19
12105 }
12106 
12107 static void
12108 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12109 {
12110 
12111 	bwn_phy_lp_b2063_tblinit(mac);
12112 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12113 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12114 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12115 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12116 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12117 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12118 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12119 	if (mac->mac_phy.rev == 2) {
12120 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12121 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12122 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12123 	} else {
12124 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12125 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12126 	}
12127 }
12128 
12129 static void
12130 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12131 {
12132 	struct bwn_softc *sc = mac->mac_sc;
12133 	static const struct bwn_wpair v1[] = {
12134 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12135 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12136 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12137 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12138 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12139 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12140 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12141 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12142 	};
12143 	static const struct bwn_wpair v2[] = {
12144 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12145 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12146 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12147 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12148 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12149 	};
12150 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12151 	int i;
12152 	uint8_t tmp;
12153 
12154 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12155 
12156 	for (i = 0; i < 2; i++)
12157 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12158 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12159 	for (i = 2; i < N(v1); i++)
12160 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12161 	for (i = 0; i < 10000; i++) {
12162 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12163 			break;
12164 		DELAY(1000);
12165 	}
12166 
12167 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12168 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12169 
12170 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12171 
12172 	for (i = 0; i < N(v2); i++)
12173 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12174 	if (freqxtal == 24000000) {
12175 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12176 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12177 	} else {
12178 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12179 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12180 	}
12181 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12182 	for (i = 0; i < 10000; i++) {
12183 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12184 			break;
12185 		DELAY(1000);
12186 	}
12187 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12188 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12189 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12190 }
12191 
12192 static void
12193 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12194 {
12195 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12196 	struct bwn_softc *sc = mac->mac_sc;
12197 	struct bwn_phy_lp_iq_est ie;
12198 	struct bwn_txgain tx_gains;
12199 	static const uint32_t pwrtbl[21] = {
12200 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12201 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12202 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12203 		0x0004c, 0x0002c, 0x0001a,
12204 	};
12205 	uint32_t npwr, ipwr, sqpwr, tmp;
12206 	int loopback, i, j, sum, error;
12207 	uint16_t save[7];
12208 	uint8_t txo, bbmult, txpctlmode;
12209 
12210 	error = bwn_phy_lp_switch_channel(mac, 7);
12211 	if (error)
12212 		device_printf(sc->sc_dev,
12213 		    "failed to change channel to 7 (%d)\n", error);
12214 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12215 	bbmult = bwn_phy_lp_get_bbmult(mac);
12216 	if (txo)
12217 		tx_gains = bwn_phy_lp_get_txgain(mac);
12218 
12219 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12220 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12221 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12222 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12223 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12224 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12225 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12226 
12227 	bwn_phy_lp_get_txpctlmode(mac);
12228 	txpctlmode = plp->plp_txpctlmode;
12229 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12230 
12231 	/* disable CRS */
12232 	bwn_phy_lp_set_deaf(mac, 1);
12233 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12234 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12235 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12236 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12237 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12238 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12239 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12240 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12241 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12242 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12243 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12244 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12245 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12246 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12247 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12248 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12249 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12250 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12251 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12252 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12253 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12254 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12255 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12256 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12257 
12258 	loopback = bwn_phy_lp_loopback(mac);
12259 	if (loopback == -1)
12260 		goto done;
12261 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12262 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12263 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12264 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12265 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12266 
12267 	tmp = 0;
12268 	memset(&ie, 0, sizeof(ie));
12269 	for (i = 128; i <= 159; i++) {
12270 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12271 		sum = 0;
12272 		for (j = 5; j <= 25; j++) {
12273 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12274 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12275 				goto done;
12276 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12277 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12278 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12279 			    12);
12280 			sum += ((ipwr - npwr) * (ipwr - npwr));
12281 			if ((i == 128) || (sum < tmp)) {
12282 				plp->plp_rccap = i;
12283 				tmp = sum;
12284 			}
12285 		}
12286 	}
12287 	bwn_phy_lp_ddfs_turnoff(mac);
12288 done:
12289 	/* restore CRS */
12290 	bwn_phy_lp_clear_deaf(mac, 1);
12291 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12292 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12293 
12294 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12295 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12296 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12297 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12298 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12299 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12300 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12301 
12302 	bwn_phy_lp_set_bbmult(mac, bbmult);
12303 	if (txo)
12304 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12305 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12306 	if (plp->plp_rccap)
12307 		bwn_phy_lp_set_rccap(mac);
12308 }
12309 
12310 static void
12311 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12312 {
12313 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12314 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12315 
12316 	if (mac->mac_phy.rev == 1)
12317 		rc_cap = MIN(rc_cap + 5, 15);
12318 
12319 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12320 	    MAX(plp->plp_rccap - 4, 0x80));
12321 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12322 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12323 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12324 }
12325 
12326 static uint32_t
12327 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12328 {
12329 	uint32_t i, q, r;
12330 
12331 	if (div == 0)
12332 		return (0);
12333 
12334 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12335 		q <<= 1;
12336 		if (r << 1 >= div) {
12337 			q++;
12338 			r = (r << 1) - div;
12339 		}
12340 	}
12341 	if (r << 1 >= div)
12342 		q++;
12343 	return (q);
12344 }
12345 
12346 static void
12347 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12348 {
12349 	struct bwn_softc *sc = mac->mac_sc;
12350 
12351 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12352 	DELAY(20);
12353 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12354 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12355 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12356 	} else {
12357 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12358 	}
12359 	DELAY(5);
12360 }
12361 
12362 static void
12363 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12364 {
12365 
12366 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12367 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12368 	DELAY(200);
12369 }
12370 
12371 static void
12372 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12373 {
12374 #define	FLAG_A	0x01
12375 #define	FLAG_G	0x02
12376 	struct bwn_softc *sc = mac->mac_sc;
12377 	struct ifnet *ifp = sc->sc_ifp;
12378 	struct ieee80211com *ic = ifp->if_l2com;
12379 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12380 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12381 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12382 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12383 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12384 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12385 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12386 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12387 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12388 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12389 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12390 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12391 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12392 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12393 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12394 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12395 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12396 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12397 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12398 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12399 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12400 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12401 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12402 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12403 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12404 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12405 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12406 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12407 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12408 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12409 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12410 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12411 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12412 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12413 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12414 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12415 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12416 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12417 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12418 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12419 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12420 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12421 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12422 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12423 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12424 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12425 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12426 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12427 	};
12428 	const struct bwn_b206x_rfinit_entry *br;
12429 	unsigned int i;
12430 
12431 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12432 		br = &bwn_b2062_init_tab[i];
12433 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12434 			if (br->br_flags & FLAG_G)
12435 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12436 		} else {
12437 			if (br->br_flags & FLAG_A)
12438 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12439 		}
12440 	}
12441 #undef FLAG_A
12442 #undef FLAG_B
12443 }
12444 
12445 static void
12446 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12447 {
12448 #define	FLAG_A	0x01
12449 #define	FLAG_G	0x02
12450 	struct bwn_softc *sc = mac->mac_sc;
12451 	struct ifnet *ifp = sc->sc_ifp;
12452 	struct ieee80211com *ic = ifp->if_l2com;
12453 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12454 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12455 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12456 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12457 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12458 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12459 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12460 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12461 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12462 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12463 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12464 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12465 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12466 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12467 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12468 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12469 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12470 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12471 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12472 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12473 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12474 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12475 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12476 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12477 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12478 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12479 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12480 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12481 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12482 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12483 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12484 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12485 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12486 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12487 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12488 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12489 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12490 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12491 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12492 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12493 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12494 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12495 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12496 	};
12497 	const struct bwn_b206x_rfinit_entry *br;
12498 	unsigned int i;
12499 
12500 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12501 		br = &bwn_b2063_init_tab[i];
12502 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12503 			if (br->br_flags & FLAG_G)
12504 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12505 		} else {
12506 			if (br->br_flags & FLAG_A)
12507 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12508 		}
12509 	}
12510 #undef FLAG_A
12511 #undef FLAG_B
12512 }
12513 
12514 static void
12515 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12516     int count, void *_data)
12517 {
12518 	unsigned int i;
12519 	uint32_t offset, type;
12520 	uint8_t *data = _data;
12521 
12522 	type = BWN_TAB_GETTYPE(typenoffset);
12523 	offset = BWN_TAB_GETOFFSET(typenoffset);
12524 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12525 
12526 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12527 
12528 	for (i = 0; i < count; i++) {
12529 		switch (type) {
12530 		case BWN_TAB_8BIT:
12531 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12532 			data++;
12533 			break;
12534 		case BWN_TAB_16BIT:
12535 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12536 			    BWN_PHY_TABLEDATALO);
12537 			data += 2;
12538 			break;
12539 		case BWN_TAB_32BIT:
12540 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12541 			    BWN_PHY_TABLEDATAHI);
12542 			*((uint32_t *)data) <<= 16;
12543 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12544 			    BWN_PHY_TABLEDATALO);
12545 			data += 4;
12546 			break;
12547 		default:
12548 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12549 		}
12550 	}
12551 }
12552 
12553 static void
12554 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12555     int count, const void *_data)
12556 {
12557 	uint32_t offset, type, value;
12558 	const uint8_t *data = _data;
12559 	unsigned int i;
12560 
12561 	type = BWN_TAB_GETTYPE(typenoffset);
12562 	offset = BWN_TAB_GETOFFSET(typenoffset);
12563 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12564 
12565 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12566 
12567 	for (i = 0; i < count; i++) {
12568 		switch (type) {
12569 		case BWN_TAB_8BIT:
12570 			value = *data;
12571 			data++;
12572 			KASSERT(!(value & ~0xff),
12573 			    ("%s:%d: fail", __func__, __LINE__));
12574 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12575 			break;
12576 		case BWN_TAB_16BIT:
12577 			value = *((const uint16_t *)data);
12578 			data += 2;
12579 			KASSERT(!(value & ~0xffff),
12580 			    ("%s:%d: fail", __func__, __LINE__));
12581 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12582 			break;
12583 		case BWN_TAB_32BIT:
12584 			value = *((const uint32_t *)data);
12585 			data += 4;
12586 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12587 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12588 			break;
12589 		default:
12590 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12591 		}
12592 	}
12593 }
12594 
12595 static struct bwn_txgain
12596 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12597 {
12598 	struct bwn_txgain tg;
12599 	uint16_t tmp;
12600 
12601 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12602 	if (mac->mac_phy.rev < 2) {
12603 		tmp = BWN_PHY_READ(mac,
12604 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12605 		tg.tg_gm = tmp & 0x0007;
12606 		tg.tg_pga = (tmp & 0x0078) >> 3;
12607 		tg.tg_pad = (tmp & 0x780) >> 7;
12608 		return (tg);
12609 	}
12610 
12611 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12612 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12613 	tg.tg_gm = tmp & 0xff;
12614 	tg.tg_pga = (tmp >> 8) & 0xff;
12615 	return (tg);
12616 }
12617 
12618 static uint8_t
12619 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12620 {
12621 
12622 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12623 }
12624 
12625 static void
12626 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12627 {
12628 	uint16_t pa;
12629 
12630 	if (mac->mac_phy.rev < 2) {
12631 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12632 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12633 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12634 		bwn_phy_lp_set_txgain_override(mac);
12635 		return;
12636 	}
12637 
12638 	pa = bwn_phy_lp_get_pa_gain(mac);
12639 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12640 	    (tg->tg_pga << 8) | tg->tg_gm);
12641 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12642 	    tg->tg_pad | (pa << 6));
12643 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12644 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12645 	    tg->tg_pad | (pa << 8));
12646 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12647 	bwn_phy_lp_set_txgain_override(mac);
12648 }
12649 
12650 static void
12651 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12652 {
12653 
12654 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12655 }
12656 
12657 static void
12658 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12659 {
12660 	uint16_t trsw = (tx << 1) | rx;
12661 
12662 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12663 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12664 }
12665 
12666 static void
12667 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12668 {
12669 	struct bwn_softc *sc = mac->mac_sc;
12670 	struct ifnet *ifp = sc->sc_ifp;
12671 	struct ieee80211com *ic = ifp->if_l2com;
12672 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12673 
12674 	if (mac->mac_phy.rev < 2) {
12675 		trsw = gain & 0x1;
12676 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12677 		ext_lna = (gain & 2) >> 1;
12678 
12679 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12680 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12681 		    0xfbff, ext_lna << 10);
12682 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12683 		    0xf7ff, ext_lna << 11);
12684 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12685 	} else {
12686 		low_gain = gain & 0xffff;
12687 		high_gain = (gain >> 16) & 0xf;
12688 		ext_lna = (gain >> 21) & 0x1;
12689 		trsw = ~(gain >> 20) & 0x1;
12690 
12691 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12692 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12693 		    0xfdff, ext_lna << 9);
12694 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12695 		    0xfbff, ext_lna << 10);
12696 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12697 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12698 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12699 			tmp = (gain >> 2) & 0x3;
12700 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12701 			    0xe7ff, tmp<<11);
12702 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12703 			    tmp << 3);
12704 		}
12705 	}
12706 
12707 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12708 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12709 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12710 	if (mac->mac_phy.rev >= 2) {
12711 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12712 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12713 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12714 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12715 		}
12716 		return;
12717 	}
12718 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12719 }
12720 
12721 static void
12722 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12723 {
12724 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12725 
12726 	if (user)
12727 		plp->plp_crsusr_off = 1;
12728 	else
12729 		plp->plp_crssys_off = 1;
12730 
12731 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12732 }
12733 
12734 static void
12735 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12736 {
12737 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12738 	struct bwn_softc *sc = mac->mac_sc;
12739 	struct ifnet *ifp = sc->sc_ifp;
12740 	struct ieee80211com *ic = ifp->if_l2com;
12741 
12742 	if (user)
12743 		plp->plp_crsusr_off = 0;
12744 	else
12745 		plp->plp_crssys_off = 0;
12746 
12747 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12748 		return;
12749 
12750 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12751 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12752 	else
12753 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12754 }
12755 
12756 static unsigned int
12757 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12758 {
12759 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12760 	static uint8_t sqrt_table[256] = {
12761 		10, 14, 17, 20, 22, 24, 26, 28,
12762 		30, 31, 33, 34, 36, 37, 38, 40,
12763 		41, 42, 43, 44, 45, 46, 47, 48,
12764 		50, 50, 51, 52, 53, 54, 55, 56,
12765 		57, 58, 59, 60, 60, 61, 62, 63,
12766 		64, 64, 65, 66, 67, 67, 68, 69,
12767 		70, 70, 71, 72, 72, 73, 74, 74,
12768 		75, 76, 76, 77, 78, 78, 79, 80,
12769 		80, 81, 81, 82, 83, 83, 84, 84,
12770 		85, 86, 86, 87, 87, 88, 88, 89,
12771 		90, 90, 91, 91, 92, 92, 93, 93,
12772 		94, 94, 95, 95, 96, 96, 97, 97,
12773 		98, 98, 99, 100, 100, 100, 101, 101,
12774 		102, 102, 103, 103, 104, 104, 105, 105,
12775 		106, 106, 107, 107, 108, 108, 109, 109,
12776 		110, 110, 110, 111, 111, 112, 112, 113,
12777 		113, 114, 114, 114, 115, 115, 116, 116,
12778 		117, 117, 117, 118, 118, 119, 119, 120,
12779 		120, 120, 121, 121, 122, 122, 122, 123,
12780 		123, 124, 124, 124, 125, 125, 126, 126,
12781 		126, 127, 127, 128, 128, 128, 129, 129,
12782 		130, 130, 130, 131, 131, 131, 132, 132,
12783 		133, 133, 133, 134, 134, 134, 135, 135,
12784 		136, 136, 136, 137, 137, 137, 138, 138,
12785 		138, 139, 139, 140, 140, 140, 141, 141,
12786 		141, 142, 142, 142, 143, 143, 143, 144,
12787 		144, 144, 145, 145, 145, 146, 146, 146,
12788 		147, 147, 147, 148, 148, 148, 149, 149,
12789 		150, 150, 150, 150, 151, 151, 151, 152,
12790 		152, 152, 153, 153, 153, 154, 154, 154,
12791 		155, 155, 155, 156, 156, 156, 157, 157,
12792 		157, 158, 158, 158, 159, 159, 159, 160
12793 	};
12794 
12795 	if (x == 0)
12796 		return (0);
12797 	if (x >= 256) {
12798 		unsigned int tmp;
12799 
12800 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12801 			/* do nothing */ ;
12802 		return (tmp);
12803 	}
12804 	return (sqrt_table[x - 1] / 10);
12805 }
12806 
12807 static int
12808 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12809 {
12810 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12811 	int _t;								\
12812 	_t = _x - 20;							\
12813 	if (_t >= 0) {							\
12814 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12815 	} else {							\
12816 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12817 	}								\
12818 } while (0)
12819 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12820 	int _t;								\
12821 	_t = _x - 11;							\
12822 	if (_t >= 0)							\
12823 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12824 	else								\
12825 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12826 } while (0)
12827 	struct bwn_phy_lp_iq_est ie;
12828 	uint16_t v0, v1;
12829 	int tmp[2], ret;
12830 
12831 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12832 	v0 = v1 >> 8;
12833 	v1 |= 0xff;
12834 
12835 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12836 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12837 
12838 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12839 	if (ret == 0)
12840 		goto done;
12841 
12842 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12843 		ret = 0;
12844 		goto done;
12845 	}
12846 
12847 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12848 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12849 
12850 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12851 	v0 = tmp[0] >> 3;
12852 	v1 = tmp[1] >> 4;
12853 done:
12854 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12855 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12856 	return ret;
12857 #undef CALC_COEFF
12858 #undef CALC_COEFF2
12859 }
12860 
12861 static void
12862 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12863 {
12864 	static const uint16_t noisescale[] = {
12865 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12866 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12867 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12868 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12869 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12870 	};
12871 	static const uint16_t crsgainnft[] = {
12872 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12873 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12874 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12875 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12876 		0x013d,
12877 	};
12878 	static const uint16_t filterctl[] = {
12879 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12880 		0xff53, 0x0127,
12881 	};
12882 	static const uint32_t psctl[] = {
12883 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12884 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12885 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12886 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12887 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12888 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12889 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12890 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12891 	};
12892 	static const uint16_t ofdmcckgain_r0[] = {
12893 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12894 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12895 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12896 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12897 		0x755d,
12898 	};
12899 	static const uint16_t ofdmcckgain_r1[] = {
12900 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12901 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12902 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12903 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12904 		0x755d,
12905 	};
12906 	static const uint16_t gaindelta[] = {
12907 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12908 		0x0000,
12909 	};
12910 	static const uint32_t txpwrctl[] = {
12911 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12912 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12913 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12914 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12915 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12916 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12917 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12918 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12919 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12920 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12921 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12922 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12923 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12924 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12949 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12950 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12951 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12952 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12953 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12954 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12955 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12956 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12957 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12958 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12959 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12960 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12961 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12962 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12963 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12964 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12965 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12966 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12967 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12968 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12969 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12970 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12971 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12972 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12973 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12974 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12975 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12976 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12977 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12978 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12979 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12980 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12981 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12982 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12983 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12984 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12985 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12986 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12987 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12988 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12989 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12990 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12991 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12992 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12993 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12994 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12995 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12996 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12997 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12998 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12999 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13000 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13001 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13002 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13003 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13004 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13005 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13006 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13007 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13008 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13009 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13010 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13011 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13012 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13013 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13014 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13015 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13016 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13017 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13018 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13019 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13020 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13021 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13022 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13023 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13024 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13025 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13026 		0x00000702,
13027 	};
13028 
13029 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13030 
13031 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13032 	    bwn_tab_sigsq_tbl);
13033 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13034 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13035 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13036 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13037 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13038 	    bwn_tab_pllfrac_tbl);
13039 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13040 	    bwn_tabl_iqlocal_tbl);
13041 	if (mac->mac_phy.rev == 0) {
13042 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13043 		    ofdmcckgain_r0);
13044 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13045 		    ofdmcckgain_r0);
13046 	} else {
13047 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13048 		    ofdmcckgain_r1);
13049 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13050 		    ofdmcckgain_r1);
13051 	}
13052 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13053 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13054 }
13055 
13056 static void
13057 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13058 {
13059 	struct bwn_softc *sc = mac->mac_sc;
13060 	int i;
13061 	static const uint16_t noisescale[] = {
13062 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13068 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13069 	};
13070 	static const uint32_t filterctl[] = {
13071 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13072 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13073 	};
13074 	static const uint32_t psctl[] = {
13075 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13076 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13077 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13078 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13079 	};
13080 	static const uint32_t gainidx[] = {
13081 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13084 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13085 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13086 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13087 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13088 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13089 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13090 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13091 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13092 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13093 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13094 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13095 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13096 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13099 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13100 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13101 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13102 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13103 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13104 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13105 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13106 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13107 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13108 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13109 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13110 		0x0000001a, 0x64ca55ad, 0x0000001a
13111 	};
13112 	static const uint16_t auxgainidx[] = {
13113 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13114 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13115 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13116 		0x0004, 0x0016
13117 	};
13118 	static const uint16_t swctl[] = {
13119 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13121 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13122 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13123 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13124 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13125 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13126 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13127 	};
13128 	static const uint8_t hf[] = {
13129 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13130 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13131 	};
13132 	static const uint32_t gainval[] = {
13133 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13134 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13135 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13136 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13137 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13138 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13139 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13141 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13142 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13143 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13144 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13145 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13146 		0x000000f1, 0x00000000, 0x00000000
13147 	};
13148 	static const uint16_t gain[] = {
13149 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13150 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13151 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13152 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13153 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13154 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13155 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13160 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13161 	};
13162 	static const uint32_t papdeps[] = {
13163 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13164 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13165 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13166 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13167 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13168 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13169 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13170 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13171 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13172 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13173 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13174 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13175 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13176 	};
13177 	static const uint32_t papdmult[] = {
13178 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13179 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13180 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13181 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13182 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13183 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13184 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13185 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13186 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13187 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13188 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13189 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13190 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13191 	};
13192 	static const uint32_t gainidx_a0[] = {
13193 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13194 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13195 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13196 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13197 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13198 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13199 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13200 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13201 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13202 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13203 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13204 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13205 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13206 	};
13207 	static const uint16_t auxgainidx_a0[] = {
13208 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13209 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13210 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13211 		0x0002, 0x0014
13212 	};
13213 	static const uint32_t gainval_a0[] = {
13214 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13215 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13216 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13217 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13218 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13219 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13220 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13221 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13222 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13223 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13224 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13225 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13226 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13227 		0x000000f7, 0x00000000, 0x00000000
13228 	};
13229 	static const uint16_t gain_a0[] = {
13230 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13231 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13232 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13233 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13234 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13235 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13236 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13241 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13242 	};
13243 
13244 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13245 
13246 	for (i = 0; i < 704; i++)
13247 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13248 
13249 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13250 	    bwn_tab_sigsq_tbl);
13251 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13252 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13253 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13254 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13255 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13256 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13257 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13258 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13259 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13260 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13261 	    bwn_tab_pllfrac_tbl);
13262 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13263 	    bwn_tabl_iqlocal_tbl);
13264 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13265 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13266 
13267 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13268 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13269 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13270 		    gainidx_a0);
13271 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13272 		    auxgainidx_a0);
13273 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13274 		    gainval_a0);
13275 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13276 	}
13277 }
13278 
13279 static void
13280 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13281 {
13282 	struct bwn_softc *sc = mac->mac_sc;
13283 	struct ifnet *ifp = sc->sc_ifp;
13284 	struct ieee80211com *ic = ifp->if_l2com;
13285 	static struct bwn_txgain_entry txgain_r2[] = {
13286 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13287 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13288 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13289 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13290 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13291 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13292 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13293 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13294 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13295 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13296 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13297 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13298 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13299 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13300 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13301 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13302 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13303 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13304 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13305 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13306 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13307 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13308 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13309 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13310 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13311 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13312 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13313 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13314 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13315 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13316 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13317 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13318 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13319 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13320 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13321 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13322 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13323 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13324 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13325 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13326 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13327 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13328 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13329 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13330 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13331 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13332 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13333 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13334 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13335 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13336 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13337 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13338 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13339 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13340 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13341 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13342 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13343 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13344 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13345 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13346 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13347 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13348 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13349 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13350 	};
13351 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13352 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13353 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13354 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13355 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13356 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13357 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13358 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13359 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13360 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13361 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13362 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13363 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13364 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13365 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13366 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13367 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13368 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13369 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13370 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13371 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13372 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13373 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13374 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13375 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13376 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13377 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13378 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13379 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13380 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13381 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13382 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13383 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13384 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13385 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13386 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13387 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13388 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13389 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13390 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13391 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13392 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13393 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13394 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13395 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13396 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13397 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13398 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13399 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13400 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13401 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13402 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13403 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13404 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13405 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13406 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13407 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13408 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13409 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13410 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13411 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13412 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13413 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13414 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13415 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13416 	};
13417 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13418 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13419 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13420 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13421 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13422 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13423 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13424 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13425 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13426 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13427 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13428 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13429 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13430 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13431 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13432 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13433 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13434 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13435 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13436 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13437 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13438 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13439 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13440 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13441 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13442 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13443 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13444 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13445 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13446 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13447 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13448 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13449 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13450 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13451 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13452 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13453 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13454 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13455 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13456 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13457 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13458 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13459 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13460 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13461 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13462 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13463 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13464 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13465 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13466 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13467 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13468 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13469 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13470 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13471 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13472 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13473 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13474 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13475 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13476 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13477 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13478 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13479 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13480 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13481 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13482 	};
13483 	static struct bwn_txgain_entry txgain_r0[] = {
13484 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13485 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13486 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13487 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13488 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13489 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13490 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13491 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13492 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13493 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13494 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13495 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13496 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13497 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13498 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13499 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13500 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13501 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13502 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13503 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13504 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13505 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13506 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13507 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13508 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13509 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13510 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13511 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13512 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13513 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13514 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13515 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13516 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13517 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13518 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13519 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13520 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13521 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13522 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13523 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13524 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13525 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13526 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13527 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13528 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13529 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13530 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13531 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13532 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13533 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13534 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13535 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13536 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13537 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13538 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13539 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13540 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13541 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13542 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13543 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13544 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13545 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13546 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13547 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13548 	};
13549 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13550 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13551 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13552 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13553 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13554 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13555 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13556 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13557 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13558 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13559 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13560 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13561 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13562 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13563 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13564 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13565 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13566 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13567 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13568 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13569 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13570 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13571 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13572 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13573 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13574 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13575 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13576 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13577 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13578 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13579 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13580 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13581 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13582 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13583 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13584 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13585 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13586 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13587 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13588 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13589 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13590 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13591 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13592 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13593 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13594 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13595 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13596 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13597 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13598 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13599 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13600 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13601 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13602 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13603 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13604 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13605 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13606 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13607 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13608 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13609 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13610 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13611 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13612 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13613 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13614 	};
13615 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13616 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13617 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13618 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13619 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13620 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13621 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13622 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13623 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13624 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13625 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13626 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13627 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13628 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13629 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13630 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13631 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13632 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13633 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13634 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13635 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13636 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13637 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13638 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13639 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13640 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13641 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13642 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13643 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13644 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13645 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13646 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13647 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13648 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13649 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13650 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13651 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13652 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13653 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13654 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13655 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13656 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13657 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13658 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13659 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13660 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13661 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13662 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13663 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13664 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13665 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13666 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13667 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13668 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13669 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13670 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13671 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13672 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13673 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13674 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13675 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13676 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13677 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13678 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13679 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13680 	};
13681 	static struct bwn_txgain_entry txgain_r1[] = {
13682 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13683 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13684 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13685 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13686 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13687 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13688 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13689 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13690 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13691 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13692 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13693 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13694 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13695 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13696 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13697 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13698 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13699 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13700 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13701 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13702 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13703 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13704 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13705 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13706 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13707 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13708 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13709 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13710 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13711 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13712 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13713 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13714 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13715 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13716 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13717 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13718 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13719 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13720 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13721 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13722 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13723 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13724 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13725 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13726 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13727 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13728 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13729 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13730 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13731 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13732 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13733 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13734 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13735 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13736 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13737 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13738 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13739 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13740 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13741 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13742 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13743 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13744 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13745 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13746 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13747 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13748 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13749 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13750 		{ 7, 11, 6, 0, 71 }
13751 	};
13752 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13753 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13754 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13755 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13756 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13757 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13758 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13759 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13760 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13761 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13762 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13763 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13764 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13765 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13766 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13767 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13768 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13769 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13770 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13771 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13772 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13773 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13774 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13775 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13776 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13777 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13778 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13779 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13780 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13781 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13782 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13783 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13784 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13785 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13786 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13787 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13788 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13789 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13790 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13791 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13792 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13793 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13794 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13795 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13796 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13797 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13798 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13799 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13800 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13801 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13802 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13803 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13804 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13805 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13806 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13807 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13808 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13809 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13810 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13811 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13812 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13813 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13814 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13815 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13816 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13817 	};
13818 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13819 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13820 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13821 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13822 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13823 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13824 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13825 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13826 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13827 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13828 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13829 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13830 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13831 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13832 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13833 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13834 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13835 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13836 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13837 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13838 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13839 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13840 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13841 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13842 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13843 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13844 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13845 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13846 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13847 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13848 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13849 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13850 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13851 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13852 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13853 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13854 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13855 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13856 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13857 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13858 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13859 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13860 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13861 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13862 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13863 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13864 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13865 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13866 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13867 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13868 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13869 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13870 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13871 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13872 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13873 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13874 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13875 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13876 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13877 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13878 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13879 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13880 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13881 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13882 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13883 	};
13884 
13885 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13886 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13887 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13888 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13889 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13890 			    txgain_2ghz_r2);
13891 		else
13892 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13893 			    txgain_5ghz_r2);
13894 		return;
13895 	}
13896 
13897 	if (mac->mac_phy.rev == 0) {
13898 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13899 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13900 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13901 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13902 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13903 			    txgain_2ghz_r0);
13904 		else
13905 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13906 			    txgain_5ghz_r0);
13907 		return;
13908 	}
13909 
13910 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13911 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13912 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13913 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13914 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13915 	else
13916 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13917 }
13918 
13919 static void
13920 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13921 {
13922 	uint32_t offset, type;
13923 
13924 	type = BWN_TAB_GETTYPE(typeoffset);
13925 	offset = BWN_TAB_GETOFFSET(typeoffset);
13926 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13927 
13928 	switch (type) {
13929 	case BWN_TAB_8BIT:
13930 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13931 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13932 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13933 		break;
13934 	case BWN_TAB_16BIT:
13935 		KASSERT(!(value & ~0xffff),
13936 		    ("%s:%d: fail", __func__, __LINE__));
13937 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13938 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13939 		break;
13940 	case BWN_TAB_32BIT:
13941 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13942 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13943 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13944 		break;
13945 	default:
13946 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13947 	}
13948 }
13949 
13950 static int
13951 bwn_phy_lp_loopback(struct bwn_mac *mac)
13952 {
13953 	struct bwn_phy_lp_iq_est ie;
13954 	int i, index = -1;
13955 	uint32_t tmp;
13956 
13957 	memset(&ie, 0, sizeof(ie));
13958 
13959 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13960 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13961 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13962 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13963 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13964 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13965 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13966 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13967 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13968 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13969 	for (i = 0; i < 32; i++) {
13970 		bwn_phy_lp_set_rxgain_idx(mac, i);
13971 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13972 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13973 			continue;
13974 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13975 		if ((tmp > 4000) && (tmp < 10000)) {
13976 			index = i;
13977 			break;
13978 		}
13979 	}
13980 	bwn_phy_lp_ddfs_turnoff(mac);
13981 	return (index);
13982 }
13983 
13984 static void
13985 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13986 {
13987 
13988 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13989 }
13990 
13991 static void
13992 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13993     int incr1, int incr2, int scale_idx)
13994 {
13995 
13996 	bwn_phy_lp_ddfs_turnoff(mac);
13997 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13998 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13999 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14000 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14001 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14002 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14003 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14004 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14005 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14006 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14007 }
14008 
14009 static uint8_t
14010 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14011     struct bwn_phy_lp_iq_est *ie)
14012 {
14013 	int i;
14014 
14015 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14016 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14017 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14018 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14019 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14020 
14021 	for (i = 0; i < 500; i++) {
14022 		if (!(BWN_PHY_READ(mac,
14023 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14024 			break;
14025 		DELAY(1000);
14026 	}
14027 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14028 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14029 		return 0;
14030 	}
14031 
14032 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14033 	ie->ie_iqprod <<= 16;
14034 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14035 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14036 	ie->ie_ipwr <<= 16;
14037 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14038 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14039 	ie->ie_qpwr <<= 16;
14040 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14041 
14042 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14043 	return 1;
14044 }
14045 
14046 static uint32_t
14047 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14048 {
14049 	uint32_t offset, type, value;
14050 
14051 	type = BWN_TAB_GETTYPE(typeoffset);
14052 	offset = BWN_TAB_GETOFFSET(typeoffset);
14053 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14054 
14055 	switch (type) {
14056 	case BWN_TAB_8BIT:
14057 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14058 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14059 		break;
14060 	case BWN_TAB_16BIT:
14061 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14062 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14063 		break;
14064 	case BWN_TAB_32BIT:
14065 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14066 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14067 		value <<= 16;
14068 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14069 		break;
14070 	default:
14071 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14072 		value = 0;
14073 	}
14074 
14075 	return (value);
14076 }
14077 
14078 static void
14079 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14080 {
14081 
14082 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14083 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14084 }
14085 
14086 static void
14087 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14088 {
14089 	uint16_t ctl;
14090 
14091 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14092 	ctl |= dac << 7;
14093 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14094 }
14095 
14096 static void
14097 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14098 {
14099 
14100 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14101 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14102 }
14103 
14104 static void
14105 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14106 {
14107 
14108 	if (mac->mac_phy.rev < 2)
14109 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14110 	else {
14111 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14112 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14113 	}
14114 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14115 }
14116 
14117 static uint16_t
14118 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14119 {
14120 
14121 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14122 }
14123 
14124 static uint8_t
14125 bwn_nbits(int32_t val)
14126 {
14127 	uint32_t tmp;
14128 	uint8_t nbits = 0;
14129 
14130 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14131 		nbits++;
14132 	return (nbits);
14133 }
14134 
14135 static void
14136 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14137     struct bwn_txgain_entry *table)
14138 {
14139 	int i;
14140 
14141 	for (i = offset; i < count; i++)
14142 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14143 }
14144 
14145 static void
14146 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14147     struct bwn_txgain_entry data)
14148 {
14149 
14150 	if (mac->mac_phy.rev >= 2)
14151 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14152 	else
14153 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14154 }
14155 
14156 static void
14157 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14158     struct bwn_txgain_entry te)
14159 {
14160 	struct bwn_softc *sc = mac->mac_sc;
14161 	struct ifnet *ifp = sc->sc_ifp;
14162 	struct ieee80211com *ic = ifp->if_l2com;
14163 	uint32_t tmp;
14164 
14165 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14166 
14167 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14168 	if (mac->mac_phy.rev >= 3) {
14169 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14170 		    (0x10 << 24) : (0x70 << 24));
14171 	} else {
14172 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14173 		    (0x14 << 24) : (0x7f << 24));
14174 	}
14175 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14176 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14177 	    te.te_bbmult << 20 | te.te_dac << 28);
14178 }
14179 
14180 static void
14181 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14182     struct bwn_txgain_entry te)
14183 {
14184 
14185 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14186 
14187 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14188 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14189 	    te.te_dac);
14190 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14191 }
14192 
14193 static void
14194 bwn_sysctl_node(struct bwn_softc *sc)
14195 {
14196 	device_t dev = sc->sc_dev;
14197 	struct bwn_mac *mac;
14198 	struct bwn_stats *stats;
14199 
14200 	/* XXX assume that count of MAC is only 1. */
14201 
14202 	if ((mac = sc->sc_curmac) == NULL)
14203 		return;
14204 	stats = &mac->mac_stats;
14205 
14206 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14207 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14208 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14209 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14210 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14211 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14212 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14213 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14214 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14215 
14216 #ifdef BWN_DEBUG
14217 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14218 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14219 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14220 #endif
14221 }
14222 
14223 static device_method_t bwn_methods[] = {
14224 	/* Device interface */
14225 	DEVMETHOD(device_probe,		bwn_probe),
14226 	DEVMETHOD(device_attach,	bwn_attach),
14227 	DEVMETHOD(device_detach,	bwn_detach),
14228 	DEVMETHOD(device_suspend,	bwn_suspend),
14229 	DEVMETHOD(device_resume,	bwn_resume),
14230 	DEVMETHOD_END
14231 };
14232 static driver_t bwn_driver = {
14233 	"bwn",
14234 	bwn_methods,
14235 	sizeof(struct bwn_softc)
14236 };
14237 static devclass_t bwn_devclass;
14238 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14239 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14240 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14241 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14242 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14243