xref: /freebsd/sys/dev/bwn/if_bwn.c (revision d1a0d267b78b542fbd7e6553af2493760f49bfa8)
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 = ic->ic_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_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 bwn_softc *sc = ic->ic_softc;
2843 	struct bwn_mac *mac;
2844 
2845 	BWN_LOCK(sc);
2846 	mac = sc->sc_curmac;
2847 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849 		bwn_set_opmode(mac);
2850 		/* disable CFP update during scan */
2851 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852 	}
2853 	BWN_UNLOCK(sc);
2854 }
2855 
2856 static void
2857 bwn_scan_end(struct ieee80211com *ic)
2858 {
2859 	struct bwn_softc *sc = ic->ic_softc;
2860 	struct bwn_mac *mac;
2861 
2862 	BWN_LOCK(sc);
2863 	mac = sc->sc_curmac;
2864 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2865 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2866 		bwn_set_opmode(mac);
2867 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2868 	}
2869 	BWN_UNLOCK(sc);
2870 }
2871 
2872 static void
2873 bwn_set_channel(struct ieee80211com *ic)
2874 {
2875 	struct bwn_softc *sc = ic->ic_softc;
2876 	struct bwn_mac *mac = sc->sc_curmac;
2877 	struct bwn_phy *phy = &mac->mac_phy;
2878 	int chan, error;
2879 
2880 	BWN_LOCK(sc);
2881 
2882 	error = bwn_switch_band(sc, ic->ic_curchan);
2883 	if (error)
2884 		goto fail;
2885 	bwn_mac_suspend(mac);
2886 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2887 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2888 	if (chan != phy->chan)
2889 		bwn_switch_channel(mac, chan);
2890 
2891 	/* TX power level */
2892 	if (ic->ic_curchan->ic_maxpower != 0 &&
2893 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2894 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2895 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2896 		    BWN_TXPWR_IGNORE_TSSI);
2897 	}
2898 
2899 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2900 	if (phy->set_antenna)
2901 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2902 
2903 	if (sc->sc_rf_enabled != phy->rf_on) {
2904 		if (sc->sc_rf_enabled) {
2905 			bwn_rf_turnon(mac);
2906 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2907 				device_printf(sc->sc_dev,
2908 				    "please turn on the RF switch\n");
2909 		} else
2910 			bwn_rf_turnoff(mac);
2911 	}
2912 
2913 	bwn_mac_enable(mac);
2914 
2915 fail:
2916 	/*
2917 	 * Setup radio tap channel freq and flags
2918 	 */
2919 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2920 		htole16(ic->ic_curchan->ic_freq);
2921 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2922 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2923 
2924 	BWN_UNLOCK(sc);
2925 }
2926 
2927 static struct ieee80211vap *
2928 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2929     enum ieee80211_opmode opmode, int flags,
2930     const uint8_t bssid[IEEE80211_ADDR_LEN],
2931     const uint8_t mac0[IEEE80211_ADDR_LEN])
2932 {
2933 	struct bwn_softc *sc = ic->ic_softc;
2934 	struct ieee80211vap *vap;
2935 	struct bwn_vap *bvp;
2936 	uint8_t mac[IEEE80211_ADDR_LEN];
2937 
2938 	IEEE80211_ADDR_COPY(mac, mac0);
2939 	switch (opmode) {
2940 	case IEEE80211_M_HOSTAP:
2941 	case IEEE80211_M_MBSS:
2942 	case IEEE80211_M_STA:
2943 	case IEEE80211_M_WDS:
2944 	case IEEE80211_M_MONITOR:
2945 	case IEEE80211_M_IBSS:
2946 	case IEEE80211_M_AHDEMO:
2947 		break;
2948 	default:
2949 		return (NULL);
2950 	}
2951 
2952 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2953 
2954 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2955 	    M_80211_VAP, M_NOWAIT | M_ZERO);
2956 	if (bvp == NULL) {
2957 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2958 		return (NULL);
2959 	}
2960 	vap = &bvp->bv_vap;
2961 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2962 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2963 	/* override with driver methods */
2964 	bvp->bv_newstate = vap->iv_newstate;
2965 	vap->iv_newstate = bwn_newstate;
2966 
2967 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2968 	vap->iv_max_aid = BWN_STAID_MAX;
2969 
2970 	ieee80211_ratectl_init(vap);
2971 
2972 	/* complete setup */
2973 	ieee80211_vap_attach(vap, ieee80211_media_change,
2974 	    ieee80211_media_status);
2975 	return (vap);
2976 }
2977 
2978 static void
2979 bwn_vap_delete(struct ieee80211vap *vap)
2980 {
2981 	struct bwn_vap *bvp = BWN_VAP(vap);
2982 
2983 	ieee80211_ratectl_deinit(vap);
2984 	ieee80211_vap_detach(vap);
2985 	free(bvp, M_80211_VAP);
2986 }
2987 
2988 static void
2989 bwn_init(void *arg)
2990 {
2991 	struct bwn_softc *sc = arg;
2992 	struct ifnet *ifp = sc->sc_ifp;
2993 	struct ieee80211com *ic = ifp->if_l2com;
2994 	int error = 0;
2995 
2996 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2997 		__func__, ifp->if_flags);
2998 
2999 	BWN_LOCK(sc);
3000 	error = bwn_init_locked(sc);
3001 	BWN_UNLOCK(sc);
3002 
3003 	if (error == 0)
3004 		ieee80211_start_all(ic);	/* start all vap's */
3005 }
3006 
3007 static int
3008 bwn_init_locked(struct bwn_softc *sc)
3009 {
3010 	struct bwn_mac *mac;
3011 	struct ifnet *ifp = sc->sc_ifp;
3012 	int error;
3013 
3014 	BWN_ASSERT_LOCKED(sc);
3015 
3016 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3017 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3018 	sc->sc_filters = 0;
3019 	bwn_wme_clear(sc);
3020 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3021 	sc->sc_rf_enabled = 1;
3022 
3023 	mac = sc->sc_curmac;
3024 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3025 		error = bwn_core_init(mac);
3026 		if (error != 0)
3027 			return (error);
3028 	}
3029 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3030 		bwn_core_start(mac);
3031 
3032 	bwn_set_opmode(mac);
3033 	bwn_set_pretbtt(mac);
3034 	bwn_spu_setdelay(mac, 0);
3035 	bwn_set_macaddr(mac);
3036 
3037 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3038 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3039 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3040 
3041 	return (0);
3042 }
3043 
3044 static void
3045 bwn_stop(struct bwn_softc *sc, int statechg)
3046 {
3047 
3048 	BWN_LOCK(sc);
3049 	bwn_stop_locked(sc, statechg);
3050 	BWN_UNLOCK(sc);
3051 }
3052 
3053 static void
3054 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3055 {
3056 	struct bwn_mac *mac = sc->sc_curmac;
3057 	struct ifnet *ifp = sc->sc_ifp;
3058 
3059 	BWN_ASSERT_LOCKED(sc);
3060 
3061 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3062 		/* XXX FIXME opmode not based on VAP */
3063 		bwn_set_opmode(mac);
3064 		bwn_set_macaddr(mac);
3065 	}
3066 
3067 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3068 		bwn_core_stop(mac);
3069 
3070 	callout_stop(&sc->sc_led_blink_ch);
3071 	sc->sc_led_blinking = 0;
3072 
3073 	bwn_core_exit(mac);
3074 	sc->sc_rf_enabled = 0;
3075 
3076 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3077 }
3078 
3079 static void
3080 bwn_wme_clear(struct bwn_softc *sc)
3081 {
3082 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3083 	struct wmeParams *p;
3084 	unsigned int i;
3085 
3086 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3087 	    ("%s:%d: fail", __func__, __LINE__));
3088 
3089 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3090 		p = &(sc->sc_wmeParams[i]);
3091 
3092 		switch (bwn_wme_shm_offsets[i]) {
3093 		case BWN_WME_VOICE:
3094 			p->wmep_txopLimit = 0;
3095 			p->wmep_aifsn = 2;
3096 			/* XXX FIXME: log2(cwmin) */
3097 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3098 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3099 			break;
3100 		case BWN_WME_VIDEO:
3101 			p->wmep_txopLimit = 0;
3102 			p->wmep_aifsn = 2;
3103 			/* XXX FIXME: log2(cwmin) */
3104 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3105 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3106 			break;
3107 		case BWN_WME_BESTEFFORT:
3108 			p->wmep_txopLimit = 0;
3109 			p->wmep_aifsn = 3;
3110 			/* XXX FIXME: log2(cwmin) */
3111 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3112 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3113 			break;
3114 		case BWN_WME_BACKGROUND:
3115 			p->wmep_txopLimit = 0;
3116 			p->wmep_aifsn = 7;
3117 			/* XXX FIXME: log2(cwmin) */
3118 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3119 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3120 			break;
3121 		default:
3122 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3123 		}
3124 	}
3125 }
3126 
3127 static int
3128 bwn_core_init(struct bwn_mac *mac)
3129 {
3130 	struct bwn_softc *sc = mac->mac_sc;
3131 	uint64_t hf;
3132 	int error;
3133 
3134 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3135 	    ("%s:%d: fail", __func__, __LINE__));
3136 
3137 	siba_powerup(sc->sc_dev, 0);
3138 	if (!siba_dev_isup(sc->sc_dev))
3139 		bwn_reset_core(mac,
3140 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3141 
3142 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3143 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3144 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3145 	BWN_GETTIME(mac->mac_phy.nexttime);
3146 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3147 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3148 	mac->mac_stats.link_noise = -95;
3149 	mac->mac_reason_intr = 0;
3150 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3151 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3152 #ifdef BWN_DEBUG
3153 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3154 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3155 #endif
3156 	mac->mac_suspended = 1;
3157 	mac->mac_task_state = 0;
3158 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3159 
3160 	mac->mac_phy.init_pre(mac);
3161 
3162 	siba_pcicore_intr(sc->sc_dev);
3163 
3164 	siba_fix_imcfglobug(sc->sc_dev);
3165 	bwn_bt_disable(mac);
3166 	if (mac->mac_phy.prepare_hw) {
3167 		error = mac->mac_phy.prepare_hw(mac);
3168 		if (error)
3169 			goto fail0;
3170 	}
3171 	error = bwn_chip_init(mac);
3172 	if (error)
3173 		goto fail0;
3174 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3175 	    siba_get_revid(sc->sc_dev));
3176 	hf = bwn_hf_read(mac);
3177 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3178 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3179 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3180 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3181 		if (mac->mac_phy.rev == 1)
3182 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3183 	}
3184 	if (mac->mac_phy.rf_ver == 0x2050) {
3185 		if (mac->mac_phy.rf_rev < 6)
3186 			hf |= BWN_HF_FORCE_VCO_RECALC;
3187 		if (mac->mac_phy.rf_rev == 6)
3188 			hf |= BWN_HF_4318_TSSI;
3189 	}
3190 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3191 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3192 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3193 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3194 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3195 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3196 	bwn_hf_write(mac, hf);
3197 
3198 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3199 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3200 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3201 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3202 
3203 	bwn_rate_init(mac);
3204 	bwn_set_phytxctl(mac);
3205 
3206 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3207 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3208 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3209 
3210 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3211 		bwn_pio_init(mac);
3212 	else
3213 		bwn_dma_init(mac);
3214 	bwn_wme_init(mac);
3215 	bwn_spu_setdelay(mac, 1);
3216 	bwn_bt_enable(mac);
3217 
3218 	siba_powerup(sc->sc_dev,
3219 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3220 	bwn_set_macaddr(mac);
3221 	bwn_crypt_init(mac);
3222 
3223 	/* XXX LED initializatin */
3224 
3225 	mac->mac_status = BWN_MAC_STATUS_INITED;
3226 
3227 	return (error);
3228 
3229 fail0:
3230 	siba_powerdown(sc->sc_dev);
3231 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3232 	    ("%s:%d: fail", __func__, __LINE__));
3233 	return (error);
3234 }
3235 
3236 static void
3237 bwn_core_start(struct bwn_mac *mac)
3238 {
3239 	struct bwn_softc *sc = mac->mac_sc;
3240 	uint32_t tmp;
3241 
3242 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3243 	    ("%s:%d: fail", __func__, __LINE__));
3244 
3245 	if (siba_get_revid(sc->sc_dev) < 5)
3246 		return;
3247 
3248 	while (1) {
3249 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3250 		if (!(tmp & 0x00000001))
3251 			break;
3252 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3253 	}
3254 
3255 	bwn_mac_enable(mac);
3256 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3257 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3258 
3259 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3260 }
3261 
3262 static void
3263 bwn_core_exit(struct bwn_mac *mac)
3264 {
3265 	struct bwn_softc *sc = mac->mac_sc;
3266 	uint32_t macctl;
3267 
3268 	BWN_ASSERT_LOCKED(mac->mac_sc);
3269 
3270 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3271 	    ("%s:%d: fail", __func__, __LINE__));
3272 
3273 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3274 		return;
3275 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3276 
3277 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3278 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3279 	macctl |= BWN_MACCTL_MCODE_JMP0;
3280 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3281 
3282 	bwn_dma_stop(mac);
3283 	bwn_pio_stop(mac);
3284 	bwn_chip_exit(mac);
3285 	mac->mac_phy.switch_analog(mac, 0);
3286 	siba_dev_down(sc->sc_dev, 0);
3287 	siba_powerdown(sc->sc_dev);
3288 }
3289 
3290 static void
3291 bwn_bt_disable(struct bwn_mac *mac)
3292 {
3293 	struct bwn_softc *sc = mac->mac_sc;
3294 
3295 	(void)sc;
3296 	/* XXX do nothing yet */
3297 }
3298 
3299 static int
3300 bwn_chip_init(struct bwn_mac *mac)
3301 {
3302 	struct bwn_softc *sc = mac->mac_sc;
3303 	struct bwn_phy *phy = &mac->mac_phy;
3304 	uint32_t macctl;
3305 	int error;
3306 
3307 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3308 	if (phy->gmode)
3309 		macctl |= BWN_MACCTL_GMODE;
3310 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3311 
3312 	error = bwn_fw_fillinfo(mac);
3313 	if (error)
3314 		return (error);
3315 	error = bwn_fw_loaducode(mac);
3316 	if (error)
3317 		return (error);
3318 
3319 	error = bwn_gpio_init(mac);
3320 	if (error)
3321 		return (error);
3322 
3323 	error = bwn_fw_loadinitvals(mac);
3324 	if (error) {
3325 		siba_gpio_set(sc->sc_dev, 0);
3326 		return (error);
3327 	}
3328 	phy->switch_analog(mac, 1);
3329 	error = bwn_phy_init(mac);
3330 	if (error) {
3331 		siba_gpio_set(sc->sc_dev, 0);
3332 		return (error);
3333 	}
3334 	if (phy->set_im)
3335 		phy->set_im(mac, BWN_IMMODE_NONE);
3336 	if (phy->set_antenna)
3337 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3338 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3339 
3340 	if (phy->type == BWN_PHYTYPE_B)
3341 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3342 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3343 	if (siba_get_revid(sc->sc_dev) < 5)
3344 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3345 
3346 	BWN_WRITE_4(mac, BWN_MACCTL,
3347 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3348 	BWN_WRITE_4(mac, BWN_MACCTL,
3349 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3350 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3351 
3352 	bwn_set_opmode(mac);
3353 	if (siba_get_revid(sc->sc_dev) < 3) {
3354 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3355 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3356 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3357 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3358 	} else {
3359 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3360 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3361 	}
3362 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3363 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3364 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3365 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3366 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3367 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3368 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3369 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3370 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3371 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3372 	return (error);
3373 }
3374 
3375 /* read hostflags */
3376 static uint64_t
3377 bwn_hf_read(struct bwn_mac *mac)
3378 {
3379 	uint64_t ret;
3380 
3381 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3382 	ret <<= 16;
3383 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3384 	ret <<= 16;
3385 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3386 	return (ret);
3387 }
3388 
3389 static void
3390 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3391 {
3392 
3393 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3394 	    (value & 0x00000000ffffull));
3395 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3396 	    (value & 0x0000ffff0000ull) >> 16);
3397 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3398 	    (value & 0xffff00000000ULL) >> 32);
3399 }
3400 
3401 static void
3402 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3403 {
3404 
3405 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3406 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3407 }
3408 
3409 static void
3410 bwn_rate_init(struct bwn_mac *mac)
3411 {
3412 
3413 	switch (mac->mac_phy.type) {
3414 	case BWN_PHYTYPE_A:
3415 	case BWN_PHYTYPE_G:
3416 	case BWN_PHYTYPE_LP:
3417 	case BWN_PHYTYPE_N:
3418 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3419 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3420 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3421 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3422 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3423 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3424 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3425 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3426 			break;
3427 		/* FALLTHROUGH */
3428 	case BWN_PHYTYPE_B:
3429 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3430 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3431 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3432 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3433 		break;
3434 	default:
3435 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3436 	}
3437 }
3438 
3439 static void
3440 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3441 {
3442 	uint16_t offset;
3443 
3444 	if (ofdm) {
3445 		offset = 0x480;
3446 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3447 	} else {
3448 		offset = 0x4c0;
3449 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3450 	}
3451 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3452 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3453 }
3454 
3455 static uint8_t
3456 bwn_plcp_getcck(const uint8_t bitrate)
3457 {
3458 
3459 	switch (bitrate) {
3460 	case BWN_CCK_RATE_1MB:
3461 		return (0x0a);
3462 	case BWN_CCK_RATE_2MB:
3463 		return (0x14);
3464 	case BWN_CCK_RATE_5MB:
3465 		return (0x37);
3466 	case BWN_CCK_RATE_11MB:
3467 		return (0x6e);
3468 	}
3469 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3470 	return (0);
3471 }
3472 
3473 static uint8_t
3474 bwn_plcp_getofdm(const uint8_t bitrate)
3475 {
3476 
3477 	switch (bitrate) {
3478 	case BWN_OFDM_RATE_6MB:
3479 		return (0xb);
3480 	case BWN_OFDM_RATE_9MB:
3481 		return (0xf);
3482 	case BWN_OFDM_RATE_12MB:
3483 		return (0xa);
3484 	case BWN_OFDM_RATE_18MB:
3485 		return (0xe);
3486 	case BWN_OFDM_RATE_24MB:
3487 		return (0x9);
3488 	case BWN_OFDM_RATE_36MB:
3489 		return (0xd);
3490 	case BWN_OFDM_RATE_48MB:
3491 		return (0x8);
3492 	case BWN_OFDM_RATE_54MB:
3493 		return (0xc);
3494 	}
3495 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3496 	return (0);
3497 }
3498 
3499 static void
3500 bwn_set_phytxctl(struct bwn_mac *mac)
3501 {
3502 	uint16_t ctl;
3503 
3504 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3505 	    BWN_TX_PHY_TXPWR);
3506 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3507 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3508 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3509 }
3510 
3511 static void
3512 bwn_pio_init(struct bwn_mac *mac)
3513 {
3514 	struct bwn_pio *pio = &mac->mac_method.pio;
3515 
3516 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3517 	    & ~BWN_MACCTL_BIGENDIAN);
3518 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3519 
3520 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3521 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3522 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3523 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3524 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3525 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3526 }
3527 
3528 static void
3529 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3530     int index)
3531 {
3532 	struct bwn_pio_txpkt *tp;
3533 	struct bwn_softc *sc = mac->mac_sc;
3534 	unsigned int i;
3535 
3536 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3537 	tq->tq_index = index;
3538 
3539 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3540 	if (siba_get_revid(sc->sc_dev) >= 8)
3541 		tq->tq_size = 1920;
3542 	else {
3543 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3544 		tq->tq_size -= 80;
3545 	}
3546 
3547 	TAILQ_INIT(&tq->tq_pktlist);
3548 	for (i = 0; i < N(tq->tq_pkts); i++) {
3549 		tp = &(tq->tq_pkts[i]);
3550 		tp->tp_index = i;
3551 		tp->tp_queue = tq;
3552 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3553 	}
3554 }
3555 
3556 static uint16_t
3557 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3558 {
3559 	struct bwn_softc *sc = mac->mac_sc;
3560 	static const uint16_t bases[] = {
3561 		BWN_PIO_BASE0,
3562 		BWN_PIO_BASE1,
3563 		BWN_PIO_BASE2,
3564 		BWN_PIO_BASE3,
3565 		BWN_PIO_BASE4,
3566 		BWN_PIO_BASE5,
3567 		BWN_PIO_BASE6,
3568 		BWN_PIO_BASE7,
3569 	};
3570 	static const uint16_t bases_rev11[] = {
3571 		BWN_PIO11_BASE0,
3572 		BWN_PIO11_BASE1,
3573 		BWN_PIO11_BASE2,
3574 		BWN_PIO11_BASE3,
3575 		BWN_PIO11_BASE4,
3576 		BWN_PIO11_BASE5,
3577 	};
3578 
3579 	if (siba_get_revid(sc->sc_dev) >= 11) {
3580 		if (index >= N(bases_rev11))
3581 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3582 		return (bases_rev11[index]);
3583 	}
3584 	if (index >= N(bases))
3585 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3586 	return (bases[index]);
3587 }
3588 
3589 static void
3590 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3591     int index)
3592 {
3593 	struct bwn_softc *sc = mac->mac_sc;
3594 
3595 	prq->prq_mac = mac;
3596 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3597 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3598 	bwn_dma_rxdirectfifo(mac, index, 1);
3599 }
3600 
3601 static void
3602 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3603 {
3604 	if (tq == NULL)
3605 		return;
3606 	bwn_pio_cancel_tx_packets(tq);
3607 }
3608 
3609 static void
3610 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3611 {
3612 
3613 	bwn_destroy_pioqueue_tx(pio);
3614 }
3615 
3616 static uint16_t
3617 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3618     uint16_t offset)
3619 {
3620 
3621 	return (BWN_READ_2(mac, tq->tq_base + offset));
3622 }
3623 
3624 static void
3625 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3626 {
3627 	uint32_t ctl;
3628 	int type;
3629 	uint16_t base;
3630 
3631 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3632 	base = bwn_dma_base(type, idx);
3633 	if (type == BWN_DMA_64BIT) {
3634 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3635 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3636 		if (enable)
3637 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3638 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3639 	} else {
3640 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3641 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3642 		if (enable)
3643 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3644 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3645 	}
3646 }
3647 
3648 static uint64_t
3649 bwn_dma_mask(struct bwn_mac *mac)
3650 {
3651 	uint32_t tmp;
3652 	uint16_t base;
3653 
3654 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3655 	if (tmp & SIBA_TGSHIGH_DMA64)
3656 		return (BWN_DMA_BIT_MASK(64));
3657 	base = bwn_dma_base(0, 0);
3658 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3659 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3660 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3661 		return (BWN_DMA_BIT_MASK(32));
3662 
3663 	return (BWN_DMA_BIT_MASK(30));
3664 }
3665 
3666 static int
3667 bwn_dma_mask2type(uint64_t dmamask)
3668 {
3669 
3670 	if (dmamask == BWN_DMA_BIT_MASK(30))
3671 		return (BWN_DMA_30BIT);
3672 	if (dmamask == BWN_DMA_BIT_MASK(32))
3673 		return (BWN_DMA_32BIT);
3674 	if (dmamask == BWN_DMA_BIT_MASK(64))
3675 		return (BWN_DMA_64BIT);
3676 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3677 	return (BWN_DMA_30BIT);
3678 }
3679 
3680 static void
3681 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3682 {
3683 	struct bwn_pio_txpkt *tp;
3684 	unsigned int i;
3685 
3686 	for (i = 0; i < N(tq->tq_pkts); i++) {
3687 		tp = &(tq->tq_pkts[i]);
3688 		if (tp->tp_m) {
3689 			m_freem(tp->tp_m);
3690 			tp->tp_m = NULL;
3691 		}
3692 	}
3693 }
3694 
3695 static uint16_t
3696 bwn_dma_base(int type, int controller_idx)
3697 {
3698 	static const uint16_t map64[] = {
3699 		BWN_DMA64_BASE0,
3700 		BWN_DMA64_BASE1,
3701 		BWN_DMA64_BASE2,
3702 		BWN_DMA64_BASE3,
3703 		BWN_DMA64_BASE4,
3704 		BWN_DMA64_BASE5,
3705 	};
3706 	static const uint16_t map32[] = {
3707 		BWN_DMA32_BASE0,
3708 		BWN_DMA32_BASE1,
3709 		BWN_DMA32_BASE2,
3710 		BWN_DMA32_BASE3,
3711 		BWN_DMA32_BASE4,
3712 		BWN_DMA32_BASE5,
3713 	};
3714 
3715 	if (type == BWN_DMA_64BIT) {
3716 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3717 		    ("%s:%d: fail", __func__, __LINE__));
3718 		return (map64[controller_idx]);
3719 	}
3720 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3721 	    ("%s:%d: fail", __func__, __LINE__));
3722 	return (map32[controller_idx]);
3723 }
3724 
3725 static void
3726 bwn_dma_init(struct bwn_mac *mac)
3727 {
3728 	struct bwn_dma *dma = &mac->mac_method.dma;
3729 
3730 	/* setup TX DMA channels. */
3731 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3732 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3733 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3734 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3735 	bwn_dma_setup(dma->mcast);
3736 	/* setup RX DMA channel. */
3737 	bwn_dma_setup(dma->rx);
3738 }
3739 
3740 static struct bwn_dma_ring *
3741 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3742     int for_tx, int type)
3743 {
3744 	struct bwn_dma *dma = &mac->mac_method.dma;
3745 	struct bwn_dma_ring *dr;
3746 	struct bwn_dmadesc_generic *desc;
3747 	struct bwn_dmadesc_meta *mt;
3748 	struct bwn_softc *sc = mac->mac_sc;
3749 	int error, i;
3750 
3751 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3752 	if (dr == NULL)
3753 		goto out;
3754 	dr->dr_numslots = BWN_RXRING_SLOTS;
3755 	if (for_tx)
3756 		dr->dr_numslots = BWN_TXRING_SLOTS;
3757 
3758 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3759 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3760 	if (dr->dr_meta == NULL)
3761 		goto fail0;
3762 
3763 	dr->dr_type = type;
3764 	dr->dr_mac = mac;
3765 	dr->dr_base = bwn_dma_base(type, controller_index);
3766 	dr->dr_index = controller_index;
3767 	if (type == BWN_DMA_64BIT) {
3768 		dr->getdesc = bwn_dma_64_getdesc;
3769 		dr->setdesc = bwn_dma_64_setdesc;
3770 		dr->start_transfer = bwn_dma_64_start_transfer;
3771 		dr->suspend = bwn_dma_64_suspend;
3772 		dr->resume = bwn_dma_64_resume;
3773 		dr->get_curslot = bwn_dma_64_get_curslot;
3774 		dr->set_curslot = bwn_dma_64_set_curslot;
3775 	} else {
3776 		dr->getdesc = bwn_dma_32_getdesc;
3777 		dr->setdesc = bwn_dma_32_setdesc;
3778 		dr->start_transfer = bwn_dma_32_start_transfer;
3779 		dr->suspend = bwn_dma_32_suspend;
3780 		dr->resume = bwn_dma_32_resume;
3781 		dr->get_curslot = bwn_dma_32_get_curslot;
3782 		dr->set_curslot = bwn_dma_32_set_curslot;
3783 	}
3784 	if (for_tx) {
3785 		dr->dr_tx = 1;
3786 		dr->dr_curslot = -1;
3787 	} else {
3788 		if (dr->dr_index == 0) {
3789 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3790 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3791 		} else
3792 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3793 	}
3794 
3795 	error = bwn_dma_allocringmemory(dr);
3796 	if (error)
3797 		goto fail2;
3798 
3799 	if (for_tx) {
3800 		/*
3801 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3802 		 * BWN_TX_SLOTS_PER_FRAME
3803 		 */
3804 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3805 		    ("%s:%d: fail", __func__, __LINE__));
3806 
3807 		dr->dr_txhdr_cache =
3808 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3809 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3810 		KASSERT(dr->dr_txhdr_cache != NULL,
3811 		    ("%s:%d: fail", __func__, __LINE__));
3812 
3813 		/*
3814 		 * Create TX ring DMA stuffs
3815 		 */
3816 		error = bus_dma_tag_create(dma->parent_dtag,
3817 				    BWN_ALIGN, 0,
3818 				    BUS_SPACE_MAXADDR,
3819 				    BUS_SPACE_MAXADDR,
3820 				    NULL, NULL,
3821 				    BWN_HDRSIZE(mac),
3822 				    1,
3823 				    BUS_SPACE_MAXSIZE_32BIT,
3824 				    0,
3825 				    NULL, NULL,
3826 				    &dr->dr_txring_dtag);
3827 		if (error) {
3828 			device_printf(sc->sc_dev,
3829 			    "can't create TX ring DMA tag: TODO frees\n");
3830 			goto fail1;
3831 		}
3832 
3833 		for (i = 0; i < dr->dr_numslots; i += 2) {
3834 			dr->getdesc(dr, i, &desc, &mt);
3835 
3836 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3837 			mt->mt_m = NULL;
3838 			mt->mt_ni = NULL;
3839 			mt->mt_islast = 0;
3840 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3841 			    &mt->mt_dmap);
3842 			if (error) {
3843 				device_printf(sc->sc_dev,
3844 				     "can't create RX buf DMA map\n");
3845 				goto fail1;
3846 			}
3847 
3848 			dr->getdesc(dr, i + 1, &desc, &mt);
3849 
3850 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3851 			mt->mt_m = NULL;
3852 			mt->mt_ni = NULL;
3853 			mt->mt_islast = 1;
3854 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3855 			    &mt->mt_dmap);
3856 			if (error) {
3857 				device_printf(sc->sc_dev,
3858 				     "can't create RX buf DMA map\n");
3859 				goto fail1;
3860 			}
3861 		}
3862 	} else {
3863 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3864 		    &dr->dr_spare_dmap);
3865 		if (error) {
3866 			device_printf(sc->sc_dev,
3867 			    "can't create RX buf DMA map\n");
3868 			goto out;		/* XXX wrong! */
3869 		}
3870 
3871 		for (i = 0; i < dr->dr_numslots; i++) {
3872 			dr->getdesc(dr, i, &desc, &mt);
3873 
3874 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3875 			    &mt->mt_dmap);
3876 			if (error) {
3877 				device_printf(sc->sc_dev,
3878 				    "can't create RX buf DMA map\n");
3879 				goto out;	/* XXX wrong! */
3880 			}
3881 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3882 			if (error) {
3883 				device_printf(sc->sc_dev,
3884 				    "failed to allocate RX buf\n");
3885 				goto out;	/* XXX wrong! */
3886 			}
3887 		}
3888 
3889 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3890 		    BUS_DMASYNC_PREWRITE);
3891 
3892 		dr->dr_usedslot = dr->dr_numslots;
3893 	}
3894 
3895       out:
3896 	return (dr);
3897 
3898 fail2:
3899 	free(dr->dr_txhdr_cache, M_DEVBUF);
3900 fail1:
3901 	free(dr->dr_meta, M_DEVBUF);
3902 fail0:
3903 	free(dr, M_DEVBUF);
3904 	return (NULL);
3905 }
3906 
3907 static void
3908 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3909 {
3910 
3911 	if (dr == NULL)
3912 		return;
3913 
3914 	bwn_dma_free_descbufs(*dr);
3915 	bwn_dma_free_ringmemory(*dr);
3916 
3917 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3918 	free((*dr)->dr_meta, M_DEVBUF);
3919 	free(*dr, M_DEVBUF);
3920 
3921 	*dr = NULL;
3922 }
3923 
3924 static void
3925 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3926     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3927 {
3928 	struct bwn_dmadesc32 *desc;
3929 
3930 	*meta = &(dr->dr_meta[slot]);
3931 	desc = dr->dr_ring_descbase;
3932 	desc = &(desc[slot]);
3933 
3934 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3935 }
3936 
3937 static void
3938 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3939     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3940     int start, int end, int irq)
3941 {
3942 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3943 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3944 	uint32_t addr, addrext, ctl;
3945 	int slot;
3946 
3947 	slot = (int)(&(desc->dma.dma32) - descbase);
3948 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3949 	    ("%s:%d: fail", __func__, __LINE__));
3950 
3951 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3952 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3953 	addr |= siba_dma_translation(sc->sc_dev);
3954 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3955 	if (slot == dr->dr_numslots - 1)
3956 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3957 	if (start)
3958 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3959 	if (end)
3960 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3961 	if (irq)
3962 		ctl |= BWN_DMA32_DCTL_IRQ;
3963 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3964 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3965 
3966 	desc->dma.dma32.control = htole32(ctl);
3967 	desc->dma.dma32.address = htole32(addr);
3968 }
3969 
3970 static void
3971 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3972 {
3973 
3974 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3975 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3976 }
3977 
3978 static void
3979 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3980 {
3981 
3982 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3983 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3984 }
3985 
3986 static void
3987 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3988 {
3989 
3990 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3991 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3992 }
3993 
3994 static int
3995 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3996 {
3997 	uint32_t val;
3998 
3999 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4000 	val &= BWN_DMA32_RXDPTR;
4001 
4002 	return (val / sizeof(struct bwn_dmadesc32));
4003 }
4004 
4005 static void
4006 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4007 {
4008 
4009 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4010 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4011 }
4012 
4013 static void
4014 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4015     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4016 {
4017 	struct bwn_dmadesc64 *desc;
4018 
4019 	*meta = &(dr->dr_meta[slot]);
4020 	desc = dr->dr_ring_descbase;
4021 	desc = &(desc[slot]);
4022 
4023 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4024 }
4025 
4026 static void
4027 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4028     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4029     int start, int end, int irq)
4030 {
4031 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4032 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4033 	int slot;
4034 	uint32_t ctl0 = 0, ctl1 = 0;
4035 	uint32_t addrlo, addrhi;
4036 	uint32_t addrext;
4037 
4038 	slot = (int)(&(desc->dma.dma64) - descbase);
4039 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4040 	    ("%s:%d: fail", __func__, __LINE__));
4041 
4042 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4043 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4044 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4045 	    30;
4046 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4047 	if (slot == dr->dr_numslots - 1)
4048 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4049 	if (start)
4050 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4051 	if (end)
4052 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4053 	if (irq)
4054 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4055 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4056 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4057 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4058 
4059 	desc->dma.dma64.control0 = htole32(ctl0);
4060 	desc->dma.dma64.control1 = htole32(ctl1);
4061 	desc->dma.dma64.address_low = htole32(addrlo);
4062 	desc->dma.dma64.address_high = htole32(addrhi);
4063 }
4064 
4065 static void
4066 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4067 {
4068 
4069 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4070 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4071 }
4072 
4073 static void
4074 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4075 {
4076 
4077 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4078 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4079 }
4080 
4081 static void
4082 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4083 {
4084 
4085 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4086 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4087 }
4088 
4089 static int
4090 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4091 {
4092 	uint32_t val;
4093 
4094 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4095 	val &= BWN_DMA64_RXSTATDPTR;
4096 
4097 	return (val / sizeof(struct bwn_dmadesc64));
4098 }
4099 
4100 static void
4101 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4102 {
4103 
4104 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4105 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4106 }
4107 
4108 static int
4109 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4110 {
4111 	struct bwn_mac *mac = dr->dr_mac;
4112 	struct bwn_dma *dma = &mac->mac_method.dma;
4113 	struct bwn_softc *sc = mac->mac_sc;
4114 	int error;
4115 
4116 	error = bus_dma_tag_create(dma->parent_dtag,
4117 			    BWN_ALIGN, 0,
4118 			    BUS_SPACE_MAXADDR,
4119 			    BUS_SPACE_MAXADDR,
4120 			    NULL, NULL,
4121 			    BWN_DMA_RINGMEMSIZE,
4122 			    1,
4123 			    BUS_SPACE_MAXSIZE_32BIT,
4124 			    0,
4125 			    NULL, NULL,
4126 			    &dr->dr_ring_dtag);
4127 	if (error) {
4128 		device_printf(sc->sc_dev,
4129 		    "can't create TX ring DMA tag: TODO frees\n");
4130 		return (-1);
4131 	}
4132 
4133 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4134 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4135 	    &dr->dr_ring_dmap);
4136 	if (error) {
4137 		device_printf(sc->sc_dev,
4138 		    "can't allocate DMA mem: TODO frees\n");
4139 		return (-1);
4140 	}
4141 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4142 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4143 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4144 	if (error) {
4145 		device_printf(sc->sc_dev,
4146 		    "can't load DMA mem: TODO free\n");
4147 		return (-1);
4148 	}
4149 
4150 	return (0);
4151 }
4152 
4153 static void
4154 bwn_dma_setup(struct bwn_dma_ring *dr)
4155 {
4156 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4157 	uint64_t ring64;
4158 	uint32_t addrext, ring32, value;
4159 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4160 
4161 	if (dr->dr_tx) {
4162 		dr->dr_curslot = -1;
4163 
4164 		if (dr->dr_type == BWN_DMA_64BIT) {
4165 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4166 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4167 			    >> 30;
4168 			value = BWN_DMA64_TXENABLE;
4169 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4170 			    & BWN_DMA64_TXADDREXT_MASK;
4171 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4172 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4173 			    (ring64 & 0xffffffff));
4174 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4175 			    ((ring64 >> 32) &
4176 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4177 		} else {
4178 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4179 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4180 			value = BWN_DMA32_TXENABLE;
4181 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4182 			    & BWN_DMA32_TXADDREXT_MASK;
4183 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4184 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4185 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4186 		}
4187 		return;
4188 	}
4189 
4190 	/*
4191 	 * set for RX
4192 	 */
4193 	dr->dr_usedslot = dr->dr_numslots;
4194 
4195 	if (dr->dr_type == BWN_DMA_64BIT) {
4196 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4197 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4198 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4199 		value |= BWN_DMA64_RXENABLE;
4200 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4201 		    & BWN_DMA64_RXADDREXT_MASK;
4202 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4203 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4204 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4205 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4206 		    | (trans << 1));
4207 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4208 		    sizeof(struct bwn_dmadesc64));
4209 	} else {
4210 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4211 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4212 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4213 		value |= BWN_DMA32_RXENABLE;
4214 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4215 		    & BWN_DMA32_RXADDREXT_MASK;
4216 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4217 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4218 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4219 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4220 		    sizeof(struct bwn_dmadesc32));
4221 	}
4222 }
4223 
4224 static void
4225 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4226 {
4227 
4228 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4229 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4230 	    dr->dr_ring_dmap);
4231 }
4232 
4233 static void
4234 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4235 {
4236 
4237 	if (dr->dr_tx) {
4238 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4239 		if (dr->dr_type == BWN_DMA_64BIT) {
4240 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4241 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4242 		} else
4243 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4244 	} else {
4245 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4246 		if (dr->dr_type == BWN_DMA_64BIT) {
4247 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4248 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4249 		} else
4250 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4251 	}
4252 }
4253 
4254 static void
4255 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4256 {
4257 	struct bwn_dmadesc_generic *desc;
4258 	struct bwn_dmadesc_meta *meta;
4259 	struct bwn_mac *mac = dr->dr_mac;
4260 	struct bwn_dma *dma = &mac->mac_method.dma;
4261 	struct bwn_softc *sc = mac->mac_sc;
4262 	int i;
4263 
4264 	if (!dr->dr_usedslot)
4265 		return;
4266 	for (i = 0; i < dr->dr_numslots; i++) {
4267 		dr->getdesc(dr, i, &desc, &meta);
4268 
4269 		if (meta->mt_m == NULL) {
4270 			if (!dr->dr_tx)
4271 				device_printf(sc->sc_dev, "%s: not TX?\n",
4272 				    __func__);
4273 			continue;
4274 		}
4275 		if (dr->dr_tx) {
4276 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4277 				bus_dmamap_unload(dr->dr_txring_dtag,
4278 				    meta->mt_dmap);
4279 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4280 				bus_dmamap_unload(dma->txbuf_dtag,
4281 				    meta->mt_dmap);
4282 		} else
4283 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4284 		bwn_dma_free_descbuf(dr, meta);
4285 	}
4286 }
4287 
4288 static int
4289 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4290     int type)
4291 {
4292 	struct bwn_softc *sc = mac->mac_sc;
4293 	uint32_t value;
4294 	int i;
4295 	uint16_t offset;
4296 
4297 	for (i = 0; i < 10; i++) {
4298 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4299 		    BWN_DMA32_TXSTATUS;
4300 		value = BWN_READ_4(mac, base + offset);
4301 		if (type == BWN_DMA_64BIT) {
4302 			value &= BWN_DMA64_TXSTAT;
4303 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4304 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4305 			    value == BWN_DMA64_TXSTAT_STOPPED)
4306 				break;
4307 		} else {
4308 			value &= BWN_DMA32_TXSTATE;
4309 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4310 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4311 			    value == BWN_DMA32_TXSTAT_STOPPED)
4312 				break;
4313 		}
4314 		DELAY(1000);
4315 	}
4316 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4317 	BWN_WRITE_4(mac, base + offset, 0);
4318 	for (i = 0; i < 10; i++) {
4319 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4320 						   BWN_DMA32_TXSTATUS;
4321 		value = BWN_READ_4(mac, base + offset);
4322 		if (type == BWN_DMA_64BIT) {
4323 			value &= BWN_DMA64_TXSTAT;
4324 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4325 				i = -1;
4326 				break;
4327 			}
4328 		} else {
4329 			value &= BWN_DMA32_TXSTATE;
4330 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4331 				i = -1;
4332 				break;
4333 			}
4334 		}
4335 		DELAY(1000);
4336 	}
4337 	if (i != -1) {
4338 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4339 		return (ENODEV);
4340 	}
4341 	DELAY(1000);
4342 
4343 	return (0);
4344 }
4345 
4346 static int
4347 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4348     int type)
4349 {
4350 	struct bwn_softc *sc = mac->mac_sc;
4351 	uint32_t value;
4352 	int i;
4353 	uint16_t offset;
4354 
4355 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4356 	BWN_WRITE_4(mac, base + offset, 0);
4357 	for (i = 0; i < 10; i++) {
4358 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4359 		    BWN_DMA32_RXSTATUS;
4360 		value = BWN_READ_4(mac, base + offset);
4361 		if (type == BWN_DMA_64BIT) {
4362 			value &= BWN_DMA64_RXSTAT;
4363 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4364 				i = -1;
4365 				break;
4366 			}
4367 		} else {
4368 			value &= BWN_DMA32_RXSTATE;
4369 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4370 				i = -1;
4371 				break;
4372 			}
4373 		}
4374 		DELAY(1000);
4375 	}
4376 	if (i != -1) {
4377 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4378 		return (ENODEV);
4379 	}
4380 
4381 	return (0);
4382 }
4383 
4384 static void
4385 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4386     struct bwn_dmadesc_meta *meta)
4387 {
4388 
4389 	if (meta->mt_m != NULL) {
4390 		m_freem(meta->mt_m);
4391 		meta->mt_m = NULL;
4392 	}
4393 	if (meta->mt_ni != NULL) {
4394 		ieee80211_free_node(meta->mt_ni);
4395 		meta->mt_ni = NULL;
4396 	}
4397 }
4398 
4399 static void
4400 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4401 {
4402 	struct bwn_rxhdr4 *rxhdr;
4403 	unsigned char *frame;
4404 
4405 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4406 	rxhdr->frame_len = 0;
4407 
4408 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4409 	    sizeof(struct bwn_plcp6) + 2,
4410 	    ("%s:%d: fail", __func__, __LINE__));
4411 	frame = mtod(m, char *) + dr->dr_frameoffset;
4412 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4413 }
4414 
4415 static uint8_t
4416 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4417 {
4418 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4419 
4420 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4421 	    == 0xff);
4422 }
4423 
4424 static void
4425 bwn_wme_init(struct bwn_mac *mac)
4426 {
4427 
4428 	bwn_wme_load(mac);
4429 
4430 	/* enable WME support. */
4431 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4432 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4433 	    BWN_IFSCTL_USE_EDCF);
4434 }
4435 
4436 static void
4437 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4438 {
4439 	struct bwn_softc *sc = mac->mac_sc;
4440 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4441 	uint16_t delay;	/* microsec */
4442 
4443 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4444 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4445 		delay = 500;
4446 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4447 		delay = max(delay, (uint16_t)2400);
4448 
4449 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4450 }
4451 
4452 static void
4453 bwn_bt_enable(struct bwn_mac *mac)
4454 {
4455 	struct bwn_softc *sc = mac->mac_sc;
4456 	uint64_t hf;
4457 
4458 	if (bwn_bluetooth == 0)
4459 		return;
4460 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4461 		return;
4462 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4463 		return;
4464 
4465 	hf = bwn_hf_read(mac);
4466 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4467 		hf |= BWN_HF_BT_COEXISTALT;
4468 	else
4469 		hf |= BWN_HF_BT_COEXIST;
4470 	bwn_hf_write(mac, hf);
4471 }
4472 
4473 static void
4474 bwn_set_macaddr(struct bwn_mac *mac)
4475 {
4476 
4477 	bwn_mac_write_bssid(mac);
4478 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4479 }
4480 
4481 static void
4482 bwn_clear_keys(struct bwn_mac *mac)
4483 {
4484 	int i;
4485 
4486 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4487 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4488 		    ("%s:%d: fail", __func__, __LINE__));
4489 
4490 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4491 		    NULL, BWN_SEC_KEYSIZE, NULL);
4492 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4493 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4494 			    NULL, BWN_SEC_KEYSIZE, NULL);
4495 		}
4496 		mac->mac_key[i].keyconf = NULL;
4497 	}
4498 }
4499 
4500 static void
4501 bwn_crypt_init(struct bwn_mac *mac)
4502 {
4503 	struct bwn_softc *sc = mac->mac_sc;
4504 
4505 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4506 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4507 	    ("%s:%d: fail", __func__, __LINE__));
4508 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4509 	mac->mac_ktp *= 2;
4510 	if (siba_get_revid(sc->sc_dev) >= 5)
4511 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4512 	bwn_clear_keys(mac);
4513 }
4514 
4515 static void
4516 bwn_chip_exit(struct bwn_mac *mac)
4517 {
4518 	struct bwn_softc *sc = mac->mac_sc;
4519 
4520 	bwn_phy_exit(mac);
4521 	siba_gpio_set(sc->sc_dev, 0);
4522 }
4523 
4524 static int
4525 bwn_fw_fillinfo(struct bwn_mac *mac)
4526 {
4527 	int error;
4528 
4529 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4530 	if (error == 0)
4531 		return (0);
4532 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4533 	if (error == 0)
4534 		return (0);
4535 	return (error);
4536 }
4537 
4538 static int
4539 bwn_gpio_init(struct bwn_mac *mac)
4540 {
4541 	struct bwn_softc *sc = mac->mac_sc;
4542 	uint32_t mask = 0x1f, set = 0xf, value;
4543 
4544 	BWN_WRITE_4(mac, BWN_MACCTL,
4545 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4546 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4547 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4548 
4549 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4550 		mask |= 0x0060;
4551 		set |= 0x0060;
4552 	}
4553 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4554 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4555 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4556 		mask |= 0x0200;
4557 		set |= 0x0200;
4558 	}
4559 	if (siba_get_revid(sc->sc_dev) >= 2)
4560 		mask |= 0x0010;
4561 
4562 	value = siba_gpio_get(sc->sc_dev);
4563 	if (value == -1)
4564 		return (0);
4565 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4566 
4567 	return (0);
4568 }
4569 
4570 static int
4571 bwn_fw_loadinitvals(struct bwn_mac *mac)
4572 {
4573 #define	GETFWOFFSET(fwp, offset)				\
4574 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4575 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4576 	const struct bwn_fwhdr *hdr;
4577 	struct bwn_fw *fw = &mac->mac_fw;
4578 	int error;
4579 
4580 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4581 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4582 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4583 	if (error)
4584 		return (error);
4585 	if (fw->initvals_band.fw) {
4586 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4587 		error = bwn_fwinitvals_write(mac,
4588 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4589 		    be32toh(hdr->size),
4590 		    fw->initvals_band.fw->datasize - hdr_len);
4591 	}
4592 	return (error);
4593 #undef GETFWOFFSET
4594 }
4595 
4596 static int
4597 bwn_phy_init(struct bwn_mac *mac)
4598 {
4599 	struct bwn_softc *sc = mac->mac_sc;
4600 	int error;
4601 
4602 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4603 	mac->mac_phy.rf_onoff(mac, 1);
4604 	error = mac->mac_phy.init(mac);
4605 	if (error) {
4606 		device_printf(sc->sc_dev, "PHY init failed\n");
4607 		goto fail0;
4608 	}
4609 	error = bwn_switch_channel(mac,
4610 	    mac->mac_phy.get_default_chan(mac));
4611 	if (error) {
4612 		device_printf(sc->sc_dev,
4613 		    "failed to switch default channel\n");
4614 		goto fail1;
4615 	}
4616 	return (0);
4617 fail1:
4618 	if (mac->mac_phy.exit)
4619 		mac->mac_phy.exit(mac);
4620 fail0:
4621 	mac->mac_phy.rf_onoff(mac, 0);
4622 
4623 	return (error);
4624 }
4625 
4626 static void
4627 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4628 {
4629 	uint16_t ant;
4630 	uint16_t tmp;
4631 
4632 	ant = bwn_ant2phy(antenna);
4633 
4634 	/* For ACK/CTS */
4635 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4636 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4637 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4638 	/* For Probe Resposes */
4639 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4640 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4641 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4642 }
4643 
4644 static void
4645 bwn_set_opmode(struct bwn_mac *mac)
4646 {
4647 	struct bwn_softc *sc = mac->mac_sc;
4648 	struct ifnet *ifp = sc->sc_ifp;
4649 	struct ieee80211com *ic = ifp->if_l2com;
4650 	uint32_t ctl;
4651 	uint16_t cfp_pretbtt;
4652 
4653 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4654 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4655 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4656 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4657 	ctl |= BWN_MACCTL_STA;
4658 
4659 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4660 	    ic->ic_opmode == IEEE80211_M_MBSS)
4661 		ctl |= BWN_MACCTL_HOSTAP;
4662 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4663 		ctl &= ~BWN_MACCTL_STA;
4664 	ctl |= sc->sc_filters;
4665 
4666 	if (siba_get_revid(sc->sc_dev) <= 4)
4667 		ctl |= BWN_MACCTL_PROMISC;
4668 
4669 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4670 
4671 	cfp_pretbtt = 2;
4672 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4673 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4674 		    siba_get_chiprev(sc->sc_dev) == 3)
4675 			cfp_pretbtt = 100;
4676 		else
4677 			cfp_pretbtt = 50;
4678 	}
4679 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4680 }
4681 
4682 static int
4683 bwn_dma_gettype(struct bwn_mac *mac)
4684 {
4685 	uint32_t tmp;
4686 	uint16_t base;
4687 
4688 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4689 	if (tmp & SIBA_TGSHIGH_DMA64)
4690 		return (BWN_DMA_64BIT);
4691 	base = bwn_dma_base(0, 0);
4692 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4693 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4694 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4695 		return (BWN_DMA_32BIT);
4696 
4697 	return (BWN_DMA_30BIT);
4698 }
4699 
4700 static void
4701 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4702 {
4703 	if (!error) {
4704 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4705 		*((bus_addr_t *)arg) = seg->ds_addr;
4706 	}
4707 }
4708 
4709 static void
4710 bwn_phy_g_init_sub(struct bwn_mac *mac)
4711 {
4712 	struct bwn_phy *phy = &mac->mac_phy;
4713 	struct bwn_phy_g *pg = &phy->phy_g;
4714 	struct bwn_softc *sc = mac->mac_sc;
4715 	uint16_t i, tmp;
4716 
4717 	if (phy->rev == 1)
4718 		bwn_phy_init_b5(mac);
4719 	else
4720 		bwn_phy_init_b6(mac);
4721 
4722 	if (phy->rev >= 2 || phy->gmode)
4723 		bwn_phy_init_a(mac);
4724 
4725 	if (phy->rev >= 2) {
4726 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4727 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4728 	}
4729 	if (phy->rev == 2) {
4730 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4731 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4732 	}
4733 	if (phy->rev > 5) {
4734 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4735 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4736 	}
4737 	if (phy->gmode || phy->rev >= 2) {
4738 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4739 		tmp &= BWN_PHYVER_VERSION;
4740 		if (tmp == 3 || tmp == 5) {
4741 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4742 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4743 		}
4744 		if (tmp == 5) {
4745 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4746 			    0x1f00);
4747 		}
4748 	}
4749 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4750 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4751 	if (phy->rf_rev == 8) {
4752 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4753 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4754 	}
4755 	if (BWN_HAS_LOOPBACK(phy))
4756 		bwn_loopback_calcgain(mac);
4757 
4758 	if (phy->rf_rev != 8) {
4759 		if (pg->pg_initval == 0xffff)
4760 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4761 		else
4762 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4763 	}
4764 	bwn_lo_g_init(mac);
4765 	if (BWN_HAS_TXMAG(phy)) {
4766 		BWN_RF_WRITE(mac, 0x52,
4767 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4768 		    | pg->pg_loctl.tx_bias |
4769 		    pg->pg_loctl.tx_magn);
4770 	} else {
4771 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4772 	}
4773 	if (phy->rev >= 6) {
4774 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4775 		    (pg->pg_loctl.tx_bias << 12));
4776 	}
4777 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4778 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4779 	else
4780 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4781 	if (phy->rev < 2)
4782 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4783 	else
4784 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4785 	if (phy->gmode || phy->rev >= 2) {
4786 		bwn_lo_g_adjust(mac);
4787 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4788 	}
4789 
4790 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4791 		for (i = 0; i < 64; i++) {
4792 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4793 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4794 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4795 			    -32), 31));
4796 		}
4797 		bwn_nrssi_threshold(mac);
4798 	} else if (phy->gmode || phy->rev >= 2) {
4799 		if (pg->pg_nrssi[0] == -1000) {
4800 			KASSERT(pg->pg_nrssi[1] == -1000,
4801 			    ("%s:%d: fail", __func__, __LINE__));
4802 			bwn_nrssi_slope_11g(mac);
4803 		} else
4804 			bwn_nrssi_threshold(mac);
4805 	}
4806 	if (phy->rf_rev == 8)
4807 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4808 	bwn_phy_hwpctl_init(mac);
4809 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4810 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4811 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4812 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4813 	}
4814 }
4815 
4816 static uint8_t
4817 bwn_has_hwpctl(struct bwn_mac *mac)
4818 {
4819 
4820 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4821 		return (0);
4822 	return (mac->mac_phy.use_hwpctl(mac));
4823 }
4824 
4825 static void
4826 bwn_phy_init_b5(struct bwn_mac *mac)
4827 {
4828 	struct bwn_phy *phy = &mac->mac_phy;
4829 	struct bwn_phy_g *pg = &phy->phy_g;
4830 	struct bwn_softc *sc = mac->mac_sc;
4831 	uint16_t offset, value;
4832 	uint8_t old_channel;
4833 
4834 	if (phy->analog == 1)
4835 		BWN_RF_SET(mac, 0x007a, 0x0050);
4836 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4837 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4838 		value = 0x2120;
4839 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4840 			BWN_PHY_WRITE(mac, offset, value);
4841 			value += 0x202;
4842 		}
4843 	}
4844 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4845 	if (phy->rf_ver == 0x2050)
4846 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4847 
4848 	if (phy->gmode || phy->rev >= 2) {
4849 		if (phy->rf_ver == 0x2050) {
4850 			BWN_RF_SET(mac, 0x007a, 0x0020);
4851 			BWN_RF_SET(mac, 0x0051, 0x0004);
4852 		}
4853 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4854 
4855 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4856 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4857 
4858 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4859 
4860 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4861 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4862 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4863 	}
4864 
4865 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4866 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4867 
4868 	if (phy->analog == 1) {
4869 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4870 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4871 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4872 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4873 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4874 	} else
4875 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4876 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4877 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4878 
4879 	if (phy->analog == 1)
4880 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4881 	else
4882 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4883 
4884 	if (phy->analog == 0)
4885 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4886 
4887 	old_channel = phy->chan;
4888 	bwn_phy_g_switch_chan(mac, 7, 0);
4889 
4890 	if (phy->rf_ver != 0x2050) {
4891 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4892 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4893 	}
4894 
4895 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4896 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4897 
4898 	if (phy->rf_ver == 0x2050) {
4899 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4900 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4901 	}
4902 
4903 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4904 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4905 	BWN_RF_SET(mac, 0x007a, 0x0007);
4906 
4907 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4908 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4909 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4910 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4911 
4912 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4913 	    pg->pg_txctl);
4914 
4915 	if (phy->rf_ver == 0x2050)
4916 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4917 
4918 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4919 }
4920 
4921 static void
4922 bwn_loopback_calcgain(struct bwn_mac *mac)
4923 {
4924 	struct bwn_phy *phy = &mac->mac_phy;
4925 	struct bwn_phy_g *pg = &phy->phy_g;
4926 	struct bwn_softc *sc = mac->mac_sc;
4927 	uint16_t backup_phy[16] = { 0 };
4928 	uint16_t backup_radio[3];
4929 	uint16_t backup_bband;
4930 	uint16_t i, j, loop_i_max;
4931 	uint16_t trsw_rx;
4932 	uint16_t loop1_outer_done, loop1_inner_done;
4933 
4934 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4935 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4936 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4937 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4938 	if (phy->rev != 1) {
4939 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4940 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4941 	}
4942 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4943 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4944 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4945 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4946 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4947 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4948 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4949 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4950 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4951 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4952 	backup_bband = pg->pg_bbatt.att;
4953 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4954 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4955 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4956 
4957 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4958 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4959 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4960 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4961 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4962 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4963 	if (phy->rev != 1) {
4964 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4965 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4966 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4967 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4968 	}
4969 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4970 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4971 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4972 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4973 
4974 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4975 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4976 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4977 
4978 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4979 	if (phy->rev != 1) {
4980 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4981 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4982 	}
4983 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4984 
4985 	if (phy->rf_rev == 8)
4986 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4987 	else {
4988 		BWN_RF_WRITE(mac, 0x52, 0);
4989 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4990 	}
4991 	bwn_phy_g_set_bbatt(mac, 11);
4992 
4993 	if (phy->rev >= 3)
4994 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4995 	else
4996 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4997 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4998 
4999 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5000 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5001 
5002 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5003 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5004 
5005 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5006 		if (phy->rev >= 7) {
5007 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5008 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5009 		}
5010 	}
5011 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5012 
5013 	j = 0;
5014 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5015 	for (i = 0; i < loop_i_max; i++) {
5016 		for (j = 0; j < 16; j++) {
5017 			BWN_RF_WRITE(mac, 0x43, i);
5018 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5019 			    (j << 8));
5020 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5021 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5022 			DELAY(20);
5023 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5024 				goto done0;
5025 		}
5026 	}
5027 done0:
5028 	loop1_outer_done = i;
5029 	loop1_inner_done = j;
5030 	if (j >= 8) {
5031 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5032 		trsw_rx = 0x1b;
5033 		for (j = j - 8; j < 16; j++) {
5034 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5035 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5036 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5037 			DELAY(20);
5038 			trsw_rx -= 3;
5039 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5040 				goto done1;
5041 		}
5042 	} else
5043 		trsw_rx = 0x18;
5044 done1:
5045 
5046 	if (phy->rev != 1) {
5047 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5048 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5049 	}
5050 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5051 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5052 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5053 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5054 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5055 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5056 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5057 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5058 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5059 
5060 	bwn_phy_g_set_bbatt(mac, backup_bband);
5061 
5062 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5063 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5064 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5065 
5066 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5067 	DELAY(10);
5068 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5069 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5070 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5071 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5072 
5073 	pg->pg_max_lb_gain =
5074 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5075 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5076 }
5077 
5078 static uint16_t
5079 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5080 {
5081 	struct bwn_phy *phy = &mac->mac_phy;
5082 	uint32_t tmp1 = 0, tmp2 = 0;
5083 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5084 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5085 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5086 	static const uint8_t rcc_table[] = {
5087 		0x02, 0x03, 0x01, 0x0f,
5088 		0x06, 0x07, 0x05, 0x0f,
5089 		0x0a, 0x0b, 0x09, 0x0f,
5090 		0x0e, 0x0f, 0x0d, 0x0f,
5091 	};
5092 
5093 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5094 	    rfoverval = rfover = cck3 = 0;
5095 	radio0 = BWN_RF_READ(mac, 0x43);
5096 	radio1 = BWN_RF_READ(mac, 0x51);
5097 	radio2 = BWN_RF_READ(mac, 0x52);
5098 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5099 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5100 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5101 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5102 
5103 	if (phy->type == BWN_PHYTYPE_B) {
5104 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5105 		reg0 = BWN_READ_2(mac, 0x3ec);
5106 
5107 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5108 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5109 	} else if (phy->gmode || phy->rev >= 2) {
5110 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5111 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5112 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5113 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5114 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5115 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5116 
5117 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5118 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5119 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5120 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5121 		if (BWN_HAS_LOOPBACK(phy)) {
5122 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5123 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5124 			if (phy->rev >= 3)
5125 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5126 			else
5127 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5128 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5129 		}
5130 
5131 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5132 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5133 			BWN_LPD(0, 1, 1)));
5134 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5135 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5136 	}
5137 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5138 
5139 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5140 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5141 	reg1 = BWN_READ_2(mac, 0x3e6);
5142 	reg2 = BWN_READ_2(mac, 0x3f4);
5143 
5144 	if (phy->analog == 0)
5145 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5146 	else {
5147 		if (phy->analog >= 2)
5148 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5149 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5150 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5151 	}
5152 
5153 	reg = BWN_RF_READ(mac, 0x60);
5154 	index = (reg & 0x001e) >> 1;
5155 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5156 
5157 	if (phy->type == BWN_PHYTYPE_B)
5158 		BWN_RF_WRITE(mac, 0x78, 0x26);
5159 	if (phy->gmode || phy->rev >= 2) {
5160 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5161 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5162 			BWN_LPD(0, 1, 1)));
5163 	}
5164 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5165 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5166 	if (phy->gmode || phy->rev >= 2) {
5167 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5168 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5169 			BWN_LPD(0, 0, 1)));
5170 	}
5171 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5172 	BWN_RF_SET(mac, 0x51, 0x0004);
5173 	if (phy->rf_rev == 8)
5174 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5175 	else {
5176 		BWN_RF_WRITE(mac, 0x52, 0);
5177 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5178 	}
5179 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5180 
5181 	for (i = 0; i < 16; i++) {
5182 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5183 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5184 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5185 		if (phy->gmode || phy->rev >= 2) {
5186 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5187 			    bwn_rf_2050_rfoverval(mac,
5188 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5189 		}
5190 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5191 		DELAY(10);
5192 		if (phy->gmode || phy->rev >= 2) {
5193 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5194 			    bwn_rf_2050_rfoverval(mac,
5195 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5196 		}
5197 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5198 		DELAY(10);
5199 		if (phy->gmode || phy->rev >= 2) {
5200 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5201 			    bwn_rf_2050_rfoverval(mac,
5202 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5203 		}
5204 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5205 		DELAY(20);
5206 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5207 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5208 		if (phy->gmode || phy->rev >= 2) {
5209 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5210 			    bwn_rf_2050_rfoverval(mac,
5211 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5212 		}
5213 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5214 	}
5215 	DELAY(10);
5216 
5217 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5218 	tmp1++;
5219 	tmp1 >>= 9;
5220 
5221 	for (i = 0; i < 16; i++) {
5222 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5223 		BWN_RF_WRITE(mac, 0x78, radio78);
5224 		DELAY(10);
5225 		for (j = 0; j < 16; j++) {
5226 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5227 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5228 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5229 			if (phy->gmode || phy->rev >= 2) {
5230 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5231 				    bwn_rf_2050_rfoverval(mac,
5232 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5233 			}
5234 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5235 			DELAY(10);
5236 			if (phy->gmode || phy->rev >= 2) {
5237 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5238 				    bwn_rf_2050_rfoverval(mac,
5239 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5240 			}
5241 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5242 			DELAY(10);
5243 			if (phy->gmode || phy->rev >= 2) {
5244 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5245 				    bwn_rf_2050_rfoverval(mac,
5246 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5247 			}
5248 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5249 			DELAY(10);
5250 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5251 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5252 			if (phy->gmode || phy->rev >= 2) {
5253 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5254 				    bwn_rf_2050_rfoverval(mac,
5255 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5256 			}
5257 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5258 		}
5259 		tmp2++;
5260 		tmp2 >>= 8;
5261 		if (tmp1 < tmp2)
5262 			break;
5263 	}
5264 
5265 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5266 	BWN_RF_WRITE(mac, 0x51, radio1);
5267 	BWN_RF_WRITE(mac, 0x52, radio2);
5268 	BWN_RF_WRITE(mac, 0x43, radio0);
5269 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5270 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5271 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5272 	BWN_WRITE_2(mac, 0x3e6, reg1);
5273 	if (phy->analog != 0)
5274 		BWN_WRITE_2(mac, 0x3f4, reg2);
5275 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5276 	bwn_spu_workaround(mac, phy->chan);
5277 	if (phy->type == BWN_PHYTYPE_B) {
5278 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5279 		BWN_WRITE_2(mac, 0x3ec, reg0);
5280 	} else if (phy->gmode) {
5281 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5282 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5283 			    & 0x7fff);
5284 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5285 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5286 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5287 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5288 			      analogoverval);
5289 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5290 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5291 		if (BWN_HAS_LOOPBACK(phy)) {
5292 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5293 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5294 		}
5295 	}
5296 
5297 	return ((i > 15) ? radio78 : rcc);
5298 }
5299 
5300 static void
5301 bwn_phy_init_b6(struct bwn_mac *mac)
5302 {
5303 	struct bwn_phy *phy = &mac->mac_phy;
5304 	struct bwn_phy_g *pg = &phy->phy_g;
5305 	struct bwn_softc *sc = mac->mac_sc;
5306 	uint16_t offset, val;
5307 	uint8_t old_channel;
5308 
5309 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5310 	    ("%s:%d: fail", __func__, __LINE__));
5311 
5312 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5313 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5314 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5315 		BWN_RF_WRITE(mac, 0x51, 0x37);
5316 		BWN_RF_WRITE(mac, 0x52, 0x70);
5317 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5318 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5319 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5320 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5321 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5322 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5323 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5324 		bwn_hf_write(mac,
5325 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5326 	}
5327 	if (phy->rf_rev == 8) {
5328 		BWN_RF_WRITE(mac, 0x51, 0);
5329 		BWN_RF_WRITE(mac, 0x52, 0x40);
5330 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5331 		BWN_RF_WRITE(mac, 0x54, 0x98);
5332 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5333 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5334 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5335 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5336 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5337 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5338 		} else {
5339 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5340 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5341 		}
5342 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5343 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5344 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5345 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5346 	}
5347 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5348 		BWN_PHY_WRITE(mac, offset, val);
5349 		val -= 0x0202;
5350 	}
5351 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5352 		BWN_PHY_WRITE(mac, offset, val);
5353 		val -= 0x0202;
5354 	}
5355 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5356 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5357 		val += 0x0202;
5358 	}
5359 	if (phy->type == BWN_PHYTYPE_G) {
5360 		BWN_RF_SET(mac, 0x007a, 0x0020);
5361 		BWN_RF_SET(mac, 0x0051, 0x0004);
5362 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5363 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5364 		BWN_PHY_WRITE(mac, 0x5b, 0);
5365 		BWN_PHY_WRITE(mac, 0x5c, 0);
5366 	}
5367 
5368 	old_channel = phy->chan;
5369 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5370 
5371 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5372 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5373 	DELAY(40);
5374 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5375 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5376 		BWN_RF_WRITE(mac, 0x50, 0x20);
5377 	}
5378 	if (phy->rf_rev <= 2) {
5379 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5380 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5381 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5382 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5383 	}
5384 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5385 
5386 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5387 
5388 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5389 	if (phy->rf_rev >= 6)
5390 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5391 	else
5392 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5393 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5394 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5395 	    pg->pg_txctl);
5396 	if (phy->rf_rev <= 5)
5397 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5398 	if (phy->rf_rev <= 2)
5399 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5400 
5401 	if (phy->analog == 4) {
5402 		BWN_WRITE_2(mac, 0x3e4, 9);
5403 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5404 	} else
5405 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5406 	if (phy->type == BWN_PHYTYPE_B)
5407 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5408 	else if (phy->type == BWN_PHYTYPE_G)
5409 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5410 }
5411 
5412 static void
5413 bwn_phy_init_a(struct bwn_mac *mac)
5414 {
5415 	struct bwn_phy *phy = &mac->mac_phy;
5416 	struct bwn_softc *sc = mac->mac_sc;
5417 
5418 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5419 	    ("%s:%d: fail", __func__, __LINE__));
5420 
5421 	if (phy->rev >= 6) {
5422 		if (phy->type == BWN_PHYTYPE_A)
5423 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5424 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5425 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5426 		else
5427 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5428 	}
5429 
5430 	bwn_wa_init(mac);
5431 
5432 	if (phy->type == BWN_PHYTYPE_G &&
5433 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5434 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5435 }
5436 
5437 static void
5438 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5439 {
5440 	int i;
5441 
5442 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5443 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5444 }
5445 
5446 static void
5447 bwn_wa_agc(struct bwn_mac *mac)
5448 {
5449 	struct bwn_phy *phy = &mac->mac_phy;
5450 
5451 	if (phy->rev == 1) {
5452 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5453 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5454 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5455 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5456 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5457 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5458 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5459 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5460 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5461 	} else {
5462 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5463 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5464 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5465 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5466 	}
5467 
5468 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5469 	    0x5700);
5470 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5471 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5472 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5473 	BWN_RF_SET(mac, 0x7a, 0x0008);
5474 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5475 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5476 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5477 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5478 	if (phy->rev == 1)
5479 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5480 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5481 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5482 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5483 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5484 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5485 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5486 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5487 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5488 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5489 	if (phy->rev == 1) {
5490 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5491 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5492 	} else {
5493 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5494 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5495 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5496 		if (phy->rev >= 6) {
5497 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5498 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5499 			    (uint16_t)~0xf000, 0x3000);
5500 		}
5501 	}
5502 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5503 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5504 	if (phy->rev == 1) {
5505 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5506 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5507 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5508 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5509 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5510 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5511 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5512 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5513 	} else {
5514 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5515 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5516 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5517 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5518 	}
5519 	if (phy->rev >= 6) {
5520 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5521 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5522 	}
5523 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5524 }
5525 
5526 static void
5527 bwn_wa_grev1(struct bwn_mac *mac)
5528 {
5529 	struct bwn_phy *phy = &mac->mac_phy;
5530 	int i;
5531 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5532 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5533 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5534 
5535 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5536 
5537 	/* init CRSTHRES and ANTDWELL */
5538 	if (phy->rev == 1) {
5539 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5540 	} else if (phy->rev == 2) {
5541 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5542 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5543 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5544 	} else {
5545 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5546 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5547 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5548 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5549 	}
5550 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5551 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5552 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5553 
5554 	/* XXX support PHY-A??? */
5555 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5556 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5557 		    bwn_tab_finefreqg[i]);
5558 
5559 	/* XXX support PHY-A??? */
5560 	if (phy->rev == 1)
5561 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5562 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5563 			    bwn_tab_noise_g1[i]);
5564 	else
5565 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5566 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5567 			    bwn_tab_noise_g2[i]);
5568 
5569 
5570 	for (i = 0; i < N(bwn_tab_rotor); i++)
5571 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5572 		    bwn_tab_rotor[i]);
5573 
5574 	/* XXX support PHY-A??? */
5575 	if (phy->rev >= 6) {
5576 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5577 		    BWN_PHY_ENCORE_EN)
5578 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5579 		else
5580 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5581 	} else
5582 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5583 
5584 	for (i = 0; i < N(bwn_tab_retard); i++)
5585 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5586 		    bwn_tab_retard[i]);
5587 
5588 	if (phy->rev == 1) {
5589 		for (i = 0; i < 16; i++)
5590 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5591 			    i, 0x0020);
5592 	} else {
5593 		for (i = 0; i < 32; i++)
5594 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5595 	}
5596 
5597 	bwn_wa_agc(mac);
5598 }
5599 
5600 static void
5601 bwn_wa_grev26789(struct bwn_mac *mac)
5602 {
5603 	struct bwn_phy *phy = &mac->mac_phy;
5604 	int i;
5605 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5606 	uint16_t ofdmrev;
5607 
5608 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5609 
5610 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5611 
5612 	/* init CRSTHRES and ANTDWELL */
5613 	if (phy->rev == 1)
5614 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5615 	else if (phy->rev == 2) {
5616 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5617 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5618 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5619 	} else {
5620 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5621 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5622 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5623 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5624 	}
5625 
5626 	for (i = 0; i < 64; i++)
5627 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5628 
5629 	/* XXX support PHY-A??? */
5630 	if (phy->rev == 1)
5631 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5632 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5633 			    bwn_tab_noise_g1[i]);
5634 	else
5635 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5636 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5637 			    bwn_tab_noise_g2[i]);
5638 
5639 	/* XXX support PHY-A??? */
5640 	if (phy->rev >= 6) {
5641 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5642 		    BWN_PHY_ENCORE_EN)
5643 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5644 		else
5645 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5646 	} else
5647 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5648 
5649 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5650 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5651 		    bwn_tab_sigmasqr2[i]);
5652 
5653 	if (phy->rev == 1) {
5654 		for (i = 0; i < 16; i++)
5655 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5656 			    0x0020);
5657 	} else {
5658 		for (i = 0; i < 32; i++)
5659 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5660 	}
5661 
5662 	bwn_wa_agc(mac);
5663 
5664 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5665 	if (ofdmrev > 2) {
5666 		if (phy->type == BWN_PHYTYPE_A)
5667 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5668 		else
5669 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5670 	} else {
5671 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5672 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5673 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5674 	}
5675 
5676 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5677 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5678 }
5679 
5680 static void
5681 bwn_wa_init(struct bwn_mac *mac)
5682 {
5683 	struct bwn_phy *phy = &mac->mac_phy;
5684 	struct bwn_softc *sc = mac->mac_sc;
5685 
5686 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5687 
5688 	switch (phy->rev) {
5689 	case 1:
5690 		bwn_wa_grev1(mac);
5691 		break;
5692 	case 2:
5693 	case 6:
5694 	case 7:
5695 	case 8:
5696 	case 9:
5697 		bwn_wa_grev26789(mac);
5698 		break;
5699 	default:
5700 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5701 	}
5702 
5703 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5704 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5705 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5706 		if (phy->rev < 2) {
5707 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5708 			    0x0002);
5709 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5710 			    0x0001);
5711 		} else {
5712 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5713 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5714 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5715 			     BWN_BFL_EXTLNA) &&
5716 			    (phy->rev >= 7)) {
5717 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5718 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5719 				    0x0020, 0x0001);
5720 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5721 				    0x0021, 0x0001);
5722 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723 				    0x0022, 0x0001);
5724 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725 				    0x0023, 0x0000);
5726 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727 				    0x0000, 0x0000);
5728 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729 				    0x0003, 0x0002);
5730 			}
5731 		}
5732 	}
5733 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5734 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5735 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5736 	}
5737 
5738 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5739 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5740 }
5741 
5742 static void
5743 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5744     uint16_t value)
5745 {
5746 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5747 	uint16_t addr;
5748 
5749 	addr = table + offset;
5750 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5751 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5752 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5753 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5754 	}
5755 	pg->pg_ofdmtab_addr = addr;
5756 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5757 }
5758 
5759 static void
5760 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5761     uint32_t value)
5762 {
5763 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5764 	uint16_t addr;
5765 
5766 	addr = table + offset;
5767 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5768 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5769 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5770 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5771 	}
5772 	pg->pg_ofdmtab_addr = addr;
5773 
5774 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5775 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5776 }
5777 
5778 static void
5779 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5780     uint16_t value)
5781 {
5782 
5783 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5784 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5785 }
5786 
5787 static void
5788 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5789 {
5790 	struct bwn_phy *phy = &mac->mac_phy;
5791 	struct bwn_softc *sc = mac->mac_sc;
5792 	unsigned int i, max_loop;
5793 	uint16_t value;
5794 	uint32_t buffer[5] = {
5795 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5796 	};
5797 
5798 	if (ofdm) {
5799 		max_loop = 0x1e;
5800 		buffer[0] = 0x000201cc;
5801 	} else {
5802 		max_loop = 0xfa;
5803 		buffer[0] = 0x000b846e;
5804 	}
5805 
5806 	BWN_ASSERT_LOCKED(mac->mac_sc);
5807 
5808 	for (i = 0; i < 5; i++)
5809 		bwn_ram_write(mac, i * 4, buffer[i]);
5810 
5811 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5812 	BWN_WRITE_2(mac, 0x07c0,
5813 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5814 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5815 	BWN_WRITE_2(mac, 0x050c, value);
5816 	if (phy->type == BWN_PHYTYPE_LP)
5817 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5818 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5819 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5820 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5821 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5822 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5823 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5824 	if (phy->type == BWN_PHYTYPE_LP)
5825 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5826 	else
5827 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5828 
5829 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5830 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5831 	for (i = 0x00; i < max_loop; i++) {
5832 		value = BWN_READ_2(mac, 0x050e);
5833 		if (value & 0x0080)
5834 			break;
5835 		DELAY(10);
5836 	}
5837 	for (i = 0x00; i < 0x0a; i++) {
5838 		value = BWN_READ_2(mac, 0x050e);
5839 		if (value & 0x0400)
5840 			break;
5841 		DELAY(10);
5842 	}
5843 	for (i = 0x00; i < 0x19; i++) {
5844 		value = BWN_READ_2(mac, 0x0690);
5845 		if (!(value & 0x0100))
5846 			break;
5847 		DELAY(10);
5848 	}
5849 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5850 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5851 }
5852 
5853 static void
5854 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5855 {
5856 	uint32_t macctl;
5857 
5858 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5859 
5860 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5861 	if (macctl & BWN_MACCTL_BIGENDIAN)
5862 		printf("TODO: need swap\n");
5863 
5864 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5865 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5866 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5867 }
5868 
5869 static void
5870 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5871 {
5872 	uint16_t value;
5873 
5874 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5875 	    ("%s:%d: fail", __func__, __LINE__));
5876 
5877 	value = (uint8_t) (ctl->q);
5878 	value |= ((uint8_t) (ctl->i)) << 8;
5879 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5880 }
5881 
5882 static uint16_t
5883 bwn_lo_calcfeed(struct bwn_mac *mac,
5884     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5885 {
5886 	struct bwn_phy *phy = &mac->mac_phy;
5887 	struct bwn_softc *sc = mac->mac_sc;
5888 	uint16_t rfover;
5889 	uint16_t feedthrough;
5890 
5891 	if (phy->gmode) {
5892 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5893 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5894 
5895 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5896 		    ("%s:%d: fail", __func__, __LINE__));
5897 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5898 		    ("%s:%d: fail", __func__, __LINE__));
5899 
5900 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5901 
5902 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5903 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5904 		    phy->rev > 6)
5905 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5906 
5907 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5908 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5909 		DELAY(10);
5910 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5911 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912 		DELAY(10);
5913 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5914 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915 		DELAY(10);
5916 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5917 	} else {
5918 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5919 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5920 		DELAY(10);
5921 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5922 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923 		DELAY(10);
5924 		pga |= BWN_PHY_PGACTL_LPF;
5925 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926 	}
5927 	DELAY(21);
5928 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5929 
5930 	return (feedthrough);
5931 }
5932 
5933 static uint16_t
5934 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5935     uint16_t *value, uint16_t *pad_mix_gain)
5936 {
5937 	struct bwn_phy *phy = &mac->mac_phy;
5938 	uint16_t reg, v, padmix;
5939 
5940 	if (phy->type == BWN_PHYTYPE_B) {
5941 		v = 0x30;
5942 		if (phy->rf_rev <= 5) {
5943 			reg = 0x43;
5944 			padmix = 0;
5945 		} else {
5946 			reg = 0x52;
5947 			padmix = 5;
5948 		}
5949 	} else {
5950 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5951 			reg = 0x43;
5952 			v = 0x10;
5953 			padmix = 2;
5954 		} else {
5955 			reg = 0x52;
5956 			v = 0x30;
5957 			padmix = 5;
5958 		}
5959 	}
5960 	if (value)
5961 		*value = v;
5962 	if (pad_mix_gain)
5963 		*pad_mix_gain = padmix;
5964 
5965 	return (reg);
5966 }
5967 
5968 static void
5969 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5970 {
5971 	struct bwn_phy *phy = &mac->mac_phy;
5972 	struct bwn_phy_g *pg = &phy->phy_g;
5973 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5974 	uint16_t reg, mask;
5975 	uint16_t trsw_rx, pga;
5976 	uint16_t rf_pctl_reg;
5977 
5978 	static const uint8_t tx_bias_values[] = {
5979 		0x09, 0x08, 0x0a, 0x01, 0x00,
5980 		0x02, 0x05, 0x04, 0x06,
5981 	};
5982 	static const uint8_t tx_magn_values[] = {
5983 		0x70, 0x40,
5984 	};
5985 
5986 	if (!BWN_HAS_LOOPBACK(phy)) {
5987 		rf_pctl_reg = 6;
5988 		trsw_rx = 2;
5989 		pga = 0;
5990 	} else {
5991 		int lb_gain;
5992 
5993 		trsw_rx = 0;
5994 		lb_gain = pg->pg_max_lb_gain / 2;
5995 		if (lb_gain > 10) {
5996 			rf_pctl_reg = 0;
5997 			pga = abs(10 - lb_gain) / 6;
5998 			pga = MIN(MAX(pga, 0), 15);
5999 		} else {
6000 			int cmp_val;
6001 			int tmp;
6002 
6003 			pga = 0;
6004 			cmp_val = 0x24;
6005 			if ((phy->rev >= 2) &&
6006 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6007 				cmp_val = 0x3c;
6008 			tmp = lb_gain;
6009 			if ((10 - lb_gain) < cmp_val)
6010 				tmp = (10 - lb_gain);
6011 			if (tmp < 0)
6012 				tmp += 6;
6013 			else
6014 				tmp += 3;
6015 			cmp_val /= 4;
6016 			tmp /= 4;
6017 			if (tmp >= cmp_val)
6018 				rf_pctl_reg = cmp_val;
6019 			else
6020 				rf_pctl_reg = tmp;
6021 		}
6022 	}
6023 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6024 	bwn_phy_g_set_bbatt(mac, 2);
6025 
6026 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6027 	mask = ~mask;
6028 	BWN_RF_MASK(mac, reg, mask);
6029 
6030 	if (BWN_HAS_TXMAG(phy)) {
6031 		int i, j;
6032 		int feedthrough;
6033 		int min_feedth = 0xffff;
6034 		uint8_t tx_magn, tx_bias;
6035 
6036 		for (i = 0; i < N(tx_magn_values); i++) {
6037 			tx_magn = tx_magn_values[i];
6038 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6039 			for (j = 0; j < N(tx_bias_values); j++) {
6040 				tx_bias = tx_bias_values[j];
6041 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6042 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6043 				    trsw_rx);
6044 				if (feedthrough < min_feedth) {
6045 					lo->tx_bias = tx_bias;
6046 					lo->tx_magn = tx_magn;
6047 					min_feedth = feedthrough;
6048 				}
6049 				if (lo->tx_bias == 0)
6050 					break;
6051 			}
6052 			BWN_RF_WRITE(mac, 0x52,
6053 					  (BWN_RF_READ(mac, 0x52)
6054 					   & 0xff00) | lo->tx_bias | lo->
6055 					  tx_magn);
6056 		}
6057 	} else {
6058 		lo->tx_magn = 0;
6059 		lo->tx_bias = 0;
6060 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6061 	}
6062 
6063 	BWN_GETTIME(lo->txctl_measured_time);
6064 }
6065 
6066 static void
6067 bwn_lo_get_powervector(struct bwn_mac *mac)
6068 {
6069 	struct bwn_phy *phy = &mac->mac_phy;
6070 	struct bwn_phy_g *pg = &phy->phy_g;
6071 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6072 	int i;
6073 	uint64_t tmp;
6074 	uint64_t power_vector = 0;
6075 
6076 	for (i = 0; i < 8; i += 2) {
6077 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6078 		power_vector |= (tmp << (i * 8));
6079 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6080 	}
6081 	if (power_vector)
6082 		lo->power_vector = power_vector;
6083 
6084 	BWN_GETTIME(lo->pwr_vec_read_time);
6085 }
6086 
6087 static void
6088 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6089     int use_trsw_rx)
6090 {
6091 	struct bwn_phy *phy = &mac->mac_phy;
6092 	struct bwn_phy_g *pg = &phy->phy_g;
6093 	uint16_t tmp;
6094 
6095 	if (max_rx_gain < 0)
6096 		max_rx_gain = 0;
6097 
6098 	if (BWN_HAS_LOOPBACK(phy)) {
6099 		int trsw_rx = 0;
6100 		int trsw_rx_gain;
6101 
6102 		if (use_trsw_rx) {
6103 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6104 			if (max_rx_gain >= trsw_rx_gain) {
6105 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6106 				trsw_rx = 0x20;
6107 			}
6108 		} else
6109 			trsw_rx_gain = max_rx_gain;
6110 		if (trsw_rx_gain < 9) {
6111 			pg->pg_lna_lod_gain = 0;
6112 		} else {
6113 			pg->pg_lna_lod_gain = 1;
6114 			trsw_rx_gain -= 8;
6115 		}
6116 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6117 		pg->pg_pga_gain = trsw_rx_gain / 3;
6118 		if (pg->pg_pga_gain >= 5) {
6119 			pg->pg_pga_gain -= 5;
6120 			pg->pg_lna_gain = 2;
6121 		} else
6122 			pg->pg_lna_gain = 0;
6123 	} else {
6124 		pg->pg_lna_gain = 0;
6125 		pg->pg_trsw_rx_gain = 0x20;
6126 		if (max_rx_gain >= 0x14) {
6127 			pg->pg_lna_lod_gain = 1;
6128 			pg->pg_pga_gain = 2;
6129 		} else if (max_rx_gain >= 0x12) {
6130 			pg->pg_lna_lod_gain = 1;
6131 			pg->pg_pga_gain = 1;
6132 		} else if (max_rx_gain >= 0xf) {
6133 			pg->pg_lna_lod_gain = 1;
6134 			pg->pg_pga_gain = 0;
6135 		} else {
6136 			pg->pg_lna_lod_gain = 0;
6137 			pg->pg_pga_gain = 0;
6138 		}
6139 	}
6140 
6141 	tmp = BWN_RF_READ(mac, 0x7a);
6142 	if (pg->pg_lna_lod_gain == 0)
6143 		tmp &= ~0x0008;
6144 	else
6145 		tmp |= 0x0008;
6146 	BWN_RF_WRITE(mac, 0x7a, tmp);
6147 }
6148 
6149 static void
6150 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6151 {
6152 	struct bwn_phy *phy = &mac->mac_phy;
6153 	struct bwn_phy_g *pg = &phy->phy_g;
6154 	struct bwn_softc *sc = mac->mac_sc;
6155 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6156 	struct timespec ts;
6157 	uint16_t tmp;
6158 
6159 	if (bwn_has_hwpctl(mac)) {
6160 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6161 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6162 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6163 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6164 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6165 
6166 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6167 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6168 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6169 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6170 	}
6171 	if (phy->type == BWN_PHYTYPE_B &&
6172 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6173 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6174 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6175 	}
6176 	if (phy->rev >= 2) {
6177 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6178 		sav->phy_analogoverval =
6179 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6180 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6181 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6182 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6183 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6184 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6185 
6186 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6187 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6188 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6189 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6190 		if (phy->type == BWN_PHYTYPE_G) {
6191 			if ((phy->rev >= 7) &&
6192 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6193 			     BWN_BFL_EXTLNA)) {
6194 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6195 			} else {
6196 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6197 			}
6198 		} else {
6199 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6200 		}
6201 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6202 	}
6203 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6204 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6205 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6206 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6207 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6208 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6209 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6210 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6211 
6212 	if (!BWN_HAS_TXMAG(phy)) {
6213 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6214 		sav->rf2 &= 0x00f0;
6215 	}
6216 	if (phy->type == BWN_PHYTYPE_B) {
6217 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6218 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6219 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6220 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6221 	} else {
6222 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6223 			    | 0x8000);
6224 	}
6225 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6226 		    & 0xf000);
6227 
6228 	tmp =
6229 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6230 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6231 
6232 	tmp = sav->phy_syncctl;
6233 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6234 	tmp = sav->rf1;
6235 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6236 
6237 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6238 	if (phy->type == BWN_PHYTYPE_G ||
6239 	    (phy->type == BWN_PHYTYPE_B &&
6240 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6241 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6242 	} else
6243 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6244 	if (phy->rev >= 2)
6245 		bwn_dummy_transmission(mac, 0, 1);
6246 	bwn_phy_g_switch_chan(mac, 6, 0);
6247 	BWN_RF_READ(mac, 0x51);
6248 	if (phy->type == BWN_PHYTYPE_G)
6249 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6250 
6251 	nanouptime(&ts);
6252 	if (time_before(lo->txctl_measured_time,
6253 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6254 		bwn_lo_measure_txctl_values(mac);
6255 
6256 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6257 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6258 	else {
6259 		if (phy->type == BWN_PHYTYPE_B)
6260 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6261 		else
6262 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6263 	}
6264 }
6265 
6266 static void
6267 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6268 {
6269 	struct bwn_phy *phy = &mac->mac_phy;
6270 	struct bwn_phy_g *pg = &phy->phy_g;
6271 	uint16_t tmp;
6272 
6273 	if (phy->rev >= 2) {
6274 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6275 		tmp = (pg->pg_pga_gain << 8);
6276 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6277 		DELAY(5);
6278 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6279 		DELAY(2);
6280 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6281 	} else {
6282 		tmp = (pg->pg_pga_gain | 0xefa0);
6283 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6284 	}
6285 	if (phy->type == BWN_PHYTYPE_G) {
6286 		if (phy->rev >= 3)
6287 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6288 		else
6289 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6290 		if (phy->rev >= 2)
6291 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6292 		else
6293 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6294 	}
6295 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6296 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6297 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6298 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6299 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6300 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6301 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6302 	if (!BWN_HAS_TXMAG(phy)) {
6303 		tmp = sav->rf2;
6304 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6305 	}
6306 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6307 	if (phy->type == BWN_PHYTYPE_B &&
6308 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6309 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6310 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6311 	}
6312 	if (phy->rev >= 2) {
6313 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6314 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6315 			      sav->phy_analogoverval);
6316 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6317 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6318 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6319 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6320 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6321 	}
6322 	if (bwn_has_hwpctl(mac)) {
6323 		tmp = (sav->phy_lomask & 0xbfff);
6324 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6325 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6326 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6327 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6328 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6329 	}
6330 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6331 }
6332 
6333 static int
6334 bwn_lo_probe_loctl(struct bwn_mac *mac,
6335     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6336 {
6337 	struct bwn_phy *phy = &mac->mac_phy;
6338 	struct bwn_phy_g *pg = &phy->phy_g;
6339 	struct bwn_loctl orig, test;
6340 	struct bwn_loctl prev = { -100, -100 };
6341 	static const struct bwn_loctl modifiers[] = {
6342 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6343 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6344 	};
6345 	int begin, end, lower = 0, i;
6346 	uint16_t feedth;
6347 
6348 	if (d->curstate == 0) {
6349 		begin = 1;
6350 		end = 8;
6351 	} else if (d->curstate % 2 == 0) {
6352 		begin = d->curstate - 1;
6353 		end = d->curstate + 1;
6354 	} else {
6355 		begin = d->curstate - 2;
6356 		end = d->curstate + 2;
6357 	}
6358 	if (begin < 1)
6359 		begin += 8;
6360 	if (end > 8)
6361 		end -= 8;
6362 
6363 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6364 	i = begin;
6365 	d->curstate = i;
6366 	while (1) {
6367 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6368 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6369 		test.i += modifiers[i - 1].i * d->multipler;
6370 		test.q += modifiers[i - 1].q * d->multipler;
6371 		if ((test.i != prev.i || test.q != prev.q) &&
6372 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6373 			bwn_lo_write(mac, &test);
6374 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6375 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6376 			if (feedth < d->feedth) {
6377 				memcpy(probe, &test,
6378 				    sizeof(struct bwn_loctl));
6379 				lower = 1;
6380 				d->feedth = feedth;
6381 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6382 					break;
6383 			}
6384 		}
6385 		memcpy(&prev, &test, sizeof(prev));
6386 		if (i == end)
6387 			break;
6388 		if (i == 8)
6389 			i = 1;
6390 		else
6391 			i++;
6392 		d->curstate = i;
6393 	}
6394 
6395 	return (lower);
6396 }
6397 
6398 static void
6399 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6400 {
6401 	struct bwn_phy *phy = &mac->mac_phy;
6402 	struct bwn_phy_g *pg = &phy->phy_g;
6403 	struct bwn_lo_g_sm d;
6404 	struct bwn_loctl probe;
6405 	int lower, repeat, cnt = 0;
6406 	uint16_t feedth;
6407 
6408 	d.nmeasure = 0;
6409 	d.multipler = 1;
6410 	if (BWN_HAS_LOOPBACK(phy))
6411 		d.multipler = 3;
6412 
6413 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6414 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6415 
6416 	do {
6417 		bwn_lo_write(mac, &d.loctl);
6418 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6419 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6420 		if (feedth < 0x258) {
6421 			if (feedth >= 0x12c)
6422 				*rxgain += 6;
6423 			else
6424 				*rxgain += 3;
6425 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6426 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6427 		}
6428 		d.feedth = feedth;
6429 		d.curstate = 0;
6430 		do {
6431 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6432 			    ("%s:%d: fail", __func__, __LINE__));
6433 			memcpy(&probe, &d.loctl,
6434 			       sizeof(struct bwn_loctl));
6435 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6436 			if (!lower)
6437 				break;
6438 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6439 				break;
6440 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6441 			d.nmeasure++;
6442 		} while (d.nmeasure < 24);
6443 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6444 
6445 		if (BWN_HAS_LOOPBACK(phy)) {
6446 			if (d.feedth > 0x1194)
6447 				*rxgain -= 6;
6448 			else if (d.feedth < 0x5dc)
6449 				*rxgain += 3;
6450 			if (cnt == 0) {
6451 				if (d.feedth <= 0x5dc) {
6452 					d.multipler = 1;
6453 					cnt++;
6454 				} else
6455 					d.multipler = 2;
6456 			} else if (cnt == 2)
6457 				d.multipler = 1;
6458 		}
6459 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6460 	} while (++cnt < repeat);
6461 }
6462 
6463 static struct bwn_lo_calib *
6464 bwn_lo_calibset(struct bwn_mac *mac,
6465     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6466 {
6467 	struct bwn_phy *phy = &mac->mac_phy;
6468 	struct bwn_phy_g *pg = &phy->phy_g;
6469 	struct bwn_loctl loctl = { 0, 0 };
6470 	struct bwn_lo_calib *cal;
6471 	struct bwn_lo_g_value sval = { 0 };
6472 	int rxgain;
6473 	uint16_t pad, reg, value;
6474 
6475 	sval.old_channel = phy->chan;
6476 	bwn_mac_suspend(mac);
6477 	bwn_lo_save(mac, &sval);
6478 
6479 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6480 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6481 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6482 
6483 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6484 	if (rfatt->padmix)
6485 		rxgain -= pad;
6486 	if (BWN_HAS_LOOPBACK(phy))
6487 		rxgain += pg->pg_max_lb_gain;
6488 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6489 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6490 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6491 
6492 	bwn_lo_restore(mac, &sval);
6493 	bwn_mac_enable(mac);
6494 
6495 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6496 	if (!cal) {
6497 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6498 		return (NULL);
6499 	}
6500 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6501 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6502 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6503 
6504 	BWN_GETTIME(cal->calib_time);
6505 
6506 	return (cal);
6507 }
6508 
6509 static struct bwn_lo_calib *
6510 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6511     const struct bwn_rfatt *rfatt)
6512 {
6513 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6514 	struct bwn_lo_calib *c;
6515 
6516 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6517 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6518 			continue;
6519 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6520 			continue;
6521 		return (c);
6522 	}
6523 
6524 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6525 	if (!c)
6526 		return (NULL);
6527 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6528 
6529 	return (c);
6530 }
6531 
6532 static void
6533 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6534 {
6535 	struct bwn_phy *phy = &mac->mac_phy;
6536 	struct bwn_phy_g *pg = &phy->phy_g;
6537 	struct bwn_softc *sc = mac->mac_sc;
6538 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6539 	const struct bwn_rfatt *rfatt;
6540 	const struct bwn_bbatt *bbatt;
6541 	uint64_t pvector;
6542 	int i;
6543 	int rf_offset, bb_offset;
6544 	uint8_t changed = 0;
6545 
6546 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6547 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6548 	    ("%s:%d: fail", __func__, __LINE__));
6549 
6550 	pvector = lo->power_vector;
6551 	if (!update && !pvector)
6552 		return;
6553 
6554 	bwn_mac_suspend(mac);
6555 
6556 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6557 		struct bwn_lo_calib *cal;
6558 		int idx;
6559 		uint16_t val;
6560 
6561 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6562 			continue;
6563 		bb_offset = i / lo->rfatt.len;
6564 		rf_offset = i % lo->rfatt.len;
6565 		bbatt = &(lo->bbatt.array[bb_offset]);
6566 		rfatt = &(lo->rfatt.array[rf_offset]);
6567 
6568 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6569 		if (!cal) {
6570 			device_printf(sc->sc_dev, "LO: Could not "
6571 			    "calibrate DC table entry\n");
6572 			continue;
6573 		}
6574 		val = (uint8_t)(cal->ctl.q);
6575 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6576 		free(cal, M_DEVBUF);
6577 
6578 		idx = i / 2;
6579 		if (i % 2)
6580 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6581 			    | ((val & 0x00ff) << 8);
6582 		else
6583 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6584 			    | (val & 0x00ff);
6585 		changed = 1;
6586 	}
6587 	if (changed) {
6588 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6589 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6590 	}
6591 	bwn_mac_enable(mac);
6592 }
6593 
6594 static void
6595 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6596 {
6597 
6598 	if (!rf->padmix)
6599 		return;
6600 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6601 		rf->att = 4;
6602 }
6603 
6604 static void
6605 bwn_lo_g_adjust(struct bwn_mac *mac)
6606 {
6607 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6608 	struct bwn_lo_calib *cal;
6609 	struct bwn_rfatt rf;
6610 
6611 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6612 	bwn_lo_fixup_rfatt(&rf);
6613 
6614 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6615 	if (!cal)
6616 		return;
6617 	bwn_lo_write(mac, &cal->ctl);
6618 }
6619 
6620 static void
6621 bwn_lo_g_init(struct bwn_mac *mac)
6622 {
6623 
6624 	if (!bwn_has_hwpctl(mac))
6625 		return;
6626 
6627 	bwn_lo_get_powervector(mac);
6628 	bwn_phy_g_dc_lookup_init(mac, 1);
6629 }
6630 
6631 static void
6632 bwn_mac_suspend(struct bwn_mac *mac)
6633 {
6634 	struct bwn_softc *sc = mac->mac_sc;
6635 	int i;
6636 	uint32_t tmp;
6637 
6638 	KASSERT(mac->mac_suspended >= 0,
6639 	    ("%s:%d: fail", __func__, __LINE__));
6640 
6641 	if (mac->mac_suspended == 0) {
6642 		bwn_psctl(mac, BWN_PS_AWAKE);
6643 		BWN_WRITE_4(mac, BWN_MACCTL,
6644 			    BWN_READ_4(mac, BWN_MACCTL)
6645 			    & ~BWN_MACCTL_ON);
6646 		BWN_READ_4(mac, BWN_MACCTL);
6647 		for (i = 35; i; i--) {
6648 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6649 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6650 				goto out;
6651 			DELAY(10);
6652 		}
6653 		for (i = 40; i; i--) {
6654 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6655 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6656 				goto out;
6657 			DELAY(1000);
6658 		}
6659 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6660 	}
6661 out:
6662 	mac->mac_suspended++;
6663 }
6664 
6665 static void
6666 bwn_mac_enable(struct bwn_mac *mac)
6667 {
6668 	struct bwn_softc *sc = mac->mac_sc;
6669 	uint16_t state;
6670 
6671 	state = bwn_shm_read_2(mac, BWN_SHARED,
6672 	    BWN_SHARED_UCODESTAT);
6673 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6674 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6675 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6676 
6677 	mac->mac_suspended--;
6678 	KASSERT(mac->mac_suspended >= 0,
6679 	    ("%s:%d: fail", __func__, __LINE__));
6680 	if (mac->mac_suspended == 0) {
6681 		BWN_WRITE_4(mac, BWN_MACCTL,
6682 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6683 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6684 		BWN_READ_4(mac, BWN_MACCTL);
6685 		BWN_READ_4(mac, BWN_INTR_REASON);
6686 		bwn_psctl(mac, 0);
6687 	}
6688 }
6689 
6690 static void
6691 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6692 {
6693 	struct bwn_softc *sc = mac->mac_sc;
6694 	int i;
6695 	uint16_t ucstat;
6696 
6697 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6698 	    ("%s:%d: fail", __func__, __LINE__));
6699 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6700 	    ("%s:%d: fail", __func__, __LINE__));
6701 
6702 	/* XXX forcibly awake and hwps-off */
6703 
6704 	BWN_WRITE_4(mac, BWN_MACCTL,
6705 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6706 	    ~BWN_MACCTL_HWPS);
6707 	BWN_READ_4(mac, BWN_MACCTL);
6708 	if (siba_get_revid(sc->sc_dev) >= 5) {
6709 		for (i = 0; i < 100; i++) {
6710 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6711 			    BWN_SHARED_UCODESTAT);
6712 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6713 				break;
6714 			DELAY(10);
6715 		}
6716 	}
6717 }
6718 
6719 static int16_t
6720 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6721 {
6722 
6723 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6724 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6725 }
6726 
6727 static void
6728 bwn_nrssi_threshold(struct bwn_mac *mac)
6729 {
6730 	struct bwn_phy *phy = &mac->mac_phy;
6731 	struct bwn_phy_g *pg = &phy->phy_g;
6732 	struct bwn_softc *sc = mac->mac_sc;
6733 	int32_t a, b;
6734 	int16_t tmp16;
6735 	uint16_t tmpu16;
6736 
6737 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6738 
6739 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6740 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6741 			a = 0x13;
6742 			b = 0x12;
6743 		} else {
6744 			a = 0xe;
6745 			b = 0x11;
6746 		}
6747 
6748 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6749 		a += (pg->pg_nrssi[0] << 6);
6750 		a += (a < 32) ? 31 : 32;
6751 		a = a >> 6;
6752 		a = MIN(MAX(a, -31), 31);
6753 
6754 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6755 		b += (pg->pg_nrssi[0] << 6);
6756 		if (b < 32)
6757 			b += 31;
6758 		else
6759 			b += 32;
6760 		b = b >> 6;
6761 		b = MIN(MAX(b, -31), 31);
6762 
6763 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6764 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6765 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6766 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6767 		return;
6768 	}
6769 
6770 	tmp16 = bwn_nrssi_read(mac, 0x20);
6771 	if (tmp16 >= 0x20)
6772 		tmp16 -= 0x40;
6773 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6774 }
6775 
6776 static void
6777 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6778 {
6779 #define	SAVE_RF_MAX		3
6780 #define	SAVE_PHY_COMM_MAX	4
6781 #define	SAVE_PHY3_MAX		8
6782 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6783 		{ 0x7a, 0x52, 0x43 };
6784 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6785 		{ 0x15, 0x5a, 0x59, 0x58 };
6786 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6787 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6788 		0x0801, 0x0060, 0x0014, 0x0478
6789 	};
6790 	struct bwn_phy *phy = &mac->mac_phy;
6791 	struct bwn_phy_g *pg = &phy->phy_g;
6792 	int32_t i, tmp32, phy3_idx = 0;
6793 	uint16_t delta, tmp;
6794 	uint16_t save_rf[SAVE_RF_MAX];
6795 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6796 	uint16_t save_phy3[SAVE_PHY3_MAX];
6797 	uint16_t ant_div, phy0, chan_ex;
6798 	int16_t nrssi0, nrssi1;
6799 
6800 	KASSERT(phy->type == BWN_PHYTYPE_G,
6801 	    ("%s:%d: fail", __func__, __LINE__));
6802 
6803 	if (phy->rf_rev >= 9)
6804 		return;
6805 	if (phy->rf_rev == 8)
6806 		bwn_nrssi_offset(mac);
6807 
6808 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6809 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6810 
6811 	/*
6812 	 * Save RF/PHY registers for later restoration
6813 	 */
6814 	ant_div = BWN_READ_2(mac, 0x03e2);
6815 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6816 	for (i = 0; i < SAVE_RF_MAX; ++i)
6817 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6818 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6819 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6820 
6821 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6822 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6823 	if (phy->rev >= 3) {
6824 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6825 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6826 		BWN_PHY_WRITE(mac, 0x002e, 0);
6827 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6828 		switch (phy->rev) {
6829 		case 4:
6830 		case 6:
6831 		case 7:
6832 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6833 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6834 			break;
6835 		case 3:
6836 		case 5:
6837 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6838 			break;
6839 		}
6840 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6841 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6842 	}
6843 	/*
6844 	 * Calculate nrssi0
6845 	 */
6846 	BWN_RF_SET(mac, 0x007a, 0x0070);
6847 	bwn_set_all_gains(mac, 0, 8, 0);
6848 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6849 	if (phy->rev >= 2) {
6850 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6851 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6852 	}
6853 	BWN_RF_SET(mac, 0x007a, 0x0080);
6854 	DELAY(20);
6855 
6856 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6857 	if (nrssi0 >= 0x0020)
6858 		nrssi0 -= 0x0040;
6859 
6860 	/*
6861 	 * Calculate nrssi1
6862 	 */
6863 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6864 	if (phy->rev >= 2)
6865 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6866 
6867 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6868 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6869 	BWN_RF_SET(mac, 0x007a, 0x000f);
6870 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6871 	if (phy->rev >= 2) {
6872 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6873 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6874 	}
6875 
6876 	bwn_set_all_gains(mac, 3, 0, 1);
6877 	if (phy->rf_rev == 8) {
6878 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6879 	} else {
6880 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6881 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6882 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6883 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6884 	}
6885 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6886 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6887 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6888 	DELAY(20);
6889 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6890 
6891 	/*
6892 	 * Install calculated narrow RSSI values
6893 	 */
6894 	if (nrssi1 >= 0x0020)
6895 		nrssi1 -= 0x0040;
6896 	if (nrssi0 == nrssi1)
6897 		pg->pg_nrssi_slope = 0x00010000;
6898 	else
6899 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6900 	if (nrssi0 >= -4) {
6901 		pg->pg_nrssi[0] = nrssi1;
6902 		pg->pg_nrssi[1] = nrssi0;
6903 	}
6904 
6905 	/*
6906 	 * Restore saved RF/PHY registers
6907 	 */
6908 	if (phy->rev >= 3) {
6909 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6910 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6911 			    save_phy3[phy3_idx]);
6912 		}
6913 	}
6914 	if (phy->rev >= 2) {
6915 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6916 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6917 	}
6918 
6919 	for (i = 0; i < SAVE_RF_MAX; ++i)
6920 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6921 
6922 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6923 	BWN_WRITE_2(mac, 0x03e6, phy0);
6924 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6925 
6926 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6927 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6928 
6929 	bwn_spu_workaround(mac, phy->chan);
6930 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6931 	bwn_set_original_gains(mac);
6932 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6933 	if (phy->rev >= 3) {
6934 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6935 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6936 			    save_phy3[phy3_idx]);
6937 		}
6938 	}
6939 
6940 	delta = 0x1f - pg->pg_nrssi[0];
6941 	for (i = 0; i < 64; i++) {
6942 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6943 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6944 		pg->pg_nrssi_lt[i] = tmp32;
6945 	}
6946 
6947 	bwn_nrssi_threshold(mac);
6948 #undef SAVE_RF_MAX
6949 #undef SAVE_PHY_COMM_MAX
6950 #undef SAVE_PHY3_MAX
6951 }
6952 
6953 static void
6954 bwn_nrssi_offset(struct bwn_mac *mac)
6955 {
6956 #define	SAVE_RF_MAX		2
6957 #define	SAVE_PHY_COMM_MAX	10
6958 #define	SAVE_PHY6_MAX		8
6959 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6960 		{ 0x7a, 0x43 };
6961 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6962 		0x0001, 0x0811, 0x0812, 0x0814,
6963 		0x0815, 0x005a, 0x0059, 0x0058,
6964 		0x000a, 0x0003
6965 	};
6966 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6967 		0x002e, 0x002f, 0x080f, 0x0810,
6968 		0x0801, 0x0060, 0x0014, 0x0478
6969 	};
6970 	struct bwn_phy *phy = &mac->mac_phy;
6971 	int i, phy6_idx = 0;
6972 	uint16_t save_rf[SAVE_RF_MAX];
6973 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6974 	uint16_t save_phy6[SAVE_PHY6_MAX];
6975 	int16_t nrssi;
6976 	uint16_t saved = 0xffff;
6977 
6978 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6979 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6980 	for (i = 0; i < SAVE_RF_MAX; ++i)
6981 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6982 
6983 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6984 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6985 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6986 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6987 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6988 	if (phy->rev >= 6) {
6989 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6990 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6991 
6992 		BWN_PHY_WRITE(mac, 0x002e, 0);
6993 		BWN_PHY_WRITE(mac, 0x002f, 0);
6994 		BWN_PHY_WRITE(mac, 0x080f, 0);
6995 		BWN_PHY_WRITE(mac, 0x0810, 0);
6996 		BWN_PHY_SET(mac, 0x0478, 0x0100);
6997 		BWN_PHY_SET(mac, 0x0801, 0x0040);
6998 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6999 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7000 	}
7001 	BWN_RF_SET(mac, 0x007a, 0x0070);
7002 	BWN_RF_SET(mac, 0x007a, 0x0080);
7003 	DELAY(30);
7004 
7005 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7006 	if (nrssi >= 0x20)
7007 		nrssi -= 0x40;
7008 	if (nrssi == 31) {
7009 		for (i = 7; i >= 4; i--) {
7010 			BWN_RF_WRITE(mac, 0x007b, i);
7011 			DELAY(20);
7012 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7013 			    0x003f);
7014 			if (nrssi >= 0x20)
7015 				nrssi -= 0x40;
7016 			if (nrssi < 31 && saved == 0xffff)
7017 				saved = i;
7018 		}
7019 		if (saved == 0xffff)
7020 			saved = 4;
7021 	} else {
7022 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7023 		if (phy->rev != 1) {
7024 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7025 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7026 		}
7027 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7028 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7029 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7030 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7031 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7032 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7033 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7034 		if (phy->rev == 0)
7035 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7036 		else
7037 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7038 		if (phy->rev != 1) {
7039 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7040 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7041 		}
7042 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7043 		BWN_RF_SET(mac, 0x007a, 0x000f);
7044 		bwn_set_all_gains(mac, 3, 0, 1);
7045 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7046 		DELAY(30);
7047 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7048 		if (nrssi >= 0x20)
7049 			nrssi -= 0x40;
7050 		if (nrssi == -32) {
7051 			for (i = 0; i < 4; i++) {
7052 				BWN_RF_WRITE(mac, 0x007b, i);
7053 				DELAY(20);
7054 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7055 				    0x047f) >> 8) & 0x003f);
7056 				if (nrssi >= 0x20)
7057 					nrssi -= 0x40;
7058 				if (nrssi > -31 && saved == 0xffff)
7059 					saved = i;
7060 			}
7061 			if (saved == 0xffff)
7062 				saved = 3;
7063 		} else
7064 			saved = 0;
7065 	}
7066 	BWN_RF_WRITE(mac, 0x007b, saved);
7067 
7068 	/*
7069 	 * Restore saved RF/PHY registers
7070 	 */
7071 	if (phy->rev >= 6) {
7072 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7073 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7074 			    save_phy6[phy6_idx]);
7075 		}
7076 	}
7077 	if (phy->rev != 1) {
7078 		for (i = 3; i < 5; i++)
7079 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7080 			    save_phy_comm[i]);
7081 	}
7082 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7083 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7084 
7085 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7086 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7087 
7088 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7089 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7090 	bwn_set_original_gains(mac);
7091 	if (phy->rev >= 6) {
7092 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7093 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7094 			    save_phy6[phy6_idx]);
7095 		}
7096 	}
7097 
7098 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7099 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7100 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7101 }
7102 
7103 static void
7104 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7105     int16_t third)
7106 {
7107 	struct bwn_phy *phy = &mac->mac_phy;
7108 	uint16_t i;
7109 	uint16_t start = 0x08, end = 0x18;
7110 	uint16_t tmp;
7111 	uint16_t table;
7112 
7113 	if (phy->rev <= 1) {
7114 		start = 0x10;
7115 		end = 0x20;
7116 	}
7117 
7118 	table = BWN_OFDMTAB_GAINX;
7119 	if (phy->rev <= 1)
7120 		table = BWN_OFDMTAB_GAINX_R1;
7121 	for (i = 0; i < 4; i++)
7122 		bwn_ofdmtab_write_2(mac, table, i, first);
7123 
7124 	for (i = start; i < end; i++)
7125 		bwn_ofdmtab_write_2(mac, table, i, second);
7126 
7127 	if (third != -1) {
7128 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7129 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7130 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7131 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7132 	}
7133 	bwn_dummy_transmission(mac, 0, 1);
7134 }
7135 
7136 static void
7137 bwn_set_original_gains(struct bwn_mac *mac)
7138 {
7139 	struct bwn_phy *phy = &mac->mac_phy;
7140 	uint16_t i, tmp;
7141 	uint16_t table;
7142 	uint16_t start = 0x0008, end = 0x0018;
7143 
7144 	if (phy->rev <= 1) {
7145 		start = 0x0010;
7146 		end = 0x0020;
7147 	}
7148 
7149 	table = BWN_OFDMTAB_GAINX;
7150 	if (phy->rev <= 1)
7151 		table = BWN_OFDMTAB_GAINX_R1;
7152 	for (i = 0; i < 4; i++) {
7153 		tmp = (i & 0xfffc);
7154 		tmp |= (i & 0x0001) << 1;
7155 		tmp |= (i & 0x0002) >> 1;
7156 
7157 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7158 	}
7159 
7160 	for (i = start; i < end; i++)
7161 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7162 
7163 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7164 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7165 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7166 	bwn_dummy_transmission(mac, 0, 1);
7167 }
7168 
7169 static void
7170 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7171 {
7172 	struct bwn_phy *phy = &mac->mac_phy;
7173 	struct bwn_phy_g *pg = &phy->phy_g;
7174 	struct bwn_rfatt old_rfatt, rfatt;
7175 	struct bwn_bbatt old_bbatt, bbatt;
7176 	struct bwn_softc *sc = mac->mac_sc;
7177 	uint8_t old_txctl = 0;
7178 
7179 	KASSERT(phy->type == BWN_PHYTYPE_G,
7180 	    ("%s:%d: fail", __func__, __LINE__));
7181 
7182 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7183 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7184 		return;
7185 
7186 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7187 
7188 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7189 
7190 	if (!phy->gmode)
7191 		return;
7192 	bwn_hwpctl_early_init(mac);
7193 	if (pg->pg_curtssi == 0) {
7194 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7195 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7196 		} else {
7197 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7198 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7199 			old_txctl = pg->pg_txctl;
7200 
7201 			bbatt.att = 11;
7202 			if (phy->rf_rev == 8) {
7203 				rfatt.att = 15;
7204 				rfatt.padmix = 1;
7205 			} else {
7206 				rfatt.att = 9;
7207 				rfatt.padmix = 0;
7208 			}
7209 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7210 		}
7211 		bwn_dummy_transmission(mac, 0, 1);
7212 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7213 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7214 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7215 		else
7216 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7217 			    &old_rfatt, old_txctl);
7218 	}
7219 	bwn_hwpctl_init_gphy(mac);
7220 
7221 	/* clear TSSI */
7222 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7223 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7224 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7225 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7226 }
7227 
7228 static void
7229 bwn_hwpctl_early_init(struct bwn_mac *mac)
7230 {
7231 	struct bwn_phy *phy = &mac->mac_phy;
7232 
7233 	if (!bwn_has_hwpctl(mac)) {
7234 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7235 		return;
7236 	}
7237 
7238 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7239 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7240 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7241 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7242 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7243 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7244 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7245 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7246 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7247 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7248 	} else {
7249 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7250 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7251 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7252 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7253 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7254 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7255 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7256 	}
7257 }
7258 
7259 static void
7260 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7261 {
7262 	struct bwn_phy *phy = &mac->mac_phy;
7263 	struct bwn_phy_g *pg = &phy->phy_g;
7264 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7265 	int i;
7266 	uint16_t nr_written = 0, tmp, value;
7267 	uint8_t rf, bb;
7268 
7269 	if (!bwn_has_hwpctl(mac)) {
7270 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7271 		return;
7272 	}
7273 
7274 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7275 	    (pg->pg_idletssi - pg->pg_curtssi));
7276 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7277 	    (pg->pg_idletssi - pg->pg_curtssi));
7278 
7279 	for (i = 0; i < 32; i++)
7280 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7281 	for (i = 32; i < 64; i++)
7282 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7283 	for (i = 0; i < 64; i += 2) {
7284 		value = (uint16_t) pg->pg_tssi2dbm[i];
7285 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7286 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7287 	}
7288 
7289 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7290 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7291 			if (nr_written >= 0x40)
7292 				return;
7293 			tmp = lo->bbatt.array[bb].att;
7294 			tmp <<= 8;
7295 			if (phy->rf_rev == 8)
7296 				tmp |= 0x50;
7297 			else
7298 				tmp |= 0x40;
7299 			tmp |= lo->rfatt.array[rf].att;
7300 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7301 			nr_written++;
7302 		}
7303 	}
7304 
7305 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7306 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7307 
7308 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7309 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7310 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7311 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7312 
7313 	bwn_phy_g_dc_lookup_init(mac, 1);
7314 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7315 }
7316 
7317 static void
7318 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7319 {
7320 	struct bwn_softc *sc = mac->mac_sc;
7321 
7322 	if (spu != 0)
7323 		bwn_spu_workaround(mac, channel);
7324 
7325 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7326 
7327 	if (channel == 14) {
7328 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7329 			bwn_hf_write(mac,
7330 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7331 		else
7332 			bwn_hf_write(mac,
7333 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7334 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7335 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7336 		return;
7337 	}
7338 
7339 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7340 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7341 }
7342 
7343 static uint16_t
7344 bwn_phy_g_chan2freq(uint8_t channel)
7345 {
7346 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7347 
7348 	KASSERT(channel >= 1 && channel <= 14,
7349 	    ("%s:%d: fail", __func__, __LINE__));
7350 
7351 	return (bwn_phy_g_rf_channels[channel - 1]);
7352 }
7353 
7354 static void
7355 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7356     const struct bwn_rfatt *rfatt, uint8_t txctl)
7357 {
7358 	struct bwn_phy *phy = &mac->mac_phy;
7359 	struct bwn_phy_g *pg = &phy->phy_g;
7360 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7361 	uint16_t bb, rf;
7362 	uint16_t tx_bias, tx_magn;
7363 
7364 	bb = bbatt->att;
7365 	rf = rfatt->att;
7366 	tx_bias = lo->tx_bias;
7367 	tx_magn = lo->tx_magn;
7368 	if (tx_bias == 0xff)
7369 		tx_bias = 0;
7370 
7371 	pg->pg_txctl = txctl;
7372 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7373 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7374 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7375 	bwn_phy_g_set_bbatt(mac, bb);
7376 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7377 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7378 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7379 	else {
7380 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7381 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7382 	}
7383 	if (BWN_HAS_TXMAG(phy))
7384 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7385 	else
7386 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7387 	bwn_lo_g_adjust(mac);
7388 }
7389 
7390 static void
7391 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7392     uint16_t bbatt)
7393 {
7394 	struct bwn_phy *phy = &mac->mac_phy;
7395 
7396 	if (phy->analog == 0) {
7397 		BWN_WRITE_2(mac, BWN_PHY0,
7398 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7399 		return;
7400 	}
7401 	if (phy->analog > 1) {
7402 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7403 		return;
7404 	}
7405 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7406 }
7407 
7408 static uint16_t
7409 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7410 {
7411 	struct bwn_phy *phy = &mac->mac_phy;
7412 	struct bwn_phy_g *pg = &phy->phy_g;
7413 	struct bwn_softc *sc = mac->mac_sc;
7414 	int max_lb_gain;
7415 	uint16_t extlna;
7416 	uint16_t i;
7417 
7418 	if (phy->gmode == 0)
7419 		return (0);
7420 
7421 	if (BWN_HAS_LOOPBACK(phy)) {
7422 		max_lb_gain = pg->pg_max_lb_gain;
7423 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7424 		if (max_lb_gain >= 0x46) {
7425 			extlna = 0x3000;
7426 			max_lb_gain -= 0x46;
7427 		} else if (max_lb_gain >= 0x3a) {
7428 			extlna = 0x1000;
7429 			max_lb_gain -= 0x3a;
7430 		} else if (max_lb_gain >= 0x2e) {
7431 			extlna = 0x2000;
7432 			max_lb_gain -= 0x2e;
7433 		} else {
7434 			extlna = 0;
7435 			max_lb_gain -= 0x10;
7436 		}
7437 
7438 		for (i = 0; i < 16; i++) {
7439 			max_lb_gain -= (i * 6);
7440 			if (max_lb_gain < 6)
7441 				break;
7442 		}
7443 
7444 		if ((phy->rev < 7) ||
7445 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7446 			if (reg == BWN_PHY_RFOVER) {
7447 				return (0x1b3);
7448 			} else if (reg == BWN_PHY_RFOVERVAL) {
7449 				extlna |= (i << 8);
7450 				switch (lpd) {
7451 				case BWN_LPD(0, 1, 1):
7452 					return (0x0f92);
7453 				case BWN_LPD(0, 0, 1):
7454 				case BWN_LPD(1, 0, 1):
7455 					return (0x0092 | extlna);
7456 				case BWN_LPD(1, 0, 0):
7457 					return (0x0093 | extlna);
7458 				}
7459 				KASSERT(0 == 1,
7460 				    ("%s:%d: fail", __func__, __LINE__));
7461 			}
7462 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7463 		} else {
7464 			if (reg == BWN_PHY_RFOVER)
7465 				return (0x9b3);
7466 			if (reg == BWN_PHY_RFOVERVAL) {
7467 				if (extlna)
7468 					extlna |= 0x8000;
7469 				extlna |= (i << 8);
7470 				switch (lpd) {
7471 				case BWN_LPD(0, 1, 1):
7472 					return (0x8f92);
7473 				case BWN_LPD(0, 0, 1):
7474 					return (0x8092 | extlna);
7475 				case BWN_LPD(1, 0, 1):
7476 					return (0x2092 | extlna);
7477 				case BWN_LPD(1, 0, 0):
7478 					return (0x2093 | extlna);
7479 				}
7480 				KASSERT(0 == 1,
7481 				    ("%s:%d: fail", __func__, __LINE__));
7482 			}
7483 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7484 		}
7485 		return (0);
7486 	}
7487 
7488 	if ((phy->rev < 7) ||
7489 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7490 		if (reg == BWN_PHY_RFOVER) {
7491 			return (0x1b3);
7492 		} else if (reg == BWN_PHY_RFOVERVAL) {
7493 			switch (lpd) {
7494 			case BWN_LPD(0, 1, 1):
7495 				return (0x0fb2);
7496 			case BWN_LPD(0, 0, 1):
7497 				return (0x00b2);
7498 			case BWN_LPD(1, 0, 1):
7499 				return (0x30b2);
7500 			case BWN_LPD(1, 0, 0):
7501 				return (0x30b3);
7502 			}
7503 			KASSERT(0 == 1,
7504 			    ("%s:%d: fail", __func__, __LINE__));
7505 		}
7506 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7507 	} else {
7508 		if (reg == BWN_PHY_RFOVER) {
7509 			return (0x9b3);
7510 		} else if (reg == BWN_PHY_RFOVERVAL) {
7511 			switch (lpd) {
7512 			case BWN_LPD(0, 1, 1):
7513 				return (0x8fb2);
7514 			case BWN_LPD(0, 0, 1):
7515 				return (0x80b2);
7516 			case BWN_LPD(1, 0, 1):
7517 				return (0x20b2);
7518 			case BWN_LPD(1, 0, 0):
7519 				return (0x20b3);
7520 			}
7521 			KASSERT(0 == 1,
7522 			    ("%s:%d: fail", __func__, __LINE__));
7523 		}
7524 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7525 	}
7526 	return (0);
7527 }
7528 
7529 static void
7530 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7531 {
7532 
7533 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7534 		return;
7535 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7536 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7537 	DELAY(1000);
7538 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7539 }
7540 
7541 static int
7542 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7543 {
7544 	struct bwn_softc *sc = mac->mac_sc;
7545 	struct bwn_fw *fw = &mac->mac_fw;
7546 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7547 	const char *filename;
7548 	uint32_t high;
7549 	int error;
7550 
7551 	/* microcode */
7552 	if (rev >= 5 && rev <= 10)
7553 		filename = "ucode5";
7554 	else if (rev >= 11 && rev <= 12)
7555 		filename = "ucode11";
7556 	else if (rev == 13)
7557 		filename = "ucode13";
7558 	else if (rev == 14)
7559 		filename = "ucode14";
7560 	else if (rev >= 15)
7561 		filename = "ucode15";
7562 	else {
7563 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7564 		bwn_release_firmware(mac);
7565 		return (EOPNOTSUPP);
7566 	}
7567 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7568 	if (error) {
7569 		bwn_release_firmware(mac);
7570 		return (error);
7571 	}
7572 
7573 	/* PCM */
7574 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7575 	if (rev >= 5 && rev <= 10) {
7576 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7577 		if (error == ENOENT)
7578 			fw->no_pcmfile = 1;
7579 		else if (error) {
7580 			bwn_release_firmware(mac);
7581 			return (error);
7582 		}
7583 	} else if (rev < 11) {
7584 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7585 		return (EOPNOTSUPP);
7586 	}
7587 
7588 	/* initvals */
7589 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7590 	switch (mac->mac_phy.type) {
7591 	case BWN_PHYTYPE_A:
7592 		if (rev < 5 || rev > 10)
7593 			goto fail1;
7594 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7595 			filename = "a0g1initvals5";
7596 		else
7597 			filename = "a0g0initvals5";
7598 		break;
7599 	case BWN_PHYTYPE_G:
7600 		if (rev >= 5 && rev <= 10)
7601 			filename = "b0g0initvals5";
7602 		else if (rev >= 13)
7603 			filename = "b0g0initvals13";
7604 		else
7605 			goto fail1;
7606 		break;
7607 	case BWN_PHYTYPE_LP:
7608 		if (rev == 13)
7609 			filename = "lp0initvals13";
7610 		else if (rev == 14)
7611 			filename = "lp0initvals14";
7612 		else if (rev >= 15)
7613 			filename = "lp0initvals15";
7614 		else
7615 			goto fail1;
7616 		break;
7617 	case BWN_PHYTYPE_N:
7618 		if (rev >= 11 && rev <= 12)
7619 			filename = "n0initvals11";
7620 		else
7621 			goto fail1;
7622 		break;
7623 	default:
7624 		goto fail1;
7625 	}
7626 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7627 	if (error) {
7628 		bwn_release_firmware(mac);
7629 		return (error);
7630 	}
7631 
7632 	/* bandswitch initvals */
7633 	switch (mac->mac_phy.type) {
7634 	case BWN_PHYTYPE_A:
7635 		if (rev >= 5 && rev <= 10) {
7636 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7637 				filename = "a0g1bsinitvals5";
7638 			else
7639 				filename = "a0g0bsinitvals5";
7640 		} else if (rev >= 11)
7641 			filename = NULL;
7642 		else
7643 			goto fail1;
7644 		break;
7645 	case BWN_PHYTYPE_G:
7646 		if (rev >= 5 && rev <= 10)
7647 			filename = "b0g0bsinitvals5";
7648 		else if (rev >= 11)
7649 			filename = NULL;
7650 		else
7651 			goto fail1;
7652 		break;
7653 	case BWN_PHYTYPE_LP:
7654 		if (rev == 13)
7655 			filename = "lp0bsinitvals13";
7656 		else if (rev == 14)
7657 			filename = "lp0bsinitvals14";
7658 		else if (rev >= 15)
7659 			filename = "lp0bsinitvals15";
7660 		else
7661 			goto fail1;
7662 		break;
7663 	case BWN_PHYTYPE_N:
7664 		if (rev >= 11 && rev <= 12)
7665 			filename = "n0bsinitvals11";
7666 		else
7667 			goto fail1;
7668 		break;
7669 	default:
7670 		goto fail1;
7671 	}
7672 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7673 	if (error) {
7674 		bwn_release_firmware(mac);
7675 		return (error);
7676 	}
7677 	return (0);
7678 fail1:
7679 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7680 	bwn_release_firmware(mac);
7681 	return (EOPNOTSUPP);
7682 }
7683 
7684 static int
7685 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7686     const char *name, struct bwn_fwfile *bfw)
7687 {
7688 	const struct bwn_fwhdr *hdr;
7689 	struct bwn_softc *sc = mac->mac_sc;
7690 	const struct firmware *fw;
7691 	char namebuf[64];
7692 
7693 	if (name == NULL) {
7694 		bwn_do_release_fw(bfw);
7695 		return (0);
7696 	}
7697 	if (bfw->filename != NULL) {
7698 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7699 			return (0);
7700 		bwn_do_release_fw(bfw);
7701 	}
7702 
7703 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7704 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7705 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7706 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7707 	fw = firmware_get(namebuf);
7708 	if (fw == NULL) {
7709 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7710 		    namebuf);
7711 		return (ENOENT);
7712 	}
7713 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7714 		goto fail;
7715 	hdr = (const struct bwn_fwhdr *)(fw->data);
7716 	switch (hdr->type) {
7717 	case BWN_FWTYPE_UCODE:
7718 	case BWN_FWTYPE_PCM:
7719 		if (be32toh(hdr->size) !=
7720 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7721 			goto fail;
7722 		/* FALLTHROUGH */
7723 	case BWN_FWTYPE_IV:
7724 		if (hdr->ver != 1)
7725 			goto fail;
7726 		break;
7727 	default:
7728 		goto fail;
7729 	}
7730 	bfw->filename = name;
7731 	bfw->fw = fw;
7732 	bfw->type = type;
7733 	return (0);
7734 fail:
7735 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7736 	if (fw != NULL)
7737 		firmware_put(fw, FIRMWARE_UNLOAD);
7738 	return (EPROTO);
7739 }
7740 
7741 static void
7742 bwn_release_firmware(struct bwn_mac *mac)
7743 {
7744 
7745 	bwn_do_release_fw(&mac->mac_fw.ucode);
7746 	bwn_do_release_fw(&mac->mac_fw.pcm);
7747 	bwn_do_release_fw(&mac->mac_fw.initvals);
7748 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7749 }
7750 
7751 static void
7752 bwn_do_release_fw(struct bwn_fwfile *bfw)
7753 {
7754 
7755 	if (bfw->fw != NULL)
7756 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7757 	bfw->fw = NULL;
7758 	bfw->filename = NULL;
7759 }
7760 
7761 static int
7762 bwn_fw_loaducode(struct bwn_mac *mac)
7763 {
7764 #define	GETFWOFFSET(fwp, offset)	\
7765 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7766 #define	GETFWSIZE(fwp, offset)	\
7767 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7768 	struct bwn_softc *sc = mac->mac_sc;
7769 	const uint32_t *data;
7770 	unsigned int i;
7771 	uint32_t ctl;
7772 	uint16_t date, fwcaps, time;
7773 	int error = 0;
7774 
7775 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7776 	ctl |= BWN_MACCTL_MCODE_JMP0;
7777 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7778 	    __LINE__));
7779 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7780 	for (i = 0; i < 64; i++)
7781 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7782 	for (i = 0; i < 4096; i += 2)
7783 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7784 
7785 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7786 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7787 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7788 	     i++) {
7789 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7790 		DELAY(10);
7791 	}
7792 
7793 	if (mac->mac_fw.pcm.fw) {
7794 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7795 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7796 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7797 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7798 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7799 		    sizeof(struct bwn_fwhdr)); i++) {
7800 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7801 			DELAY(10);
7802 		}
7803 	}
7804 
7805 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7806 	BWN_WRITE_4(mac, BWN_MACCTL,
7807 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7808 	    BWN_MACCTL_MCODE_RUN);
7809 
7810 	for (i = 0; i < 21; i++) {
7811 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7812 			break;
7813 		if (i >= 20) {
7814 			device_printf(sc->sc_dev, "ucode timeout\n");
7815 			error = ENXIO;
7816 			goto error;
7817 		}
7818 		DELAY(50000);
7819 	}
7820 	BWN_READ_4(mac, BWN_INTR_REASON);
7821 
7822 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7823 	if (mac->mac_fw.rev <= 0x128) {
7824 		device_printf(sc->sc_dev, "the firmware is too old\n");
7825 		error = EOPNOTSUPP;
7826 		goto error;
7827 	}
7828 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7829 	    BWN_SHARED_UCODE_PATCH);
7830 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7831 	mac->mac_fw.opensource = (date == 0xffff);
7832 	if (bwn_wme != 0)
7833 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7834 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7835 
7836 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7837 	if (mac->mac_fw.opensource == 0) {
7838 		device_printf(sc->sc_dev,
7839 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7840 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7841 		if (mac->mac_fw.no_pcmfile)
7842 			device_printf(sc->sc_dev,
7843 			    "no HW crypto acceleration due to pcm5\n");
7844 	} else {
7845 		mac->mac_fw.patch = time;
7846 		fwcaps = bwn_fwcaps_read(mac);
7847 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7848 			device_printf(sc->sc_dev,
7849 			    "disabling HW crypto acceleration\n");
7850 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7851 		}
7852 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7853 			device_printf(sc->sc_dev, "disabling WME support\n");
7854 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7855 		}
7856 	}
7857 
7858 	if (BWN_ISOLDFMT(mac))
7859 		device_printf(sc->sc_dev, "using old firmware image\n");
7860 
7861 	return (0);
7862 
7863 error:
7864 	BWN_WRITE_4(mac, BWN_MACCTL,
7865 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7866 	    BWN_MACCTL_MCODE_JMP0);
7867 
7868 	return (error);
7869 #undef GETFWSIZE
7870 #undef GETFWOFFSET
7871 }
7872 
7873 /* OpenFirmware only */
7874 static uint16_t
7875 bwn_fwcaps_read(struct bwn_mac *mac)
7876 {
7877 
7878 	KASSERT(mac->mac_fw.opensource == 1,
7879 	    ("%s:%d: fail", __func__, __LINE__));
7880 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7881 }
7882 
7883 static int
7884 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7885     size_t count, size_t array_size)
7886 {
7887 #define	GET_NEXTIV16(iv)						\
7888 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7889 	    sizeof(uint16_t) + sizeof(uint16_t)))
7890 #define	GET_NEXTIV32(iv)						\
7891 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7892 	    sizeof(uint16_t) + sizeof(uint32_t)))
7893 	struct bwn_softc *sc = mac->mac_sc;
7894 	const struct bwn_fwinitvals *iv;
7895 	uint16_t offset;
7896 	size_t i;
7897 	uint8_t bit32;
7898 
7899 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7900 	    ("%s:%d: fail", __func__, __LINE__));
7901 	iv = ivals;
7902 	for (i = 0; i < count; i++) {
7903 		if (array_size < sizeof(iv->offset_size))
7904 			goto fail;
7905 		array_size -= sizeof(iv->offset_size);
7906 		offset = be16toh(iv->offset_size);
7907 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7908 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7909 		if (offset >= 0x1000)
7910 			goto fail;
7911 		if (bit32) {
7912 			if (array_size < sizeof(iv->data.d32))
7913 				goto fail;
7914 			array_size -= sizeof(iv->data.d32);
7915 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7916 			iv = GET_NEXTIV32(iv);
7917 		} else {
7918 
7919 			if (array_size < sizeof(iv->data.d16))
7920 				goto fail;
7921 			array_size -= sizeof(iv->data.d16);
7922 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7923 
7924 			iv = GET_NEXTIV16(iv);
7925 		}
7926 	}
7927 	if (array_size != 0)
7928 		goto fail;
7929 	return (0);
7930 fail:
7931 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7932 	return (EPROTO);
7933 #undef GET_NEXTIV16
7934 #undef GET_NEXTIV32
7935 }
7936 
7937 static int
7938 bwn_switch_channel(struct bwn_mac *mac, int chan)
7939 {
7940 	struct bwn_phy *phy = &(mac->mac_phy);
7941 	struct bwn_softc *sc = mac->mac_sc;
7942 	struct ifnet *ifp = sc->sc_ifp;
7943 	struct ieee80211com *ic = ifp->if_l2com;
7944 	uint16_t channelcookie, savedcookie;
7945 	int error;
7946 
7947 	if (chan == 0xffff)
7948 		chan = phy->get_default_chan(mac);
7949 
7950 	channelcookie = chan;
7951 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7952 		channelcookie |= 0x100;
7953 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7954 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7955 	error = phy->switch_channel(mac, chan);
7956 	if (error)
7957 		goto fail;
7958 
7959 	mac->mac_phy.chan = chan;
7960 	DELAY(8000);
7961 	return (0);
7962 fail:
7963 	device_printf(sc->sc_dev, "failed to switch channel\n");
7964 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7965 	return (error);
7966 }
7967 
7968 static uint16_t
7969 bwn_ant2phy(int antenna)
7970 {
7971 
7972 	switch (antenna) {
7973 	case BWN_ANT0:
7974 		return (BWN_TX_PHY_ANT0);
7975 	case BWN_ANT1:
7976 		return (BWN_TX_PHY_ANT1);
7977 	case BWN_ANT2:
7978 		return (BWN_TX_PHY_ANT2);
7979 	case BWN_ANT3:
7980 		return (BWN_TX_PHY_ANT3);
7981 	case BWN_ANTAUTO:
7982 		return (BWN_TX_PHY_ANT01AUTO);
7983 	}
7984 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7985 	return (0);
7986 }
7987 
7988 static void
7989 bwn_wme_load(struct bwn_mac *mac)
7990 {
7991 	struct bwn_softc *sc = mac->mac_sc;
7992 	int i;
7993 
7994 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7995 	    ("%s:%d: fail", __func__, __LINE__));
7996 
7997 	bwn_mac_suspend(mac);
7998 	for (i = 0; i < N(sc->sc_wmeParams); i++)
7999 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8000 		    bwn_wme_shm_offsets[i]);
8001 	bwn_mac_enable(mac);
8002 }
8003 
8004 static void
8005 bwn_wme_loadparams(struct bwn_mac *mac,
8006     const struct wmeParams *p, uint16_t shm_offset)
8007 {
8008 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8009 	struct bwn_softc *sc = mac->mac_sc;
8010 	uint16_t params[BWN_NR_WMEPARAMS];
8011 	int slot, tmp;
8012 	unsigned int i;
8013 
8014 	slot = BWN_READ_2(mac, BWN_RNG) &
8015 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8016 
8017 	memset(&params, 0, sizeof(params));
8018 
8019 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8020 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8021 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8022 
8023 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8024 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8025 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8026 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8027 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8028 	params[BWN_WMEPARAM_BSLOTS] = slot;
8029 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8030 
8031 	for (i = 0; i < N(params); i++) {
8032 		if (i == BWN_WMEPARAM_STATUS) {
8033 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8034 			    shm_offset + (i * 2));
8035 			tmp |= 0x100;
8036 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8037 			    tmp);
8038 		} else {
8039 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040 			    params[i]);
8041 		}
8042 	}
8043 }
8044 
8045 static void
8046 bwn_mac_write_bssid(struct bwn_mac *mac)
8047 {
8048 	struct bwn_softc *sc = mac->mac_sc;
8049 	uint32_t tmp;
8050 	int i;
8051 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8052 
8053 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8054 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8055 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8056 	    IEEE80211_ADDR_LEN);
8057 
8058 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8059 		tmp = (uint32_t) (mac_bssid[i + 0]);
8060 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8061 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8062 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8063 		bwn_ram_write(mac, 0x20 + i, tmp);
8064 	}
8065 }
8066 
8067 static void
8068 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8069     const uint8_t *macaddr)
8070 {
8071 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8072 	uint16_t data;
8073 
8074 	if (!mac)
8075 		macaddr = zero;
8076 
8077 	offset |= 0x0020;
8078 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8079 
8080 	data = macaddr[0];
8081 	data |= macaddr[1] << 8;
8082 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8083 	data = macaddr[2];
8084 	data |= macaddr[3] << 8;
8085 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086 	data = macaddr[4];
8087 	data |= macaddr[5] << 8;
8088 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089 }
8090 
8091 static void
8092 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8093     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8094 {
8095 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8096 	uint8_t per_sta_keys_start = 8;
8097 
8098 	if (BWN_SEC_NEWAPI(mac))
8099 		per_sta_keys_start = 4;
8100 
8101 	KASSERT(index < mac->mac_max_nr_keys,
8102 	    ("%s:%d: fail", __func__, __LINE__));
8103 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8104 	    ("%s:%d: fail", __func__, __LINE__));
8105 
8106 	if (index >= per_sta_keys_start)
8107 		bwn_key_macwrite(mac, index, NULL);
8108 	if (key)
8109 		memcpy(buf, key, key_len);
8110 	bwn_key_write(mac, index, algorithm, buf);
8111 	if (index >= per_sta_keys_start)
8112 		bwn_key_macwrite(mac, index, mac_addr);
8113 
8114 	mac->mac_key[index].algorithm = algorithm;
8115 }
8116 
8117 static void
8118 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8119 {
8120 	struct bwn_softc *sc = mac->mac_sc;
8121 	uint32_t addrtmp[2] = { 0, 0 };
8122 	uint8_t start = 8;
8123 
8124 	if (BWN_SEC_NEWAPI(mac))
8125 		start = 4;
8126 
8127 	KASSERT(index >= start,
8128 	    ("%s:%d: fail", __func__, __LINE__));
8129 	index -= start;
8130 
8131 	if (addr) {
8132 		addrtmp[0] = addr[0];
8133 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8134 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8135 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8136 		addrtmp[1] = addr[4];
8137 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8138 	}
8139 
8140 	if (siba_get_revid(sc->sc_dev) >= 5) {
8141 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8142 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8143 	} else {
8144 		if (index >= 8) {
8145 			bwn_shm_write_4(mac, BWN_SHARED,
8146 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8147 			bwn_shm_write_2(mac, BWN_SHARED,
8148 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8149 		}
8150 	}
8151 }
8152 
8153 static void
8154 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8155     const uint8_t *key)
8156 {
8157 	unsigned int i;
8158 	uint32_t offset;
8159 	uint16_t kidx, value;
8160 
8161 	kidx = BWN_SEC_KEY2FW(mac, index);
8162 	bwn_shm_write_2(mac, BWN_SHARED,
8163 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8164 
8165 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8166 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8167 		value = key[i];
8168 		value |= (uint16_t)(key[i + 1]) << 8;
8169 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8170 	}
8171 }
8172 
8173 static void
8174 bwn_phy_exit(struct bwn_mac *mac)
8175 {
8176 
8177 	mac->mac_phy.rf_onoff(mac, 0);
8178 	if (mac->mac_phy.exit != NULL)
8179 		mac->mac_phy.exit(mac);
8180 }
8181 
8182 static void
8183 bwn_dma_free(struct bwn_mac *mac)
8184 {
8185 	struct bwn_dma *dma;
8186 
8187 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8188 		return;
8189 	dma = &mac->mac_method.dma;
8190 
8191 	bwn_dma_ringfree(&dma->rx);
8192 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8193 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8194 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8195 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8196 	bwn_dma_ringfree(&dma->mcast);
8197 }
8198 
8199 static void
8200 bwn_core_stop(struct bwn_mac *mac)
8201 {
8202 	struct bwn_softc *sc = mac->mac_sc;
8203 
8204 	BWN_ASSERT_LOCKED(sc);
8205 
8206 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8207 		return;
8208 
8209 	callout_stop(&sc->sc_rfswitch_ch);
8210 	callout_stop(&sc->sc_task_ch);
8211 	callout_stop(&sc->sc_watchdog_ch);
8212 	sc->sc_watchdog_timer = 0;
8213 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8214 	BWN_READ_4(mac, BWN_INTR_MASK);
8215 	bwn_mac_suspend(mac);
8216 
8217 	mac->mac_status = BWN_MAC_STATUS_INITED;
8218 }
8219 
8220 static int
8221 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8222 {
8223 	struct bwn_mac *up_dev = NULL;
8224 	struct bwn_mac *down_dev;
8225 	struct bwn_mac *mac;
8226 	int err, status;
8227 	uint8_t gmode;
8228 
8229 	BWN_ASSERT_LOCKED(sc);
8230 
8231 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8232 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8233 		    mac->mac_phy.supports_2ghz) {
8234 			up_dev = mac;
8235 			gmode = 1;
8236 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8237 		    mac->mac_phy.supports_5ghz) {
8238 			up_dev = mac;
8239 			gmode = 0;
8240 		} else {
8241 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8242 			return (EINVAL);
8243 		}
8244 		if (up_dev != NULL)
8245 			break;
8246 	}
8247 	if (up_dev == NULL) {
8248 		device_printf(sc->sc_dev, "Could not find a device\n");
8249 		return (ENODEV);
8250 	}
8251 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8252 		return (0);
8253 
8254 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8255 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8256 
8257 	down_dev = sc->sc_curmac;
8258 	status = down_dev->mac_status;
8259 	if (status >= BWN_MAC_STATUS_STARTED)
8260 		bwn_core_stop(down_dev);
8261 	if (status >= BWN_MAC_STATUS_INITED)
8262 		bwn_core_exit(down_dev);
8263 
8264 	if (down_dev != up_dev)
8265 		bwn_phy_reset(down_dev);
8266 
8267 	up_dev->mac_phy.gmode = gmode;
8268 	if (status >= BWN_MAC_STATUS_INITED) {
8269 		err = bwn_core_init(up_dev);
8270 		if (err) {
8271 			device_printf(sc->sc_dev,
8272 			    "fatal: failed to initialize for %s-GHz\n",
8273 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8274 			goto fail;
8275 		}
8276 	}
8277 	if (status >= BWN_MAC_STATUS_STARTED)
8278 		bwn_core_start(up_dev);
8279 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8280 	sc->sc_curmac = up_dev;
8281 
8282 	return (0);
8283 fail:
8284 	sc->sc_curmac = NULL;
8285 	return (err);
8286 }
8287 
8288 static void
8289 bwn_rf_turnon(struct bwn_mac *mac)
8290 {
8291 
8292 	bwn_mac_suspend(mac);
8293 	mac->mac_phy.rf_onoff(mac, 1);
8294 	mac->mac_phy.rf_on = 1;
8295 	bwn_mac_enable(mac);
8296 }
8297 
8298 static void
8299 bwn_rf_turnoff(struct bwn_mac *mac)
8300 {
8301 
8302 	bwn_mac_suspend(mac);
8303 	mac->mac_phy.rf_onoff(mac, 0);
8304 	mac->mac_phy.rf_on = 0;
8305 	bwn_mac_enable(mac);
8306 }
8307 
8308 static void
8309 bwn_phy_reset(struct bwn_mac *mac)
8310 {
8311 	struct bwn_softc *sc = mac->mac_sc;
8312 
8313 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8314 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8315 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8316 	DELAY(1000);
8317 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8318 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8319 	    BWN_TGSLOW_PHYRESET);
8320 	DELAY(1000);
8321 }
8322 
8323 static int
8324 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8325 {
8326 	struct bwn_vap *bvp = BWN_VAP(vap);
8327 	struct ieee80211com *ic= vap->iv_ic;
8328 	struct ifnet *ifp = ic->ic_ifp;
8329 	enum ieee80211_state ostate = vap->iv_state;
8330 	struct bwn_softc *sc = ic->ic_softc;
8331 	struct bwn_mac *mac = sc->sc_curmac;
8332 	int error;
8333 
8334 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8335 	    ieee80211_state_name[vap->iv_state],
8336 	    ieee80211_state_name[nstate]);
8337 
8338 	error = bvp->bv_newstate(vap, nstate, arg);
8339 	if (error != 0)
8340 		return (error);
8341 
8342 	BWN_LOCK(sc);
8343 
8344 	bwn_led_newstate(mac, nstate);
8345 
8346 	/*
8347 	 * Clear the BSSID when we stop a STA
8348 	 */
8349 	if (vap->iv_opmode == IEEE80211_M_STA) {
8350 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8351 			/*
8352 			 * Clear out the BSSID.  If we reassociate to
8353 			 * the same AP, this will reinialize things
8354 			 * correctly...
8355 			 */
8356 			if (ic->ic_opmode == IEEE80211_M_STA &&
8357 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8358 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8359 				bwn_set_macaddr(mac);
8360 			}
8361 		}
8362 	}
8363 
8364 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8365 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8366 		/* XXX nothing to do? */
8367 	} else if (nstate == IEEE80211_S_RUN) {
8368 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8369 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8370 		bwn_set_opmode(mac);
8371 		bwn_set_pretbtt(mac);
8372 		bwn_spu_setdelay(mac, 0);
8373 		bwn_set_macaddr(mac);
8374 	}
8375 
8376 	BWN_UNLOCK(sc);
8377 
8378 	return (error);
8379 }
8380 
8381 static void
8382 bwn_set_pretbtt(struct bwn_mac *mac)
8383 {
8384 	struct bwn_softc *sc = mac->mac_sc;
8385 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8386 	uint16_t pretbtt;
8387 
8388 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8389 		pretbtt = 2;
8390 	else
8391 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8392 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8393 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8394 }
8395 
8396 static int
8397 bwn_intr(void *arg)
8398 {
8399 	struct bwn_mac *mac = arg;
8400 	struct bwn_softc *sc = mac->mac_sc;
8401 	uint32_t reason;
8402 
8403 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8404 	    (sc->sc_flags & BWN_FLAG_INVALID))
8405 		return (FILTER_STRAY);
8406 
8407 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8408 	if (reason == 0xffffffff)	/* shared IRQ */
8409 		return (FILTER_STRAY);
8410 	reason &= mac->mac_intr_mask;
8411 	if (reason == 0)
8412 		return (FILTER_HANDLED);
8413 
8414 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8415 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8416 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8417 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8418 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8419 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8420 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8421 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8422 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8423 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8424 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8425 
8426 	/* Disable interrupts. */
8427 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8428 
8429 	mac->mac_reason_intr = reason;
8430 
8431 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8432 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8433 
8434 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8435 	return (FILTER_HANDLED);
8436 }
8437 
8438 static void
8439 bwn_intrtask(void *arg, int npending)
8440 {
8441 	struct bwn_mac *mac = arg;
8442 	struct bwn_softc *sc = mac->mac_sc;
8443 	struct ifnet *ifp = sc->sc_ifp;
8444 	uint32_t merged = 0;
8445 	int i, tx = 0, rx = 0;
8446 
8447 	BWN_LOCK(sc);
8448 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8449 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8450 		BWN_UNLOCK(sc);
8451 		return;
8452 	}
8453 
8454 	for (i = 0; i < N(mac->mac_reason); i++)
8455 		merged |= mac->mac_reason[i];
8456 
8457 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8458 		device_printf(sc->sc_dev, "MAC trans error\n");
8459 
8460 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8461 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8462 		mac->mac_phy.txerrors--;
8463 		if (mac->mac_phy.txerrors == 0) {
8464 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8465 			bwn_restart(mac, "PHY TX errors");
8466 		}
8467 	}
8468 
8469 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8470 		if (merged & BWN_DMAINTR_FATALMASK) {
8471 			device_printf(sc->sc_dev,
8472 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8473 			    mac->mac_reason[0], mac->mac_reason[1],
8474 			    mac->mac_reason[2], mac->mac_reason[3],
8475 			    mac->mac_reason[4], mac->mac_reason[5]);
8476 			bwn_restart(mac, "DMA error");
8477 			BWN_UNLOCK(sc);
8478 			return;
8479 		}
8480 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8481 			device_printf(sc->sc_dev,
8482 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8483 			    mac->mac_reason[0], mac->mac_reason[1],
8484 			    mac->mac_reason[2], mac->mac_reason[3],
8485 			    mac->mac_reason[4], mac->mac_reason[5]);
8486 		}
8487 	}
8488 
8489 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8490 		bwn_intr_ucode_debug(mac);
8491 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8492 		bwn_intr_tbtt_indication(mac);
8493 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8494 		bwn_intr_atim_end(mac);
8495 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8496 		bwn_intr_beacon(mac);
8497 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8498 		bwn_intr_pmq(mac);
8499 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8500 		bwn_intr_noise(mac);
8501 
8502 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8503 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8504 			bwn_dma_rx(mac->mac_method.dma.rx);
8505 			rx = 1;
8506 		}
8507 	} else
8508 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8509 
8510 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8511 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8512 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8513 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 
8516 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8517 		bwn_intr_txeof(mac);
8518 		tx = 1;
8519 	}
8520 
8521 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8522 
8523 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8524 		int evt = BWN_LED_EVENT_NONE;
8525 
8526 		if (tx && rx) {
8527 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8528 				evt = BWN_LED_EVENT_RX;
8529 			else
8530 				evt = BWN_LED_EVENT_TX;
8531 		} else if (tx) {
8532 			evt = BWN_LED_EVENT_TX;
8533 		} else if (rx) {
8534 			evt = BWN_LED_EVENT_RX;
8535 		} else if (rx == 0) {
8536 			evt = BWN_LED_EVENT_POLL;
8537 		}
8538 
8539 		if (evt != BWN_LED_EVENT_NONE)
8540 			bwn_led_event(mac, evt);
8541        }
8542 
8543 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8544 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8545 			bwn_start_locked(ifp);
8546 	}
8547 
8548 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8549 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8550 
8551 	BWN_UNLOCK(sc);
8552 }
8553 
8554 static void
8555 bwn_restart(struct bwn_mac *mac, const char *msg)
8556 {
8557 	struct bwn_softc *sc = mac->mac_sc;
8558 	struct ifnet *ifp = sc->sc_ifp;
8559 	struct ieee80211com *ic = ifp->if_l2com;
8560 
8561 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8562 		return;
8563 
8564 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8565 	ieee80211_runtask(ic, &mac->mac_hwreset);
8566 }
8567 
8568 static void
8569 bwn_intr_ucode_debug(struct bwn_mac *mac)
8570 {
8571 	struct bwn_softc *sc = mac->mac_sc;
8572 	uint16_t reason;
8573 
8574 	if (mac->mac_fw.opensource == 0)
8575 		return;
8576 
8577 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8578 	switch (reason) {
8579 	case BWN_DEBUGINTR_PANIC:
8580 		bwn_handle_fwpanic(mac);
8581 		break;
8582 	case BWN_DEBUGINTR_DUMP_SHM:
8583 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8584 		break;
8585 	case BWN_DEBUGINTR_DUMP_REGS:
8586 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8587 		break;
8588 	case BWN_DEBUGINTR_MARKER:
8589 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8590 		break;
8591 	default:
8592 		device_printf(sc->sc_dev,
8593 		    "ucode debug unknown reason: %#x\n", reason);
8594 	}
8595 
8596 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8597 	    BWN_DEBUGINTR_ACK);
8598 }
8599 
8600 static void
8601 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8602 {
8603 	struct bwn_softc *sc = mac->mac_sc;
8604 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8605 
8606 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8607 		bwn_psctl(mac, 0);
8608 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8609 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8610 }
8611 
8612 static void
8613 bwn_intr_atim_end(struct bwn_mac *mac)
8614 {
8615 
8616 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8617 		BWN_WRITE_4(mac, BWN_MACCMD,
8618 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8619 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8620 	}
8621 }
8622 
8623 static void
8624 bwn_intr_beacon(struct bwn_mac *mac)
8625 {
8626 	struct bwn_softc *sc = mac->mac_sc;
8627 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8628 	uint32_t cmd, beacon0, beacon1;
8629 
8630 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8631 	    ic->ic_opmode == IEEE80211_M_MBSS)
8632 		return;
8633 
8634 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8635 
8636 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8637 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8638 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8639 
8640 	if (beacon0 && beacon1) {
8641 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8642 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8643 		return;
8644 	}
8645 
8646 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8647 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8648 		bwn_load_beacon0(mac);
8649 		bwn_load_beacon1(mac);
8650 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8651 		cmd |= BWN_MACCMD_BEACON0_VALID;
8652 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8653 	} else {
8654 		if (!beacon0) {
8655 			bwn_load_beacon0(mac);
8656 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8657 			cmd |= BWN_MACCMD_BEACON0_VALID;
8658 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8659 		} else if (!beacon1) {
8660 			bwn_load_beacon1(mac);
8661 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8662 			cmd |= BWN_MACCMD_BEACON1_VALID;
8663 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8664 		}
8665 	}
8666 }
8667 
8668 static void
8669 bwn_intr_pmq(struct bwn_mac *mac)
8670 {
8671 	uint32_t tmp;
8672 
8673 	while (1) {
8674 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8675 		if (!(tmp & 0x00000008))
8676 			break;
8677 	}
8678 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8679 }
8680 
8681 static void
8682 bwn_intr_noise(struct bwn_mac *mac)
8683 {
8684 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8685 	uint16_t tmp;
8686 	uint8_t noise[4];
8687 	uint8_t i, j;
8688 	int32_t average;
8689 
8690 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8691 		return;
8692 
8693 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8694 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8695 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8696 	    noise[3] == 0x7f)
8697 		goto new;
8698 
8699 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8700 	    ("%s:%d: fail", __func__, __LINE__));
8701 	i = mac->mac_noise.noi_nsamples;
8702 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8703 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8704 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8705 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8706 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8707 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8708 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8709 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8710 	mac->mac_noise.noi_nsamples++;
8711 	if (mac->mac_noise.noi_nsamples == 8) {
8712 		average = 0;
8713 		for (i = 0; i < 8; i++) {
8714 			for (j = 0; j < 4; j++)
8715 				average += mac->mac_noise.noi_samples[i][j];
8716 		}
8717 		average = (((average / 32) * 125) + 64) / 128;
8718 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8719 		if (tmp >= 8)
8720 			average += 2;
8721 		else
8722 			average -= 25;
8723 		average -= (tmp == 8) ? 72 : 48;
8724 
8725 		mac->mac_stats.link_noise = average;
8726 		mac->mac_noise.noi_running = 0;
8727 		return;
8728 	}
8729 new:
8730 	bwn_noise_gensample(mac);
8731 }
8732 
8733 static int
8734 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8735 {
8736 	struct bwn_mac *mac = prq->prq_mac;
8737 	struct bwn_softc *sc = mac->mac_sc;
8738 	unsigned int i;
8739 
8740 	BWN_ASSERT_LOCKED(sc);
8741 
8742 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8743 		return (0);
8744 
8745 	for (i = 0; i < 5000; i++) {
8746 		if (bwn_pio_rxeof(prq) == 0)
8747 			break;
8748 	}
8749 	if (i >= 5000)
8750 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8751 	return ((i > 0) ? 1 : 0);
8752 }
8753 
8754 static void
8755 bwn_dma_rx(struct bwn_dma_ring *dr)
8756 {
8757 	int slot, curslot;
8758 
8759 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8760 	curslot = dr->get_curslot(dr);
8761 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8762 	    ("%s:%d: fail", __func__, __LINE__));
8763 
8764 	slot = dr->dr_curslot;
8765 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8766 		bwn_dma_rxeof(dr, &slot);
8767 
8768 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8769 	    BUS_DMASYNC_PREWRITE);
8770 
8771 	dr->set_curslot(dr, slot);
8772 	dr->dr_curslot = slot;
8773 }
8774 
8775 static void
8776 bwn_intr_txeof(struct bwn_mac *mac)
8777 {
8778 	struct bwn_txstatus stat;
8779 	uint32_t stat0, stat1;
8780 	uint16_t tmp;
8781 
8782 	BWN_ASSERT_LOCKED(mac->mac_sc);
8783 
8784 	while (1) {
8785 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8786 		if (!(stat0 & 0x00000001))
8787 			break;
8788 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8789 
8790 		stat.cookie = (stat0 >> 16);
8791 		stat.seq = (stat1 & 0x0000ffff);
8792 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8793 		tmp = (stat0 & 0x0000ffff);
8794 		stat.framecnt = ((tmp & 0xf000) >> 12);
8795 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8796 		stat.sreason = ((tmp & 0x001c) >> 2);
8797 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8798 		stat.im = (tmp & 0x0040) ? 1 : 0;
8799 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8800 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8801 
8802 		bwn_handle_txeof(mac, &stat);
8803 	}
8804 }
8805 
8806 static void
8807 bwn_hwreset(void *arg, int npending)
8808 {
8809 	struct bwn_mac *mac = arg;
8810 	struct bwn_softc *sc = mac->mac_sc;
8811 	int error = 0;
8812 	int prev_status;
8813 
8814 	BWN_LOCK(sc);
8815 
8816 	prev_status = mac->mac_status;
8817 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8818 		bwn_core_stop(mac);
8819 	if (prev_status >= BWN_MAC_STATUS_INITED)
8820 		bwn_core_exit(mac);
8821 
8822 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8823 		error = bwn_core_init(mac);
8824 		if (error)
8825 			goto out;
8826 	}
8827 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8828 		bwn_core_start(mac);
8829 out:
8830 	if (error) {
8831 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8832 		sc->sc_curmac = NULL;
8833 	}
8834 	BWN_UNLOCK(sc);
8835 }
8836 
8837 static void
8838 bwn_handle_fwpanic(struct bwn_mac *mac)
8839 {
8840 	struct bwn_softc *sc = mac->mac_sc;
8841 	uint16_t reason;
8842 
8843 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8844 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8845 
8846 	if (reason == BWN_FWPANIC_RESTART)
8847 		bwn_restart(mac, "ucode panic");
8848 }
8849 
8850 static void
8851 bwn_load_beacon0(struct bwn_mac *mac)
8852 {
8853 
8854 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8855 }
8856 
8857 static void
8858 bwn_load_beacon1(struct bwn_mac *mac)
8859 {
8860 
8861 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8862 }
8863 
8864 static uint32_t
8865 bwn_jssi_read(struct bwn_mac *mac)
8866 {
8867 	uint32_t val = 0;
8868 
8869 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8870 	val <<= 16;
8871 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8872 
8873 	return (val);
8874 }
8875 
8876 static void
8877 bwn_noise_gensample(struct bwn_mac *mac)
8878 {
8879 	uint32_t jssi = 0x7f7f7f7f;
8880 
8881 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8882 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8883 	BWN_WRITE_4(mac, BWN_MACCMD,
8884 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8885 }
8886 
8887 static int
8888 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8889 {
8890 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8891 
8892 	return (dr->dr_numslots - dr->dr_usedslot);
8893 }
8894 
8895 static int
8896 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8897 {
8898 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8899 
8900 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8901 	    ("%s:%d: fail", __func__, __LINE__));
8902 	if (slot == dr->dr_numslots - 1)
8903 		return (0);
8904 	return (slot + 1);
8905 }
8906 
8907 static void
8908 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8909 {
8910 	struct bwn_mac *mac = dr->dr_mac;
8911 	struct bwn_softc *sc = mac->mac_sc;
8912 	struct bwn_dma *dma = &mac->mac_method.dma;
8913 	struct bwn_dmadesc_generic *desc;
8914 	struct bwn_dmadesc_meta *meta;
8915 	struct bwn_rxhdr4 *rxhdr;
8916 	struct ifnet *ifp = sc->sc_ifp;
8917 	struct mbuf *m;
8918 	uint32_t macstat;
8919 	int32_t tmp;
8920 	int cnt = 0;
8921 	uint16_t len;
8922 
8923 	dr->getdesc(dr, *slot, &desc, &meta);
8924 
8925 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8926 	m = meta->mt_m;
8927 
8928 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8929 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8930 		return;
8931 	}
8932 
8933 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8934 	len = le16toh(rxhdr->frame_len);
8935 	if (len <= 0) {
8936 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
8937 		return;
8938 	}
8939 	if (bwn_dma_check_redzone(dr, m)) {
8940 		device_printf(sc->sc_dev, "redzone error.\n");
8941 		bwn_dma_set_redzone(dr, m);
8942 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8943 		    BUS_DMASYNC_PREWRITE);
8944 		return;
8945 	}
8946 	if (len > dr->dr_rx_bufsize) {
8947 		tmp = len;
8948 		while (1) {
8949 			dr->getdesc(dr, *slot, &desc, &meta);
8950 			bwn_dma_set_redzone(dr, meta->mt_m);
8951 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8952 			    BUS_DMASYNC_PREWRITE);
8953 			*slot = bwn_dma_nextslot(dr, *slot);
8954 			cnt++;
8955 			tmp -= dr->dr_rx_bufsize;
8956 			if (tmp <= 0)
8957 				break;
8958 		}
8959 		device_printf(sc->sc_dev, "too small buffer "
8960 		       "(len %u buffer %u dropped %d)\n",
8961 		       len, dr->dr_rx_bufsize, cnt);
8962 		return;
8963 	}
8964 	macstat = le32toh(rxhdr->mac_status);
8965 	if (macstat & BWN_RX_MAC_FCSERR) {
8966 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8967 			device_printf(sc->sc_dev, "RX drop\n");
8968 			return;
8969 		}
8970 	}
8971 
8972 	m->m_pkthdr.rcvif = ifp;
8973 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8974 	m_adj(m, dr->dr_frameoffset);
8975 
8976 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8977 }
8978 
8979 static void
8980 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8981 {
8982 	struct bwn_dma_ring *dr;
8983 	struct bwn_dmadesc_generic *desc;
8984 	struct bwn_dmadesc_meta *meta;
8985 	struct bwn_pio_txqueue *tq;
8986 	struct bwn_pio_txpkt *tp = NULL;
8987 	struct bwn_softc *sc = mac->mac_sc;
8988 	struct bwn_stats *stats = &mac->mac_stats;
8989 	struct ieee80211_node *ni;
8990 	struct ieee80211vap *vap;
8991 	int retrycnt = 0, slot;
8992 
8993 	BWN_ASSERT_LOCKED(mac->mac_sc);
8994 
8995 	if (status->im)
8996 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8997 	if (status->ampdu)
8998 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8999 	if (status->rtscnt) {
9000 		if (status->rtscnt == 0xf)
9001 			stats->rtsfail++;
9002 		else
9003 			stats->rts++;
9004 	}
9005 
9006 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9007 		if (status->ack) {
9008 			dr = bwn_dma_parse_cookie(mac, status,
9009 			    status->cookie, &slot);
9010 			if (dr == NULL) {
9011 				device_printf(sc->sc_dev,
9012 				    "failed to parse cookie\n");
9013 				return;
9014 			}
9015 			while (1) {
9016 				dr->getdesc(dr, slot, &desc, &meta);
9017 				if (meta->mt_islast) {
9018 					ni = meta->mt_ni;
9019 					vap = ni->ni_vap;
9020 					ieee80211_ratectl_tx_complete(vap, ni,
9021 					    status->ack ?
9022 					      IEEE80211_RATECTL_TX_SUCCESS :
9023 					      IEEE80211_RATECTL_TX_FAILURE,
9024 					    &retrycnt, 0);
9025 					break;
9026 				}
9027 				slot = bwn_dma_nextslot(dr, slot);
9028 			}
9029 		}
9030 		bwn_dma_handle_txeof(mac, status);
9031 	} else {
9032 		if (status->ack) {
9033 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9034 			if (tq == NULL) {
9035 				device_printf(sc->sc_dev,
9036 				    "failed to parse cookie\n");
9037 				return;
9038 			}
9039 			ni = tp->tp_ni;
9040 			vap = ni->ni_vap;
9041 			ieee80211_ratectl_tx_complete(vap, ni,
9042 			    status->ack ?
9043 			      IEEE80211_RATECTL_TX_SUCCESS :
9044 			      IEEE80211_RATECTL_TX_FAILURE,
9045 			    &retrycnt, 0);
9046 		}
9047 		bwn_pio_handle_txeof(mac, status);
9048 	}
9049 
9050 	bwn_phy_txpower_check(mac, 0);
9051 }
9052 
9053 static uint8_t
9054 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9055 {
9056 	struct bwn_mac *mac = prq->prq_mac;
9057 	struct bwn_softc *sc = mac->mac_sc;
9058 	struct bwn_rxhdr4 rxhdr;
9059 	struct ifnet *ifp = sc->sc_ifp;
9060 	struct mbuf *m;
9061 	uint32_t ctl32, macstat, v32;
9062 	unsigned int i, padding;
9063 	uint16_t ctl16, len, totlen, v16;
9064 	unsigned char *mp;
9065 	char *data;
9066 
9067 	memset(&rxhdr, 0, sizeof(rxhdr));
9068 
9069 	if (prq->prq_rev >= 8) {
9070 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9071 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9072 			return (0);
9073 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9074 		    BWN_PIO8_RXCTL_FRAMEREADY);
9075 		for (i = 0; i < 10; i++) {
9076 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9077 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9078 				goto ready;
9079 			DELAY(10);
9080 		}
9081 	} else {
9082 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9083 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9084 			return (0);
9085 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9086 		    BWN_PIO_RXCTL_FRAMEREADY);
9087 		for (i = 0; i < 10; i++) {
9088 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9089 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9090 				goto ready;
9091 			DELAY(10);
9092 		}
9093 	}
9094 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9095 	return (1);
9096 ready:
9097 	if (prq->prq_rev >= 8)
9098 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9099 		    prq->prq_base + BWN_PIO8_RXDATA);
9100 	else
9101 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102 		    prq->prq_base + BWN_PIO_RXDATA);
9103 	len = le16toh(rxhdr.frame_len);
9104 	if (len > 0x700) {
9105 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9106 		goto error;
9107 	}
9108 	if (len == 0) {
9109 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9110 		goto error;
9111 	}
9112 
9113 	macstat = le32toh(rxhdr.mac_status);
9114 	if (macstat & BWN_RX_MAC_FCSERR) {
9115 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9116 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9117 			goto error;
9118 		}
9119 	}
9120 
9121 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9122 	totlen = len + padding;
9123 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9124 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9125 	if (m == NULL) {
9126 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9127 		goto error;
9128 	}
9129 	mp = mtod(m, unsigned char *);
9130 	if (prq->prq_rev >= 8) {
9131 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9132 		    prq->prq_base + BWN_PIO8_RXDATA);
9133 		if (totlen & 3) {
9134 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9135 			data = &(mp[totlen - 1]);
9136 			switch (totlen & 3) {
9137 			case 3:
9138 				*data = (v32 >> 16);
9139 				data--;
9140 			case 2:
9141 				*data = (v32 >> 8);
9142 				data--;
9143 			case 1:
9144 				*data = v32;
9145 			}
9146 		}
9147 	} else {
9148 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9149 		    prq->prq_base + BWN_PIO_RXDATA);
9150 		if (totlen & 1) {
9151 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9152 			mp[totlen - 1] = v16;
9153 		}
9154 	}
9155 
9156 	m->m_pkthdr.rcvif = ifp;
9157 	m->m_len = m->m_pkthdr.len = totlen;
9158 
9159 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9160 
9161 	return (1);
9162 error:
9163 	if (prq->prq_rev >= 8)
9164 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9165 		    BWN_PIO8_RXCTL_DATAREADY);
9166 	else
9167 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9168 	return (1);
9169 }
9170 
9171 static int
9172 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9173     struct bwn_dmadesc_meta *meta, int init)
9174 {
9175 	struct bwn_mac *mac = dr->dr_mac;
9176 	struct bwn_dma *dma = &mac->mac_method.dma;
9177 	struct bwn_rxhdr4 *hdr;
9178 	bus_dmamap_t map;
9179 	bus_addr_t paddr;
9180 	struct mbuf *m;
9181 	int error;
9182 
9183 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9184 	if (m == NULL) {
9185 		error = ENOBUFS;
9186 
9187 		/*
9188 		 * If the NIC is up and running, we need to:
9189 		 * - Clear RX buffer's header.
9190 		 * - Restore RX descriptor settings.
9191 		 */
9192 		if (init)
9193 			return (error);
9194 		else
9195 			goto back;
9196 	}
9197 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9198 
9199 	bwn_dma_set_redzone(dr, m);
9200 
9201 	/*
9202 	 * Try to load RX buf into temporary DMA map
9203 	 */
9204 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9205 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9206 	if (error) {
9207 		m_freem(m);
9208 
9209 		/*
9210 		 * See the comment above
9211 		 */
9212 		if (init)
9213 			return (error);
9214 		else
9215 			goto back;
9216 	}
9217 
9218 	if (!init)
9219 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9220 	meta->mt_m = m;
9221 	meta->mt_paddr = paddr;
9222 
9223 	/*
9224 	 * Swap RX buf's DMA map with the loaded temporary one
9225 	 */
9226 	map = meta->mt_dmap;
9227 	meta->mt_dmap = dr->dr_spare_dmap;
9228 	dr->dr_spare_dmap = map;
9229 
9230 back:
9231 	/*
9232 	 * Clear RX buf header
9233 	 */
9234 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9235 	bzero(hdr, sizeof(*hdr));
9236 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9237 	    BUS_DMASYNC_PREWRITE);
9238 
9239 	/*
9240 	 * Setup RX buf descriptor
9241 	 */
9242 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9243 	    sizeof(*hdr), 0, 0, 0);
9244 	return (error);
9245 }
9246 
9247 static void
9248 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9249 		 bus_size_t mapsz __unused, int error)
9250 {
9251 
9252 	if (!error) {
9253 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9254 		*((bus_addr_t *)arg) = seg->ds_addr;
9255 	}
9256 }
9257 
9258 static int
9259 bwn_hwrate2ieeerate(int rate)
9260 {
9261 
9262 	switch (rate) {
9263 	case BWN_CCK_RATE_1MB:
9264 		return (2);
9265 	case BWN_CCK_RATE_2MB:
9266 		return (4);
9267 	case BWN_CCK_RATE_5MB:
9268 		return (11);
9269 	case BWN_CCK_RATE_11MB:
9270 		return (22);
9271 	case BWN_OFDM_RATE_6MB:
9272 		return (12);
9273 	case BWN_OFDM_RATE_9MB:
9274 		return (18);
9275 	case BWN_OFDM_RATE_12MB:
9276 		return (24);
9277 	case BWN_OFDM_RATE_18MB:
9278 		return (36);
9279 	case BWN_OFDM_RATE_24MB:
9280 		return (48);
9281 	case BWN_OFDM_RATE_36MB:
9282 		return (72);
9283 	case BWN_OFDM_RATE_48MB:
9284 		return (96);
9285 	case BWN_OFDM_RATE_54MB:
9286 		return (108);
9287 	default:
9288 		printf("Ooops\n");
9289 		return (0);
9290 	}
9291 }
9292 
9293 static void
9294 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9295 {
9296 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9297 	struct bwn_plcp6 *plcp;
9298 	struct bwn_softc *sc = mac->mac_sc;
9299 	struct ieee80211_frame_min *wh;
9300 	struct ieee80211_node *ni;
9301 	struct ifnet *ifp = sc->sc_ifp;
9302 	struct ieee80211com *ic = ifp->if_l2com;
9303 	uint32_t macstat;
9304 	int padding, rate, rssi = 0, noise = 0, type;
9305 	uint16_t phytype, phystat0, phystat3, chanstat;
9306 	unsigned char *mp = mtod(m, unsigned char *);
9307 	static int rx_mac_dec_rpt = 0;
9308 
9309 	BWN_ASSERT_LOCKED(sc);
9310 
9311 	phystat0 = le16toh(rxhdr->phy_status0);
9312 	phystat3 = le16toh(rxhdr->phy_status3);
9313 	macstat = le32toh(rxhdr->mac_status);
9314 	chanstat = le16toh(rxhdr->channel);
9315 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9316 
9317 	if (macstat & BWN_RX_MAC_FCSERR)
9318 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9319 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9320 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9321 	if (macstat & BWN_RX_MAC_DECERR)
9322 		goto drop;
9323 
9324 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9325 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9326 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9327 		    m->m_pkthdr.len);
9328 		goto drop;
9329 	}
9330 	plcp = (struct bwn_plcp6 *)(mp + padding);
9331 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9332 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9333 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9334 		    m->m_pkthdr.len);
9335 		goto drop;
9336 	}
9337 	wh = mtod(m, struct ieee80211_frame_min *);
9338 
9339 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9340 		device_printf(sc->sc_dev,
9341 		    "RX decryption attempted (old %d keyidx %#x)\n",
9342 		    BWN_ISOLDFMT(mac),
9343 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9344 
9345 	/* XXX calculating RSSI & noise & antenna */
9346 
9347 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9348 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9349 		    phytype == BWN_PHYTYPE_A);
9350 	else
9351 		rate = bwn_plcp_get_cckrate(mac, plcp);
9352 	if (rate == -1) {
9353 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9354 			goto drop;
9355 	}
9356 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9357 
9358 	/* RX radio tap */
9359 	if (ieee80211_radiotap_active(ic))
9360 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9361 	m_adj(m, -IEEE80211_CRC_LEN);
9362 
9363 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9364 	noise = mac->mac_stats.link_noise;
9365 
9366 	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
9367 
9368 	BWN_UNLOCK(sc);
9369 
9370 	ni = ieee80211_find_rxnode(ic, wh);
9371 	if (ni != NULL) {
9372 		type = ieee80211_input(ni, m, rssi, noise);
9373 		ieee80211_free_node(ni);
9374 	} else
9375 		type = ieee80211_input_all(ic, m, rssi, noise);
9376 
9377 	BWN_LOCK(sc);
9378 	return;
9379 drop:
9380 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9381 }
9382 
9383 static void
9384 bwn_dma_handle_txeof(struct bwn_mac *mac,
9385     const struct bwn_txstatus *status)
9386 {
9387 	struct bwn_dma *dma = &mac->mac_method.dma;
9388 	struct bwn_dma_ring *dr;
9389 	struct bwn_dmadesc_generic *desc;
9390 	struct bwn_dmadesc_meta *meta;
9391 	struct bwn_softc *sc = mac->mac_sc;
9392 	struct ieee80211_node *ni;
9393 	struct ifnet *ifp = sc->sc_ifp;
9394 	struct mbuf *m;
9395 	int slot;
9396 
9397 	BWN_ASSERT_LOCKED(sc);
9398 
9399 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9400 	if (dr == NULL) {
9401 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9402 		return;
9403 	}
9404 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9405 
9406 	while (1) {
9407 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9408 		    ("%s:%d: fail", __func__, __LINE__));
9409 		dr->getdesc(dr, slot, &desc, &meta);
9410 
9411 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9412 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9413 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9414 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9415 
9416 		if (meta->mt_islast) {
9417 			KASSERT(meta->mt_m != NULL,
9418 			    ("%s:%d: fail", __func__, __LINE__));
9419 
9420 			ni = meta->mt_ni;
9421 			m = meta->mt_m;
9422 			if (ni != NULL) {
9423 				/*
9424 				 * Do any tx complete callback. Note this must
9425 				 * be done before releasing the node reference.
9426 				 */
9427 				if (m->m_flags & M_TXCB)
9428 					ieee80211_process_callback(ni, m, 0);
9429 				ieee80211_free_node(ni);
9430 				meta->mt_ni = NULL;
9431 			}
9432 			m_freem(m);
9433 			meta->mt_m = NULL;
9434 		} else {
9435 			KASSERT(meta->mt_m == NULL,
9436 			    ("%s:%d: fail", __func__, __LINE__));
9437 		}
9438 
9439 		dr->dr_usedslot--;
9440 		if (meta->mt_islast) {
9441 			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9442 			break;
9443 		}
9444 		slot = bwn_dma_nextslot(dr, slot);
9445 	}
9446 	sc->sc_watchdog_timer = 0;
9447 	if (dr->dr_stop) {
9448 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9449 		    ("%s:%d: fail", __func__, __LINE__));
9450 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9451 		dr->dr_stop = 0;
9452 	}
9453 }
9454 
9455 static void
9456 bwn_pio_handle_txeof(struct bwn_mac *mac,
9457     const struct bwn_txstatus *status)
9458 {
9459 	struct bwn_pio_txqueue *tq;
9460 	struct bwn_pio_txpkt *tp = NULL;
9461 	struct bwn_softc *sc = mac->mac_sc;
9462 	struct ifnet *ifp = sc->sc_ifp;
9463 
9464 	BWN_ASSERT_LOCKED(sc);
9465 
9466 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9467 	if (tq == NULL)
9468 		return;
9469 
9470 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9471 	tq->tq_free++;
9472 
9473 	if (tp->tp_ni != NULL) {
9474 		/*
9475 		 * Do any tx complete callback.  Note this must
9476 		 * be done before releasing the node reference.
9477 		 */
9478 		if (tp->tp_m->m_flags & M_TXCB)
9479 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9480 		ieee80211_free_node(tp->tp_ni);
9481 		tp->tp_ni = NULL;
9482 	}
9483 	m_freem(tp->tp_m);
9484 	tp->tp_m = NULL;
9485 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9486 
9487 	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
9488 
9489 	sc->sc_watchdog_timer = 0;
9490 	if (tq->tq_stop) {
9491 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9492 		tq->tq_stop = 0;
9493 	}
9494 }
9495 
9496 static void
9497 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9498 {
9499 	struct bwn_softc *sc = mac->mac_sc;
9500 	struct bwn_phy *phy = &mac->mac_phy;
9501 	struct ifnet *ifp = sc->sc_ifp;
9502 	struct ieee80211com *ic = ifp->if_l2com;
9503 	unsigned long now;
9504 	int result;
9505 
9506 	BWN_GETTIME(now);
9507 
9508 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9509 		return;
9510 	phy->nexttime = now + 2 * 1000;
9511 
9512 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9513 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9514 		return;
9515 
9516 	if (phy->recalc_txpwr != NULL) {
9517 		result = phy->recalc_txpwr(mac,
9518 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9519 		if (result == BWN_TXPWR_RES_DONE)
9520 			return;
9521 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9522 		    ("%s: fail", __func__));
9523 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9524 
9525 		ieee80211_runtask(ic, &mac->mac_txpower);
9526 	}
9527 }
9528 
9529 static uint16_t
9530 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9531 {
9532 
9533 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9534 }
9535 
9536 static uint32_t
9537 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9538 {
9539 
9540 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9541 }
9542 
9543 static void
9544 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9545 {
9546 
9547 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9548 }
9549 
9550 static void
9551 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9552 {
9553 
9554 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9555 }
9556 
9557 static int
9558 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9559 {
9560 
9561 	switch (rate) {
9562 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9563 	case 12:
9564 		return (BWN_OFDM_RATE_6MB);
9565 	case 18:
9566 		return (BWN_OFDM_RATE_9MB);
9567 	case 24:
9568 		return (BWN_OFDM_RATE_12MB);
9569 	case 36:
9570 		return (BWN_OFDM_RATE_18MB);
9571 	case 48:
9572 		return (BWN_OFDM_RATE_24MB);
9573 	case 72:
9574 		return (BWN_OFDM_RATE_36MB);
9575 	case 96:
9576 		return (BWN_OFDM_RATE_48MB);
9577 	case 108:
9578 		return (BWN_OFDM_RATE_54MB);
9579 	/* CCK rates (NB: not IEEE std, device-specific) */
9580 	case 2:
9581 		return (BWN_CCK_RATE_1MB);
9582 	case 4:
9583 		return (BWN_CCK_RATE_2MB);
9584 	case 11:
9585 		return (BWN_CCK_RATE_5MB);
9586 	case 22:
9587 		return (BWN_CCK_RATE_11MB);
9588 	}
9589 
9590 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9591 	return (BWN_CCK_RATE_1MB);
9592 }
9593 
9594 static int
9595 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9596     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9597 {
9598 	const struct bwn_phy *phy = &mac->mac_phy;
9599 	struct bwn_softc *sc = mac->mac_sc;
9600 	struct ieee80211_frame *wh;
9601 	struct ieee80211_frame *protwh;
9602 	struct ieee80211_frame_cts *cts;
9603 	struct ieee80211_frame_rts *rts;
9604 	const struct ieee80211_txparam *tp;
9605 	struct ieee80211vap *vap = ni->ni_vap;
9606 	struct ifnet *ifp = sc->sc_ifp;
9607 	struct ieee80211com *ic = ifp->if_l2com;
9608 	struct mbuf *mprot;
9609 	unsigned int len;
9610 	uint32_t macctl = 0;
9611 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9612 	uint16_t phyctl = 0;
9613 	uint8_t rate, rate_fb;
9614 
9615 	wh = mtod(m, struct ieee80211_frame *);
9616 	memset(txhdr, 0, sizeof(*txhdr));
9617 
9618 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9619 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9620 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9621 
9622 	/*
9623 	 * Find TX rate
9624 	 */
9625 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9626 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9627 		rate = rate_fb = tp->mgmtrate;
9628 	else if (ismcast)
9629 		rate = rate_fb = tp->mcastrate;
9630 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9631 		rate = rate_fb = tp->ucastrate;
9632 	else {
9633 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9634 		rate = ni->ni_txrate;
9635 
9636 		if (rix > 0)
9637 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9638 			    IEEE80211_RATE_VAL;
9639 		else
9640 			rate_fb = rate;
9641 	}
9642 
9643 	sc->sc_tx_rate = rate;
9644 
9645 	rate = bwn_ieeerate2hwrate(sc, rate);
9646 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9647 
9648 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9649 	    bwn_plcp_getcck(rate);
9650 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9651 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9652 
9653 	if ((rate_fb == rate) ||
9654 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9655 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9656 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9657 	else
9658 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9659 		    m->m_pkthdr.len, rate, isshort);
9660 
9661 	/* XXX TX encryption */
9662 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9663 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9664 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9665 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9666 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9667 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9668 
9669 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9670 	    BWN_TX_EFT_FB_CCK;
9671 	txhdr->chan = phy->chan;
9672 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9673 	    BWN_TX_PHY_ENC_CCK;
9674 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9675 	     rate == BWN_CCK_RATE_11MB))
9676 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9677 
9678 	/* XXX TX antenna selection */
9679 
9680 	switch (bwn_antenna_sanitize(mac, 0)) {
9681 	case 0:
9682 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9683 		break;
9684 	case 1:
9685 		phyctl |= BWN_TX_PHY_ANT0;
9686 		break;
9687 	case 2:
9688 		phyctl |= BWN_TX_PHY_ANT1;
9689 		break;
9690 	case 3:
9691 		phyctl |= BWN_TX_PHY_ANT2;
9692 		break;
9693 	case 4:
9694 		phyctl |= BWN_TX_PHY_ANT3;
9695 		break;
9696 	default:
9697 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9698 	}
9699 
9700 	if (!ismcast)
9701 		macctl |= BWN_TX_MAC_ACK;
9702 
9703 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9704 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9705 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9706 		macctl |= BWN_TX_MAC_LONGFRAME;
9707 
9708 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9709 		/* XXX RTS rate is always 1MB??? */
9710 		rts_rate = BWN_CCK_RATE_1MB;
9711 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9712 
9713 		protdur = ieee80211_compute_duration(ic->ic_rt,
9714 		    m->m_pkthdr.len, rate, isshort) +
9715 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9716 
9717 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9718 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9719 			    (txhdr->body.old.rts_frame) :
9720 			    (txhdr->body.new.rts_frame));
9721 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9722 			    protdur);
9723 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9724 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9725 			    mprot->m_pkthdr.len);
9726 			m_freem(mprot);
9727 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9728 			len = sizeof(struct ieee80211_frame_cts);
9729 		} else {
9730 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9731 			    (txhdr->body.old.rts_frame) :
9732 			    (txhdr->body.new.rts_frame));
9733 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9734 			    isshort);
9735 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9736 			    wh->i_addr2, protdur);
9737 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9738 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9739 			    mprot->m_pkthdr.len);
9740 			m_freem(mprot);
9741 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9742 			len = sizeof(struct ieee80211_frame_rts);
9743 		}
9744 		len += IEEE80211_CRC_LEN;
9745 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9746 		    &txhdr->body.old.rts_plcp :
9747 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9748 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9749 		    rts_rate_fb);
9750 
9751 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9752 		    (&txhdr->body.old.rts_frame) :
9753 		    (&txhdr->body.new.rts_frame));
9754 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9755 
9756 		if (BWN_ISOFDMRATE(rts_rate)) {
9757 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9758 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9759 		} else {
9760 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9761 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9762 		}
9763 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9764 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9765 	}
9766 
9767 	if (BWN_ISOLDFMT(mac))
9768 		txhdr->body.old.cookie = htole16(cookie);
9769 	else
9770 		txhdr->body.new.cookie = htole16(cookie);
9771 
9772 	txhdr->macctl = htole32(macctl);
9773 	txhdr->phyctl = htole16(phyctl);
9774 
9775 	/*
9776 	 * TX radio tap
9777 	 */
9778 	if (ieee80211_radiotap_active_vap(vap)) {
9779 		sc->sc_tx_th.wt_flags = 0;
9780 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9781 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9782 		if (isshort &&
9783 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9784 		     rate == BWN_CCK_RATE_11MB))
9785 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9786 		sc->sc_tx_th.wt_rate = rate;
9787 
9788 		ieee80211_radiotap_tx(vap, m);
9789 	}
9790 
9791 	return (0);
9792 }
9793 
9794 static void
9795 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9796     const uint8_t rate)
9797 {
9798 	uint32_t d, plen;
9799 	uint8_t *raw = plcp->o.raw;
9800 
9801 	if (BWN_ISOFDMRATE(rate)) {
9802 		d = bwn_plcp_getofdm(rate);
9803 		KASSERT(!(octets & 0xf000),
9804 		    ("%s:%d: fail", __func__, __LINE__));
9805 		d |= (octets << 5);
9806 		plcp->o.data = htole32(d);
9807 	} else {
9808 		plen = octets * 16 / rate;
9809 		if ((octets * 16 % rate) > 0) {
9810 			plen++;
9811 			if ((rate == BWN_CCK_RATE_11MB)
9812 			    && ((octets * 8 % 11) < 4)) {
9813 				raw[1] = 0x84;
9814 			} else
9815 				raw[1] = 0x04;
9816 		} else
9817 			raw[1] = 0x04;
9818 		plcp->o.data |= htole32(plen << 16);
9819 		raw[0] = bwn_plcp_getcck(rate);
9820 	}
9821 }
9822 
9823 static uint8_t
9824 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9825 {
9826 	struct bwn_softc *sc = mac->mac_sc;
9827 	uint8_t mask;
9828 
9829 	if (n == 0)
9830 		return (0);
9831 	if (mac->mac_phy.gmode)
9832 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9833 	else
9834 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9835 	if (!(mask & (1 << (n - 1))))
9836 		return (0);
9837 	return (n);
9838 }
9839 
9840 static uint8_t
9841 bwn_get_fbrate(uint8_t bitrate)
9842 {
9843 	switch (bitrate) {
9844 	case BWN_CCK_RATE_1MB:
9845 		return (BWN_CCK_RATE_1MB);
9846 	case BWN_CCK_RATE_2MB:
9847 		return (BWN_CCK_RATE_1MB);
9848 	case BWN_CCK_RATE_5MB:
9849 		return (BWN_CCK_RATE_2MB);
9850 	case BWN_CCK_RATE_11MB:
9851 		return (BWN_CCK_RATE_5MB);
9852 	case BWN_OFDM_RATE_6MB:
9853 		return (BWN_CCK_RATE_5MB);
9854 	case BWN_OFDM_RATE_9MB:
9855 		return (BWN_OFDM_RATE_6MB);
9856 	case BWN_OFDM_RATE_12MB:
9857 		return (BWN_OFDM_RATE_9MB);
9858 	case BWN_OFDM_RATE_18MB:
9859 		return (BWN_OFDM_RATE_12MB);
9860 	case BWN_OFDM_RATE_24MB:
9861 		return (BWN_OFDM_RATE_18MB);
9862 	case BWN_OFDM_RATE_36MB:
9863 		return (BWN_OFDM_RATE_24MB);
9864 	case BWN_OFDM_RATE_48MB:
9865 		return (BWN_OFDM_RATE_36MB);
9866 	case BWN_OFDM_RATE_54MB:
9867 		return (BWN_OFDM_RATE_48MB);
9868 	}
9869 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9870 	return (0);
9871 }
9872 
9873 static uint32_t
9874 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9875     uint32_t ctl, const void *_data, int len)
9876 {
9877 	struct bwn_softc *sc = mac->mac_sc;
9878 	uint32_t value = 0;
9879 	const uint8_t *data = _data;
9880 
9881 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9882 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9883 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9884 
9885 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9886 	    tq->tq_base + BWN_PIO8_TXDATA);
9887 	if (len & 3) {
9888 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9889 		    BWN_PIO8_TXCTL_24_31);
9890 		data = &(data[len - 1]);
9891 		switch (len & 3) {
9892 		case 3:
9893 			ctl |= BWN_PIO8_TXCTL_16_23;
9894 			value |= (uint32_t)(*data) << 16;
9895 			data--;
9896 		case 2:
9897 			ctl |= BWN_PIO8_TXCTL_8_15;
9898 			value |= (uint32_t)(*data) << 8;
9899 			data--;
9900 		case 1:
9901 			value |= (uint32_t)(*data);
9902 		}
9903 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9904 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9905 	}
9906 
9907 	return (ctl);
9908 }
9909 
9910 static void
9911 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9912     uint16_t offset, uint32_t value)
9913 {
9914 
9915 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9916 }
9917 
9918 static uint16_t
9919 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9920     uint16_t ctl, const void *_data, int len)
9921 {
9922 	struct bwn_softc *sc = mac->mac_sc;
9923 	const uint8_t *data = _data;
9924 
9925 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9926 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9927 
9928 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9929 	    tq->tq_base + BWN_PIO_TXDATA);
9930 	if (len & 1) {
9931 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9932 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9933 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9934 	}
9935 
9936 	return (ctl);
9937 }
9938 
9939 static uint16_t
9940 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9941     uint16_t ctl, struct mbuf *m0)
9942 {
9943 	int i, j = 0;
9944 	uint16_t data = 0;
9945 	const uint8_t *buf;
9946 	struct mbuf *m = m0;
9947 
9948 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9949 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9950 
9951 	for (; m != NULL; m = m->m_next) {
9952 		buf = mtod(m, const uint8_t *);
9953 		for (i = 0; i < m->m_len; i++) {
9954 			if (!((j++) % 2))
9955 				data |= buf[i];
9956 			else {
9957 				data |= (buf[i] << 8);
9958 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9959 				data = 0;
9960 			}
9961 		}
9962 	}
9963 	if (m0->m_pkthdr.len % 2) {
9964 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9965 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9966 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9967 	}
9968 
9969 	return (ctl);
9970 }
9971 
9972 static void
9973 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9974 {
9975 
9976 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9977 		return;
9978 	BWN_WRITE_2(mac, 0x684, 510 + time);
9979 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9980 }
9981 
9982 static struct bwn_dma_ring *
9983 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9984 {
9985 
9986 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9987 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9988 
9989 	switch (prio) {
9990 	case 3:
9991 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9992 	case 2:
9993 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9994 	case 0:
9995 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9996 	case 1:
9997 		return (mac->mac_method.dma.wme[WME_AC_BK]);
9998 	}
9999 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10000 	return (NULL);
10001 }
10002 
10003 static int
10004 bwn_dma_getslot(struct bwn_dma_ring *dr)
10005 {
10006 	int slot;
10007 
10008 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10009 
10010 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10011 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10012 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10013 
10014 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10015 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10016 	dr->dr_curslot = slot;
10017 	dr->dr_usedslot++;
10018 
10019 	return (slot);
10020 }
10021 
10022 static int
10023 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10024 {
10025 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10026 	unsigned int a, b, c, d;
10027 	unsigned int avg;
10028 	uint32_t tmp;
10029 
10030 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10031 	a = tmp & 0xff;
10032 	b = (tmp >> 8) & 0xff;
10033 	c = (tmp >> 16) & 0xff;
10034 	d = (tmp >> 24) & 0xff;
10035 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10036 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10037 		return (ENOENT);
10038 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10039 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10040 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10041 
10042 	if (ofdm) {
10043 		a = (a + 32) & 0x3f;
10044 		b = (b + 32) & 0x3f;
10045 		c = (c + 32) & 0x3f;
10046 		d = (d + 32) & 0x3f;
10047 	}
10048 
10049 	avg = (a + b + c + d + 2) / 4;
10050 	if (ofdm) {
10051 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10052 		    & BWN_HF_4DB_CCK_POWERBOOST)
10053 			avg = (avg >= 13) ? (avg - 13) : 0;
10054 	}
10055 	return (avg);
10056 }
10057 
10058 static void
10059 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10060 {
10061 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10062 	int rfatt = *rfattp;
10063 	int bbatt = *bbattp;
10064 
10065 	while (1) {
10066 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10067 			break;
10068 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10069 			break;
10070 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10071 			break;
10072 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10073 			break;
10074 		if (bbatt > lo->bbatt.max) {
10075 			bbatt -= 4;
10076 			rfatt += 1;
10077 			continue;
10078 		}
10079 		if (bbatt < lo->bbatt.min) {
10080 			bbatt += 4;
10081 			rfatt -= 1;
10082 			continue;
10083 		}
10084 		if (rfatt > lo->rfatt.max) {
10085 			rfatt -= 1;
10086 			bbatt += 4;
10087 			continue;
10088 		}
10089 		if (rfatt < lo->rfatt.min) {
10090 			rfatt += 1;
10091 			bbatt -= 4;
10092 			continue;
10093 		}
10094 		break;
10095 	}
10096 
10097 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10098 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10099 }
10100 
10101 static void
10102 bwn_phy_lock(struct bwn_mac *mac)
10103 {
10104 	struct bwn_softc *sc = mac->mac_sc;
10105 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10106 
10107 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10108 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10109 
10110 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10111 		bwn_psctl(mac, BWN_PS_AWAKE);
10112 }
10113 
10114 static void
10115 bwn_phy_unlock(struct bwn_mac *mac)
10116 {
10117 	struct bwn_softc *sc = mac->mac_sc;
10118 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10119 
10120 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10121 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10122 
10123 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10124 		bwn_psctl(mac, 0);
10125 }
10126 
10127 static void
10128 bwn_rf_lock(struct bwn_mac *mac)
10129 {
10130 
10131 	BWN_WRITE_4(mac, BWN_MACCTL,
10132 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10133 	BWN_READ_4(mac, BWN_MACCTL);
10134 	DELAY(10);
10135 }
10136 
10137 static void
10138 bwn_rf_unlock(struct bwn_mac *mac)
10139 {
10140 
10141 	BWN_READ_2(mac, BWN_PHYVER);
10142 	BWN_WRITE_4(mac, BWN_MACCTL,
10143 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10144 }
10145 
10146 static struct bwn_pio_txqueue *
10147 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10148     struct bwn_pio_txpkt **pack)
10149 {
10150 	struct bwn_pio *pio = &mac->mac_method.pio;
10151 	struct bwn_pio_txqueue *tq = NULL;
10152 	unsigned int index;
10153 
10154 	switch (cookie & 0xf000) {
10155 	case 0x1000:
10156 		tq = &pio->wme[WME_AC_BK];
10157 		break;
10158 	case 0x2000:
10159 		tq = &pio->wme[WME_AC_BE];
10160 		break;
10161 	case 0x3000:
10162 		tq = &pio->wme[WME_AC_VI];
10163 		break;
10164 	case 0x4000:
10165 		tq = &pio->wme[WME_AC_VO];
10166 		break;
10167 	case 0x5000:
10168 		tq = &pio->mcast;
10169 		break;
10170 	}
10171 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10172 	if (tq == NULL)
10173 		return (NULL);
10174 	index = (cookie & 0x0fff);
10175 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10176 	if (index >= N(tq->tq_pkts))
10177 		return (NULL);
10178 	*pack = &tq->tq_pkts[index];
10179 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10180 	return (tq);
10181 }
10182 
10183 static void
10184 bwn_txpwr(void *arg, int npending)
10185 {
10186 	struct bwn_mac *mac = arg;
10187 	struct bwn_softc *sc = mac->mac_sc;
10188 
10189 	BWN_LOCK(sc);
10190 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10191 	    mac->mac_phy.set_txpwr != NULL)
10192 		mac->mac_phy.set_txpwr(mac);
10193 	BWN_UNLOCK(sc);
10194 }
10195 
10196 static void
10197 bwn_task_15s(struct bwn_mac *mac)
10198 {
10199 	uint16_t reg;
10200 
10201 	if (mac->mac_fw.opensource) {
10202 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10203 		if (reg) {
10204 			bwn_restart(mac, "fw watchdog");
10205 			return;
10206 		}
10207 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10208 	}
10209 	if (mac->mac_phy.task_15s)
10210 		mac->mac_phy.task_15s(mac);
10211 
10212 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10213 }
10214 
10215 static void
10216 bwn_task_30s(struct bwn_mac *mac)
10217 {
10218 
10219 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10220 		return;
10221 	mac->mac_noise.noi_running = 1;
10222 	mac->mac_noise.noi_nsamples = 0;
10223 
10224 	bwn_noise_gensample(mac);
10225 }
10226 
10227 static void
10228 bwn_task_60s(struct bwn_mac *mac)
10229 {
10230 
10231 	if (mac->mac_phy.task_60s)
10232 		mac->mac_phy.task_60s(mac);
10233 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10234 }
10235 
10236 static void
10237 bwn_tasks(void *arg)
10238 {
10239 	struct bwn_mac *mac = arg;
10240 	struct bwn_softc *sc = mac->mac_sc;
10241 
10242 	BWN_ASSERT_LOCKED(sc);
10243 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10244 		return;
10245 
10246 	if (mac->mac_task_state % 4 == 0)
10247 		bwn_task_60s(mac);
10248 	if (mac->mac_task_state % 2 == 0)
10249 		bwn_task_30s(mac);
10250 	bwn_task_15s(mac);
10251 
10252 	mac->mac_task_state++;
10253 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10254 }
10255 
10256 static int
10257 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10258 {
10259 	struct bwn_softc *sc = mac->mac_sc;
10260 
10261 	KASSERT(a == 0, ("not support APHY\n"));
10262 
10263 	switch (plcp->o.raw[0] & 0xf) {
10264 	case 0xb:
10265 		return (BWN_OFDM_RATE_6MB);
10266 	case 0xf:
10267 		return (BWN_OFDM_RATE_9MB);
10268 	case 0xa:
10269 		return (BWN_OFDM_RATE_12MB);
10270 	case 0xe:
10271 		return (BWN_OFDM_RATE_18MB);
10272 	case 0x9:
10273 		return (BWN_OFDM_RATE_24MB);
10274 	case 0xd:
10275 		return (BWN_OFDM_RATE_36MB);
10276 	case 0x8:
10277 		return (BWN_OFDM_RATE_48MB);
10278 	case 0xc:
10279 		return (BWN_OFDM_RATE_54MB);
10280 	}
10281 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10282 	    plcp->o.raw[0] & 0xf);
10283 	return (-1);
10284 }
10285 
10286 static int
10287 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10288 {
10289 	struct bwn_softc *sc = mac->mac_sc;
10290 
10291 	switch (plcp->o.raw[0]) {
10292 	case 0x0a:
10293 		return (BWN_CCK_RATE_1MB);
10294 	case 0x14:
10295 		return (BWN_CCK_RATE_2MB);
10296 	case 0x37:
10297 		return (BWN_CCK_RATE_5MB);
10298 	case 0x6e:
10299 		return (BWN_CCK_RATE_11MB);
10300 	}
10301 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10302 	return (-1);
10303 }
10304 
10305 static void
10306 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10307     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10308     int rssi, int noise)
10309 {
10310 	struct bwn_softc *sc = mac->mac_sc;
10311 	const struct ieee80211_frame_min *wh;
10312 	uint64_t tsf;
10313 	uint16_t low_mactime_now;
10314 
10315 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10316 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10317 
10318 	wh = mtod(m, const struct ieee80211_frame_min *);
10319 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10320 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10321 
10322 	bwn_tsf_read(mac, &tsf);
10323 	low_mactime_now = tsf;
10324 	tsf = tsf & ~0xffffULL;
10325 	tsf += le16toh(rxhdr->mac_time);
10326 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10327 		tsf -= 0x10000;
10328 
10329 	sc->sc_rx_th.wr_tsf = tsf;
10330 	sc->sc_rx_th.wr_rate = rate;
10331 	sc->sc_rx_th.wr_antsignal = rssi;
10332 	sc->sc_rx_th.wr_antnoise = noise;
10333 }
10334 
10335 static void
10336 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10337 {
10338 	uint32_t low, high;
10339 
10340 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10341 	    ("%s:%d: fail", __func__, __LINE__));
10342 
10343 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10344 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10345 	*tsf = high;
10346 	*tsf <<= 32;
10347 	*tsf |= low;
10348 }
10349 
10350 static int
10351 bwn_dma_attach(struct bwn_mac *mac)
10352 {
10353 	struct bwn_dma *dma = &mac->mac_method.dma;
10354 	struct bwn_softc *sc = mac->mac_sc;
10355 	bus_addr_t lowaddr = 0;
10356 	int error;
10357 
10358 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10359 		return (0);
10360 
10361 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10362 
10363 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10364 
10365 	dma->dmatype = bwn_dma_gettype(mac);
10366 	if (dma->dmatype == BWN_DMA_30BIT)
10367 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10368 	else if (dma->dmatype == BWN_DMA_32BIT)
10369 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10370 	else
10371 		lowaddr = BUS_SPACE_MAXADDR;
10372 
10373 	/*
10374 	 * Create top level DMA tag
10375 	 */
10376 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10377 			       BWN_ALIGN, 0,		/* alignment, bounds */
10378 			       lowaddr,			/* lowaddr */
10379 			       BUS_SPACE_MAXADDR,	/* highaddr */
10380 			       NULL, NULL,		/* filter, filterarg */
10381 			       BUS_SPACE_MAXSIZE,	/* maxsize */
10382 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10383 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10384 			       0,			/* flags */
10385 			       NULL, NULL,		/* lockfunc, lockarg */
10386 			       &dma->parent_dtag);
10387 	if (error) {
10388 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10389 		return (error);
10390 	}
10391 
10392 	/*
10393 	 * Create TX/RX mbuf DMA tag
10394 	 */
10395 	error = bus_dma_tag_create(dma->parent_dtag,
10396 				1,
10397 				0,
10398 				BUS_SPACE_MAXADDR,
10399 				BUS_SPACE_MAXADDR,
10400 				NULL, NULL,
10401 				MCLBYTES,
10402 				1,
10403 				BUS_SPACE_MAXSIZE_32BIT,
10404 				0,
10405 				NULL, NULL,
10406 				&dma->rxbuf_dtag);
10407 	if (error) {
10408 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10409 		goto fail0;
10410 	}
10411 	error = bus_dma_tag_create(dma->parent_dtag,
10412 				1,
10413 				0,
10414 				BUS_SPACE_MAXADDR,
10415 				BUS_SPACE_MAXADDR,
10416 				NULL, NULL,
10417 				MCLBYTES,
10418 				1,
10419 				BUS_SPACE_MAXSIZE_32BIT,
10420 				0,
10421 				NULL, NULL,
10422 				&dma->txbuf_dtag);
10423 	if (error) {
10424 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10425 		goto fail1;
10426 	}
10427 
10428 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10429 	if (!dma->wme[WME_AC_BK])
10430 		goto fail2;
10431 
10432 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10433 	if (!dma->wme[WME_AC_BE])
10434 		goto fail3;
10435 
10436 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10437 	if (!dma->wme[WME_AC_VI])
10438 		goto fail4;
10439 
10440 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10441 	if (!dma->wme[WME_AC_VO])
10442 		goto fail5;
10443 
10444 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10445 	if (!dma->mcast)
10446 		goto fail6;
10447 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10448 	if (!dma->rx)
10449 		goto fail7;
10450 
10451 	return (error);
10452 
10453 fail7:	bwn_dma_ringfree(&dma->mcast);
10454 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10455 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10456 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10457 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10458 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10459 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10460 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10461 	return (error);
10462 }
10463 
10464 static struct bwn_dma_ring *
10465 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10466     uint16_t cookie, int *slot)
10467 {
10468 	struct bwn_dma *dma = &mac->mac_method.dma;
10469 	struct bwn_dma_ring *dr;
10470 	struct bwn_softc *sc = mac->mac_sc;
10471 
10472 	BWN_ASSERT_LOCKED(mac->mac_sc);
10473 
10474 	switch (cookie & 0xf000) {
10475 	case 0x1000:
10476 		dr = dma->wme[WME_AC_BK];
10477 		break;
10478 	case 0x2000:
10479 		dr = dma->wme[WME_AC_BE];
10480 		break;
10481 	case 0x3000:
10482 		dr = dma->wme[WME_AC_VI];
10483 		break;
10484 	case 0x4000:
10485 		dr = dma->wme[WME_AC_VO];
10486 		break;
10487 	case 0x5000:
10488 		dr = dma->mcast;
10489 		break;
10490 	default:
10491 		dr = NULL;
10492 		KASSERT(0 == 1,
10493 		    ("invalid cookie value %d", cookie & 0xf000));
10494 	}
10495 	*slot = (cookie & 0x0fff);
10496 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10497 		/*
10498 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10499 		 * that it occurs events which have same H/W sequence numbers.
10500 		 * When it's occurred just prints a WARNING msgs and ignores.
10501 		 */
10502 		KASSERT(status->seq == dma->lastseq,
10503 		    ("%s:%d: fail", __func__, __LINE__));
10504 		device_printf(sc->sc_dev,
10505 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10506 		    dr->dr_numslots);
10507 		return (NULL);
10508 	}
10509 	dma->lastseq = status->seq;
10510 	return (dr);
10511 }
10512 
10513 static void
10514 bwn_dma_stop(struct bwn_mac *mac)
10515 {
10516 	struct bwn_dma *dma;
10517 
10518 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10519 		return;
10520 	dma = &mac->mac_method.dma;
10521 
10522 	bwn_dma_ringstop(&dma->rx);
10523 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10524 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10525 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10526 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10527 	bwn_dma_ringstop(&dma->mcast);
10528 }
10529 
10530 static void
10531 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10532 {
10533 
10534 	if (dr == NULL)
10535 		return;
10536 
10537 	bwn_dma_cleanup(*dr);
10538 }
10539 
10540 static void
10541 bwn_pio_stop(struct bwn_mac *mac)
10542 {
10543 	struct bwn_pio *pio;
10544 
10545 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10546 		return;
10547 	pio = &mac->mac_method.pio;
10548 
10549 	bwn_destroy_queue_tx(&pio->mcast);
10550 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10551 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10552 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10553 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10554 }
10555 
10556 static void
10557 bwn_led_attach(struct bwn_mac *mac)
10558 {
10559 	struct bwn_softc *sc = mac->mac_sc;
10560 	const uint8_t *led_act = NULL;
10561 	uint16_t val[BWN_LED_MAX];
10562 	int i;
10563 
10564 	sc->sc_led_idle = (2350 * hz) / 1000;
10565 	sc->sc_led_blink = 1;
10566 
10567 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10568 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10569 		    bwn_vendor_led_act[i].vid) {
10570 			led_act = bwn_vendor_led_act[i].led_act;
10571 			break;
10572 		}
10573 	}
10574 	if (led_act == NULL)
10575 		led_act = bwn_default_led_act;
10576 
10577 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10578 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10579 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10580 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10581 
10582 	for (i = 0; i < BWN_LED_MAX; ++i) {
10583 		struct bwn_led *led = &sc->sc_leds[i];
10584 
10585 		if (val[i] == 0xff) {
10586 			led->led_act = led_act[i];
10587 		} else {
10588 			if (val[i] & BWN_LED_ACT_LOW)
10589 				led->led_flags |= BWN_LED_F_ACTLOW;
10590 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10591 		}
10592 		led->led_mask = (1 << i);
10593 
10594 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10595 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10596 		    led->led_act == BWN_LED_ACT_BLINK) {
10597 			led->led_flags |= BWN_LED_F_BLINK;
10598 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10599 				led->led_flags |= BWN_LED_F_POLLABLE;
10600 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10601 				led->led_flags |= BWN_LED_F_SLOW;
10602 
10603 			if (sc->sc_blink_led == NULL) {
10604 				sc->sc_blink_led = led;
10605 				if (led->led_flags & BWN_LED_F_SLOW)
10606 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10607 			}
10608 		}
10609 
10610 		DPRINTF(sc, BWN_DEBUG_LED,
10611 		    "%dth led, act %d, lowact %d\n", i,
10612 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10613 	}
10614 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10615 }
10616 
10617 static __inline uint16_t
10618 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10619 {
10620 
10621 	if (led->led_flags & BWN_LED_F_ACTLOW)
10622 		on = !on;
10623 	if (on)
10624 		val |= led->led_mask;
10625 	else
10626 		val &= ~led->led_mask;
10627 	return val;
10628 }
10629 
10630 static void
10631 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10632 {
10633 	struct bwn_softc *sc = mac->mac_sc;
10634 	struct ifnet *ifp = sc->sc_ifp;
10635 	struct ieee80211com *ic = ifp->if_l2com;
10636 	uint16_t val;
10637 	int i;
10638 
10639 	if (nstate == IEEE80211_S_INIT) {
10640 		callout_stop(&sc->sc_led_blink_ch);
10641 		sc->sc_led_blinking = 0;
10642 	}
10643 
10644 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10645 		return;
10646 
10647 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10648 	for (i = 0; i < BWN_LED_MAX; ++i) {
10649 		struct bwn_led *led = &sc->sc_leds[i];
10650 		int on;
10651 
10652 		if (led->led_act == BWN_LED_ACT_UNKN ||
10653 		    led->led_act == BWN_LED_ACT_NULL)
10654 			continue;
10655 
10656 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10657 		    nstate != IEEE80211_S_INIT)
10658 			continue;
10659 
10660 		switch (led->led_act) {
10661 		case BWN_LED_ACT_ON:    /* Always on */
10662 			on = 1;
10663 			break;
10664 		case BWN_LED_ACT_OFF:   /* Always off */
10665 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10666 			on = 0;
10667 			break;
10668 		default:
10669 			on = 1;
10670 			switch (nstate) {
10671 			case IEEE80211_S_INIT:
10672 				on = 0;
10673 				break;
10674 			case IEEE80211_S_RUN:
10675 				if (led->led_act == BWN_LED_ACT_11G &&
10676 				    ic->ic_curmode != IEEE80211_MODE_11G)
10677 					on = 0;
10678 				break;
10679 			default:
10680 				if (led->led_act == BWN_LED_ACT_ASSOC)
10681 					on = 0;
10682 				break;
10683 			}
10684 			break;
10685 		}
10686 
10687 		val = bwn_led_onoff(led, val, on);
10688 	}
10689 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10690 }
10691 
10692 static void
10693 bwn_led_event(struct bwn_mac *mac, int event)
10694 {
10695 	struct bwn_softc *sc = mac->mac_sc;
10696 	struct bwn_led *led = sc->sc_blink_led;
10697 	int rate;
10698 
10699 	if (event == BWN_LED_EVENT_POLL) {
10700 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10701 			return;
10702 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10703 			return;
10704 	}
10705 
10706 	sc->sc_led_ticks = ticks;
10707 	if (sc->sc_led_blinking)
10708 		return;
10709 
10710 	switch (event) {
10711 	case BWN_LED_EVENT_RX:
10712 		rate = sc->sc_rx_rate;
10713 		break;
10714 	case BWN_LED_EVENT_TX:
10715 		rate = sc->sc_tx_rate;
10716 		break;
10717 	case BWN_LED_EVENT_POLL:
10718 		rate = 0;
10719 		break;
10720 	default:
10721 		panic("unknown LED event %d\n", event);
10722 		break;
10723 	}
10724 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10725 	    bwn_led_duration[rate].off_dur);
10726 }
10727 
10728 static void
10729 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10730 {
10731 	struct bwn_softc *sc = mac->mac_sc;
10732 	struct bwn_led *led = sc->sc_blink_led;
10733 	uint16_t val;
10734 
10735 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10736 	val = bwn_led_onoff(led, val, 1);
10737 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10738 
10739 	if (led->led_flags & BWN_LED_F_SLOW) {
10740 		BWN_LED_SLOWDOWN(on_dur);
10741 		BWN_LED_SLOWDOWN(off_dur);
10742 	}
10743 
10744 	sc->sc_led_blinking = 1;
10745 	sc->sc_led_blink_offdur = off_dur;
10746 
10747 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10748 }
10749 
10750 static void
10751 bwn_led_blink_next(void *arg)
10752 {
10753 	struct bwn_mac *mac = arg;
10754 	struct bwn_softc *sc = mac->mac_sc;
10755 	uint16_t val;
10756 
10757 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10758 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10759 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10760 
10761 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10762 	    bwn_led_blink_end, mac);
10763 }
10764 
10765 static void
10766 bwn_led_blink_end(void *arg)
10767 {
10768 	struct bwn_mac *mac = arg;
10769 	struct bwn_softc *sc = mac->mac_sc;
10770 
10771 	sc->sc_led_blinking = 0;
10772 }
10773 
10774 static int
10775 bwn_suspend(device_t dev)
10776 {
10777 	struct bwn_softc *sc = device_get_softc(dev);
10778 
10779 	bwn_stop(sc, 1);
10780 	return (0);
10781 }
10782 
10783 static int
10784 bwn_resume(device_t dev)
10785 {
10786 	struct bwn_softc *sc = device_get_softc(dev);
10787 	struct ifnet *ifp = sc->sc_ifp;
10788 
10789 	if (ifp->if_flags & IFF_UP)
10790 		bwn_init(sc);
10791 	return (0);
10792 }
10793 
10794 static void
10795 bwn_rfswitch(void *arg)
10796 {
10797 	struct bwn_softc *sc = arg;
10798 	struct bwn_mac *mac = sc->sc_curmac;
10799 	int cur = 0, prev = 0;
10800 
10801 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10802 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10803 
10804 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10805 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10806 			& BWN_RF_HWENABLED_HI_MASK))
10807 			cur = 1;
10808 	} else {
10809 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10810 		    & BWN_RF_HWENABLED_LO_MASK)
10811 			cur = 1;
10812 	}
10813 
10814 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10815 		prev = 1;
10816 
10817 	if (cur != prev) {
10818 		if (cur)
10819 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10820 		else
10821 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10822 
10823 		device_printf(sc->sc_dev,
10824 		    "status of RF switch is changed to %s\n",
10825 		    cur ? "ON" : "OFF");
10826 		if (cur != mac->mac_phy.rf_on) {
10827 			if (cur)
10828 				bwn_rf_turnon(mac);
10829 			else
10830 				bwn_rf_turnoff(mac);
10831 		}
10832 	}
10833 
10834 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10835 }
10836 
10837 static void
10838 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10839 {
10840 	struct bwn_phy *phy = &mac->mac_phy;
10841 	struct bwn_phy_lp *plp = &phy->phy_lp;
10842 
10843 	plp->plp_antenna = BWN_ANT_DEFAULT;
10844 }
10845 
10846 static int
10847 bwn_phy_lp_init(struct bwn_mac *mac)
10848 {
10849 	static const struct bwn_stxtable tables[] = {
10850 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10851 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10852 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10853 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10854 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10855 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10856 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10857 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10858 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10859 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10860 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10861 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10862 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10863 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10864 		{ 2, 11, 0x40, 0, 0x0f }
10865 	};
10866 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10867 	struct bwn_softc *sc = mac->mac_sc;
10868 	const struct bwn_stxtable *st;
10869 	struct ifnet *ifp = sc->sc_ifp;
10870 	struct ieee80211com *ic = ifp->if_l2com;
10871 	int i, error;
10872 	uint16_t tmp;
10873 
10874 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10875 	bwn_phy_lp_bbinit(mac);
10876 
10877 	/* initialize RF */
10878 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10879 	DELAY(1);
10880 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10881 	DELAY(1);
10882 
10883 	if (mac->mac_phy.rf_ver == 0x2062)
10884 		bwn_phy_lp_b2062_init(mac);
10885 	else {
10886 		bwn_phy_lp_b2063_init(mac);
10887 
10888 		/* synchronize stx table. */
10889 		for (i = 0; i < N(tables); i++) {
10890 			st = &tables[i];
10891 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10892 			tmp >>= st->st_rfshift;
10893 			tmp <<= st->st_physhift;
10894 			BWN_PHY_SETMASK(mac,
10895 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10896 			    ~(st->st_mask << st->st_physhift), tmp);
10897 		}
10898 
10899 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10900 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10901 	}
10902 
10903 	/* calibrate RC */
10904 	if (mac->mac_phy.rev >= 2)
10905 		bwn_phy_lp_rxcal_r2(mac);
10906 	else if (!plp->plp_rccap) {
10907 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10908 			bwn_phy_lp_rccal_r12(mac);
10909 	} else
10910 		bwn_phy_lp_set_rccap(mac);
10911 
10912 	error = bwn_phy_lp_switch_channel(mac, 7);
10913 	if (error)
10914 		device_printf(sc->sc_dev,
10915 		    "failed to change channel 7 (%d)\n", error);
10916 	bwn_phy_lp_txpctl_init(mac);
10917 	bwn_phy_lp_calib(mac);
10918 	return (0);
10919 }
10920 
10921 static uint16_t
10922 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10923 {
10924 
10925 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10926 	return (BWN_READ_2(mac, BWN_PHYDATA));
10927 }
10928 
10929 static void
10930 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10931 {
10932 
10933 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10934 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10935 }
10936 
10937 static void
10938 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10939     uint16_t set)
10940 {
10941 
10942 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10943 	BWN_WRITE_2(mac, BWN_PHYDATA,
10944 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10945 }
10946 
10947 static uint16_t
10948 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10949 {
10950 
10951 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10952 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10953 		reg |= 0x100;
10954 	if (mac->mac_phy.rev >= 2)
10955 		reg |= 0x200;
10956 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10957 	return BWN_READ_2(mac, BWN_RFDATALO);
10958 }
10959 
10960 static void
10961 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10962 {
10963 
10964 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10965 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10966 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10967 }
10968 
10969 static void
10970 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10971 {
10972 
10973 	if (on) {
10974 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10975 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10976 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10977 		return;
10978 	}
10979 
10980 	if (mac->mac_phy.rev >= 2) {
10981 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10982 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10983 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10984 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10985 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10986 		return;
10987 	}
10988 
10989 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10990 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10991 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10992 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10993 }
10994 
10995 static int
10996 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10997 {
10998 	struct bwn_phy *phy = &mac->mac_phy;
10999 	struct bwn_phy_lp *plp = &phy->phy_lp;
11000 	int error;
11001 
11002 	if (phy->rf_ver == 0x2063) {
11003 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11004 		if (error)
11005 			return (error);
11006 	} else {
11007 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11008 		if (error)
11009 			return (error);
11010 		bwn_phy_lp_set_anafilter(mac, chan);
11011 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11012 	}
11013 
11014 	plp->plp_chan = chan;
11015 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11016 	return (0);
11017 }
11018 
11019 static uint32_t
11020 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11021 {
11022 	struct bwn_softc *sc = mac->mac_sc;
11023 	struct ifnet *ifp = sc->sc_ifp;
11024 	struct ieee80211com *ic = ifp->if_l2com;
11025 
11026 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11027 }
11028 
11029 static void
11030 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11031 {
11032 	struct bwn_phy *phy = &mac->mac_phy;
11033 	struct bwn_phy_lp *plp = &phy->phy_lp;
11034 
11035 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11036 		return;
11037 
11038 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11039 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11040 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11041 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11042 	plp->plp_antenna = antenna;
11043 }
11044 
11045 static void
11046 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11047 {
11048 
11049 	bwn_phy_lp_calib(mac);
11050 }
11051 
11052 static void
11053 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11054 {
11055 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11056 	struct bwn_softc *sc = mac->mac_sc;
11057 	struct ifnet *ifp = sc->sc_ifp;
11058 	struct ieee80211com *ic = ifp->if_l2com;
11059 
11060 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11061 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11062 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11063 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11064 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11065 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11066 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11067 		return;
11068 	}
11069 
11070 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11071 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11072 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11073 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11074 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11075 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11076 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11077 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11078 }
11079 
11080 static void
11081 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11082 {
11083 
11084 	bwn_phy_lp_tblinit(mac);
11085 	if (mac->mac_phy.rev >= 2)
11086 		bwn_phy_lp_bbinit_r2(mac);
11087 	else
11088 		bwn_phy_lp_bbinit_r01(mac);
11089 }
11090 
11091 static void
11092 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11093 {
11094 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11095 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11096 	struct bwn_softc *sc = mac->mac_sc;
11097 	struct ifnet *ifp = sc->sc_ifp;
11098 	struct ieee80211com *ic = ifp->if_l2com;
11099 
11100 	bwn_phy_lp_set_txgain(mac,
11101 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11102 	bwn_phy_lp_set_bbmult(mac, 150);
11103 }
11104 
11105 static void
11106 bwn_phy_lp_calib(struct bwn_mac *mac)
11107 {
11108 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11109 	struct bwn_softc *sc = mac->mac_sc;
11110 	struct ifnet *ifp = sc->sc_ifp;
11111 	struct ieee80211com *ic = ifp->if_l2com;
11112 	const struct bwn_rxcompco *rc = NULL;
11113 	struct bwn_txgain ogain;
11114 	int i, omode, oafeovr, orf, obbmult;
11115 	uint8_t mode, fc = 0;
11116 
11117 	if (plp->plp_chanfullcal != plp->plp_chan) {
11118 		plp->plp_chanfullcal = plp->plp_chan;
11119 		fc = 1;
11120 	}
11121 
11122 	bwn_mac_suspend(mac);
11123 
11124 	/* BlueTooth Coexistance Override */
11125 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11126 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11127 
11128 	if (mac->mac_phy.rev >= 2)
11129 		bwn_phy_lp_digflt_save(mac);
11130 	bwn_phy_lp_get_txpctlmode(mac);
11131 	mode = plp->plp_txpctlmode;
11132 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11133 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11134 		bwn_phy_lp_bugfix(mac);
11135 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11136 		bwn_phy_lp_get_txpctlmode(mac);
11137 		omode = plp->plp_txpctlmode;
11138 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11139 		if (oafeovr)
11140 			ogain = bwn_phy_lp_get_txgain(mac);
11141 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11142 		obbmult = bwn_phy_lp_get_bbmult(mac);
11143 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11144 		if (oafeovr)
11145 			bwn_phy_lp_set_txgain(mac, &ogain);
11146 		bwn_phy_lp_set_bbmult(mac, obbmult);
11147 		bwn_phy_lp_set_txpctlmode(mac, omode);
11148 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11149 	}
11150 	bwn_phy_lp_set_txpctlmode(mac, mode);
11151 	if (mac->mac_phy.rev >= 2)
11152 		bwn_phy_lp_digflt_restore(mac);
11153 
11154 	/* do RX IQ Calculation; assumes that noise is true. */
11155 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11156 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11157 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11158 				rc = &bwn_rxcompco_5354[i];
11159 		}
11160 	} else if (mac->mac_phy.rev >= 2)
11161 		rc = &bwn_rxcompco_r2;
11162 	else {
11163 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11164 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11165 				rc = &bwn_rxcompco_r12[i];
11166 		}
11167 	}
11168 	if (rc == NULL)
11169 		goto fail;
11170 
11171 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11172 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11173 
11174 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11175 
11176 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11177 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11178 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11179 	} else {
11180 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11181 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11182 	}
11183 
11184 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11185 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11186 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11187 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11188 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11189 	bwn_phy_lp_set_deaf(mac, 0);
11190 	/* XXX no checking return value? */
11191 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11192 	bwn_phy_lp_clear_deaf(mac, 0);
11193 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11194 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11195 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11196 
11197 	/* disable RX GAIN override. */
11198 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11199 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11200 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11201 	if (mac->mac_phy.rev >= 2) {
11202 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11203 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11204 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11205 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11206 		}
11207 	} else {
11208 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11209 	}
11210 
11211 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11212 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11213 fail:
11214 	bwn_mac_enable(mac);
11215 }
11216 
11217 static void
11218 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11219 {
11220 
11221 	if (on) {
11222 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11223 		return;
11224 	}
11225 
11226 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11227 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11228 }
11229 
11230 static int
11231 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11232 {
11233 	static const struct bwn_b206x_chan *bc = NULL;
11234 	struct bwn_softc *sc = mac->mac_sc;
11235 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11236 	    tmp[6];
11237 	uint16_t old, scale, tmp16;
11238 	int i, div;
11239 
11240 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11241 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11242 			bc = &bwn_b2063_chantable[i];
11243 			break;
11244 		}
11245 	}
11246 	if (bc == NULL)
11247 		return (EINVAL);
11248 
11249 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11250 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11251 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11252 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11253 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11254 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11255 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11256 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11257 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11258 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11259 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11260 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11261 
11262 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11263 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11264 
11265 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11266 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11267 	freqref = freqxtal * 3;
11268 	div = (freqxtal <= 26000000 ? 1 : 2);
11269 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11270 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11271 		999999) / 1000000) + 1;
11272 
11273 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11274 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11275 	    0xfff8, timeout >> 2);
11276 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11277 	    0xff9f,timeout << 5);
11278 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11279 
11280 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11281 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11282 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11283 
11284 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11285 	    (timeoutref + 1)) - 1;
11286 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11287 	    0xf0, count >> 8);
11288 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11289 
11290 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11291 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11292 	while (tmp[1] >= freqref) {
11293 		tmp[0]++;
11294 		tmp[1] -= freqref;
11295 	}
11296 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11297 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11298 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11299 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11300 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11301 
11302 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11303 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11304 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11305 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11306 
11307 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11308 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11309 
11310 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11311 		scale = 1;
11312 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11313 	} else {
11314 		scale = 0;
11315 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11316 	}
11317 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11318 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11319 
11320 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11321 	    (scale + 1);
11322 	if (tmp[5] > 150)
11323 		tmp[5] = 0;
11324 
11325 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11326 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11327 
11328 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11329 	if (freqxtal > 26000000)
11330 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11331 	else
11332 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11333 
11334 	if (val[0] == 45)
11335 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11336 	else
11337 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11338 
11339 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11340 	DELAY(1);
11341 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11342 
11343 	/* VCO Calibration */
11344 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11345 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11346 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11347 	DELAY(1);
11348 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11349 	DELAY(1);
11350 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11351 	DELAY(1);
11352 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11353 	DELAY(300);
11354 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11355 
11356 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11357 	return (0);
11358 }
11359 
11360 static int
11361 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11362 {
11363 	struct bwn_softc *sc = mac->mac_sc;
11364 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11365 	const struct bwn_b206x_chan *bc = NULL;
11366 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11367 	uint32_t tmp[9];
11368 	int i;
11369 
11370 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11371 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11372 			bc = &bwn_b2062_chantable[i];
11373 			break;
11374 		}
11375 	}
11376 
11377 	if (bc == NULL)
11378 		return (EINVAL);
11379 
11380 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11381 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11382 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11383 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11384 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11385 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11386 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11387 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11388 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11389 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11390 
11391 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11392 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11393 	bwn_phy_lp_b2062_reset_pllbias(mac);
11394 	tmp[0] = freqxtal / 1000;
11395 	tmp[1] = plp->plp_div * 1000;
11396 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11397 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11398 		tmp[2] *= 2;
11399 	tmp[3] = 48 * tmp[0];
11400 	tmp[5] = tmp[2] / tmp[3];
11401 	tmp[6] = tmp[2] % tmp[3];
11402 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11403 	tmp[4] = tmp[6] * 0x100;
11404 	tmp[5] = tmp[4] / tmp[3];
11405 	tmp[6] = tmp[4] % tmp[3];
11406 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, 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_RFPLLCTL28, 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_RFPLLCTL29,
11415 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11416 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11417 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11418 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11419 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11420 
11421 	bwn_phy_lp_b2062_vco_calib(mac);
11422 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11423 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11424 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11425 		bwn_phy_lp_b2062_reset_pllbias(mac);
11426 		bwn_phy_lp_b2062_vco_calib(mac);
11427 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11428 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11429 			return (EIO);
11430 		}
11431 	}
11432 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11433 	return (0);
11434 }
11435 
11436 static void
11437 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11438 {
11439 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11440 	uint16_t tmp = (channel == 14);
11441 
11442 	if (mac->mac_phy.rev < 2) {
11443 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11444 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11445 			bwn_phy_lp_set_rccap(mac);
11446 		return;
11447 	}
11448 
11449 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11450 }
11451 
11452 static void
11453 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11454 {
11455 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11456 	struct bwn_softc *sc = mac->mac_sc;
11457 	struct ifnet *ifp = sc->sc_ifp;
11458 	struct ieee80211com *ic = ifp->if_l2com;
11459 	uint16_t iso, tmp[3];
11460 
11461 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11462 
11463 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11464 		iso = plp->plp_txisoband_m;
11465 	else if (freq <= 5320)
11466 		iso = plp->plp_txisoband_l;
11467 	else if (freq <= 5700)
11468 		iso = plp->plp_txisoband_m;
11469 	else
11470 		iso = plp->plp_txisoband_h;
11471 
11472 	tmp[0] = ((iso - 26) / 12) << 12;
11473 	tmp[1] = tmp[0] + 0x1000;
11474 	tmp[2] = tmp[0] + 0x2000;
11475 
11476 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11477 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11478 }
11479 
11480 static void
11481 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11482 {
11483 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11484 	int i;
11485 	static const uint16_t addr[] = {
11486 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11487 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11488 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11489 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11490 		BWN_PHY_OFDM(0xcf),
11491 	};
11492 	static const uint16_t val[] = {
11493 		0xde5e, 0xe832, 0xe331, 0x4d26,
11494 		0x0026, 0x1420, 0x0020, 0xfe08,
11495 		0x0008,
11496 	};
11497 
11498 	for (i = 0; i < N(addr); i++) {
11499 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11500 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11501 	}
11502 }
11503 
11504 static void
11505 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11506 {
11507 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11508 	struct bwn_softc *sc = mac->mac_sc;
11509 	uint16_t ctl;
11510 
11511 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11512 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11513 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11514 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11515 		break;
11516 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11517 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11518 		break;
11519 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11520 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11521 		break;
11522 	default:
11523 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11524 		device_printf(sc->sc_dev, "unknown command mode\n");
11525 		break;
11526 	}
11527 }
11528 
11529 static void
11530 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11531 {
11532 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11533 	uint16_t ctl;
11534 	uint8_t old;
11535 
11536 	bwn_phy_lp_get_txpctlmode(mac);
11537 	old = plp->plp_txpctlmode;
11538 	if (old == mode)
11539 		return;
11540 	plp->plp_txpctlmode = mode;
11541 
11542 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11543 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11544 		    plp->plp_tssiidx);
11545 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11546 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11547 
11548 		/* disable TX GAIN override */
11549 		if (mac->mac_phy.rev < 2)
11550 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11551 		else {
11552 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11553 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11554 		}
11555 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11556 
11557 		plp->plp_txpwridx = -1;
11558 	}
11559 	if (mac->mac_phy.rev >= 2) {
11560 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11561 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11562 		else
11563 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11564 	}
11565 
11566 	/* writes TX Power Control mode */
11567 	switch (plp->plp_txpctlmode) {
11568 	case BWN_PHYLP_TXPCTL_OFF:
11569 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11570 		break;
11571 	case BWN_PHYLP_TXPCTL_ON_HW:
11572 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11573 		break;
11574 	case BWN_PHYLP_TXPCTL_ON_SW:
11575 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11576 		break;
11577 	default:
11578 		ctl = 0;
11579 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11580 	}
11581 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11582 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11583 }
11584 
11585 static void
11586 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11587 {
11588 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11589 	struct bwn_softc *sc = mac->mac_sc;
11590 	const unsigned int size = 256;
11591 	struct bwn_txgain tg;
11592 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11593 	uint16_t tssinpt, tssiidx, value[2];
11594 	uint8_t mode;
11595 	int8_t txpwridx;
11596 
11597 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11598 	    M_NOWAIT | M_ZERO);
11599 	if (tabs == NULL) {
11600 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11601 		return;
11602 	}
11603 
11604 	bwn_phy_lp_get_txpctlmode(mac);
11605 	mode = plp->plp_txpctlmode;
11606 	txpwridx = plp->plp_txpwridx;
11607 	tssinpt = plp->plp_tssinpt;
11608 	tssiidx = plp->plp_tssiidx;
11609 
11610 	bwn_tab_read_multi(mac,
11611 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11612 	    BWN_TAB_4(7, 0x140), size, tabs);
11613 
11614 	bwn_phy_lp_tblinit(mac);
11615 	bwn_phy_lp_bbinit(mac);
11616 	bwn_phy_lp_txpctl_init(mac);
11617 	bwn_phy_lp_rf_onoff(mac, 1);
11618 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11619 
11620 	bwn_tab_write_multi(mac,
11621 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11622 	    BWN_TAB_4(7, 0x140), size, tabs);
11623 
11624 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11625 	plp->plp_tssinpt = tssinpt;
11626 	plp->plp_tssiidx = tssiidx;
11627 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11628 	if (txpwridx != -1) {
11629 		/* set TX power by index */
11630 		plp->plp_txpwridx = txpwridx;
11631 		bwn_phy_lp_get_txpctlmode(mac);
11632 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11633 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11634 		if (mac->mac_phy.rev >= 2) {
11635 			rxcomp = bwn_tab_read(mac,
11636 			    BWN_TAB_4(7, txpwridx + 320));
11637 			txgain = bwn_tab_read(mac,
11638 			    BWN_TAB_4(7, txpwridx + 192));
11639 			tg.tg_pad = (txgain >> 16) & 0xff;
11640 			tg.tg_gm = txgain & 0xff;
11641 			tg.tg_pga = (txgain >> 8) & 0xff;
11642 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11643 			bwn_phy_lp_set_txgain(mac, &tg);
11644 		} else {
11645 			rxcomp = bwn_tab_read(mac,
11646 			    BWN_TAB_4(10, txpwridx + 320));
11647 			txgain = bwn_tab_read(mac,
11648 			    BWN_TAB_4(10, txpwridx + 192));
11649 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11650 			    0xf800, (txgain >> 4) & 0x7fff);
11651 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11652 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11653 		}
11654 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11655 
11656 		/* set TX IQCC */
11657 		value[0] = (rxcomp >> 10) & 0x3ff;
11658 		value[1] = rxcomp & 0x3ff;
11659 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11660 
11661 		coeff = bwn_tab_read(mac,
11662 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11663 		    BWN_TAB_4(10, txpwridx + 448));
11664 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11665 		if (mac->mac_phy.rev >= 2) {
11666 			rfpwr = bwn_tab_read(mac,
11667 			    BWN_TAB_4(7, txpwridx + 576));
11668 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11669 			    rfpwr & 0xffff);
11670 		}
11671 		bwn_phy_lp_set_txgain_override(mac);
11672 	}
11673 	if (plp->plp_rccap)
11674 		bwn_phy_lp_set_rccap(mac);
11675 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11676 	bwn_phy_lp_set_txpctlmode(mac, mode);
11677 	free(tabs, M_DEVBUF);
11678 }
11679 
11680 static void
11681 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11682 {
11683 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11684 	int i;
11685 	static const uint16_t addr[] = {
11686 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11687 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11688 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11689 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11690 		BWN_PHY_OFDM(0xcf),
11691 	};
11692 
11693 	for (i = 0; i < N(addr); i++)
11694 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11695 }
11696 
11697 static void
11698 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11699 {
11700 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11701 
11702 	if (mac->mac_phy.rev < 2) {
11703 		bwn_phy_lp_tblinit_r01(mac);
11704 		bwn_phy_lp_tblinit_txgain(mac);
11705 		bwn_phy_lp_set_gaintbl(mac, freq);
11706 		return;
11707 	}
11708 
11709 	bwn_phy_lp_tblinit_r2(mac);
11710 	bwn_phy_lp_tblinit_txgain(mac);
11711 }
11712 
11713 struct bwn_wpair {
11714 	uint16_t		reg;
11715 	uint16_t		value;
11716 };
11717 
11718 struct bwn_smpair {
11719 	uint16_t		offset;
11720 	uint16_t		mask;
11721 	uint16_t		set;
11722 };
11723 
11724 static void
11725 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11726 {
11727 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11728 	struct bwn_softc *sc = mac->mac_sc;
11729 	struct ifnet *ifp = sc->sc_ifp;
11730 	struct ieee80211com *ic = ifp->if_l2com;
11731 	static const struct bwn_wpair v1[] = {
11732 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11733 		{ BWN_PHY_AFE_CTL, 0x8800 },
11734 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11735 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11736 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11737 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11738 		{ BWN_PHY_OFDM(0xf9), 0 },
11739 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11740 	};
11741 	static const struct bwn_smpair v2[] = {
11742 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11743 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11744 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11745 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11746 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11747 	};
11748 	static const struct bwn_smpair v3[] = {
11749 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11750 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11751 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11752 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11753 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11754 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11755 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11756 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11757 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11758 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11759 
11760 	};
11761 	int i;
11762 
11763 	for (i = 0; i < N(v1); i++)
11764 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11765 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11766 	for (i = 0; i < N(v2); i++)
11767 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11768 
11769 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11770 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11771 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11772 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11773 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11774 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11775 	} else {
11776 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11777 	}
11778 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11779 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11780 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11781 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11782 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11783 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11784 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11785 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11786 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11787 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11788 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11789 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11790 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11791 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11792 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11793 	} else {
11794 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11795 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11796 	}
11797 	for (i = 0; i < N(v3); i++)
11798 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11799 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11800 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11801 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11802 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11803 	}
11804 
11805 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11806 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11807 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11808 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11809 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11810 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11811 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11812 	} else
11813 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11814 
11815 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11816 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11817 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11818 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11819 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11820 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11821 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11822 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11823 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11824 
11825 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11826 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11827 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11828 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11829 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11830 	}
11831 
11832 	bwn_phy_lp_digflt_save(mac);
11833 }
11834 
11835 static void
11836 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11837 {
11838 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11839 	struct bwn_softc *sc = mac->mac_sc;
11840 	struct ifnet *ifp = sc->sc_ifp;
11841 	struct ieee80211com *ic = ifp->if_l2com;
11842 	static const struct bwn_smpair v1[] = {
11843 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11844 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11845 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11846 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11847 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11848 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11849 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11850 	};
11851 	static const struct bwn_smpair v2[] = {
11852 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11853 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11854 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11855 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11856 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11857 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11858 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11859 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11860 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11861 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11862 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11863 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11864 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11865 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11866 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11867 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11868 	};
11869 	static const struct bwn_smpair v3[] = {
11870 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11871 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11872 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11873 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11874 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11875 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11876 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11877 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11878 	};
11879 	static const struct bwn_smpair v4[] = {
11880 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11881 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11882 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11883 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11884 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11885 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11886 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11887 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11888 	};
11889 	static const struct bwn_smpair v5[] = {
11890 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11891 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11892 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11893 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11894 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11895 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11896 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11897 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11898 	};
11899 	int i;
11900 	uint16_t tmp, tmp2;
11901 
11902 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11903 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11904 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11905 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11906 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11907 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11908 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11909 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11910 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11911 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11912 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11913 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11914 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11915 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11916 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11917 	for (i = 0; i < N(v1); i++)
11918 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11919 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11920 	    0xff00, plp->plp_rxpwroffset);
11921 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11922 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11923 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11924 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11925 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11926 		if (mac->mac_phy.rev == 0)
11927 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11928 			    0xffcf, 0x0010);
11929 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11930 	} else {
11931 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11932 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11933 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11934 	}
11935 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11936 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11937 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11938 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11939 	else
11940 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11941 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11942 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11943 	    0xfff9, (plp->plp_bxarch << 1));
11944 	if (mac->mac_phy.rev == 1 &&
11945 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11946 		for (i = 0; i < N(v2); i++)
11947 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11948 			    v2[i].set);
11949 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11950 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11951 	    ((mac->mac_phy.rev == 0) &&
11952 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11953 		for (i = 0; i < N(v3); i++)
11954 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11955 			    v3[i].set);
11956 	} else if (mac->mac_phy.rev == 1 ||
11957 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11958 		for (i = 0; i < N(v4); i++)
11959 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11960 			    v4[i].set);
11961 	} else {
11962 		for (i = 0; i < N(v5); i++)
11963 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11964 			    v5[i].set);
11965 	}
11966 	if (mac->mac_phy.rev == 1 &&
11967 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11968 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11969 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11970 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11971 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11972 	}
11973 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11974 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11975 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11976 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11977 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11978 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11979 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11980 	}
11981 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11982 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11983 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11984 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11985 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11986 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11987 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11988 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11989 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11990 	} else {
11991 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11992 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11993 	}
11994 	if (mac->mac_phy.rev == 1) {
11995 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11996 		tmp2 = (tmp & 0x03e0) >> 5;
11997 		tmp2 |= tmp2 << 5;
11998 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11999 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12000 		tmp2 = (tmp & 0x1f00) >> 8;
12001 		tmp2 |= tmp2 << 5;
12002 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12003 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12004 		tmp2 = tmp & 0x00ff;
12005 		tmp2 |= tmp << 8;
12006 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12007 	}
12008 }
12009 
12010 struct bwn_b2062_freq {
12011 	uint16_t		freq;
12012 	uint8_t			value[6];
12013 };
12014 
12015 static void
12016 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12017 {
12018 #define	CALC_CTL7(freq, div)						\
12019 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12020 #define	CALC_CTL18(freq, div)						\
12021 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12022 #define	CALC_CTL19(freq, div)						\
12023 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12024 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12025 	struct bwn_softc *sc = mac->mac_sc;
12026 	struct ifnet *ifp = sc->sc_ifp;
12027 	struct ieee80211com *ic = ifp->if_l2com;
12028 	static const struct bwn_b2062_freq freqdata_tab[] = {
12029 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12030 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12031 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12032 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12033 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12034 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12035 	};
12036 	static const struct bwn_wpair v1[] = {
12037 		{ BWN_B2062_N_TXCTL3, 0 },
12038 		{ BWN_B2062_N_TXCTL4, 0 },
12039 		{ BWN_B2062_N_TXCTL5, 0 },
12040 		{ BWN_B2062_N_TXCTL6, 0 },
12041 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12042 		{ BWN_B2062_N_PDNCTL0, 0 },
12043 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12044 		{ BWN_B2062_N_CALIB_TS, 0 }
12045 	};
12046 	const struct bwn_b2062_freq *f = NULL;
12047 	uint32_t xtalfreq, ref;
12048 	unsigned int i;
12049 
12050 	bwn_phy_lp_b2062_tblinit(mac);
12051 
12052 	for (i = 0; i < N(v1); i++)
12053 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12054 	if (mac->mac_phy.rev > 0)
12055 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12056 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12057 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12058 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12059 	else
12060 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12061 
12062 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12063 	    ("%s:%d: fail", __func__, __LINE__));
12064 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12065 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12066 
12067 	if (xtalfreq <= 30000000) {
12068 		plp->plp_div = 1;
12069 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12070 	} else {
12071 		plp->plp_div = 2;
12072 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12073 	}
12074 
12075 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12076 	    CALC_CTL7(xtalfreq, plp->plp_div));
12077 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12078 	    CALC_CTL18(xtalfreq, plp->plp_div));
12079 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12080 	    CALC_CTL19(xtalfreq, plp->plp_div));
12081 
12082 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12083 	ref &= 0xffff;
12084 	for (i = 0; i < N(freqdata_tab); i++) {
12085 		if (ref < freqdata_tab[i].freq) {
12086 			f = &freqdata_tab[i];
12087 			break;
12088 		}
12089 	}
12090 	if (f == NULL)
12091 		f = &freqdata_tab[N(freqdata_tab) - 1];
12092 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12093 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12094 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12095 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12096 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12097 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12098 #undef CALC_CTL7
12099 #undef CALC_CTL18
12100 #undef CALC_CTL19
12101 }
12102 
12103 static void
12104 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12105 {
12106 
12107 	bwn_phy_lp_b2063_tblinit(mac);
12108 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12109 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12110 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12111 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12112 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12113 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12114 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12115 	if (mac->mac_phy.rev == 2) {
12116 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12117 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12118 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12119 	} else {
12120 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12121 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12122 	}
12123 }
12124 
12125 static void
12126 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12127 {
12128 	struct bwn_softc *sc = mac->mac_sc;
12129 	static const struct bwn_wpair v1[] = {
12130 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12131 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12132 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12133 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12134 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12135 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12136 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12137 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12138 	};
12139 	static const struct bwn_wpair v2[] = {
12140 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12141 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12142 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12143 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12144 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12145 	};
12146 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12147 	int i;
12148 	uint8_t tmp;
12149 
12150 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12151 
12152 	for (i = 0; i < 2; i++)
12153 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12154 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12155 	for (i = 2; i < N(v1); i++)
12156 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157 	for (i = 0; i < 10000; i++) {
12158 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12159 			break;
12160 		DELAY(1000);
12161 	}
12162 
12163 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12164 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12165 
12166 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12167 
12168 	for (i = 0; i < N(v2); i++)
12169 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12170 	if (freqxtal == 24000000) {
12171 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12172 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12173 	} else {
12174 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12175 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12176 	}
12177 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12178 	for (i = 0; i < 10000; i++) {
12179 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12180 			break;
12181 		DELAY(1000);
12182 	}
12183 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12184 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12185 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12186 }
12187 
12188 static void
12189 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12190 {
12191 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12192 	struct bwn_softc *sc = mac->mac_sc;
12193 	struct bwn_phy_lp_iq_est ie;
12194 	struct bwn_txgain tx_gains;
12195 	static const uint32_t pwrtbl[21] = {
12196 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12197 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12198 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12199 		0x0004c, 0x0002c, 0x0001a,
12200 	};
12201 	uint32_t npwr, ipwr, sqpwr, tmp;
12202 	int loopback, i, j, sum, error;
12203 	uint16_t save[7];
12204 	uint8_t txo, bbmult, txpctlmode;
12205 
12206 	error = bwn_phy_lp_switch_channel(mac, 7);
12207 	if (error)
12208 		device_printf(sc->sc_dev,
12209 		    "failed to change channel to 7 (%d)\n", error);
12210 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12211 	bbmult = bwn_phy_lp_get_bbmult(mac);
12212 	if (txo)
12213 		tx_gains = bwn_phy_lp_get_txgain(mac);
12214 
12215 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12216 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12217 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12218 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12219 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12220 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12221 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12222 
12223 	bwn_phy_lp_get_txpctlmode(mac);
12224 	txpctlmode = plp->plp_txpctlmode;
12225 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12226 
12227 	/* disable CRS */
12228 	bwn_phy_lp_set_deaf(mac, 1);
12229 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12230 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12231 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12232 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12233 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12234 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12235 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12236 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12237 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12238 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12239 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12240 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12241 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12242 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12243 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12244 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12245 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12246 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12247 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12248 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12249 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12250 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12251 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12252 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12253 
12254 	loopback = bwn_phy_lp_loopback(mac);
12255 	if (loopback == -1)
12256 		goto done;
12257 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12258 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12259 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12260 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12261 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12262 
12263 	tmp = 0;
12264 	memset(&ie, 0, sizeof(ie));
12265 	for (i = 128; i <= 159; i++) {
12266 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12267 		sum = 0;
12268 		for (j = 5; j <= 25; j++) {
12269 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12270 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12271 				goto done;
12272 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12273 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12274 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12275 			    12);
12276 			sum += ((ipwr - npwr) * (ipwr - npwr));
12277 			if ((i == 128) || (sum < tmp)) {
12278 				plp->plp_rccap = i;
12279 				tmp = sum;
12280 			}
12281 		}
12282 	}
12283 	bwn_phy_lp_ddfs_turnoff(mac);
12284 done:
12285 	/* restore CRS */
12286 	bwn_phy_lp_clear_deaf(mac, 1);
12287 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12288 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12289 
12290 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12291 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12292 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12293 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12294 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12295 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12296 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12297 
12298 	bwn_phy_lp_set_bbmult(mac, bbmult);
12299 	if (txo)
12300 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12301 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12302 	if (plp->plp_rccap)
12303 		bwn_phy_lp_set_rccap(mac);
12304 }
12305 
12306 static void
12307 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12308 {
12309 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12310 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12311 
12312 	if (mac->mac_phy.rev == 1)
12313 		rc_cap = MIN(rc_cap + 5, 15);
12314 
12315 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12316 	    MAX(plp->plp_rccap - 4, 0x80));
12317 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12318 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12319 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12320 }
12321 
12322 static uint32_t
12323 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12324 {
12325 	uint32_t i, q, r;
12326 
12327 	if (div == 0)
12328 		return (0);
12329 
12330 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12331 		q <<= 1;
12332 		if (r << 1 >= div) {
12333 			q++;
12334 			r = (r << 1) - div;
12335 		}
12336 	}
12337 	if (r << 1 >= div)
12338 		q++;
12339 	return (q);
12340 }
12341 
12342 static void
12343 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12344 {
12345 	struct bwn_softc *sc = mac->mac_sc;
12346 
12347 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12348 	DELAY(20);
12349 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12350 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12351 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12352 	} else {
12353 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12354 	}
12355 	DELAY(5);
12356 }
12357 
12358 static void
12359 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12360 {
12361 
12362 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12363 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12364 	DELAY(200);
12365 }
12366 
12367 static void
12368 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12369 {
12370 #define	FLAG_A	0x01
12371 #define	FLAG_G	0x02
12372 	struct bwn_softc *sc = mac->mac_sc;
12373 	struct ifnet *ifp = sc->sc_ifp;
12374 	struct ieee80211com *ic = ifp->if_l2com;
12375 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12376 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12377 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12378 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12379 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12380 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12381 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12382 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12383 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12384 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12385 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12386 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12387 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12388 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12389 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12390 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12391 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12392 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12393 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12394 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12395 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12396 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12397 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12398 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12399 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12400 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12401 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12402 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12403 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12404 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12405 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12406 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12407 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12408 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12409 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12410 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12411 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12412 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12413 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12414 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12415 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12416 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12417 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12418 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12419 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12420 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12421 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12422 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12423 	};
12424 	const struct bwn_b206x_rfinit_entry *br;
12425 	unsigned int i;
12426 
12427 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12428 		br = &bwn_b2062_init_tab[i];
12429 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12430 			if (br->br_flags & FLAG_G)
12431 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12432 		} else {
12433 			if (br->br_flags & FLAG_A)
12434 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12435 		}
12436 	}
12437 #undef FLAG_A
12438 #undef FLAG_B
12439 }
12440 
12441 static void
12442 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12443 {
12444 #define	FLAG_A	0x01
12445 #define	FLAG_G	0x02
12446 	struct bwn_softc *sc = mac->mac_sc;
12447 	struct ifnet *ifp = sc->sc_ifp;
12448 	struct ieee80211com *ic = ifp->if_l2com;
12449 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12450 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12451 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12452 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12453 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12454 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12455 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12456 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12457 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12458 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12459 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12460 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12461 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12462 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12463 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12464 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12465 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12466 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12467 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12468 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12469 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12470 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12471 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12472 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12473 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12474 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12475 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12476 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12477 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12478 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12479 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12480 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12481 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12482 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12483 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12484 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12485 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12486 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12487 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12488 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12489 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12490 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12491 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12492 	};
12493 	const struct bwn_b206x_rfinit_entry *br;
12494 	unsigned int i;
12495 
12496 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12497 		br = &bwn_b2063_init_tab[i];
12498 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12499 			if (br->br_flags & FLAG_G)
12500 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12501 		} else {
12502 			if (br->br_flags & FLAG_A)
12503 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12504 		}
12505 	}
12506 #undef FLAG_A
12507 #undef FLAG_B
12508 }
12509 
12510 static void
12511 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12512     int count, void *_data)
12513 {
12514 	unsigned int i;
12515 	uint32_t offset, type;
12516 	uint8_t *data = _data;
12517 
12518 	type = BWN_TAB_GETTYPE(typenoffset);
12519 	offset = BWN_TAB_GETOFFSET(typenoffset);
12520 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12521 
12522 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12523 
12524 	for (i = 0; i < count; i++) {
12525 		switch (type) {
12526 		case BWN_TAB_8BIT:
12527 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12528 			data++;
12529 			break;
12530 		case BWN_TAB_16BIT:
12531 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12532 			    BWN_PHY_TABLEDATALO);
12533 			data += 2;
12534 			break;
12535 		case BWN_TAB_32BIT:
12536 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12537 			    BWN_PHY_TABLEDATAHI);
12538 			*((uint32_t *)data) <<= 16;
12539 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12540 			    BWN_PHY_TABLEDATALO);
12541 			data += 4;
12542 			break;
12543 		default:
12544 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12545 		}
12546 	}
12547 }
12548 
12549 static void
12550 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12551     int count, const void *_data)
12552 {
12553 	uint32_t offset, type, value;
12554 	const uint8_t *data = _data;
12555 	unsigned int i;
12556 
12557 	type = BWN_TAB_GETTYPE(typenoffset);
12558 	offset = BWN_TAB_GETOFFSET(typenoffset);
12559 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12560 
12561 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12562 
12563 	for (i = 0; i < count; i++) {
12564 		switch (type) {
12565 		case BWN_TAB_8BIT:
12566 			value = *data;
12567 			data++;
12568 			KASSERT(!(value & ~0xff),
12569 			    ("%s:%d: fail", __func__, __LINE__));
12570 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12571 			break;
12572 		case BWN_TAB_16BIT:
12573 			value = *((const uint16_t *)data);
12574 			data += 2;
12575 			KASSERT(!(value & ~0xffff),
12576 			    ("%s:%d: fail", __func__, __LINE__));
12577 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12578 			break;
12579 		case BWN_TAB_32BIT:
12580 			value = *((const uint32_t *)data);
12581 			data += 4;
12582 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12583 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12584 			break;
12585 		default:
12586 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12587 		}
12588 	}
12589 }
12590 
12591 static struct bwn_txgain
12592 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12593 {
12594 	struct bwn_txgain tg;
12595 	uint16_t tmp;
12596 
12597 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12598 	if (mac->mac_phy.rev < 2) {
12599 		tmp = BWN_PHY_READ(mac,
12600 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12601 		tg.tg_gm = tmp & 0x0007;
12602 		tg.tg_pga = (tmp & 0x0078) >> 3;
12603 		tg.tg_pad = (tmp & 0x780) >> 7;
12604 		return (tg);
12605 	}
12606 
12607 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12608 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12609 	tg.tg_gm = tmp & 0xff;
12610 	tg.tg_pga = (tmp >> 8) & 0xff;
12611 	return (tg);
12612 }
12613 
12614 static uint8_t
12615 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12616 {
12617 
12618 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12619 }
12620 
12621 static void
12622 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12623 {
12624 	uint16_t pa;
12625 
12626 	if (mac->mac_phy.rev < 2) {
12627 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12628 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12629 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12630 		bwn_phy_lp_set_txgain_override(mac);
12631 		return;
12632 	}
12633 
12634 	pa = bwn_phy_lp_get_pa_gain(mac);
12635 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12636 	    (tg->tg_pga << 8) | tg->tg_gm);
12637 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12638 	    tg->tg_pad | (pa << 6));
12639 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12640 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12641 	    tg->tg_pad | (pa << 8));
12642 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12643 	bwn_phy_lp_set_txgain_override(mac);
12644 }
12645 
12646 static void
12647 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12648 {
12649 
12650 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12651 }
12652 
12653 static void
12654 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12655 {
12656 	uint16_t trsw = (tx << 1) | rx;
12657 
12658 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12659 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12660 }
12661 
12662 static void
12663 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12664 {
12665 	struct bwn_softc *sc = mac->mac_sc;
12666 	struct ifnet *ifp = sc->sc_ifp;
12667 	struct ieee80211com *ic = ifp->if_l2com;
12668 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12669 
12670 	if (mac->mac_phy.rev < 2) {
12671 		trsw = gain & 0x1;
12672 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12673 		ext_lna = (gain & 2) >> 1;
12674 
12675 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12676 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12677 		    0xfbff, ext_lna << 10);
12678 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12679 		    0xf7ff, ext_lna << 11);
12680 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12681 	} else {
12682 		low_gain = gain & 0xffff;
12683 		high_gain = (gain >> 16) & 0xf;
12684 		ext_lna = (gain >> 21) & 0x1;
12685 		trsw = ~(gain >> 20) & 0x1;
12686 
12687 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12688 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12689 		    0xfdff, ext_lna << 9);
12690 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12691 		    0xfbff, ext_lna << 10);
12692 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12693 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12694 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12695 			tmp = (gain >> 2) & 0x3;
12696 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12697 			    0xe7ff, tmp<<11);
12698 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12699 			    tmp << 3);
12700 		}
12701 	}
12702 
12703 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12704 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12705 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12706 	if (mac->mac_phy.rev >= 2) {
12707 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12708 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12709 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12710 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12711 		}
12712 		return;
12713 	}
12714 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12715 }
12716 
12717 static void
12718 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12719 {
12720 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12721 
12722 	if (user)
12723 		plp->plp_crsusr_off = 1;
12724 	else
12725 		plp->plp_crssys_off = 1;
12726 
12727 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12728 }
12729 
12730 static void
12731 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12732 {
12733 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12734 	struct bwn_softc *sc = mac->mac_sc;
12735 	struct ifnet *ifp = sc->sc_ifp;
12736 	struct ieee80211com *ic = ifp->if_l2com;
12737 
12738 	if (user)
12739 		plp->plp_crsusr_off = 0;
12740 	else
12741 		plp->plp_crssys_off = 0;
12742 
12743 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12744 		return;
12745 
12746 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12747 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12748 	else
12749 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12750 }
12751 
12752 static unsigned int
12753 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12754 {
12755 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12756 	static uint8_t sqrt_table[256] = {
12757 		10, 14, 17, 20, 22, 24, 26, 28,
12758 		30, 31, 33, 34, 36, 37, 38, 40,
12759 		41, 42, 43, 44, 45, 46, 47, 48,
12760 		50, 50, 51, 52, 53, 54, 55, 56,
12761 		57, 58, 59, 60, 60, 61, 62, 63,
12762 		64, 64, 65, 66, 67, 67, 68, 69,
12763 		70, 70, 71, 72, 72, 73, 74, 74,
12764 		75, 76, 76, 77, 78, 78, 79, 80,
12765 		80, 81, 81, 82, 83, 83, 84, 84,
12766 		85, 86, 86, 87, 87, 88, 88, 89,
12767 		90, 90, 91, 91, 92, 92, 93, 93,
12768 		94, 94, 95, 95, 96, 96, 97, 97,
12769 		98, 98, 99, 100, 100, 100, 101, 101,
12770 		102, 102, 103, 103, 104, 104, 105, 105,
12771 		106, 106, 107, 107, 108, 108, 109, 109,
12772 		110, 110, 110, 111, 111, 112, 112, 113,
12773 		113, 114, 114, 114, 115, 115, 116, 116,
12774 		117, 117, 117, 118, 118, 119, 119, 120,
12775 		120, 120, 121, 121, 122, 122, 122, 123,
12776 		123, 124, 124, 124, 125, 125, 126, 126,
12777 		126, 127, 127, 128, 128, 128, 129, 129,
12778 		130, 130, 130, 131, 131, 131, 132, 132,
12779 		133, 133, 133, 134, 134, 134, 135, 135,
12780 		136, 136, 136, 137, 137, 137, 138, 138,
12781 		138, 139, 139, 140, 140, 140, 141, 141,
12782 		141, 142, 142, 142, 143, 143, 143, 144,
12783 		144, 144, 145, 145, 145, 146, 146, 146,
12784 		147, 147, 147, 148, 148, 148, 149, 149,
12785 		150, 150, 150, 150, 151, 151, 151, 152,
12786 		152, 152, 153, 153, 153, 154, 154, 154,
12787 		155, 155, 155, 156, 156, 156, 157, 157,
12788 		157, 158, 158, 158, 159, 159, 159, 160
12789 	};
12790 
12791 	if (x == 0)
12792 		return (0);
12793 	if (x >= 256) {
12794 		unsigned int tmp;
12795 
12796 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12797 			/* do nothing */ ;
12798 		return (tmp);
12799 	}
12800 	return (sqrt_table[x - 1] / 10);
12801 }
12802 
12803 static int
12804 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12805 {
12806 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12807 	int _t;								\
12808 	_t = _x - 20;							\
12809 	if (_t >= 0) {							\
12810 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12811 	} else {							\
12812 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12813 	}								\
12814 } while (0)
12815 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12816 	int _t;								\
12817 	_t = _x - 11;							\
12818 	if (_t >= 0)							\
12819 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12820 	else								\
12821 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12822 } while (0)
12823 	struct bwn_phy_lp_iq_est ie;
12824 	uint16_t v0, v1;
12825 	int tmp[2], ret;
12826 
12827 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12828 	v0 = v1 >> 8;
12829 	v1 |= 0xff;
12830 
12831 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12832 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12833 
12834 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12835 	if (ret == 0)
12836 		goto done;
12837 
12838 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12839 		ret = 0;
12840 		goto done;
12841 	}
12842 
12843 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12844 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12845 
12846 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12847 	v0 = tmp[0] >> 3;
12848 	v1 = tmp[1] >> 4;
12849 done:
12850 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12851 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12852 	return ret;
12853 #undef CALC_COEFF
12854 #undef CALC_COEFF2
12855 }
12856 
12857 static void
12858 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12859 {
12860 	static const uint16_t noisescale[] = {
12861 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12862 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12863 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12864 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12865 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12866 	};
12867 	static const uint16_t crsgainnft[] = {
12868 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12869 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12870 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12871 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12872 		0x013d,
12873 	};
12874 	static const uint16_t filterctl[] = {
12875 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12876 		0xff53, 0x0127,
12877 	};
12878 	static const uint32_t psctl[] = {
12879 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12880 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12881 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12882 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12883 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12884 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12885 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12886 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12887 	};
12888 	static const uint16_t ofdmcckgain_r0[] = {
12889 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12890 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12891 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12892 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12893 		0x755d,
12894 	};
12895 	static const uint16_t ofdmcckgain_r1[] = {
12896 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12897 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12898 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12899 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12900 		0x755d,
12901 	};
12902 	static const uint16_t gaindelta[] = {
12903 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12904 		0x0000,
12905 	};
12906 	static const uint32_t txpwrctl[] = {
12907 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12908 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12909 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12910 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12911 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12912 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12913 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12914 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12915 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12916 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12917 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12918 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12919 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12920 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12921 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12922 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12923 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 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, 0x000075a0, 0x000075a0, 0x000075a1,
12946 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12947 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12948 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12949 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12950 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12951 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12952 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12953 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12954 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12955 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12956 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12957 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12958 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12959 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12960 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12961 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12962 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12963 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12964 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12965 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12966 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12967 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12968 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12969 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12970 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12971 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12972 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12973 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12974 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
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, 0x000000ff, 0x000002fc,
12997 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12998 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12999 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13000 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13001 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13002 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13003 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13004 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13005 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13006 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13007 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13008 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13009 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13010 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13011 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13012 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13013 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13014 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13015 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13016 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13017 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13018 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13019 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13020 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13021 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13022 		0x00000702,
13023 	};
13024 
13025 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13026 
13027 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13028 	    bwn_tab_sigsq_tbl);
13029 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13030 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13031 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13032 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13033 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13034 	    bwn_tab_pllfrac_tbl);
13035 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13036 	    bwn_tabl_iqlocal_tbl);
13037 	if (mac->mac_phy.rev == 0) {
13038 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13039 		    ofdmcckgain_r0);
13040 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13041 		    ofdmcckgain_r0);
13042 	} else {
13043 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13044 		    ofdmcckgain_r1);
13045 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13046 		    ofdmcckgain_r1);
13047 	}
13048 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13049 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13050 }
13051 
13052 static void
13053 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13054 {
13055 	struct bwn_softc *sc = mac->mac_sc;
13056 	int i;
13057 	static const uint16_t noisescale[] = {
13058 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13059 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13060 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13061 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13065 	};
13066 	static const uint32_t filterctl[] = {
13067 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13068 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13069 	};
13070 	static const uint32_t psctl[] = {
13071 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13072 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13073 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13074 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13075 	};
13076 	static const uint32_t gainidx[] = {
13077 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13078 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13079 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13080 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13081 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13082 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13083 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13084 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13085 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13086 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13087 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13088 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13089 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13090 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13091 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13092 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13093 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13094 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13095 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13096 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13097 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13098 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13099 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13100 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13101 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13102 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13103 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13104 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13105 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13106 		0x0000001a, 0x64ca55ad, 0x0000001a
13107 	};
13108 	static const uint16_t auxgainidx[] = {
13109 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13110 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13111 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13112 		0x0004, 0x0016
13113 	};
13114 	static const uint16_t swctl[] = {
13115 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13116 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13117 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13118 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
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 	};
13124 	static const uint8_t hf[] = {
13125 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13126 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13127 	};
13128 	static const uint32_t gainval[] = {
13129 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13130 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13131 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13132 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13133 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13134 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13135 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13136 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13137 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13138 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13139 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13140 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13141 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13142 		0x000000f1, 0x00000000, 0x00000000
13143 	};
13144 	static const uint16_t gain[] = {
13145 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13146 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13147 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13148 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13149 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13150 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13151 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13152 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13153 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13154 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13157 	};
13158 	static const uint32_t papdeps[] = {
13159 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13160 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13161 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13162 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13163 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13164 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13165 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13166 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13167 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13168 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13169 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13170 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13171 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13172 	};
13173 	static const uint32_t papdmult[] = {
13174 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13175 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13176 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13177 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13178 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13179 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13180 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13181 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13182 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13183 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13184 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13185 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13186 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13187 	};
13188 	static const uint32_t gainidx_a0[] = {
13189 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13190 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13191 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13192 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13193 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13194 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13195 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13196 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13197 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13198 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13199 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13200 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13201 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13202 	};
13203 	static const uint16_t auxgainidx_a0[] = {
13204 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13205 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13206 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13207 		0x0002, 0x0014
13208 	};
13209 	static const uint32_t gainval_a0[] = {
13210 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13211 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13212 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13213 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13214 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13215 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13216 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13217 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13218 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13219 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13220 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13221 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13222 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13223 		0x000000f7, 0x00000000, 0x00000000
13224 	};
13225 	static const uint16_t gain_a0[] = {
13226 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13227 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13228 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13229 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13230 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13231 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13232 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13233 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13234 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13235 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13238 	};
13239 
13240 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13241 
13242 	for (i = 0; i < 704; i++)
13243 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13244 
13245 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13246 	    bwn_tab_sigsq_tbl);
13247 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13248 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13249 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13250 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13251 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13252 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13253 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13254 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13255 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13256 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13257 	    bwn_tab_pllfrac_tbl);
13258 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13259 	    bwn_tabl_iqlocal_tbl);
13260 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13261 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13262 
13263 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13264 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13265 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13266 		    gainidx_a0);
13267 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13268 		    auxgainidx_a0);
13269 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13270 		    gainval_a0);
13271 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13272 	}
13273 }
13274 
13275 static void
13276 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13277 {
13278 	struct bwn_softc *sc = mac->mac_sc;
13279 	struct ifnet *ifp = sc->sc_ifp;
13280 	struct ieee80211com *ic = ifp->if_l2com;
13281 	static struct bwn_txgain_entry txgain_r2[] = {
13282 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13283 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13284 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13285 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13286 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13287 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13288 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13289 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13290 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13291 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13292 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13293 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13294 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13295 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13296 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13297 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13298 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13299 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13300 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13301 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13302 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13303 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13304 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13305 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13306 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13307 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13308 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13309 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13310 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13311 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13312 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13313 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13314 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13315 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13316 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13317 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13318 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13319 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13320 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13321 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13322 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13323 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13324 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13325 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13326 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13327 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13328 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13329 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13330 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13331 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13332 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13333 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13334 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13335 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13336 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13337 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13338 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13339 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13340 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13341 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13342 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13343 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13344 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13345 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13346 	};
13347 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13348 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13349 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13350 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13351 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13352 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13353 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13354 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13355 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13356 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13357 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13358 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13359 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13360 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13361 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13362 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13363 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13364 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13365 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13366 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13367 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13368 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13369 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13370 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13371 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13372 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13373 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13374 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13375 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13376 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13377 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13378 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13379 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13380 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13381 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13382 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13383 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13384 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13385 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13386 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13387 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13388 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13389 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13390 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13391 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13392 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13393 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13394 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13395 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13396 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13397 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13398 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13399 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13400 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13401 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13402 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13403 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13404 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13405 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13406 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13407 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13408 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13409 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13410 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13411 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13412 	};
13413 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13414 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13415 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13416 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13417 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13418 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13419 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13420 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13421 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13422 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13423 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13424 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13425 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13426 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13427 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13428 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13429 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13430 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13431 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13432 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13433 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13434 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13435 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13436 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13437 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13438 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13439 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13440 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13441 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13442 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13443 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13444 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13445 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13446 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13447 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13448 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13449 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13450 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13451 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13452 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13453 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13454 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13455 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13456 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13457 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13458 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13459 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13460 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13461 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13462 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13463 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13464 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13465 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13466 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13467 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13468 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13469 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13470 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13471 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13472 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13473 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13474 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13475 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13476 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13477 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13478 	};
13479 	static struct bwn_txgain_entry txgain_r0[] = {
13480 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13481 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13482 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13483 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13484 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13485 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13486 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13487 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13488 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13489 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13490 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13491 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13492 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13493 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13494 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13495 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13496 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13497 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13498 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13499 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13500 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13501 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13502 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13503 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13504 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13505 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13506 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13507 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13508 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13509 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13510 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13511 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13512 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13513 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13514 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13515 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13516 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13517 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13518 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13519 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13520 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13521 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13522 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13523 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13524 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13525 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13526 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13527 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13528 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13529 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13530 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13531 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13532 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13533 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13534 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13535 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13536 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13537 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13538 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13539 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13540 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13541 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13542 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13543 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13544 	};
13545 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13546 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13547 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13548 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13549 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13550 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13551 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13552 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13553 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13554 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13555 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13556 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13557 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13558 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13559 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13560 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13561 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13562 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13563 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13564 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13565 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13566 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13567 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13568 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13569 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13570 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13571 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13572 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13573 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13574 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13575 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13576 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13577 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13578 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13579 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13580 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13581 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13582 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13583 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13584 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13585 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13586 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13587 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13588 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13589 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13590 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13591 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13592 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13593 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13594 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13595 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13596 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13597 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13598 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13599 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13600 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13601 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13602 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13603 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13604 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13605 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13606 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13607 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13608 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13609 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13610 	};
13611 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13612 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13613 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13614 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13615 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13616 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13617 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13618 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13619 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13620 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13621 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13622 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13623 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13624 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13625 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13626 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13627 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13628 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13629 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13630 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13631 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13632 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13633 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13634 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13635 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13636 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13637 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13638 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13639 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13640 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13641 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13642 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13643 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13644 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13645 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13646 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13647 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13648 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13649 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13650 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13651 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13652 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13653 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13654 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13655 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13656 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13657 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13658 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13659 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13660 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13661 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13662 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13663 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13664 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13665 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13666 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13667 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13668 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13669 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13670 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13671 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13672 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13673 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13674 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13675 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13676 	};
13677 	static struct bwn_txgain_entry txgain_r1[] = {
13678 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13679 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13680 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13681 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13682 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13683 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13684 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13685 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13686 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13687 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13688 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13689 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13690 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13691 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13692 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13693 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13694 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13695 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13696 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13697 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13698 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13699 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13700 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13701 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13702 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13703 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13704 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13705 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13706 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13707 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13708 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13709 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13710 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13711 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13712 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13713 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13714 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13715 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13716 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13717 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13718 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13719 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13720 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13721 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13722 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13723 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13724 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13725 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13726 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13727 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13728 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13729 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13730 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13731 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13732 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13733 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13734 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13735 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13736 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13737 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13738 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13739 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13740 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13741 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13742 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13743 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13744 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13745 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13746 		{ 7, 11, 6, 0, 71 }
13747 	};
13748 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13749 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13750 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13751 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13752 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13753 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13754 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13755 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13756 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13757 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13758 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13759 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13760 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13761 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13762 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13763 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13764 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13765 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13766 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13767 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13768 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13769 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13770 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13771 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13772 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13773 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13774 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13775 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13776 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13777 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13778 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13779 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13780 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13781 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13782 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13783 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13784 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13785 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13786 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13787 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13788 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13789 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13790 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13791 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13792 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13793 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13794 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13795 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13796 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13797 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13798 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13799 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13800 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13801 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13802 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13803 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13804 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13805 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13806 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13807 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13808 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13809 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13810 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13811 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13812 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13813 	};
13814 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13815 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13816 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13817 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13818 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13819 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13820 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13821 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13822 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13823 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13824 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13825 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13826 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13827 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13828 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13829 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13830 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13831 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13832 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13833 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13834 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13835 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13836 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13837 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13838 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13839 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13840 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13841 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13842 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13843 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13844 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13845 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13846 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13847 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13848 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13849 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13850 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13851 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13852 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13853 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13854 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13855 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13856 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13857 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13858 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13859 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13860 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13861 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13862 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13863 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13864 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13865 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13866 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13867 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13868 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13869 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13870 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13871 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13872 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13873 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13874 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13875 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13876 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13877 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13878 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13879 	};
13880 
13881 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13882 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13883 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13884 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13885 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13886 			    txgain_2ghz_r2);
13887 		else
13888 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13889 			    txgain_5ghz_r2);
13890 		return;
13891 	}
13892 
13893 	if (mac->mac_phy.rev == 0) {
13894 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13895 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13896 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13897 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13898 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13899 			    txgain_2ghz_r0);
13900 		else
13901 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902 			    txgain_5ghz_r0);
13903 		return;
13904 	}
13905 
13906 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13907 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13908 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13909 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13910 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13911 	else
13912 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13913 }
13914 
13915 static void
13916 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13917 {
13918 	uint32_t offset, type;
13919 
13920 	type = BWN_TAB_GETTYPE(typeoffset);
13921 	offset = BWN_TAB_GETOFFSET(typeoffset);
13922 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13923 
13924 	switch (type) {
13925 	case BWN_TAB_8BIT:
13926 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13927 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13928 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13929 		break;
13930 	case BWN_TAB_16BIT:
13931 		KASSERT(!(value & ~0xffff),
13932 		    ("%s:%d: fail", __func__, __LINE__));
13933 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13934 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13935 		break;
13936 	case BWN_TAB_32BIT:
13937 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13938 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13939 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13940 		break;
13941 	default:
13942 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13943 	}
13944 }
13945 
13946 static int
13947 bwn_phy_lp_loopback(struct bwn_mac *mac)
13948 {
13949 	struct bwn_phy_lp_iq_est ie;
13950 	int i, index = -1;
13951 	uint32_t tmp;
13952 
13953 	memset(&ie, 0, sizeof(ie));
13954 
13955 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13956 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13957 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13958 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13959 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13960 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13961 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13962 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13963 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13964 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13965 	for (i = 0; i < 32; i++) {
13966 		bwn_phy_lp_set_rxgain_idx(mac, i);
13967 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13968 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13969 			continue;
13970 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13971 		if ((tmp > 4000) && (tmp < 10000)) {
13972 			index = i;
13973 			break;
13974 		}
13975 	}
13976 	bwn_phy_lp_ddfs_turnoff(mac);
13977 	return (index);
13978 }
13979 
13980 static void
13981 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13982 {
13983 
13984 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13985 }
13986 
13987 static void
13988 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13989     int incr1, int incr2, int scale_idx)
13990 {
13991 
13992 	bwn_phy_lp_ddfs_turnoff(mac);
13993 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13994 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13995 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13996 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13997 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13998 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13999 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14000 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14001 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14002 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14003 }
14004 
14005 static uint8_t
14006 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14007     struct bwn_phy_lp_iq_est *ie)
14008 {
14009 	int i;
14010 
14011 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14012 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14013 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14014 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14015 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14016 
14017 	for (i = 0; i < 500; i++) {
14018 		if (!(BWN_PHY_READ(mac,
14019 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14020 			break;
14021 		DELAY(1000);
14022 	}
14023 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14024 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14025 		return 0;
14026 	}
14027 
14028 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14029 	ie->ie_iqprod <<= 16;
14030 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14031 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14032 	ie->ie_ipwr <<= 16;
14033 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14034 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14035 	ie->ie_qpwr <<= 16;
14036 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14037 
14038 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14039 	return 1;
14040 }
14041 
14042 static uint32_t
14043 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14044 {
14045 	uint32_t offset, type, value;
14046 
14047 	type = BWN_TAB_GETTYPE(typeoffset);
14048 	offset = BWN_TAB_GETOFFSET(typeoffset);
14049 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14050 
14051 	switch (type) {
14052 	case BWN_TAB_8BIT:
14053 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14054 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14055 		break;
14056 	case BWN_TAB_16BIT:
14057 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14058 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14059 		break;
14060 	case BWN_TAB_32BIT:
14061 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14062 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14063 		value <<= 16;
14064 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14065 		break;
14066 	default:
14067 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14068 		value = 0;
14069 	}
14070 
14071 	return (value);
14072 }
14073 
14074 static void
14075 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14076 {
14077 
14078 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14079 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14080 }
14081 
14082 static void
14083 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14084 {
14085 	uint16_t ctl;
14086 
14087 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14088 	ctl |= dac << 7;
14089 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14090 }
14091 
14092 static void
14093 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14094 {
14095 
14096 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14097 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14098 }
14099 
14100 static void
14101 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14102 {
14103 
14104 	if (mac->mac_phy.rev < 2)
14105 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14106 	else {
14107 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14108 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14109 	}
14110 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14111 }
14112 
14113 static uint16_t
14114 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14115 {
14116 
14117 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14118 }
14119 
14120 static uint8_t
14121 bwn_nbits(int32_t val)
14122 {
14123 	uint32_t tmp;
14124 	uint8_t nbits = 0;
14125 
14126 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14127 		nbits++;
14128 	return (nbits);
14129 }
14130 
14131 static void
14132 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14133     struct bwn_txgain_entry *table)
14134 {
14135 	int i;
14136 
14137 	for (i = offset; i < count; i++)
14138 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14139 }
14140 
14141 static void
14142 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14143     struct bwn_txgain_entry data)
14144 {
14145 
14146 	if (mac->mac_phy.rev >= 2)
14147 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14148 	else
14149 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14150 }
14151 
14152 static void
14153 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14154     struct bwn_txgain_entry te)
14155 {
14156 	struct bwn_softc *sc = mac->mac_sc;
14157 	struct ifnet *ifp = sc->sc_ifp;
14158 	struct ieee80211com *ic = ifp->if_l2com;
14159 	uint32_t tmp;
14160 
14161 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14162 
14163 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14164 	if (mac->mac_phy.rev >= 3) {
14165 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14166 		    (0x10 << 24) : (0x70 << 24));
14167 	} else {
14168 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14169 		    (0x14 << 24) : (0x7f << 24));
14170 	}
14171 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14172 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14173 	    te.te_bbmult << 20 | te.te_dac << 28);
14174 }
14175 
14176 static void
14177 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14178     struct bwn_txgain_entry te)
14179 {
14180 
14181 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14182 
14183 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14184 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14185 	    te.te_dac);
14186 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14187 }
14188 
14189 static void
14190 bwn_sysctl_node(struct bwn_softc *sc)
14191 {
14192 	device_t dev = sc->sc_dev;
14193 	struct bwn_mac *mac;
14194 	struct bwn_stats *stats;
14195 
14196 	/* XXX assume that count of MAC is only 1. */
14197 
14198 	if ((mac = sc->sc_curmac) == NULL)
14199 		return;
14200 	stats = &mac->mac_stats;
14201 
14202 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14203 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14204 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14205 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14206 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14207 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14208 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14209 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14210 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14211 
14212 #ifdef BWN_DEBUG
14213 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14214 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14215 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14216 #endif
14217 }
14218 
14219 static device_method_t bwn_methods[] = {
14220 	/* Device interface */
14221 	DEVMETHOD(device_probe,		bwn_probe),
14222 	DEVMETHOD(device_attach,	bwn_attach),
14223 	DEVMETHOD(device_detach,	bwn_detach),
14224 	DEVMETHOD(device_suspend,	bwn_suspend),
14225 	DEVMETHOD(device_resume,	bwn_resume),
14226 	DEVMETHOD_END
14227 };
14228 static driver_t bwn_driver = {
14229 	"bwn",
14230 	bwn_methods,
14231 	sizeof(struct bwn_softc)
14232 };
14233 static devclass_t bwn_devclass;
14234 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14235 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14236 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14237 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14238 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14239