xref: /freebsd/sys/dev/bwn/if_bwn.c (revision 21fdc27a054f668c8b6c2be503fa68622e5226da)
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * The Broadcom Wireless LAN controller driver.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/module.h>
40 #include <sys/kernel.h>
41 #include <sys/endian.h>
42 #include <sys/errno.h>
43 #include <sys/firmware.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_arp.h>
56 #include <net/if_dl.h>
57 #include <net/if_llc.h>
58 #include <net/if_media.h>
59 #include <net/if_types.h>
60 
61 #include <dev/pci/pcivar.h>
62 #include <dev/pci/pcireg.h>
63 #include <dev/siba/siba_ids.h>
64 #include <dev/siba/sibareg.h>
65 #include <dev/siba/sibavar.h>
66 
67 #include <net80211/ieee80211_var.h>
68 #include <net80211/ieee80211_radiotap.h>
69 #include <net80211/ieee80211_regdomain.h>
70 #include <net80211/ieee80211_amrr.h>
71 #include <net80211/ieee80211_phy.h>
72 
73 #include <dev/bwn/if_bwnreg.h>
74 #include <dev/bwn/if_bwnvar.h>
75 
76 SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77 
78 /*
79  * Tunable & sysctl variables.
80  */
81 
82 #ifdef BWN_DEBUG
83 static	int bwn_debug = 0;
84 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85     "Broadcom debugging printfs");
86 TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87 enum {
88 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106 	BWN_DEBUG_ANY		= 0xffffffff
107 };
108 #define	DPRINTF(sc, m, fmt, ...) do {			\
109 	if (sc->sc_debug & (m))				\
110 		printf(fmt, __VA_ARGS__);		\
111 } while (0)
112 #else
113 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114 #endif
115 
116 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118     "uses Bad Frames Preemption");
119 static int	bwn_bluetooth = 1;
120 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121     "turns on Bluetooth Coexistence");
122 static int	bwn_hwpctl = 0;
123 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124     "uses H/W power control");
125 static int	bwn_msi_disable = 0;		/* MSI disabled  */
126 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127 static int	bwn_usedma = 1;
128 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129     "uses DMA");
130 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131 static int	bwn_wme = 1;
132 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133     "uses WME support");
134 
135 static int	bwn_attach_pre(struct bwn_softc *);
136 static int	bwn_attach_post(struct bwn_softc *);
137 static void	bwn_sprom_bugfixes(struct siba_softc *);
138 static void	bwn_init(void *);
139 static int	bwn_init_locked(struct bwn_softc *);
140 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141 static void	bwn_start(struct ifnet *);
142 static int	bwn_attach_core(struct bwn_mac *);
143 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144 static int	bwn_phy_getinfo(struct bwn_mac *, int);
145 static int	bwn_chiptest(struct bwn_mac *);
146 static int	bwn_setup_channels(struct bwn_mac *, int, int);
147 static int	bwn_phy_g_attach(struct bwn_mac *);
148 static void	bwn_phy_g_detach(struct bwn_mac *);
149 static void	bwn_phy_g_init_pre(struct bwn_mac *);
150 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151 static int	bwn_phy_g_init(struct bwn_mac *);
152 static void	bwn_phy_g_exit(struct bwn_mac *);
153 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155 		    uint16_t);
156 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158 		    uint16_t);
159 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164 static int	bwn_phy_g_im(struct bwn_mac *, int);
165 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167 static void	bwn_phy_g_task_15s(struct bwn_mac *);
168 static void	bwn_phy_g_task_60s(struct bwn_mac *);
169 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173 		    uint16_t);
174 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176 		    uint32_t);
177 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178 		    uint16_t);
179 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180 		    const struct bwn_channelinfo *, int);
181 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182 		    const struct ieee80211_bpf_params *);
183 static void	bwn_newassoc(struct ieee80211_node *, int);
184 static void	bwn_updateslot(struct ifnet *);
185 static void	bwn_update_promisc(struct ifnet *);
186 static void	bwn_wme_init(struct bwn_mac *);
187 static int	bwn_wme_update(struct ieee80211com *);
188 static struct ieee80211_node *bwn_node_alloc(struct ieee80211vap *,
189 		    const uint8_t [IEEE80211_ADDR_LEN]);
190 static void	bwn_wme_clear(struct bwn_softc *);
191 static void	bwn_wme_load(struct bwn_mac *);
192 static void	bwn_wme_loadparams(struct bwn_mac *,
193 		    const struct wmeParams *, uint16_t);
194 static void	bwn_node_cleanup(struct ieee80211_node *);
195 static void	bwn_scan_start(struct ieee80211com *);
196 static void	bwn_scan_end(struct ieee80211com *);
197 static void	bwn_set_channel(struct ieee80211com *);
198 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
199 		    const char [IFNAMSIZ], int, int,
200 		    int, const uint8_t [IEEE80211_ADDR_LEN],
201 		    const uint8_t [IEEE80211_ADDR_LEN]);
202 static void	bwn_vap_delete(struct ieee80211vap *);
203 static void	bwn_stop(struct bwn_softc *, int);
204 static void	bwn_stop_locked(struct bwn_softc *, int);
205 static int	bwn_core_init(struct bwn_mac *);
206 static void	bwn_core_start(struct bwn_mac *);
207 static void	bwn_core_exit(struct bwn_mac *);
208 static void	bwn_fix_imcfglobug(struct bwn_mac *);
209 static void	bwn_bt_disable(struct bwn_mac *);
210 static int	bwn_chip_init(struct bwn_mac *);
211 static uint64_t	bwn_hf_read(struct bwn_mac *);
212 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
213 static void	bwn_set_txretry(struct bwn_mac *, int, int);
214 static void	bwn_rate_init(struct bwn_mac *);
215 static void	bwn_set_phytxctl(struct bwn_mac *);
216 static void	bwn_spu_setdelay(struct bwn_mac *, int);
217 static void	bwn_bt_enable(struct bwn_mac *);
218 static void	bwn_set_macaddr(struct bwn_mac *);
219 static void	bwn_crypt_init(struct bwn_mac *);
220 static void	bwn_chip_exit(struct bwn_mac *);
221 static int	bwn_fw_fillinfo(struct bwn_mac *);
222 static int	bwn_fw_loaducode(struct bwn_mac *);
223 static int	bwn_gpio_init(struct bwn_mac *);
224 static int	bwn_fw_loadinitvals(struct bwn_mac *);
225 static int	bwn_phy_init(struct bwn_mac *);
226 static void	bwn_set_txantenna(struct bwn_mac *, int);
227 static void	bwn_set_opmode(struct bwn_mac *);
228 static void	bwn_gpio_cleanup(struct bwn_mac *);
229 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
230 static uint8_t	bwn_plcp_getcck(const uint8_t);
231 static uint8_t	bwn_plcp_getofdm(const uint8_t);
232 static void	bwn_pio_init(struct bwn_mac *);
233 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
234 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
235 		    int);
236 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
237 		    struct bwn_pio_rxqueue *, int);
238 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
239 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
240 		    uint16_t);
241 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
242 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
243 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
244 static void	bwn_pio_handle_txeof(struct bwn_mac *,
245 		    const struct bwn_txstatus *);
246 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
247 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
248 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
249 		    uint16_t);
250 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
251 		    uint32_t);
252 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
253 		    struct mbuf *);
254 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
255 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
256 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
257 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
258 		    uint16_t, uint32_t);
259 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
260 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
261 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
262 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
263 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
264 		    uint16_t, struct bwn_pio_txpkt **);
265 static void	bwn_dma_init(struct bwn_mac *);
266 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
267 static int	bwn_dma_mask2type(uint64_t);
268 static uint64_t	bwn_dma_mask(struct bwn_mac *);
269 static uint16_t	bwn_dma_base(int, int);
270 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
271 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
272 		    int, struct bwn_dmadesc_generic **,
273 		    struct bwn_dmadesc_meta **);
274 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
275 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
276 		    int, int);
277 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
278 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
279 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
280 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
281 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
282 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
283 		    int, struct bwn_dmadesc_generic **,
284 		    struct bwn_dmadesc_meta **);
285 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
286 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
287 		    int, int);
288 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
289 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
290 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
291 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
292 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
293 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
294 static void	bwn_dma_setup(struct bwn_dma_ring *);
295 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
296 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
297 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
298 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
299 static void	bwn_dma_rx(struct bwn_dma_ring *);
300 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
301 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
302 		    struct bwn_dmadesc_meta *);
303 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
304 static int	bwn_dma_gettype(struct bwn_mac *);
305 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
306 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
307 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
308 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
309 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
310 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
311 		    int);
312 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
313 		    bus_size_t, int);
314 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
315 static void	bwn_dma_handle_txeof(struct bwn_mac *,
316 		    const struct bwn_txstatus *);
317 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
318 		    struct mbuf *);
319 static int	bwn_dma_getslot(struct bwn_dma_ring *);
320 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
321 		    uint8_t);
322 static int	bwn_dma_attach(struct bwn_mac *);
323 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
324 		    int, int, int);
325 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
326 		    const struct bwn_txstatus *, uint16_t, int *);
327 static void	bwn_dma_free(struct bwn_mac *);
328 static void	bwn_phy_g_init_sub(struct bwn_mac *);
329 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
330 static void	bwn_phy_init_b5(struct bwn_mac *);
331 static void	bwn_phy_init_b6(struct bwn_mac *);
332 static void	bwn_phy_init_a(struct bwn_mac *);
333 static void	bwn_loopback_calcgain(struct bwn_mac *);
334 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
335 static void	bwn_lo_g_init(struct bwn_mac *);
336 static void	bwn_lo_g_adjust(struct bwn_mac *);
337 static void	bwn_lo_get_powervector(struct bwn_mac *);
338 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
339 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
340 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
341 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
342 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
343 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
344 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
345 		    uint8_t);
346 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
347 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
348 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
349 static void	bwn_wa_init(struct bwn_mac *);
350 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
351 		    uint16_t);
352 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
353 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
354 		    uint32_t);
355 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
356 		    uint16_t);
357 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
358 static void	bwn_mac_suspend(struct bwn_mac *);
359 static void	bwn_mac_enable(struct bwn_mac *);
360 static void	bwn_psctl(struct bwn_mac *, uint32_t);
361 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
362 static void	bwn_nrssi_offset(struct bwn_mac *);
363 static void	bwn_nrssi_threshold(struct bwn_mac *);
364 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
365 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
366 		    int16_t);
367 static void	bwn_set_original_gains(struct bwn_mac *);
368 static void	bwn_hwpctl_early_init(struct bwn_mac *);
369 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
370 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
371 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
372 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
373 		    const char *, struct bwn_fwfile *);
374 static void	bwn_release_firmware(struct bwn_mac *);
375 static void	bwn_do_release_fw(struct bwn_fwfile *);
376 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
377 static int	bwn_fwinitvals_write(struct bwn_mac *,
378 		    const struct bwn_fwinitvals *, size_t, size_t);
379 static int	bwn_switch_channel(struct bwn_mac *, int);
380 static uint16_t	bwn_ant2phy(int);
381 static void	bwn_mac_write_bssid(struct bwn_mac *);
382 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
383 		    const uint8_t *);
384 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
385 		    const uint8_t *, size_t, const uint8_t *);
386 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
387 		    const uint8_t *);
388 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
389 		    const uint8_t *);
390 static void	bwn_phy_exit(struct bwn_mac *);
391 static void	bwn_core_stop(struct bwn_mac *);
392 static int	bwn_switch_band(struct bwn_softc *,
393 		    struct ieee80211_channel *);
394 static void	bwn_phy_reset(struct bwn_mac *);
395 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
396 static void	bwn_set_pretbtt(struct bwn_mac *);
397 static int	bwn_intr(void *);
398 static void	bwn_intrtask(void *, int);
399 static void	bwn_restart(struct bwn_mac *, const char *);
400 static void	bwn_intr_ucode_debug(struct bwn_mac *);
401 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
402 static void	bwn_intr_atim_end(struct bwn_mac *);
403 static void	bwn_intr_beacon(struct bwn_mac *);
404 static void	bwn_intr_pmq(struct bwn_mac *);
405 static void	bwn_intr_noise(struct bwn_mac *);
406 static void	bwn_intr_txeof(struct bwn_mac *);
407 static void	bwn_hwreset(void *, int);
408 static void	bwn_handle_fwpanic(struct bwn_mac *);
409 static void	bwn_load_beacon0(struct bwn_mac *);
410 static void	bwn_load_beacon1(struct bwn_mac *);
411 static uint32_t	bwn_jssi_read(struct bwn_mac *);
412 static void	bwn_noise_gensample(struct bwn_mac *);
413 static void	bwn_handle_txeof(struct bwn_mac *,
414 		    const struct bwn_txstatus *);
415 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
416 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
417 static void	bwn_start_locked(struct ifnet *);
418 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
419 		    struct mbuf *);
420 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
421 static int	bwn_set_txhdr(struct bwn_mac *,
422 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
423 		    uint16_t);
424 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
425 		    const uint8_t);
426 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
427 static uint8_t	bwn_get_fbrate(uint8_t);
428 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
429 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
430 static void	bwn_phy_lock(struct bwn_mac *);
431 static void	bwn_phy_unlock(struct bwn_mac *);
432 static void	bwn_rf_lock(struct bwn_mac *);
433 static void	bwn_rf_unlock(struct bwn_mac *);
434 static void	bwn_txpwr(void *, int);
435 static void	bwn_tasks(void *);
436 static void	bwn_task_15s(struct bwn_mac *);
437 static void	bwn_task_30s(struct bwn_mac *);
438 static void	bwn_task_60s(struct bwn_mac *);
439 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
440 		    uint8_t);
441 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
442 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
443 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
444 		    int, int);
445 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
446 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
447 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
448 static void	bwn_watchdog(void *);
449 static void	bwn_dma_stop(struct bwn_mac *);
450 static void	bwn_pio_stop(struct bwn_mac *);
451 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
452 static void	bwn_led_attach(struct bwn_mac *);
453 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
454 static void	bwn_led_event(struct bwn_mac *, int);
455 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
456 static void	bwn_led_blink_next(void *);
457 static void	bwn_led_blink_end(void *);
458 static void	bwn_rfswitch(void *);
459 static void	bwn_rf_turnon(struct bwn_mac *);
460 static void	bwn_rf_turnoff(struct bwn_mac *);
461 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
462 static int	bwn_phy_lp_init(struct bwn_mac *);
463 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
464 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
465 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
466 		    uint16_t);
467 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
468 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
469 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
470 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
471 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
472 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
473 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
474 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
475 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
476 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
477 static void	bwn_phy_lp_calib(struct bwn_mac *);
478 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
479 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
480 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
481 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
482 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
483 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
484 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
485 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
486 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
487 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
488 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
489 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
490 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
491 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
492 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
493 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
494 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
495 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
496 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
497 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
498 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
499 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
500 		    const void *);
501 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
502 static struct bwn_txgain
503 		bwn_phy_lp_get_txgain(struct bwn_mac *);
504 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
505 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
506 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
507 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
508 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
509 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
510 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
511 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
512 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
513 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
514 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
515 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
516 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
517 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
518 static int	bwn_phy_lp_loopback(struct bwn_mac *);
519 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
520 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
521 		    int);
522 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
523 		    struct bwn_phy_lp_iq_est *);
524 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
525 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
526 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
527 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
528 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
529 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
530 static uint8_t	bwn_nbits(int32_t);
531 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
532 		    struct bwn_txgain_entry *);
533 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
534 		    struct bwn_txgain_entry);
535 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
536 		    struct bwn_txgain_entry);
537 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
538 		    struct bwn_txgain_entry);
539 static void	bwn_sysctl_node(struct bwn_softc *);
540 
541 static struct resource_spec bwn_res_spec_legacy[] = {
542 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
543 	{ -1,			0,		0 }
544 };
545 
546 static struct resource_spec bwn_res_spec_msi[] = {
547 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
548 	{ -1,			0,		0 }
549 };
550 
551 static const struct bwn_channelinfo bwn_chantable_bg = {
552 	.channels = {
553 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
554 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
555 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
556 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
557 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
558 	.nchannels = 14
559 };
560 
561 static const struct bwn_channelinfo bwn_chantable_a = {
562 	.channels = {
563 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
564 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
565 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
566 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
567 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
568 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
569 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
570 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
571 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
572 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
573 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
574 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
575 		{ 6080, 216, 30 } },
576 	.nchannels = 37
577 };
578 
579 static const struct bwn_channelinfo bwn_chantable_n = {
580 	.channels = {
581 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
582 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
583 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
584 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
585 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
586 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
587 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
588 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
589 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
590 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
591 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
592 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
593 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
594 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
595 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
596 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
597 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
598 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
599 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
600 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
601 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
602 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
603 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
604 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
605 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
606 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
607 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
608 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
609 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
610 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
611 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
612 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
613 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
614 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
615 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
616 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
617 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
618 	.nchannels = 110
619 };
620 
621 static const uint8_t bwn_b2063_chantable_data[33][12] = {
622 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
623 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
624 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
625 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
626 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
627 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
628 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
629 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
630 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
631 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
632 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
633 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
634 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
635 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
636 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
637 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
638 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
639 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
640 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
641 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
642 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
643 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
644 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
645 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
646 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
647 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
648 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
649 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
650 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
651 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
652 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
653 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
654 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
655 };
656 
657 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
658 	{ 1, 2412, bwn_b2063_chantable_data[0] },
659 	{ 2, 2417, bwn_b2063_chantable_data[0] },
660 	{ 3, 2422, bwn_b2063_chantable_data[0] },
661 	{ 4, 2427, bwn_b2063_chantable_data[1] },
662 	{ 5, 2432, bwn_b2063_chantable_data[1] },
663 	{ 6, 2437, bwn_b2063_chantable_data[1] },
664 	{ 7, 2442, bwn_b2063_chantable_data[1] },
665 	{ 8, 2447, bwn_b2063_chantable_data[1] },
666 	{ 9, 2452, bwn_b2063_chantable_data[2] },
667 	{ 10, 2457, bwn_b2063_chantable_data[2] },
668 	{ 11, 2462, bwn_b2063_chantable_data[3] },
669 	{ 12, 2467, bwn_b2063_chantable_data[3] },
670 	{ 13, 2472, bwn_b2063_chantable_data[3] },
671 	{ 14, 2484, bwn_b2063_chantable_data[4] },
672 	{ 34, 5170, bwn_b2063_chantable_data[5] },
673 	{ 36, 5180, bwn_b2063_chantable_data[6] },
674 	{ 38, 5190, bwn_b2063_chantable_data[7] },
675 	{ 40, 5200, bwn_b2063_chantable_data[8] },
676 	{ 42, 5210, bwn_b2063_chantable_data[9] },
677 	{ 44, 5220, bwn_b2063_chantable_data[10] },
678 	{ 46, 5230, bwn_b2063_chantable_data[11] },
679 	{ 48, 5240, bwn_b2063_chantable_data[12] },
680 	{ 52, 5260, bwn_b2063_chantable_data[13] },
681 	{ 56, 5280, bwn_b2063_chantable_data[14] },
682 	{ 60, 5300, bwn_b2063_chantable_data[14] },
683 	{ 64, 5320, bwn_b2063_chantable_data[15] },
684 	{ 100, 5500, bwn_b2063_chantable_data[16] },
685 	{ 104, 5520, bwn_b2063_chantable_data[17] },
686 	{ 108, 5540, bwn_b2063_chantable_data[18] },
687 	{ 112, 5560, bwn_b2063_chantable_data[19] },
688 	{ 116, 5580, bwn_b2063_chantable_data[20] },
689 	{ 120, 5600, bwn_b2063_chantable_data[21] },
690 	{ 124, 5620, bwn_b2063_chantable_data[21] },
691 	{ 128, 5640, bwn_b2063_chantable_data[22] },
692 	{ 132, 5660, bwn_b2063_chantable_data[22] },
693 	{ 136, 5680, bwn_b2063_chantable_data[22] },
694 	{ 140, 5700, bwn_b2063_chantable_data[23] },
695 	{ 149, 5745, bwn_b2063_chantable_data[23] },
696 	{ 153, 5765, bwn_b2063_chantable_data[23] },
697 	{ 157, 5785, bwn_b2063_chantable_data[23] },
698 	{ 161, 5805, bwn_b2063_chantable_data[23] },
699 	{ 165, 5825, bwn_b2063_chantable_data[23] },
700 	{ 184, 4920, bwn_b2063_chantable_data[24] },
701 	{ 188, 4940, bwn_b2063_chantable_data[25] },
702 	{ 192, 4960, bwn_b2063_chantable_data[26] },
703 	{ 196, 4980, bwn_b2063_chantable_data[27] },
704 	{ 200, 5000, bwn_b2063_chantable_data[28] },
705 	{ 204, 5020, bwn_b2063_chantable_data[29] },
706 	{ 208, 5040, bwn_b2063_chantable_data[30] },
707 	{ 212, 5060, bwn_b2063_chantable_data[31] },
708 	{ 216, 5080, bwn_b2063_chantable_data[32] }
709 };
710 
711 static const uint8_t bwn_b2062_chantable_data[22][12] = {
712 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
713 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
717 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
718 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
719 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
720 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
721 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
722 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
723 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
724 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
725 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
728 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
729 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
730 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
731 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
732 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
733 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
734 };
735 
736 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
737 	{ 1, 2412, bwn_b2062_chantable_data[0] },
738 	{ 2, 2417, bwn_b2062_chantable_data[0] },
739 	{ 3, 2422, bwn_b2062_chantable_data[0] },
740 	{ 4, 2427, bwn_b2062_chantable_data[0] },
741 	{ 5, 2432, bwn_b2062_chantable_data[0] },
742 	{ 6, 2437, bwn_b2062_chantable_data[0] },
743 	{ 7, 2442, bwn_b2062_chantable_data[0] },
744 	{ 8, 2447, bwn_b2062_chantable_data[0] },
745 	{ 9, 2452, bwn_b2062_chantable_data[0] },
746 	{ 10, 2457, bwn_b2062_chantable_data[0] },
747 	{ 11, 2462, bwn_b2062_chantable_data[0] },
748 	{ 12, 2467, bwn_b2062_chantable_data[0] },
749 	{ 13, 2472, bwn_b2062_chantable_data[0] },
750 	{ 14, 2484, bwn_b2062_chantable_data[0] },
751 	{ 34, 5170, bwn_b2062_chantable_data[1] },
752 	{ 38, 5190, bwn_b2062_chantable_data[2] },
753 	{ 42, 5210, bwn_b2062_chantable_data[2] },
754 	{ 46, 5230, bwn_b2062_chantable_data[3] },
755 	{ 36, 5180, bwn_b2062_chantable_data[4] },
756 	{ 40, 5200, bwn_b2062_chantable_data[5] },
757 	{ 44, 5220, bwn_b2062_chantable_data[6] },
758 	{ 48, 5240, bwn_b2062_chantable_data[3] },
759 	{ 52, 5260, bwn_b2062_chantable_data[3] },
760 	{ 56, 5280, bwn_b2062_chantable_data[3] },
761 	{ 60, 5300, bwn_b2062_chantable_data[7] },
762 	{ 64, 5320, bwn_b2062_chantable_data[8] },
763 	{ 100, 5500, bwn_b2062_chantable_data[9] },
764 	{ 104, 5520, bwn_b2062_chantable_data[10] },
765 	{ 108, 5540, bwn_b2062_chantable_data[10] },
766 	{ 112, 5560, bwn_b2062_chantable_data[10] },
767 	{ 116, 5580, bwn_b2062_chantable_data[11] },
768 	{ 120, 5600, bwn_b2062_chantable_data[12] },
769 	{ 124, 5620, bwn_b2062_chantable_data[12] },
770 	{ 128, 5640, bwn_b2062_chantable_data[12] },
771 	{ 132, 5660, bwn_b2062_chantable_data[12] },
772 	{ 136, 5680, bwn_b2062_chantable_data[12] },
773 	{ 140, 5700, bwn_b2062_chantable_data[12] },
774 	{ 149, 5745, bwn_b2062_chantable_data[12] },
775 	{ 153, 5765, bwn_b2062_chantable_data[12] },
776 	{ 157, 5785, bwn_b2062_chantable_data[12] },
777 	{ 161, 5805, bwn_b2062_chantable_data[12] },
778 	{ 165, 5825, bwn_b2062_chantable_data[12] },
779 	{ 184, 4920, bwn_b2062_chantable_data[13] },
780 	{ 188, 4940, bwn_b2062_chantable_data[14] },
781 	{ 192, 4960, bwn_b2062_chantable_data[15] },
782 	{ 196, 4980, bwn_b2062_chantable_data[16] },
783 	{ 200, 5000, bwn_b2062_chantable_data[17] },
784 	{ 204, 5020, bwn_b2062_chantable_data[18] },
785 	{ 208, 5040, bwn_b2062_chantable_data[19] },
786 	{ 212, 5060, bwn_b2062_chantable_data[20] },
787 	{ 216, 5080, bwn_b2062_chantable_data[21] }
788 };
789 
790 /* for LP PHY */
791 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
792 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
793 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
794 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
795 	{ 13, -66, 13 }, { 14, -66, 13 },
796 };
797 
798 /* for LP PHY */
799 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
800 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
801 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
802 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
803 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
804 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
805 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
806 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
807 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
808 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
809 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
810 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
811 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
812 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
813 };
814 
815 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
816 
817 static const uint8_t bwn_tab_sigsq_tbl[] = {
818 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
819 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
820 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
821 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
822 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
823 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
824 };
825 
826 static const uint8_t bwn_tab_pllfrac_tbl[] = {
827 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
828 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
829 };
830 
831 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
832 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
833 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
834 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
836 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
837 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
838 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
840 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
841 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
842 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
843 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
844 };
845 
846 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
847 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
848 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
849 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
850 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
851 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
852 
853 #define	VENDOR_LED_ACT(vendor)				\
854 {							\
855 	.vid = PCI_VENDOR_##vendor,			\
856 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
857 }
858 
859 static const struct {
860 	uint16_t	vid;
861 	uint8_t		led_act[BWN_LED_MAX];
862 } bwn_vendor_led_act[] = {
863 	VENDOR_LED_ACT(COMPAQ),
864 	VENDOR_LED_ACT(ASUSTEK)
865 };
866 
867 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
868 	{ BWN_VENDOR_LED_ACT_DEFAULT };
869 
870 #undef VENDOR_LED_ACT
871 
872 static const struct {
873 	int		on_dur;
874 	int		off_dur;
875 } bwn_led_duration[109] = {
876 	[0]	= { 400, 100 },
877 	[2]	= { 150, 75 },
878 	[4]	= { 90, 45 },
879 	[11]	= { 66, 34 },
880 	[12]	= { 53, 26 },
881 	[18]	= { 42, 21 },
882 	[22]	= { 35, 17 },
883 	[24]	= { 32, 16 },
884 	[36]	= { 21, 10 },
885 	[48]	= { 16, 8 },
886 	[72]	= { 11, 5 },
887 	[96]	= { 9, 4 },
888 	[108]	= { 7, 3 }
889 };
890 
891 static const uint16_t bwn_wme_shm_offsets[] = {
892 	[0] = BWN_WME_BESTEFFORT,
893 	[1] = BWN_WME_BACKGROUND,
894 	[2] = BWN_WME_VOICE,
895 	[3] = BWN_WME_VIDEO,
896 };
897 
898 static const struct siba_devid bwn_devs[] = {
899 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
900 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
901 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
902 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
903 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
904 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
905 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
906 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
907 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
908 };
909 
910 static int
911 bwn_probe(device_t dev)
912 {
913 	struct siba_dev_softc *sd = device_get_ivars(dev);
914 	int i;
915 
916 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
917 		if (sd->sd_id.sd_vendor == bwn_devs[i].sd_vendor &&
918 		    sd->sd_id.sd_device == bwn_devs[i].sd_device &&
919 		    sd->sd_id.sd_rev == bwn_devs[i].sd_rev)
920 			return (BUS_PROBE_DEFAULT);
921 	}
922 
923 	return (ENXIO);
924 }
925 
926 static int
927 bwn_attach(device_t dev)
928 {
929 	struct bwn_mac *mac;
930 	struct bwn_softc *sc = device_get_softc(dev);
931 	struct siba_dev_softc *sd = device_get_ivars(dev);
932 	struct siba_softc *siba = sd->sd_bus;
933 	int error, i, msic, reg;
934 
935 	sc->sc_dev = dev;
936 	sc->sc_sd = sd;
937 #ifdef BWN_DEBUG
938 	sc->sc_debug = bwn_debug;
939 #endif
940 
941 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
942 		error = bwn_attach_pre(sc);
943 		if (error != 0)
944 			return (error);
945 		bwn_sprom_bugfixes(sd->sd_bus);
946 		sc->sc_flags |= BWN_FLAG_ATTACHED;
947 	}
948 
949 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
950 		if (siba->siba_pci_did != 0x4313 &&
951 		    siba->siba_pci_did != 0x431a &&
952 		    siba->siba_pci_did != 0x4321) {
953 			device_printf(sc->sc_dev,
954 			    "skip 802.11 cores\n");
955 			return (ENODEV);
956 		}
957 	}
958 
959 	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
960 	    M_NOWAIT | M_ZERO);
961 	if (mac == NULL)
962 		return (ENOMEM);
963 	mac->mac_sc = sc;
964 	mac->mac_sd = sd;
965 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
966 	if (bwn_bfp != 0)
967 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
968 
969 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
970 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
971 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
972 
973 	error = bwn_attach_core(mac);
974 	if (error)
975 		goto fail0;
976 	bwn_led_attach(mac);
977 
978 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
979 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
980 	    sd->sd_bus->siba_chipid, sd->sd_id.sd_rev,
981 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
982 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
983 	    mac->mac_phy.rf_rev);
984 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
985 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
986 		    mac->mac_method.dma.dmatype);
987 	else
988 		device_printf(sc->sc_dev, "PIO\n");
989 
990 	/*
991 	 * setup PCI resources and interrupt.
992 	 */
993 	if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
994 		msic = pci_msi_count(dev);
995 		if (bootverbose)
996 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
997 	} else
998 		msic = 0;
999 
1000 	mac->mac_intr_spec = bwn_res_spec_legacy;
1001 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
1002 		if (pci_alloc_msi(dev, &msic) == 0) {
1003 			device_printf(sc->sc_dev,
1004 			    "Using %d MSI messages\n", msic);
1005 			mac->mac_intr_spec = bwn_res_spec_msi;
1006 			mac->mac_msi = 1;
1007 		}
1008 	}
1009 
1010 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1011 	    mac->mac_res_irq);
1012 	if (error) {
1013 		device_printf(sc->sc_dev,
1014 		    "couldn't allocate IRQ resources (%d)\n", error);
1015 		goto fail1;
1016 	}
1017 
1018 	if (mac->mac_msi == 0)
1019 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1020 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1021 		    &mac->mac_intrhand[0]);
1022 	else {
1023 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1024 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1025 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1026 			    &mac->mac_intrhand[i]);
1027 			if (error != 0) {
1028 				device_printf(sc->sc_dev,
1029 				    "couldn't setup interrupt (%d)\n", error);
1030 				break;
1031 			}
1032 		}
1033 	}
1034 
1035 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1036 
1037 	/*
1038 	 * calls attach-post routine
1039 	 */
1040 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1041 		bwn_attach_post(sc);
1042 
1043 	return (0);
1044 fail1:
1045 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1046 		pci_release_msi(dev);
1047 fail0:
1048 	free(mac, M_DEVBUF);
1049 	return (error);
1050 }
1051 
1052 static int
1053 bwn_is_valid_ether_addr(uint8_t *addr)
1054 {
1055 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1056 
1057 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1058 		return (FALSE);
1059 
1060 	return (TRUE);
1061 }
1062 
1063 static int
1064 bwn_attach_post(struct bwn_softc *sc)
1065 {
1066 	struct ieee80211com *ic;
1067 	struct ifnet *ifp = sc->sc_ifp;
1068 	struct siba_dev_softc *sd = sc->sc_sd;
1069 	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
1070 
1071 	ic = ifp->if_l2com;
1072 	ic->ic_ifp = ifp;
1073 	/* XXX not right but it's not used anywhere important */
1074 	ic->ic_phytype = IEEE80211_T_OFDM;
1075 	ic->ic_opmode = IEEE80211_M_STA;
1076 	ic->ic_caps =
1077 		  IEEE80211_C_STA		/* station mode supported */
1078 		| IEEE80211_C_MONITOR		/* monitor mode */
1079 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1080 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1081 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1082 		| IEEE80211_C_WME		/* WME/WMM supported */
1083 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1084 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1085 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1086 		;
1087 
1088 	/* call MI attach routine. */
1089 	ieee80211_ifattach(ic,
1090 	    bwn_is_valid_ether_addr(sprom->mac_80211a) ? sprom->mac_80211a :
1091 	    sprom->mac_80211bg);
1092 
1093 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1094 
1095 	/* override default methods */
1096 	ic->ic_raw_xmit = bwn_raw_xmit;
1097 	ic->ic_newassoc = bwn_newassoc;
1098 	ic->ic_updateslot = bwn_updateslot;
1099 	ic->ic_update_promisc = bwn_update_promisc;
1100 	ic->ic_wme.wme_update = bwn_wme_update;
1101 
1102 	ic->ic_node_alloc = bwn_node_alloc;
1103 	sc->sc_node_cleanup = ic->ic_node_cleanup;
1104 	ic->ic_node_cleanup = bwn_node_cleanup;
1105 
1106 	ic->ic_scan_start = bwn_scan_start;
1107 	ic->ic_scan_end = bwn_scan_end;
1108 	ic->ic_set_channel = bwn_set_channel;
1109 
1110 	ic->ic_vap_create = bwn_vap_create;
1111 	ic->ic_vap_delete = bwn_vap_delete;
1112 
1113 	ieee80211_radiotap_attach(ic,
1114 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1115 	    BWN_TX_RADIOTAP_PRESENT,
1116 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1117 	    BWN_RX_RADIOTAP_PRESENT);
1118 
1119 	bwn_sysctl_node(sc);
1120 
1121 	if (bootverbose)
1122 		ieee80211_announce(ic);
1123 	return (0);
1124 }
1125 
1126 static void
1127 bwn_phy_detach(struct bwn_mac *mac)
1128 {
1129 
1130 	if (mac->mac_phy.detach != NULL)
1131 		mac->mac_phy.detach(mac);
1132 }
1133 
1134 static int
1135 bwn_detach(device_t dev)
1136 {
1137 	struct bwn_softc *sc = device_get_softc(dev);
1138 	struct bwn_mac *mac = sc->sc_curmac;
1139 	struct ifnet *ifp = sc->sc_ifp;
1140 	struct ieee80211com *ic = ifp->if_l2com;
1141 	int i;
1142 
1143 	sc->sc_flags |= BWN_FLAG_INVALID;
1144 
1145 	if (device_is_attached(sc->sc_dev)) {
1146 		bwn_stop(sc, 1);
1147 		bwn_dma_free(mac);
1148 		callout_drain(&sc->sc_led_blink_ch);
1149 		callout_drain(&sc->sc_rfswitch_ch);
1150 		callout_drain(&sc->sc_task_ch);
1151 		callout_drain(&sc->sc_watchdog_ch);
1152 		bwn_phy_detach(mac);
1153 		if (ifp != NULL) {
1154 			ieee80211_draintask(ic, &mac->mac_hwreset);
1155 			ieee80211_draintask(ic, &mac->mac_txpower);
1156 			ieee80211_ifdetach(ic);
1157 			if_free(ifp);
1158 		}
1159 	}
1160 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1161 	taskqueue_free(sc->sc_tq);
1162 
1163 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1164 		if (mac->mac_intrhand[i] != NULL) {
1165 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1166 			    mac->mac_intrhand[i]);
1167 			mac->mac_intrhand[i] = NULL;
1168 		}
1169 	}
1170 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1171 	if (mac->mac_msi != 0)
1172 		pci_release_msi(dev);
1173 
1174 	BWN_LOCK_DESTROY(sc);
1175 	return (0);
1176 }
1177 
1178 static int
1179 bwn_attach_pre(struct bwn_softc *sc)
1180 {
1181 	struct ifnet *ifp;
1182 	int error = 0;
1183 
1184 	BWN_LOCK_INIT(sc);
1185 	TAILQ_INIT(&sc->sc_maclist);
1186 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1187 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1188 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1189 
1190 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1191 		taskqueue_thread_enqueue, &sc->sc_tq);
1192 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1193 		"%s taskq", device_get_nameunit(sc->sc_dev));
1194 
1195 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1196 	if (ifp == NULL) {
1197 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1198 		error = ENOSPC;
1199 		goto fail;
1200 	}
1201 
1202 	/* set these up early for if_printf use */
1203 	if_initname(ifp, device_get_name(sc->sc_dev),
1204 	    device_get_unit(sc->sc_dev));
1205 
1206 	ifp->if_softc = sc;
1207 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1208 	ifp->if_init = bwn_init;
1209 	ifp->if_ioctl = bwn_ioctl;
1210 	ifp->if_start = bwn_start;
1211 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1212 	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1213 	IFQ_SET_READY(&ifp->if_snd);
1214 
1215 	return (0);
1216 
1217 fail:	BWN_LOCK_DESTROY(sc);
1218 	return (error);
1219 }
1220 
1221 static void
1222 bwn_sprom_bugfixes(struct siba_softc *siba)
1223 {
1224 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1225 	((siba->siba_pci_vid == PCI_VENDOR_##_vendor) &&		\
1226 	 (siba->siba_pci_did == _device) &&				\
1227 	 (siba->siba_pci_subvid == PCI_VENDOR_##_subvendor) &&		\
1228 	 (siba->siba_pci_subdid == _subdevice))
1229 
1230 	if (siba->siba_board_vendor == PCI_VENDOR_APPLE &&
1231 	    siba->siba_board_type == 0x4e && siba->siba_board_rev > 0x40)
1232 		siba->siba_sprom.bf_lo |= BWN_BFL_PACTRL;
1233 	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_DELL &&
1234 	    siba->siba_chipid == 0x4301 && siba->siba_board_rev == 0x74)
1235 		siba->siba_sprom.bf_lo |= BWN_BFL_BTCOEXIST;
1236 	if (siba->siba_type == SIBA_TYPE_PCI) {
1237 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1238 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1239 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1240 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1241 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1242 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1243 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1244 			siba->siba_sprom.bf_lo &= ~BWN_BFL_BTCOEXIST;
1245 	}
1246 #undef	BWN_ISDEV
1247 }
1248 
1249 static int
1250 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1251 {
1252 #define	IS_RUNNING(ifp) \
1253 	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1254 	struct bwn_softc *sc = ifp->if_softc;
1255 	struct ieee80211com *ic = ifp->if_l2com;
1256 	struct ifreq *ifr = (struct ifreq *)data;
1257 	int error = 0, startall;
1258 
1259 	switch (cmd) {
1260 	case SIOCSIFFLAGS:
1261 		startall = 0;
1262 		if (IS_RUNNING(ifp)) {
1263 			bwn_update_promisc(ifp);
1264 		} else if (ifp->if_flags & IFF_UP) {
1265 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1266 				bwn_init(sc);
1267 				startall = 1;
1268 			}
1269 		} else
1270 			bwn_stop(sc, 1);
1271 		if (startall)
1272 			ieee80211_start_all(ic);
1273 		break;
1274 	case SIOCGIFMEDIA:
1275 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1276 		break;
1277 	case SIOCGIFADDR:
1278 		error = ether_ioctl(ifp, cmd, data);
1279 		break;
1280 	default:
1281 		error = EINVAL;
1282 		break;
1283 	}
1284 	return (error);
1285 }
1286 
1287 static void
1288 bwn_start(struct ifnet *ifp)
1289 {
1290 	struct bwn_softc *sc = ifp->if_softc;
1291 
1292 	BWN_LOCK(sc);
1293 	bwn_start_locked(ifp);
1294 	BWN_UNLOCK(sc);
1295 }
1296 
1297 static void
1298 bwn_start_locked(struct ifnet *ifp)
1299 {
1300 	struct bwn_softc *sc = ifp->if_softc;
1301 	struct bwn_mac *mac = sc->sc_curmac;
1302 	struct ieee80211_frame *wh;
1303 	struct ieee80211_node *ni;
1304 	struct ieee80211_key *k;
1305 	struct mbuf *m;
1306 
1307 	BWN_ASSERT_LOCKED(sc);
1308 
1309 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1310 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1311 		return;
1312 
1313 	for (;;) {
1314 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1315 		if (m == NULL)
1316 			break;
1317 
1318 		if (bwn_tx_isfull(sc, m))
1319 			break;
1320 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1321 		if (ni == NULL) {
1322 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1323 			m_freem(m);
1324 			ifp->if_oerrors++;
1325 			continue;
1326 		}
1327 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1328 		wh = mtod(m, struct ieee80211_frame *);
1329 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1330 			k = ieee80211_crypto_encap(ni, m);
1331 			if (k == NULL) {
1332 				ieee80211_free_node(ni);
1333 				m_freem(m);
1334 				ifp->if_oerrors++;
1335 				continue;
1336 			}
1337 		}
1338 		wh = NULL;	/* Catch any invalid use */
1339 
1340 		if (bwn_tx_start(sc, ni, m) != 0) {
1341 			if (ni != NULL)
1342 				ieee80211_free_node(ni);
1343 			ifp->if_oerrors++;
1344 			continue;
1345 		}
1346 
1347 		sc->sc_watchdog_timer = 5;
1348 	}
1349 }
1350 
1351 static int
1352 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1353 {
1354 	struct bwn_dma_ring *dr;
1355 	struct bwn_mac *mac = sc->sc_curmac;
1356 	struct bwn_pio_txqueue *tq;
1357 	struct ifnet *ifp = sc->sc_ifp;
1358 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1359 
1360 	BWN_ASSERT_LOCKED(sc);
1361 
1362 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1363 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1364 		if (dr->dr_stop == 1 ||
1365 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1366 			dr->dr_stop = 1;
1367 			goto full;
1368 		}
1369 	} else {
1370 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1371 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1372 		    pktlen > (tq->tq_size - tq->tq_used)) {
1373 			tq->tq_stop = 1;
1374 			goto full;
1375 		}
1376 	}
1377 	return (0);
1378 full:
1379 	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1380 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1381 	return (1);
1382 }
1383 
1384 static int
1385 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1386 {
1387 	struct bwn_mac *mac = sc->sc_curmac;
1388 	int error;
1389 
1390 	BWN_ASSERT_LOCKED(sc);
1391 
1392 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1393 		m_freem(m);
1394 		return (ENXIO);
1395 	}
1396 
1397 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1398 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1399 	if (error) {
1400 		m_freem(m);
1401 		return (error);
1402 	}
1403 	return (0);
1404 }
1405 
1406 static int
1407 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1408 {
1409 	struct bwn_pio_txpkt *tp;
1410 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1411 	struct bwn_softc *sc = mac->mac_sc;
1412 	struct bwn_txhdr txhdr;
1413 	struct mbuf *m_new;
1414 	uint32_t ctl32;
1415 	int error;
1416 	uint16_t ctl16;
1417 
1418 	BWN_ASSERT_LOCKED(sc);
1419 
1420 	/* XXX TODO send packets after DTIM */
1421 
1422 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1423 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1424 	tp->tp_ni = ni;
1425 	tp->tp_m = m;
1426 
1427 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1428 	if (error) {
1429 		device_printf(sc->sc_dev, "tx fail\n");
1430 		return (error);
1431 	}
1432 
1433 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1434 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1435 	tq->tq_free--;
1436 
1437 	if (mac->mac_sd->sd_id.sd_rev >= 8) {
1438 		/*
1439 		 * XXX please removes m_defrag(9)
1440 		 */
1441 		m_new = m_defrag(m, M_DONTWAIT);
1442 		if (m_new == NULL) {
1443 			device_printf(sc->sc_dev,
1444 			    "%s: can't defrag TX buffer\n",
1445 			    __func__);
1446 			return (ENOBUFS);
1447 		}
1448 		if (m_new->m_next != NULL)
1449 			device_printf(sc->sc_dev,
1450 			    "TODO: fragmented packets for PIO\n");
1451 		tp->tp_m = m_new;
1452 
1453 		/* send HEADER */
1454 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1455 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1456 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1457 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458 		/* send BODY */
1459 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1460 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1461 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1462 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1463 	} else {
1464 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1465 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1466 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1467 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1468 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1469 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1470 		    ctl16 | BWN_PIO_TXCTL_EOF);
1471 	}
1472 
1473 	return (0);
1474 }
1475 
1476 static struct bwn_pio_txqueue *
1477 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1478 {
1479 
1480 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1481 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1482 
1483 	switch (prio) {
1484 	case 0:
1485 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1486 	case 1:
1487 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1488 	case 2:
1489 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1490 	case 3:
1491 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1492 	}
1493 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1494 	return (NULL);
1495 }
1496 
1497 static int
1498 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1499 {
1500 #define	BWN_GET_TXHDRCACHE(slot)					\
1501 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1502 	struct bwn_dma *dma = &mac->mac_method.dma;
1503 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1504 	struct bwn_dmadesc_generic *desc;
1505 	struct bwn_dmadesc_meta *mt;
1506 	struct bwn_softc *sc = mac->mac_sc;
1507 	struct ifnet *ifp = sc->sc_ifp;
1508 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1509 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1510 
1511 	BWN_ASSERT_LOCKED(sc);
1512 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1513 
1514 	/* XXX send after DTIM */
1515 
1516 	slot = bwn_dma_getslot(dr);
1517 	dr->getdesc(dr, slot, &desc, &mt);
1518 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1519 	    ("%s:%d: fail", __func__, __LINE__));
1520 
1521 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1522 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1523 	    BWN_DMA_COOKIE(dr, slot));
1524 	if (error)
1525 		goto fail;
1526 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1527 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1528 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1529 	if (error) {
1530 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1531 		    __func__, error);
1532 		goto fail;
1533 	}
1534 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1535 	    BUS_DMASYNC_PREWRITE);
1536 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1537 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1538 	    BUS_DMASYNC_PREWRITE);
1539 
1540 	slot = bwn_dma_getslot(dr);
1541 	dr->getdesc(dr, slot, &desc, &mt);
1542 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1543 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1544 	mt->mt_m = m;
1545 	mt->mt_ni = ni;
1546 
1547 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1548 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1549 	if (error && error != EFBIG) {
1550 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1551 		    __func__, error);
1552 		goto fail;
1553 	}
1554 	if (error) {    /* error == EFBIG */
1555 		struct mbuf *m_new;
1556 
1557 		m_new = m_defrag(m, M_DONTWAIT);
1558 		if (m_new == NULL) {
1559 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1560 			    __func__);
1561 			error = ENOBUFS;
1562 			goto fail;
1563 		} else {
1564 			m = m_new;
1565 		}
1566 
1567 		mt->mt_m = m;
1568 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1569 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1570 		if (error) {
1571 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1572 			    __func__, error);
1573 			goto fail;
1574 		}
1575 	}
1576 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1577 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1578 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1579 	    BUS_DMASYNC_PREWRITE);
1580 
1581 	/* XXX send after DTIM */
1582 
1583 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1584 	return (0);
1585 fail:
1586 	dr->dr_curslot = backup[0];
1587 	dr->dr_usedslot = backup[1];
1588 	return (error);
1589 #undef BWN_GET_TXHDRCACHE
1590 }
1591 
1592 static void
1593 bwn_watchdog(void *arg)
1594 {
1595 	struct bwn_softc *sc = arg;
1596 	struct ifnet *ifp = sc->sc_ifp;
1597 
1598 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1599 		if_printf(ifp, "device timeout\n");
1600 		ifp->if_oerrors++;
1601 	}
1602 	callout_schedule(&sc->sc_watchdog_ch, hz);
1603 }
1604 
1605 static int
1606 bwn_attach_core(struct bwn_mac *mac)
1607 {
1608 	struct bwn_softc *sc = mac->mac_sc;
1609 	struct siba_dev_softc *sd = mac->mac_sd;
1610 	struct siba_softc *siba = sd->sd_bus;
1611 	int error, have_bg = 0, have_a = 0;
1612 	uint32_t high;
1613 
1614 	KASSERT(sd->sd_id.sd_rev >= 5,
1615 	    ("unsupported revision %d", sd->sd_id.sd_rev));
1616 
1617 	siba_powerup(siba, 0);
1618 
1619 	high = siba_read_4(sd, SIBA_TGSHIGH);
1620 	bwn_reset_core(mac,
1621 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1622 	error = bwn_phy_getinfo(mac, high);
1623 	if (error)
1624 		goto fail;
1625 
1626 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1627 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1628 	if (siba->siba_pci_did != 0x4312 && siba->siba_pci_did != 0x4319 &&
1629 	    siba->siba_pci_did != 0x4324) {
1630 		have_a = have_bg = 0;
1631 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1632 			have_a = 1;
1633 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1634 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1635 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1636 			have_bg = 1;
1637 		else
1638 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1639 			    mac->mac_phy.type));
1640 	}
1641 	/* XXX turns off PHY A because it's not supported */
1642 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1643 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1644 		have_a = 0;
1645 		have_bg = 1;
1646 	}
1647 
1648 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1649 		mac->mac_phy.attach = bwn_phy_g_attach;
1650 		mac->mac_phy.detach = bwn_phy_g_detach;
1651 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1652 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1653 		mac->mac_phy.init = bwn_phy_g_init;
1654 		mac->mac_phy.exit = bwn_phy_g_exit;
1655 		mac->mac_phy.phy_read = bwn_phy_g_read;
1656 		mac->mac_phy.phy_write = bwn_phy_g_write;
1657 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1658 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1659 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1660 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1661 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1662 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1663 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1664 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1665 		mac->mac_phy.set_im = bwn_phy_g_im;
1666 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1667 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1668 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1669 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1670 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1671 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1672 		mac->mac_phy.init = bwn_phy_lp_init;
1673 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1674 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1675 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1676 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1677 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1678 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1679 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1680 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1681 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1682 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1683 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1684 	} else {
1685 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1686 		    mac->mac_phy.type);
1687 		error = ENXIO;
1688 		goto fail;
1689 	}
1690 
1691 	mac->mac_phy.gmode = have_bg;
1692 	if (mac->mac_phy.attach != NULL) {
1693 		error = mac->mac_phy.attach(mac);
1694 		if (error) {
1695 			device_printf(sc->sc_dev, "failed\n");
1696 			goto fail;
1697 		}
1698 	}
1699 
1700 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1701 
1702 	error = bwn_chiptest(mac);
1703 	if (error)
1704 		goto fail;
1705 	error = bwn_setup_channels(mac, have_bg, have_a);
1706 	if (error) {
1707 		device_printf(sc->sc_dev, "failed to setup channels\n");
1708 		goto fail;
1709 	}
1710 
1711 	if (sc->sc_curmac == NULL)
1712 		sc->sc_curmac = mac;
1713 
1714 	error = bwn_dma_attach(mac);
1715 	if (error != 0) {
1716 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1717 		goto fail;
1718 	}
1719 
1720 	mac->mac_phy.switch_analog(mac, 0);
1721 
1722 	siba_dev_down(sd, 0);
1723 fail:
1724 	siba_powerdown(siba);
1725 	return (error);
1726 }
1727 
1728 static void
1729 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1730 {
1731 	struct siba_dev_softc *sd = mac->mac_sd;
1732 	uint32_t low, ctl;
1733 
1734 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1735 
1736 	siba_dev_up(sd, flags);
1737 	DELAY(2000);
1738 
1739 	low = (siba_read_4(sd, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1740 	    ~BWN_TGSLOW_PHYRESET;
1741 	siba_write_4(sd, SIBA_TGSLOW, low);
1742 	siba_read_4(sd, SIBA_TGSLOW);
1743 	DELAY(1000);
1744 	siba_write_4(sd, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1745 	siba_read_4(sd, SIBA_TGSLOW);
1746 	DELAY(1000);
1747 
1748 	if (mac->mac_phy.switch_analog != NULL)
1749 		mac->mac_phy.switch_analog(mac, 1);
1750 
1751 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1752 	if (flags & BWN_TGSLOW_SUPPORT_G)
1753 		ctl |= BWN_MACCTL_GMODE;
1754 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1755 }
1756 
1757 static int
1758 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1759 {
1760 	struct bwn_phy *phy = &mac->mac_phy;
1761 	struct bwn_softc *sc = mac->mac_sc;
1762 	struct siba_dev_softc *sd = mac->mac_sd;
1763 	struct siba_softc *siba = sd->sd_bus;
1764 	uint32_t tmp;
1765 
1766 	/* PHY */
1767 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1768 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1769 	phy->rf_on = 1;
1770 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1771 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1772 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1773 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1774 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1775 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1776 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1777 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1778 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1779 		goto unsupphy;
1780 
1781 	/* RADIO */
1782 	if (siba->siba_chipid == 0x4317) {
1783 		if (siba->siba_chiprev == 0)
1784 			tmp = 0x3205017f;
1785 		else if (siba->siba_chiprev == 1)
1786 			tmp = 0x4205017f;
1787 		else
1788 			tmp = 0x5205017f;
1789 	} else {
1790 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1791 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1792 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1793 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1794 	}
1795 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1796 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1797 	phy->rf_manuf = (tmp & 0x00000fff);
1798 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1799 		goto unsupradio;
1800 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1801 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1802 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1803 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1804 	    (phy->type == BWN_PHYTYPE_N &&
1805 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1806 	    (phy->type == BWN_PHYTYPE_LP &&
1807 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1808 		goto unsupradio;
1809 
1810 	return (0);
1811 unsupphy:
1812 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1813 	    "analog %#x)\n",
1814 	    phy->type, phy->rev, phy->analog);
1815 	return (ENXIO);
1816 unsupradio:
1817 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1818 	    "rev %#x)\n",
1819 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1820 	return (ENXIO);
1821 }
1822 
1823 static int
1824 bwn_chiptest(struct bwn_mac *mac)
1825 {
1826 #define	TESTVAL0	0x55aaaa55
1827 #define	TESTVAL1	0xaa5555aa
1828 	struct bwn_softc *sc = mac->mac_sc;
1829 	struct siba_dev_softc *sd = mac->mac_sd;
1830 	uint32_t v, backup;
1831 
1832 	BWN_LOCK(sc);
1833 
1834 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1835 
1836 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1837 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1838 		goto error;
1839 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1840 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1841 		goto error;
1842 
1843 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1844 
1845 	if ((sd->sd_id.sd_rev >= 3) && (sd->sd_id.sd_rev <= 10)) {
1846 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1847 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1848 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1849 			goto error;
1850 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1851 			goto error;
1852 	}
1853 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1854 
1855 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1856 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1857 		goto error;
1858 
1859 	BWN_UNLOCK(sc);
1860 	return (0);
1861 error:
1862 	BWN_UNLOCK(sc);
1863 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1864 	return (ENODEV);
1865 }
1866 
1867 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1868 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1869 
1870 static int
1871 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1872 {
1873 	struct bwn_softc *sc = mac->mac_sc;
1874 	struct ifnet *ifp = sc->sc_ifp;
1875 	struct ieee80211com *ic = ifp->if_l2com;
1876 
1877 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1878 	ic->ic_nchans = 0;
1879 
1880 	if (have_bg)
1881 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1882 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1883 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1884 		if (have_a)
1885 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1886 			    &ic->ic_nchans, &bwn_chantable_n,
1887 			    IEEE80211_CHAN_HTA);
1888 	} else {
1889 		if (have_a)
1890 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1891 			    &ic->ic_nchans, &bwn_chantable_a,
1892 			    IEEE80211_CHAN_A);
1893 	}
1894 
1895 	mac->mac_phy.supports_2ghz = have_bg;
1896 	mac->mac_phy.supports_5ghz = have_a;
1897 
1898 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1899 }
1900 
1901 static uint32_t
1902 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1903 {
1904 	uint32_t ret;
1905 
1906 	BWN_ASSERT_LOCKED(mac->mac_sc);
1907 
1908 	if (way == BWN_SHARED) {
1909 		KASSERT((offset & 0x0001) == 0,
1910 		    ("%s:%d warn", __func__, __LINE__));
1911 		if (offset & 0x0003) {
1912 			bwn_shm_ctlword(mac, way, offset >> 2);
1913 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1914 			ret <<= 16;
1915 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1916 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1917 			goto out;
1918 		}
1919 		offset >>= 2;
1920 	}
1921 	bwn_shm_ctlword(mac, way, offset);
1922 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1923 out:
1924 	return (ret);
1925 }
1926 
1927 static uint16_t
1928 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1929 {
1930 	uint16_t ret;
1931 
1932 	BWN_ASSERT_LOCKED(mac->mac_sc);
1933 
1934 	if (way == BWN_SHARED) {
1935 		KASSERT((offset & 0x0001) == 0,
1936 		    ("%s:%d warn", __func__, __LINE__));
1937 		if (offset & 0x0003) {
1938 			bwn_shm_ctlword(mac, way, offset >> 2);
1939 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1940 			goto out;
1941 		}
1942 		offset >>= 2;
1943 	}
1944 	bwn_shm_ctlword(mac, way, offset);
1945 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1946 out:
1947 
1948 	return (ret);
1949 }
1950 
1951 static void
1952 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1953     uint16_t offset)
1954 {
1955 	uint32_t control;
1956 
1957 	control = way;
1958 	control <<= 16;
1959 	control |= offset;
1960 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1961 }
1962 
1963 static void
1964 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1965     uint32_t value)
1966 {
1967 	BWN_ASSERT_LOCKED(mac->mac_sc);
1968 
1969 	if (way == BWN_SHARED) {
1970 		KASSERT((offset & 0x0001) == 0,
1971 		    ("%s:%d warn", __func__, __LINE__));
1972 		if (offset & 0x0003) {
1973 			bwn_shm_ctlword(mac, way, offset >> 2);
1974 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1975 				    (value >> 16) & 0xffff);
1976 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1977 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1978 			return;
1979 		}
1980 		offset >>= 2;
1981 	}
1982 	bwn_shm_ctlword(mac, way, offset);
1983 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1984 }
1985 
1986 static void
1987 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1988     uint16_t value)
1989 {
1990 	BWN_ASSERT_LOCKED(mac->mac_sc);
1991 
1992 	if (way == BWN_SHARED) {
1993 		KASSERT((offset & 0x0001) == 0,
1994 		    ("%s:%d warn", __func__, __LINE__));
1995 		if (offset & 0x0003) {
1996 			bwn_shm_ctlword(mac, way, offset >> 2);
1997 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1998 			return;
1999 		}
2000 		offset >>= 2;
2001 	}
2002 	bwn_shm_ctlword(mac, way, offset);
2003 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
2004 }
2005 
2006 static void
2007 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
2008     int txpow)
2009 {
2010 
2011 	c->ic_freq = freq;
2012 	c->ic_flags = flags;
2013 	c->ic_ieee = ieee;
2014 	c->ic_minpower = 0;
2015 	c->ic_maxpower = 2 * txpow;
2016 	c->ic_maxregpower = txpow;
2017 }
2018 
2019 static void
2020 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2021     const struct bwn_channelinfo *ci, int flags)
2022 {
2023 	struct ieee80211_channel *c;
2024 	int i;
2025 
2026 	c = &chans[*nchans];
2027 
2028 	for (i = 0; i < ci->nchannels; i++) {
2029 		const struct bwn_channel *hc;
2030 
2031 		hc = &ci->channels[i];
2032 		if (*nchans >= maxchans)
2033 			break;
2034 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2035 		c++, (*nchans)++;
2036 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2037 			/* g channel have a separate b-only entry */
2038 			if (*nchans >= maxchans)
2039 				break;
2040 			c[0] = c[-1];
2041 			c[-1].ic_flags = IEEE80211_CHAN_B;
2042 			c++, (*nchans)++;
2043 		}
2044 		if (flags == IEEE80211_CHAN_HTG) {
2045 			/* HT g channel have a separate g-only entry */
2046 			if (*nchans >= maxchans)
2047 				break;
2048 			c[-1].ic_flags = IEEE80211_CHAN_G;
2049 			c[0] = c[-1];
2050 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2051 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2052 			c++, (*nchans)++;
2053 		}
2054 		if (flags == IEEE80211_CHAN_HTA) {
2055 			/* HT a channel have a separate a-only entry */
2056 			if (*nchans >= maxchans)
2057 				break;
2058 			c[-1].ic_flags = IEEE80211_CHAN_A;
2059 			c[0] = c[-1];
2060 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2061 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2062 			c++, (*nchans)++;
2063 		}
2064 	}
2065 }
2066 
2067 static int
2068 bwn_phy_g_attach(struct bwn_mac *mac)
2069 {
2070 	struct bwn_softc *sc = mac->mac_sc;
2071 	struct bwn_phy *phy = &mac->mac_phy;
2072 	struct bwn_phy_g *pg = &phy->phy_g;
2073 	struct siba_dev_softc *sd = mac->mac_sd;
2074 	struct siba_sprom *sprom = &sd->sd_bus->siba_sprom;
2075 	unsigned int i;
2076 	int16_t pab0 = (int16_t)(sprom->pa0b0), pab1 = (int16_t)(sprom->pa0b1),
2077 	    pab2 = (int16_t)(sprom->pa0b2);
2078 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2079 	int8_t bg = (int8_t)sprom->tssi_bg;
2080 
2081 	if ((sd->sd_bus->siba_chipid == 0x4301) && (phy->rf_ver != 0x2050))
2082 		device_printf(sc->sc_dev, "not supported anymore\n");
2083 
2084 	pg->pg_flags = 0;
2085 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2086 	    pab2 == -1) {
2087 		pg->pg_idletssi = 52;
2088 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2089 		return (0);
2090 	}
2091 
2092 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2093 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2094 	if (pg->pg_tssi2dbm == NULL) {
2095 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2096 		return (ENOMEM);
2097 	}
2098 	for (i = 0; i < 64; i++) {
2099 		int32_t m1, m2, f, q, delta;
2100 		int8_t j = 0;
2101 
2102 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2103 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2104 		f = 256;
2105 
2106 		do {
2107 			if (j > 15) {
2108 				device_printf(sc->sc_dev,
2109 				    "failed to generate tssi2dBm\n");
2110 				free(pg->pg_tssi2dbm, M_DEVBUF);
2111 				return (ENOMEM);
2112 			}
2113 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2114 			    f, 2048);
2115 			delta = abs(q - f);
2116 			f = q;
2117 			j++;
2118 		} while (delta >= 2);
2119 
2120 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2121 		    128);
2122 	}
2123 
2124 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2125 	return (0);
2126 }
2127 
2128 static void
2129 bwn_phy_g_detach(struct bwn_mac *mac)
2130 {
2131 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2132 
2133 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2134 		free(pg->pg_tssi2dbm, M_DEVBUF);
2135 		pg->pg_tssi2dbm = NULL;
2136 	}
2137 	pg->pg_flags = 0;
2138 }
2139 
2140 static void
2141 bwn_phy_g_init_pre(struct bwn_mac *mac)
2142 {
2143 	struct bwn_phy *phy = &mac->mac_phy;
2144 	struct bwn_phy_g *pg = &phy->phy_g;
2145 	void *tssi2dbm;
2146 	int idletssi;
2147 	unsigned int i;
2148 
2149 	tssi2dbm = pg->pg_tssi2dbm;
2150 	idletssi = pg->pg_idletssi;
2151 
2152 	memset(pg, 0, sizeof(*pg));
2153 
2154 	pg->pg_tssi2dbm = tssi2dbm;
2155 	pg->pg_idletssi = idletssi;
2156 
2157 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2158 
2159 	for (i = 0; i < N(pg->pg_nrssi); i++)
2160 		pg->pg_nrssi[i] = -1000;
2161 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2162 		pg->pg_nrssi_lt[i] = i;
2163 	pg->pg_lofcal = 0xffff;
2164 	pg->pg_initval = 0xffff;
2165 	pg->pg_immode = BWN_IMMODE_NONE;
2166 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2167 	pg->pg_avgtssi = 0xff;
2168 
2169 	pg->pg_loctl.tx_bias = 0xff;
2170 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2171 }
2172 
2173 static int
2174 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2175 {
2176 	struct bwn_phy *phy = &mac->mac_phy;
2177 	struct bwn_phy_g *pg = &phy->phy_g;
2178 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2179 	struct siba_softc *bus = mac->mac_sd->sd_bus;
2180 	static const struct bwn_rfatt rfatt0[] = {
2181 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2182 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2183 		{ 3, 1 }, { 4, 1 }
2184 	};
2185 	static const struct bwn_rfatt rfatt1[] = {
2186 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2187 		{ 14, 1 }
2188 	};
2189 	static const struct bwn_rfatt rfatt2[] = {
2190 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2191 		{ 9, 1 }
2192 	};
2193 	static const struct bwn_bbatt bbatt_0[] = {
2194 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2195 	};
2196 
2197 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2198 
2199 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2200 		pg->pg_bbatt.att = 0;
2201 	else
2202 		pg->pg_bbatt.att = 2;
2203 
2204 	/* prepare Radio Attenuation */
2205 	pg->pg_rfatt.padmix = 0;
2206 
2207 	if (bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
2208 	    bus->siba_board_type == SIBA_BOARD_BCM4309G) {
2209 		if (bus->siba_board_rev < 0x43) {
2210 			pg->pg_rfatt.att = 2;
2211 			goto done;
2212 		} else if (bus->siba_board_rev < 0x51) {
2213 			pg->pg_rfatt.att = 3;
2214 			goto done;
2215 		}
2216 	}
2217 
2218 	if (phy->type == BWN_PHYTYPE_A) {
2219 		pg->pg_rfatt.att = 0x60;
2220 		goto done;
2221 	}
2222 
2223 	switch (phy->rf_ver) {
2224 	case 0x2050:
2225 		switch (phy->rf_rev) {
2226 		case 0:
2227 			pg->pg_rfatt.att = 5;
2228 			goto done;
2229 		case 1:
2230 			if (phy->type == BWN_PHYTYPE_G) {
2231 				if (bus->siba_board_vendor ==
2232 				    SIBA_BOARDVENDOR_BCM &&
2233 				    bus->siba_board_type ==
2234 				    SIBA_BOARD_BCM4309G &&
2235 				    bus->siba_board_rev >= 30)
2236 					pg->pg_rfatt.att = 3;
2237 				else if (bus->siba_board_vendor ==
2238 				    SIBA_BOARDVENDOR_BCM &&
2239 				    bus->siba_board_type == SIBA_BOARD_BU4306)
2240 					pg->pg_rfatt.att = 3;
2241 				else
2242 					pg->pg_rfatt.att = 1;
2243 			} else {
2244 				if (bus->siba_board_vendor ==
2245 				    SIBA_BOARDVENDOR_BCM &&
2246 				    bus->siba_board_type ==
2247 				    SIBA_BOARD_BCM4309G &&
2248 				    bus->siba_board_rev >= 30)
2249 					pg->pg_rfatt.att = 7;
2250 				else
2251 					pg->pg_rfatt.att = 6;
2252 			}
2253 			goto done;
2254 		case 2:
2255 			if (phy->type == BWN_PHYTYPE_G) {
2256 				if (bus->siba_board_vendor ==
2257 				    SIBA_BOARDVENDOR_BCM &&
2258 				    bus->siba_board_type ==
2259 				    SIBA_BOARD_BCM4309G &&
2260 				    bus->siba_board_rev >= 30)
2261 					pg->pg_rfatt.att = 3;
2262 				else if (bus->siba_board_vendor ==
2263 				    SIBA_BOARDVENDOR_BCM &&
2264 				    bus->siba_board_type == SIBA_BOARD_BU4306)
2265 					pg->pg_rfatt.att = 5;
2266 				else if (bus->siba_chipid == 0x4320)
2267 					pg->pg_rfatt.att = 4;
2268 				else
2269 					pg->pg_rfatt.att = 3;
2270 			} else
2271 				pg->pg_rfatt.att = 6;
2272 			goto done;
2273 		case 3:
2274 			pg->pg_rfatt.att = 5;
2275 			goto done;
2276 		case 4:
2277 		case 5:
2278 			pg->pg_rfatt.att = 1;
2279 			goto done;
2280 		case 6:
2281 		case 7:
2282 			pg->pg_rfatt.att = 5;
2283 			goto done;
2284 		case 8:
2285 			pg->pg_rfatt.att = 0xa;
2286 			pg->pg_rfatt.padmix = 1;
2287 			goto done;
2288 		case 9:
2289 		default:
2290 			pg->pg_rfatt.att = 5;
2291 			goto done;
2292 		}
2293 		break;
2294 	case 0x2053:
2295 		switch (phy->rf_rev) {
2296 		case 1:
2297 			pg->pg_rfatt.att = 6;
2298 			goto done;
2299 		}
2300 		break;
2301 	}
2302 	pg->pg_rfatt.att = 5;
2303 done:
2304 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2305 
2306 	if (!bwn_has_hwpctl(mac)) {
2307 		lo->rfatt.array = rfatt0;
2308 		lo->rfatt.len = N(rfatt0);
2309 		lo->rfatt.min = 0;
2310 		lo->rfatt.max = 9;
2311 		goto genbbatt;
2312 	}
2313 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2314 		lo->rfatt.array = rfatt1;
2315 		lo->rfatt.len = N(rfatt1);
2316 		lo->rfatt.min = 0;
2317 		lo->rfatt.max = 14;
2318 		goto genbbatt;
2319 	}
2320 	lo->rfatt.array = rfatt2;
2321 	lo->rfatt.len = N(rfatt2);
2322 	lo->rfatt.min = 0;
2323 	lo->rfatt.max = 9;
2324 genbbatt:
2325 	lo->bbatt.array = bbatt_0;
2326 	lo->bbatt.len = N(bbatt_0);
2327 	lo->bbatt.min = 0;
2328 	lo->bbatt.max = 8;
2329 
2330 	BWN_READ_4(mac, BWN_MACCTL);
2331 	if (phy->rev == 1) {
2332 		phy->gmode = 0;
2333 		bwn_reset_core(mac, 0);
2334 		bwn_phy_g_init_sub(mac);
2335 		phy->gmode = 1;
2336 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2337 	}
2338 	return (0);
2339 }
2340 
2341 static uint16_t
2342 bwn_phy_g_txctl(struct bwn_mac *mac)
2343 {
2344 	struct bwn_phy *phy = &mac->mac_phy;
2345 
2346 	if (phy->rf_ver != 0x2050)
2347 		return (0);
2348 	if (phy->rf_rev == 1)
2349 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2350 	if (phy->rf_rev < 6)
2351 		return (BWN_TXCTL_PA2DB);
2352 	if (phy->rf_rev == 8)
2353 		return (BWN_TXCTL_TXMIX);
2354 	return (0);
2355 }
2356 
2357 static int
2358 bwn_phy_g_init(struct bwn_mac *mac)
2359 {
2360 
2361 	bwn_phy_g_init_sub(mac);
2362 	return (0);
2363 }
2364 
2365 static void
2366 bwn_phy_g_exit(struct bwn_mac *mac)
2367 {
2368 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2369 	struct bwn_lo_calib *cal, *tmp;
2370 
2371 	if (lo == NULL)
2372 		return;
2373 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2374 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2375 		free(cal, M_DEVBUF);
2376 	}
2377 }
2378 
2379 static uint16_t
2380 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2381 {
2382 
2383 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2384 	return (BWN_READ_2(mac, BWN_PHYDATA));
2385 }
2386 
2387 static void
2388 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2389 {
2390 
2391 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2392 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2393 }
2394 
2395 static uint16_t
2396 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2397 {
2398 
2399 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2401 	return (BWN_READ_2(mac, BWN_RFDATALO));
2402 }
2403 
2404 static void
2405 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2406 {
2407 
2408 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2409 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2410 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2411 }
2412 
2413 static int
2414 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2415 {
2416 
2417 	return (mac->mac_phy.rev >= 6);
2418 }
2419 
2420 static void
2421 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2422 {
2423 	struct bwn_phy *phy = &mac->mac_phy;
2424 	struct bwn_phy_g *pg = &phy->phy_g;
2425 	unsigned int channel;
2426 	uint16_t rfover, rfoverval;
2427 
2428 	if (on) {
2429 		if (phy->rf_on)
2430 			return;
2431 
2432 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2433 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2434 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2435 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2436 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2437 			    pg->pg_radioctx_over);
2438 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2439 			    pg->pg_radioctx_overval);
2440 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2441 		}
2442 		channel = phy->chan;
2443 		bwn_phy_g_switch_chan(mac, 6, 1);
2444 		bwn_phy_g_switch_chan(mac, channel, 0);
2445 		return;
2446 	}
2447 
2448 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2449 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2450 	pg->pg_radioctx_over = rfover;
2451 	pg->pg_radioctx_overval = rfoverval;
2452 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2453 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2454 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2455 }
2456 
2457 static int
2458 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2459 {
2460 
2461 	if ((newchan < 1) || (newchan > 14))
2462 		return (EINVAL);
2463 	bwn_phy_g_switch_chan(mac, newchan, 0);
2464 
2465 	return (0);
2466 }
2467 
2468 static uint32_t
2469 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2470 {
2471 
2472 	return (1);
2473 }
2474 
2475 static void
2476 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2477 {
2478 	struct bwn_phy *phy = &mac->mac_phy;
2479 	uint64_t hf;
2480 	int autodiv = 0;
2481 	uint16_t tmp;
2482 
2483 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2484 		autodiv = 1;
2485 
2486 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2487 	bwn_hf_write(mac, hf);
2488 
2489 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2490 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2491 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2492 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2493 
2494 	if (autodiv) {
2495 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2496 		if (antenna == BWN_ANTAUTO1)
2497 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2498 		else
2499 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2500 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2501 	}
2502 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2503 	if (autodiv)
2504 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2505 	else
2506 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2507 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2508 	if (phy->rev >= 2) {
2509 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2510 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2511 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2512 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2513 		    0x15);
2514 		if (phy->rev == 2)
2515 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2516 		else
2517 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2518 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2519 			    8);
2520 	}
2521 	if (phy->rev >= 6)
2522 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2523 
2524 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2525 	bwn_hf_write(mac, hf);
2526 }
2527 
2528 static int
2529 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2530 {
2531 	struct bwn_phy *phy = &mac->mac_phy;
2532 	struct bwn_phy_g *pg = &phy->phy_g;
2533 
2534 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2535 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2536 
2537 	if (phy->rev == 0 || !phy->gmode)
2538 		return (ENODEV);
2539 
2540 	pg->pg_aci_wlan_automatic = 0;
2541 	return (0);
2542 }
2543 
2544 static int
2545 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2546 {
2547 	struct bwn_phy *phy = &mac->mac_phy;
2548 	struct bwn_phy_g *pg = &phy->phy_g;
2549 	struct bwn_softc *sc = mac->mac_sc;
2550 	struct siba_softc *siba = mac->mac_sd->sd_bus;
2551 	unsigned int tssi;
2552 	int cck, ofdm;
2553 	int power;
2554 	int rfatt, bbatt;
2555 	unsigned int max;
2556 
2557 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2558 
2559 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2560 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2561 	if (cck < 0 && ofdm < 0) {
2562 		if (ignore_tssi == 0)
2563 			return (BWN_TXPWR_RES_DONE);
2564 		cck = 0;
2565 		ofdm = 0;
2566 	}
2567 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2568 	if (pg->pg_avgtssi != 0xff)
2569 		tssi = (tssi + pg->pg_avgtssi) / 2;
2570 	pg->pg_avgtssi = tssi;
2571 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2572 
2573 	max = siba->siba_sprom.maxpwr_bg;
2574 	if (siba->siba_sprom.bf_lo & BWN_BFL_PACTRL)
2575 		max -= 3;
2576 	if (max >= 120) {
2577 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2578 		siba->siba_sprom.maxpwr_bg = max = 80;
2579 	}
2580 
2581 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2582 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2583 	     tssi, 0x00), 0x3f)]);
2584 	if (power == 0)
2585 		return (BWN_TXPWR_RES_DONE);
2586 
2587 	rfatt = -((power + 7) / 8);
2588 	bbatt = (-(power / 2)) - (4 * rfatt);
2589 	if ((rfatt == 0) && (bbatt == 0))
2590 		return (BWN_TXPWR_RES_DONE);
2591 	pg->pg_bbatt_delta = bbatt;
2592 	pg->pg_rfatt_delta = rfatt;
2593 	return (BWN_TXPWR_RES_NEED_ADJUST);
2594 }
2595 
2596 static void
2597 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2598 {
2599 	struct bwn_phy *phy = &mac->mac_phy;
2600 	struct bwn_phy_g *pg = &phy->phy_g;
2601 	struct bwn_softc *sc = mac->mac_sc;
2602 	int rfatt, bbatt;
2603 	uint8_t txctl;
2604 
2605 	bwn_mac_suspend(mac);
2606 
2607 	BWN_ASSERT_LOCKED(sc);
2608 
2609 	bbatt = pg->pg_bbatt.att;
2610 	bbatt += pg->pg_bbatt_delta;
2611 	rfatt = pg->pg_rfatt.att;
2612 	rfatt += pg->pg_rfatt_delta;
2613 
2614 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2615 	txctl = pg->pg_txctl;
2616 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2617 		if (rfatt <= 1) {
2618 			if (txctl == 0) {
2619 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2620 				rfatt += 2;
2621 				bbatt += 2;
2622 			} else if (mac->mac_sd->sd_bus->siba_sprom.
2623 				   bf_lo &
2624 				   BWN_BFL_PACTRL) {
2625 				bbatt += 4 * (rfatt - 2);
2626 				rfatt = 2;
2627 			}
2628 		} else if (rfatt > 4 && txctl) {
2629 			txctl = 0;
2630 			if (bbatt < 3) {
2631 				rfatt -= 3;
2632 				bbatt += 2;
2633 			} else {
2634 				rfatt -= 2;
2635 				bbatt -= 2;
2636 			}
2637 		}
2638 	}
2639 	pg->pg_txctl = txctl;
2640 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2641 	pg->pg_rfatt.att = rfatt;
2642 	pg->pg_bbatt.att = bbatt;
2643 
2644 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2645 
2646 	bwn_phy_lock(mac);
2647 	bwn_rf_lock(mac);
2648 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2649 	    pg->pg_txctl);
2650 	bwn_rf_unlock(mac);
2651 	bwn_phy_unlock(mac);
2652 
2653 	bwn_mac_enable(mac);
2654 }
2655 
2656 static void
2657 bwn_phy_g_task_15s(struct bwn_mac *mac)
2658 {
2659 	struct bwn_phy *phy = &mac->mac_phy;
2660 	struct bwn_phy_g *pg = &phy->phy_g;
2661 	struct bwn_softc *sc = mac->mac_sc;
2662 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2663 	unsigned long expire, now;
2664 	struct bwn_lo_calib *cal, *tmp;
2665 	uint8_t expired = 0;
2666 
2667 	bwn_mac_suspend(mac);
2668 
2669 	if (lo == NULL)
2670 		goto fail;
2671 
2672 	BWN_GETTIME(now);
2673 	if (bwn_has_hwpctl(mac)) {
2674 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2675 		if (time_before(lo->pwr_vec_read_time, expire)) {
2676 			bwn_lo_get_powervector(mac);
2677 			bwn_phy_g_dc_lookup_init(mac, 0);
2678 		}
2679 		goto fail;
2680 	}
2681 
2682 	expire = now - BWN_LO_CALIB_EXPIRE;
2683 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2684 		if (!time_before(cal->calib_time, expire))
2685 			continue;
2686 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2687 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2688 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2689 			expired = 1;
2690 		}
2691 
2692 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2693 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2694 		    cal->ctl.i, cal->ctl.q);
2695 
2696 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2697 		free(cal, M_DEVBUF);
2698 	}
2699 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2700 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2701 		    &pg->pg_rfatt);
2702 		if (cal == NULL) {
2703 			device_printf(sc->sc_dev,
2704 			    "failed to recalibrate LO\n");
2705 			goto fail;
2706 		}
2707 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2708 		bwn_lo_write(mac, &cal->ctl);
2709 	}
2710 
2711 fail:
2712 	bwn_mac_enable(mac);
2713 }
2714 
2715 static void
2716 bwn_phy_g_task_60s(struct bwn_mac *mac)
2717 {
2718 	struct bwn_phy *phy = &mac->mac_phy;
2719 	uint8_t old = phy->chan;
2720 
2721 	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI))
2722 		return;
2723 
2724 	bwn_mac_suspend(mac);
2725 	bwn_nrssi_slope_11g(mac);
2726 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2727 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2728 		bwn_switch_channel(mac, old);
2729 	}
2730 	bwn_mac_enable(mac);
2731 }
2732 
2733 static void
2734 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2735 {
2736 
2737 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2738 }
2739 
2740 static int
2741 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2742 	const struct ieee80211_bpf_params *params)
2743 {
2744 	struct ieee80211com *ic = ni->ni_ic;
2745 	struct ifnet *ifp = ic->ic_ifp;
2746 	struct bwn_softc *sc = ifp->if_softc;
2747 	struct bwn_mac *mac = sc->sc_curmac;
2748 
2749 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2750 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2751 		ieee80211_free_node(ni);
2752 		m_freem(m);
2753 		return (ENETDOWN);
2754 	}
2755 
2756 	BWN_LOCK(sc);
2757 	if (bwn_tx_isfull(sc, m)) {
2758 		ieee80211_free_node(ni);
2759 		m_freem(m);
2760 		ifp->if_oerrors++;
2761 		BWN_UNLOCK(sc);
2762 		return (ENOBUFS);
2763 	}
2764 
2765 	if (bwn_tx_start(sc, ni, m) != 0) {
2766 		if (ni != NULL)
2767 			ieee80211_free_node(ni);
2768 		ifp->if_oerrors++;
2769 	}
2770 	sc->sc_watchdog_timer = 5;
2771 	BWN_UNLOCK(sc);
2772 	return (0);
2773 }
2774 
2775 /*
2776  * Setup driver-specific state for a newly associated node.
2777  * Note that we're called also on a re-associate, the isnew
2778  * param tells us if this is the first time or not.
2779  */
2780 static void
2781 bwn_newassoc(struct ieee80211_node *ni, int isnew)
2782 {
2783 	struct ieee80211vap *vap = ni->ni_vap;
2784 
2785 	ieee80211_amrr_node_init(&BWN_VAP(vap)->bv_amrr,
2786 	    &BWN_NODE(ni)->bn_amn, ni);
2787 }
2788 
2789 /*
2790  * Callback from the 802.11 layer to update the slot time
2791  * based on the current setting.  We use it to notify the
2792  * firmware of ERP changes and the f/w takes care of things
2793  * like slot time and preamble.
2794  */
2795 static void
2796 bwn_updateslot(struct ifnet *ifp)
2797 {
2798 	struct bwn_softc *sc = ifp->if_softc;
2799 	struct ieee80211com *ic = ifp->if_l2com;
2800 	struct bwn_mac *mac;
2801 
2802 	BWN_LOCK(sc);
2803 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2804 		mac = (struct bwn_mac *)sc->sc_curmac;
2805 		bwn_set_slot_time(mac,
2806 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2807 	}
2808 	BWN_UNLOCK(sc);
2809 }
2810 
2811 /*
2812  * Callback from the 802.11 layer after a promiscuous mode change.
2813  * Note this interface does not check the operating mode as this
2814  * is an internal callback and we are expected to honor the current
2815  * state (e.g. this is used for setting the interface in promiscuous
2816  * mode when operating in hostap mode to do ACS).
2817  */
2818 static void
2819 bwn_update_promisc(struct ifnet *ifp)
2820 {
2821 	struct bwn_softc *sc = ifp->if_softc;
2822 	struct bwn_mac *mac = sc->sc_curmac;
2823 
2824 	BWN_LOCK(sc);
2825 	mac = sc->sc_curmac;
2826 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827 		if (ifp->if_flags & IFF_PROMISC)
2828 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2829 		else
2830 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2831 		bwn_set_opmode(mac);
2832 	}
2833 	BWN_UNLOCK(sc);
2834 }
2835 
2836 /*
2837  * Callback from the 802.11 layer to update WME parameters.
2838  */
2839 static int
2840 bwn_wme_update(struct ieee80211com *ic)
2841 {
2842 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2843 	struct bwn_mac *mac = sc->sc_curmac;
2844 	struct wmeParams *wmep;
2845 	int i;
2846 
2847 	BWN_LOCK(sc);
2848 	mac = sc->sc_curmac;
2849 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2850 		bwn_mac_suspend(mac);
2851 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2852 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2853 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2854 		}
2855 		bwn_mac_enable(mac);
2856 	}
2857 	BWN_UNLOCK(sc);
2858 	return (0);
2859 }
2860 
2861 static struct ieee80211_node *
2862 bwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2863 {
2864 	struct ieee80211com *ic = vap->iv_ic;
2865 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2866 	const size_t space = sizeof(struct bwn_node);
2867 	struct bwn_node *bn;
2868 
2869 	bn = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
2870 	if (bn == NULL) {
2871 		/* XXX stat+msg */
2872 		return (NULL);
2873 	}
2874 	DPRINTF(sc, BWN_DEBUG_NODE, "%s: bn %p\n", __func__, bn);
2875 	return (&bn->bn_node);
2876 }
2877 
2878 static void
2879 bwn_node_cleanup(struct ieee80211_node *ni)
2880 {
2881 	struct ieee80211com *ic = ni->ni_ic;
2882 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2883 
2884 	sc->sc_node_cleanup(ni);
2885 }
2886 
2887 static void
2888 bwn_scan_start(struct ieee80211com *ic)
2889 {
2890 	struct ifnet *ifp = ic->ic_ifp;
2891 	struct bwn_softc *sc = ifp->if_softc;
2892 	struct bwn_mac *mac;
2893 
2894 	BWN_LOCK(sc);
2895 	mac = sc->sc_curmac;
2896 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2897 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2898 		bwn_set_opmode(mac);
2899 		/* disable CFP update during scan */
2900 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2901 	}
2902 	BWN_UNLOCK(sc);
2903 }
2904 
2905 static void
2906 bwn_scan_end(struct ieee80211com *ic)
2907 {
2908 	struct ifnet *ifp = ic->ic_ifp;
2909 	struct bwn_softc *sc = ifp->if_softc;
2910 	struct bwn_mac *mac;
2911 
2912 	BWN_LOCK(sc);
2913 	mac = sc->sc_curmac;
2914 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2915 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2916 		bwn_set_opmode(mac);
2917 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2918 	}
2919 	BWN_UNLOCK(sc);
2920 }
2921 
2922 static void
2923 bwn_set_channel(struct ieee80211com *ic)
2924 {
2925 	struct ifnet *ifp = ic->ic_ifp;
2926 	struct bwn_softc *sc = ifp->if_softc;
2927 	struct bwn_mac *mac = sc->sc_curmac;
2928 	struct bwn_phy *phy = &mac->mac_phy;
2929 	int chan, error;
2930 
2931 	BWN_LOCK(sc);
2932 
2933 	error = bwn_switch_band(sc, ic->ic_curchan);
2934 	if (error)
2935 		goto fail;;
2936 	bwn_mac_suspend(mac);
2937 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2938 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2939 	if (chan != phy->chan)
2940 		bwn_switch_channel(mac, chan);
2941 
2942 	/* TX power level */
2943 	if (ic->ic_curchan->ic_maxpower != 0 &&
2944 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2945 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2946 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2947 		    BWN_TXPWR_IGNORE_TSSI);
2948 	}
2949 
2950 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2951 	if (phy->set_antenna)
2952 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2953 
2954 	if (sc->sc_rf_enabled != phy->rf_on) {
2955 		if (sc->sc_rf_enabled) {
2956 			bwn_rf_turnon(mac);
2957 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2958 				device_printf(sc->sc_dev,
2959 				    "please turns on the RF switch\n");
2960 		} else
2961 			bwn_rf_turnoff(mac);
2962 	}
2963 
2964 	bwn_mac_enable(mac);
2965 
2966 fail:
2967 	/*
2968 	 * Setup radio tap channel freq and flags
2969 	 */
2970 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2971 		htole16(ic->ic_curchan->ic_freq);
2972 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2973 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2974 
2975 	BWN_UNLOCK(sc);
2976 }
2977 
2978 static struct ieee80211vap *
2979 bwn_vap_create(struct ieee80211com *ic,
2980 	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2981 	const uint8_t bssid[IEEE80211_ADDR_LEN],
2982 	const uint8_t mac0[IEEE80211_ADDR_LEN])
2983 {
2984 	struct ifnet *ifp = ic->ic_ifp;
2985 	struct bwn_softc *sc = ifp->if_softc;
2986 	struct ieee80211vap *vap;
2987 	struct bwn_vap *bvp;
2988 	uint8_t mac[IEEE80211_ADDR_LEN];
2989 
2990 	IEEE80211_ADDR_COPY(mac, mac0);
2991 	switch (opmode) {
2992 	case IEEE80211_M_HOSTAP:
2993 	case IEEE80211_M_MBSS:
2994 	case IEEE80211_M_STA:
2995 	case IEEE80211_M_WDS:
2996 	case IEEE80211_M_MONITOR:
2997 	case IEEE80211_M_IBSS:
2998 	case IEEE80211_M_AHDEMO:
2999 		break;
3000 	default:
3001 		return (NULL);
3002 	}
3003 
3004 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
3005 
3006 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
3007 	    M_80211_VAP, M_NOWAIT | M_ZERO);
3008 	if (bvp == NULL) {
3009 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
3010 		return (NULL);
3011 	}
3012 	vap = &bvp->bv_vap;
3013 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
3014 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
3015 	/* override with driver methods */
3016 	bvp->bv_newstate = vap->iv_newstate;
3017 	vap->iv_newstate = bwn_newstate;
3018 
3019 	/* override max aid so sta's cannot assoc when we're out of sta id's */
3020 	vap->iv_max_aid = BWN_STAID_MAX;
3021 
3022 	ieee80211_amrr_init(&bvp->bv_amrr, vap,
3023 	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
3024 	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
3025 	    500 /*ms*/);
3026 
3027 	/* complete setup */
3028 	ieee80211_vap_attach(vap, ieee80211_media_change,
3029 	    ieee80211_media_status);
3030 	return (vap);
3031 }
3032 
3033 static void
3034 bwn_vap_delete(struct ieee80211vap *vap)
3035 {
3036 	struct bwn_vap *bvp = BWN_VAP(vap);
3037 
3038 	ieee80211_amrr_cleanup(&bvp->bv_amrr);
3039 	ieee80211_vap_detach(vap);
3040 	free(bvp, M_80211_VAP);
3041 }
3042 
3043 static void
3044 bwn_init(void *arg)
3045 {
3046 	struct bwn_softc *sc = arg;
3047 	struct ifnet *ifp = sc->sc_ifp;
3048 	struct ieee80211com *ic = ifp->if_l2com;
3049 	int error = 0;
3050 
3051 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3052 		__func__, ifp->if_flags);
3053 
3054 	BWN_LOCK(sc);
3055 	error = bwn_init_locked(sc);
3056 	BWN_UNLOCK(sc);
3057 
3058 	if (error == 0)
3059 		ieee80211_start_all(ic);	/* start all vap's */
3060 }
3061 
3062 static int
3063 bwn_init_locked(struct bwn_softc *sc)
3064 {
3065 	struct bwn_mac *mac;
3066 	struct ifnet *ifp = sc->sc_ifp;
3067 	int error;
3068 
3069 	BWN_ASSERT_LOCKED(sc);
3070 
3071 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3072 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3073 	sc->sc_filters = 0;
3074 	bwn_wme_clear(sc);
3075 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3076 	sc->sc_rf_enabled = 1;
3077 
3078 	mac = sc->sc_curmac;
3079 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3080 		error = bwn_core_init(mac);
3081 		if (error != 0)
3082 			return (error);
3083 	}
3084 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3085 		bwn_core_start(mac);
3086 
3087 	bwn_set_opmode(mac);
3088 	bwn_set_pretbtt(mac);
3089 	bwn_spu_setdelay(mac, 0);
3090 	bwn_set_macaddr(mac);
3091 
3092 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3093 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3094 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3095 
3096 	return (0);
3097 }
3098 
3099 static void
3100 bwn_stop(struct bwn_softc *sc, int statechg)
3101 {
3102 
3103 	BWN_LOCK(sc);
3104 	bwn_stop_locked(sc, statechg);
3105 	BWN_UNLOCK(sc);
3106 }
3107 
3108 static void
3109 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3110 {
3111 	struct bwn_mac *mac = sc->sc_curmac;
3112 	struct ifnet *ifp = sc->sc_ifp;
3113 
3114 	BWN_ASSERT_LOCKED(sc);
3115 
3116 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3117 		/* XXX FIXME opmode not based on VAP */
3118 		bwn_set_opmode(mac);
3119 		bwn_set_macaddr(mac);
3120 	}
3121 
3122 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3123 		bwn_core_stop(mac);
3124 
3125 	callout_stop(&sc->sc_led_blink_ch);
3126 	sc->sc_led_blinking = 0;
3127 
3128 	bwn_core_exit(mac);
3129 	sc->sc_rf_enabled = 0;
3130 
3131 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3132 }
3133 
3134 static void
3135 bwn_wme_clear(struct bwn_softc *sc)
3136 {
3137 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3138 	struct wmeParams *p;
3139 	unsigned int i;
3140 
3141 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3142 	    ("%s:%d: fail", __func__, __LINE__));
3143 
3144 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3145 		p = &(sc->sc_wmeParams[i]);
3146 
3147 		switch (bwn_wme_shm_offsets[i]) {
3148 		case BWN_WME_VOICE:
3149 			p->wmep_txopLimit = 0;
3150 			p->wmep_aifsn = 2;
3151 			/* XXX FIXME: log2(cwmin) */
3152 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3153 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3154 			break;
3155 		case BWN_WME_VIDEO:
3156 			p->wmep_txopLimit = 0;
3157 			p->wmep_aifsn = 2;
3158 			/* XXX FIXME: log2(cwmin) */
3159 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3160 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3161 			break;
3162 		case BWN_WME_BESTEFFORT:
3163 			p->wmep_txopLimit = 0;
3164 			p->wmep_aifsn = 3;
3165 			/* XXX FIXME: log2(cwmin) */
3166 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3167 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3168 			break;
3169 		case BWN_WME_BACKGROUND:
3170 			p->wmep_txopLimit = 0;
3171 			p->wmep_aifsn = 7;
3172 			/* XXX FIXME: log2(cwmin) */
3173 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3174 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3175 			break;
3176 		default:
3177 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3178 		}
3179 	}
3180 }
3181 
3182 static int
3183 bwn_core_init(struct bwn_mac *mac)
3184 {
3185 #ifdef BWN_DEBUG
3186 	struct bwn_softc *sc = mac->mac_sc;
3187 #endif
3188 	struct siba_dev_softc *sd = mac->mac_sd;
3189 	struct siba_softc *siba = sd->sd_bus;
3190 	struct siba_sprom *sprom = &siba->siba_sprom;
3191 	uint64_t hf;
3192 	int error;
3193 
3194 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3195 	    ("%s:%d: fail", __func__, __LINE__));
3196 
3197 	siba_powerup(siba, 0);
3198 	if (!siba_dev_isup(sd))
3199 		bwn_reset_core(mac,
3200 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3201 
3202 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3203 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3204 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3205 	BWN_GETTIME(mac->mac_phy.nexttime);
3206 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3207 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3208 	mac->mac_stats.link_noise = -95;
3209 	mac->mac_reason_intr = 0;
3210 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3211 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3212 #ifdef BWN_DEBUG
3213 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3214 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3215 #endif
3216 	mac->mac_suspended = 1;
3217 	mac->mac_task_state = 0;
3218 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3219 
3220 	mac->mac_phy.init_pre(mac);
3221 
3222 	siba_pcicore_intr(&siba->siba_pci, sd);
3223 
3224 	bwn_fix_imcfglobug(mac);
3225 	bwn_bt_disable(mac);
3226 	if (mac->mac_phy.prepare_hw) {
3227 		error = mac->mac_phy.prepare_hw(mac);
3228 		if (error)
3229 			goto fail0;
3230 	}
3231 	error = bwn_chip_init(mac);
3232 	if (error)
3233 		goto fail0;
3234 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3235 	    mac->mac_sd->sd_id.sd_rev);
3236 	hf = bwn_hf_read(mac);
3237 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3238 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3239 		if (sprom->bf_lo & BWN_BFL_PACTRL)
3240 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3241 		if (mac->mac_phy.rev == 1)
3242 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3243 	}
3244 	if (mac->mac_phy.rf_ver == 0x2050) {
3245 		if (mac->mac_phy.rf_rev < 6)
3246 			hf |= BWN_HF_FORCE_VCO_RECALC;
3247 		if (mac->mac_phy.rf_rev == 6)
3248 			hf |= BWN_HF_4318_TSSI;
3249 	}
3250 	if (sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW)
3251 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3252 	if ((siba->siba_type == SIBA_TYPE_PCI) &&
3253 	    (siba->siba_pci.spc_dev->sd_id.sd_rev <= 10))
3254 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3255 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3256 	bwn_hf_write(mac, hf);
3257 
3258 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3259 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3260 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3261 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3262 
3263 	bwn_rate_init(mac);
3264 	bwn_set_phytxctl(mac);
3265 
3266 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3267 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3268 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3269 
3270 	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3271 		bwn_pio_init(mac);
3272 	else
3273 		bwn_dma_init(mac);
3274 	if (error)
3275 		goto fail1;
3276 	bwn_wme_init(mac);
3277 	bwn_spu_setdelay(mac, 1);
3278 	bwn_bt_enable(mac);
3279 
3280 	siba_powerup(siba, !(sprom->bf_lo & BWN_BFL_CRYSTAL_NOSLOW));
3281 	bwn_set_macaddr(mac);
3282 	bwn_crypt_init(mac);
3283 
3284 	/* XXX LED initializatin */
3285 
3286 	mac->mac_status = BWN_MAC_STATUS_INITED;
3287 
3288 	return (error);
3289 
3290 fail1:
3291 	bwn_chip_exit(mac);
3292 fail0:
3293 	siba_powerdown(siba);
3294 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3295 	    ("%s:%d: fail", __func__, __LINE__));
3296 	return (error);
3297 }
3298 
3299 static void
3300 bwn_core_start(struct bwn_mac *mac)
3301 {
3302 	struct bwn_softc *sc = mac->mac_sc;
3303 	uint32_t tmp;
3304 
3305 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3306 	    ("%s:%d: fail", __func__, __LINE__));
3307 
3308 	if (mac->mac_sd->sd_id.sd_rev < 5)
3309 		return;
3310 
3311 	while (1) {
3312 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3313 		if (!(tmp & 0x00000001))
3314 			break;
3315 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3316 	}
3317 
3318 	bwn_mac_enable(mac);
3319 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3320 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3321 
3322 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3323 }
3324 
3325 static void
3326 bwn_core_exit(struct bwn_mac *mac)
3327 {
3328 	uint32_t macctl;
3329 
3330 	BWN_ASSERT_LOCKED(mac->mac_sc);
3331 
3332 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3333 	    ("%s:%d: fail", __func__, __LINE__));
3334 
3335 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3336 		return;
3337 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3338 
3339 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3340 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3341 	macctl |= BWN_MACCTL_MCODE_JMP0;
3342 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3343 
3344 	bwn_dma_stop(mac);
3345 	bwn_pio_stop(mac);
3346 	bwn_chip_exit(mac);
3347 	mac->mac_phy.switch_analog(mac, 0);
3348 	siba_dev_down(mac->mac_sd, 0);
3349 	siba_powerdown(mac->mac_sd->sd_bus);
3350 }
3351 
3352 static void
3353 bwn_fix_imcfglobug(struct bwn_mac *mac)
3354 {
3355 	struct siba_dev_softc *sd = mac->mac_sd;
3356 	struct siba_softc *siba = sd->sd_bus;
3357 	uint32_t tmp;
3358 
3359 	if (siba->siba_pci.spc_dev == NULL)
3360 		return;
3361 	if (siba->siba_pci.spc_dev->sd_id.sd_device != SIBA_DEVID_PCI ||
3362 	    siba->siba_pci.spc_dev->sd_id.sd_rev > 5)
3363 		return;
3364 
3365 	tmp = siba_read_4(sd, SIBA_IMCFGLO) &
3366 	    ~(SIBA_IMCFGLO_REQTO | SIBA_IMCFGLO_SERTO);
3367 	switch (siba->siba_type) {
3368 	case SIBA_TYPE_PCI:
3369 	case SIBA_TYPE_PCMCIA:
3370 		tmp |= 0x32;
3371 		break;
3372 	case SIBA_TYPE_SSB:
3373 		tmp |= 0x53;
3374 		break;
3375 	}
3376 	siba_write_4(sd, SIBA_IMCFGLO, tmp);
3377 }
3378 
3379 static void
3380 bwn_bt_disable(struct bwn_mac *mac)
3381 {
3382 	struct bwn_softc *sc = mac->mac_sc;
3383 
3384 	(void)sc;
3385 	/* XXX do nothing yet */
3386 }
3387 
3388 static int
3389 bwn_chip_init(struct bwn_mac *mac)
3390 {
3391 	struct bwn_phy *phy = &mac->mac_phy;
3392 	uint32_t macctl;
3393 	int error;
3394 
3395 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3396 	if (phy->gmode)
3397 		macctl |= BWN_MACCTL_GMODE;
3398 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3399 
3400 	error = bwn_fw_fillinfo(mac);
3401 	if (error)
3402 		return (error);
3403 	error = bwn_fw_loaducode(mac);
3404 	if (error)
3405 		return (error);
3406 
3407 	error = bwn_gpio_init(mac);
3408 	if (error)
3409 		return (error);
3410 
3411 	error = bwn_fw_loadinitvals(mac);
3412 	if (error) {
3413 		bwn_gpio_cleanup(mac);
3414 		return (error);
3415 	}
3416 	phy->switch_analog(mac, 1);
3417 	error = bwn_phy_init(mac);
3418 	if (error) {
3419 		bwn_gpio_cleanup(mac);
3420 		return (error);
3421 	}
3422 	if (phy->set_im)
3423 		phy->set_im(mac, BWN_IMMODE_NONE);
3424 	if (phy->set_antenna)
3425 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3426 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3427 
3428 	if (phy->type == BWN_PHYTYPE_B)
3429 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3430 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3431 	if (mac->mac_sd->sd_id.sd_rev < 5)
3432 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3433 
3434 	BWN_WRITE_4(mac, BWN_MACCTL,
3435 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3436 	BWN_WRITE_4(mac, BWN_MACCTL,
3437 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3438 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3439 
3440 	bwn_set_opmode(mac);
3441 	if (mac->mac_sd->sd_id.sd_rev < 3) {
3442 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3443 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3444 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3445 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3446 	} else {
3447 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3448 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3449 	}
3450 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3451 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3452 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3453 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3454 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3455 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3456 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3457 	siba_write_4(mac->mac_sd, SIBA_TGSLOW,
3458 	    siba_read_4(mac->mac_sd, SIBA_TGSLOW) | 0x00100000);
3459 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY,
3460 	    mac->mac_sd->sd_bus->siba_cc.scc_powerup_delay);
3461 	return (error);
3462 }
3463 
3464 /* read hostflags */
3465 static uint64_t
3466 bwn_hf_read(struct bwn_mac *mac)
3467 {
3468 	uint64_t ret;
3469 
3470 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3471 	ret <<= 16;
3472 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3473 	ret <<= 16;
3474 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3475 	return (ret);
3476 }
3477 
3478 static void
3479 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3480 {
3481 
3482 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3483 	    (value & 0x00000000ffffull));
3484 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3485 	    (value & 0x0000ffff0000ull) >> 16);
3486 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3487 	    (value & 0xffff00000000ULL) >> 32);
3488 }
3489 
3490 static void
3491 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3492 {
3493 
3494 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3495 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3496 }
3497 
3498 static void
3499 bwn_rate_init(struct bwn_mac *mac)
3500 {
3501 
3502 	switch (mac->mac_phy.type) {
3503 	case BWN_PHYTYPE_A:
3504 	case BWN_PHYTYPE_G:
3505 	case BWN_PHYTYPE_LP:
3506 	case BWN_PHYTYPE_N:
3507 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3508 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3509 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3510 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3511 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3512 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3513 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3514 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3515 			break;
3516 		/* FALLTHROUGH */
3517 	case BWN_PHYTYPE_B:
3518 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3519 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3520 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3521 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3522 		break;
3523 	default:
3524 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3525 	}
3526 }
3527 
3528 static void
3529 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3530 {
3531 	uint16_t offset;
3532 
3533 	if (ofdm) {
3534 		offset = 0x480;
3535 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3536 	} else {
3537 		offset = 0x4c0;
3538 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3539 	}
3540 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3541 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3542 }
3543 
3544 static uint8_t
3545 bwn_plcp_getcck(const uint8_t bitrate)
3546 {
3547 
3548 	switch (bitrate) {
3549 	case BWN_CCK_RATE_1MB:
3550 		return (0x0a);
3551 	case BWN_CCK_RATE_2MB:
3552 		return (0x14);
3553 	case BWN_CCK_RATE_5MB:
3554 		return (0x37);
3555 	case BWN_CCK_RATE_11MB:
3556 		return (0x6e);
3557 	}
3558 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3559 	return (0);
3560 }
3561 
3562 static uint8_t
3563 bwn_plcp_getofdm(const uint8_t bitrate)
3564 {
3565 
3566 	switch (bitrate) {
3567 	case BWN_OFDM_RATE_6MB:
3568 		return (0xb);
3569 	case BWN_OFDM_RATE_9MB:
3570 		return (0xf);
3571 	case BWN_OFDM_RATE_12MB:
3572 		return (0xa);
3573 	case BWN_OFDM_RATE_18MB:
3574 		return (0xe);
3575 	case BWN_OFDM_RATE_24MB:
3576 		return (0x9);
3577 	case BWN_OFDM_RATE_36MB:
3578 		return (0xd);
3579 	case BWN_OFDM_RATE_48MB:
3580 		return (0x8);
3581 	case BWN_OFDM_RATE_54MB:
3582 		return (0xc);
3583 	}
3584 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3585 	return (0);
3586 }
3587 
3588 static void
3589 bwn_set_phytxctl(struct bwn_mac *mac)
3590 {
3591 	uint16_t ctl;
3592 
3593 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3594 	    BWN_TX_PHY_TXPWR);
3595 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3596 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3597 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3598 }
3599 
3600 static void
3601 bwn_pio_init(struct bwn_mac *mac)
3602 {
3603 	struct bwn_pio *pio = &mac->mac_method.pio;
3604 
3605 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3606 	    & ~BWN_MACCTL_BIGENDIAN);
3607 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3608 
3609 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3610 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3611 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3612 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3613 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3614 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3615 }
3616 
3617 static void
3618 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3619     int index)
3620 {
3621 	struct bwn_pio_txpkt *tp;
3622 	unsigned int i;
3623 
3624 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3625 	tq->tq_index = index;
3626 
3627 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3628 	if (mac->mac_sd->sd_id.sd_rev >= 8)
3629 		tq->tq_size = 1920;
3630 	else {
3631 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3632 		tq->tq_size -= 80;
3633 	}
3634 
3635 	TAILQ_INIT(&tq->tq_pktlist);
3636 	for (i = 0; i < N(tq->tq_pkts); i++) {
3637 		tp = &(tq->tq_pkts[i]);
3638 		tp->tp_index = i;
3639 		tp->tp_queue = tq;
3640 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3641 	}
3642 }
3643 
3644 static uint16_t
3645 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3646 {
3647 	struct bwn_softc *sc = mac->mac_sc;
3648 	static const uint16_t bases[] = {
3649 		BWN_PIO_BASE0,
3650 		BWN_PIO_BASE1,
3651 		BWN_PIO_BASE2,
3652 		BWN_PIO_BASE3,
3653 		BWN_PIO_BASE4,
3654 		BWN_PIO_BASE5,
3655 		BWN_PIO_BASE6,
3656 		BWN_PIO_BASE7,
3657 	};
3658 	static const uint16_t bases_rev11[] = {
3659 		BWN_PIO11_BASE0,
3660 		BWN_PIO11_BASE1,
3661 		BWN_PIO11_BASE2,
3662 		BWN_PIO11_BASE3,
3663 		BWN_PIO11_BASE4,
3664 		BWN_PIO11_BASE5,
3665 	};
3666 
3667 	if (mac->mac_sd->sd_id.sd_rev >= 11) {
3668 		if (index >= N(bases_rev11))
3669 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3670 		return (bases_rev11[index]);
3671 	}
3672 	if (index >= N(bases))
3673 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3674 	return (bases[index]);
3675 }
3676 
3677 static void
3678 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3679     int index)
3680 {
3681 
3682 	prq->prq_mac = mac;
3683 	prq->prq_rev = mac->mac_sd->sd_id.sd_rev;
3684 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3685 	bwn_dma_rxdirectfifo(mac, index, 1);
3686 }
3687 
3688 static void
3689 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3690 {
3691 	if (tq == NULL)
3692 		return;
3693 	bwn_pio_cancel_tx_packets(tq);
3694 }
3695 
3696 static void
3697 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3698 {
3699 
3700 	bwn_destroy_pioqueue_tx(pio);
3701 }
3702 
3703 static uint16_t
3704 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3705     uint16_t offset)
3706 {
3707 
3708 	return (BWN_READ_2(mac, tq->tq_base + offset));
3709 }
3710 
3711 static void
3712 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3713 {
3714 	uint32_t ctl;
3715 	int type;
3716 	uint16_t base;
3717 
3718 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3719 	base = bwn_dma_base(type, idx);
3720 	if (type == BWN_DMA_64BIT) {
3721 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3722 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3723 		if (enable)
3724 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3725 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3726 	} else {
3727 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3728 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3729 		if (enable)
3730 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3731 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3732 	}
3733 }
3734 
3735 static uint64_t
3736 bwn_dma_mask(struct bwn_mac *mac)
3737 {
3738 	uint32_t tmp;
3739 	uint16_t base;
3740 
3741 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3742 	if (tmp & SIBA_TGSHIGH_DMA64)
3743 		return (BWN_DMA_BIT_MASK(64));
3744 	base = bwn_dma_base(0, 0);
3745 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3746 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3747 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3748 		return (BWN_DMA_BIT_MASK(32));
3749 
3750 	return (BWN_DMA_BIT_MASK(30));
3751 }
3752 
3753 static int
3754 bwn_dma_mask2type(uint64_t dmamask)
3755 {
3756 
3757 	if (dmamask == BWN_DMA_BIT_MASK(30))
3758 		return (BWN_DMA_30BIT);
3759 	if (dmamask == BWN_DMA_BIT_MASK(32))
3760 		return (BWN_DMA_32BIT);
3761 	if (dmamask == BWN_DMA_BIT_MASK(64))
3762 		return (BWN_DMA_64BIT);
3763 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3764 	return (BWN_DMA_30BIT);
3765 }
3766 
3767 static void
3768 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3769 {
3770 	struct bwn_pio_txpkt *tp;
3771 	unsigned int i;
3772 
3773 	for (i = 0; i < N(tq->tq_pkts); i++) {
3774 		tp = &(tq->tq_pkts[i]);
3775 		if (tp->tp_m) {
3776 			m_freem(tp->tp_m);
3777 			tp->tp_m = NULL;
3778 		}
3779 	}
3780 }
3781 
3782 static uint16_t
3783 bwn_dma_base(int type, int controller_idx)
3784 {
3785 	static const uint16_t map64[] = {
3786 		BWN_DMA64_BASE0,
3787 		BWN_DMA64_BASE1,
3788 		BWN_DMA64_BASE2,
3789 		BWN_DMA64_BASE3,
3790 		BWN_DMA64_BASE4,
3791 		BWN_DMA64_BASE5,
3792 	};
3793 	static const uint16_t map32[] = {
3794 		BWN_DMA32_BASE0,
3795 		BWN_DMA32_BASE1,
3796 		BWN_DMA32_BASE2,
3797 		BWN_DMA32_BASE3,
3798 		BWN_DMA32_BASE4,
3799 		BWN_DMA32_BASE5,
3800 	};
3801 
3802 	if (type == BWN_DMA_64BIT) {
3803 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3804 		    ("%s:%d: fail", __func__, __LINE__));
3805 		return (map64[controller_idx]);
3806 	}
3807 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3808 	    ("%s:%d: fail", __func__, __LINE__));
3809 	return (map32[controller_idx]);
3810 }
3811 
3812 static void
3813 bwn_dma_init(struct bwn_mac *mac)
3814 {
3815 	struct bwn_dma *dma = &mac->mac_method.dma;
3816 
3817 	/* setup TX DMA channels. */
3818 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3819 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3820 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3821 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3822 	bwn_dma_setup(dma->mcast);
3823 	/* setup RX DMA channel. */
3824 	bwn_dma_setup(dma->rx);
3825 }
3826 
3827 static struct bwn_dma_ring *
3828 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3829     int for_tx, int type)
3830 {
3831 	struct bwn_dma *dma = &mac->mac_method.dma;
3832 	struct bwn_dma_ring *dr;
3833 	struct bwn_dmadesc_generic *desc;
3834 	struct bwn_dmadesc_meta *mt;
3835 	struct bwn_softc *sc = mac->mac_sc;
3836 	int error, i;
3837 
3838 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3839 	if (dr == NULL)
3840 		goto out;
3841 	dr->dr_numslots = BWN_RXRING_SLOTS;
3842 	if (for_tx)
3843 		dr->dr_numslots = BWN_TXRING_SLOTS;
3844 
3845 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3846 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3847 	if (dr->dr_meta == NULL)
3848 		goto fail0;
3849 
3850 	dr->dr_type = type;
3851 	dr->dr_mac = mac;
3852 	dr->dr_base = bwn_dma_base(type, controller_index);
3853 	dr->dr_index = controller_index;
3854 	if (type == BWN_DMA_64BIT) {
3855 		dr->getdesc = bwn_dma_64_getdesc;
3856 		dr->setdesc = bwn_dma_64_setdesc;
3857 		dr->start_transfer = bwn_dma_64_start_transfer;
3858 		dr->suspend = bwn_dma_64_suspend;
3859 		dr->resume = bwn_dma_64_resume;
3860 		dr->get_curslot = bwn_dma_64_get_curslot;
3861 		dr->set_curslot = bwn_dma_64_set_curslot;
3862 	} else {
3863 		dr->getdesc = bwn_dma_32_getdesc;
3864 		dr->setdesc = bwn_dma_32_setdesc;
3865 		dr->start_transfer = bwn_dma_32_start_transfer;
3866 		dr->suspend = bwn_dma_32_suspend;
3867 		dr->resume = bwn_dma_32_resume;
3868 		dr->get_curslot = bwn_dma_32_get_curslot;
3869 		dr->set_curslot = bwn_dma_32_set_curslot;
3870 	}
3871 	if (for_tx) {
3872 		dr->dr_tx = 1;
3873 		dr->dr_curslot = -1;
3874 	} else {
3875 		if (dr->dr_index == 0) {
3876 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3877 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3878 		} else
3879 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3880 	}
3881 
3882 	error = bwn_dma_allocringmemory(dr);
3883 	if (error)
3884 		goto fail2;
3885 
3886 	if (for_tx) {
3887 		/*
3888 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3889 		 * BWN_TX_SLOTS_PER_FRAME
3890 		 */
3891 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3892 		    ("%s:%d: fail", __func__, __LINE__));
3893 
3894 		dr->dr_txhdr_cache =
3895 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3896 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3897 		KASSERT(dr->dr_txhdr_cache != NULL,
3898 		    ("%s:%d: fail", __func__, __LINE__));
3899 
3900 		/*
3901 		 * Create TX ring DMA stuffs
3902 		 */
3903 		error = bus_dma_tag_create(dma->parent_dtag,
3904 				    BWN_ALIGN, 0,
3905 				    BUS_SPACE_MAXADDR,
3906 				    BUS_SPACE_MAXADDR,
3907 				    NULL, NULL,
3908 				    BWN_HDRSIZE(mac),
3909 				    1,
3910 				    BUS_SPACE_MAXSIZE_32BIT,
3911 				    0,
3912 				    NULL, NULL,
3913 				    &dr->dr_txring_dtag);
3914 		if (error) {
3915 			device_printf(sc->sc_dev,
3916 			    "can't create TX ring DMA tag: TODO frees\n");
3917 			goto fail1;
3918 		}
3919 
3920 		for (i = 0; i < dr->dr_numslots; i += 2) {
3921 			dr->getdesc(dr, i, &desc, &mt);
3922 
3923 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3924 			mt->mt_m = NULL;
3925 			mt->mt_ni = NULL;
3926 			mt->mt_islast = 0;
3927 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3928 			    &mt->mt_dmap);
3929 			if (error) {
3930 				device_printf(sc->sc_dev,
3931 				     "can't create RX buf DMA map\n");
3932 				goto fail1;
3933 			}
3934 
3935 			dr->getdesc(dr, i + 1, &desc, &mt);
3936 
3937 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3938 			mt->mt_m = NULL;
3939 			mt->mt_ni = NULL;
3940 			mt->mt_islast = 1;
3941 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3942 			    &mt->mt_dmap);
3943 			if (error) {
3944 				device_printf(sc->sc_dev,
3945 				     "can't create RX buf DMA map\n");
3946 				goto fail1;
3947 			}
3948 		}
3949 	} else {
3950 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3951 		    &dr->dr_spare_dmap);
3952 		if (error) {
3953 			device_printf(sc->sc_dev,
3954 			    "can't create RX buf DMA map\n");
3955 			goto out;		/* XXX wrong! */
3956 		}
3957 
3958 		for (i = 0; i < dr->dr_numslots; i++) {
3959 			dr->getdesc(dr, i, &desc, &mt);
3960 
3961 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3962 			    &mt->mt_dmap);
3963 			if (error) {
3964 				device_printf(sc->sc_dev,
3965 				    "can't create RX buf DMA map\n");
3966 				goto out;	/* XXX wrong! */
3967 			}
3968 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3969 			if (error) {
3970 				device_printf(sc->sc_dev,
3971 				    "failed to allocate RX buf\n");
3972 				goto out;	/* XXX wrong! */
3973 			}
3974 		}
3975 
3976 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3977 		    BUS_DMASYNC_PREWRITE);
3978 
3979 		dr->dr_usedslot = dr->dr_numslots;
3980 	}
3981 
3982       out:
3983 	return (dr);
3984 
3985 fail2:
3986 	free(dr->dr_txhdr_cache, M_DEVBUF);
3987 fail1:
3988 	free(dr->dr_meta, M_DEVBUF);
3989 fail0:
3990 	free(dr, M_DEVBUF);
3991 	return (NULL);
3992 }
3993 
3994 static void
3995 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3996 {
3997 
3998 	if (dr == NULL)
3999 		return;
4000 
4001 	bwn_dma_free_descbufs(*dr);
4002 	bwn_dma_free_ringmemory(*dr);
4003 
4004 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
4005 	free((*dr)->dr_meta, M_DEVBUF);
4006 	free(*dr, M_DEVBUF);
4007 
4008 	*dr = NULL;
4009 }
4010 
4011 static void
4012 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
4013     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4014 {
4015 	struct bwn_dmadesc32 *desc;
4016 
4017 	*meta = &(dr->dr_meta[slot]);
4018 	desc = dr->dr_ring_descbase;
4019 	desc = &(desc[slot]);
4020 
4021 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4022 }
4023 
4024 static void
4025 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
4026     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4027     int start, int end, int irq)
4028 {
4029 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
4030 	uint32_t addr, addrext, ctl;
4031 	int slot;
4032 
4033 	slot = (int)(&(desc->dma.dma32) - descbase);
4034 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4035 	    ("%s:%d: fail", __func__, __LINE__));
4036 
4037 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
4038 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
4039 	addr |= siba_dma_translation(dr->dr_mac->mac_sd);
4040 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
4041 	if (slot == dr->dr_numslots - 1)
4042 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
4043 	if (start)
4044 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
4045 	if (end)
4046 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
4047 	if (irq)
4048 		ctl |= BWN_DMA32_DCTL_IRQ;
4049 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
4050 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
4051 
4052 	desc->dma.dma32.control = htole32(ctl);
4053 	desc->dma.dma32.address = htole32(addr);
4054 }
4055 
4056 static void
4057 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
4058 {
4059 
4060 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
4061 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
4062 }
4063 
4064 static void
4065 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
4066 {
4067 
4068 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4069 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
4070 }
4071 
4072 static void
4073 bwn_dma_32_resume(struct bwn_dma_ring *dr)
4074 {
4075 
4076 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
4077 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
4078 }
4079 
4080 static int
4081 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
4082 {
4083 	uint32_t val;
4084 
4085 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4086 	val &= BWN_DMA32_RXDPTR;
4087 
4088 	return (val / sizeof(struct bwn_dmadesc32));
4089 }
4090 
4091 static void
4092 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4093 {
4094 
4095 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4096 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4097 }
4098 
4099 static void
4100 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4101     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4102 {
4103 	struct bwn_dmadesc64 *desc;
4104 
4105 	*meta = &(dr->dr_meta[slot]);
4106 	desc = dr->dr_ring_descbase;
4107 	desc = &(desc[slot]);
4108 
4109 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4110 }
4111 
4112 static void
4113 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4114     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4115     int start, int end, int irq)
4116 {
4117 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4118 	int slot;
4119 	uint32_t ctl0 = 0, ctl1 = 0;
4120 	uint32_t addrlo, addrhi;
4121 	uint32_t addrext;
4122 
4123 	slot = (int)(&(desc->dma.dma64) - descbase);
4124 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4125 	    ("%s:%d: fail", __func__, __LINE__));
4126 
4127 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4128 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4129 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4130 	    30;
4131 	addrhi |= (siba_dma_translation(dr->dr_mac->mac_sd) << 1);
4132 	if (slot == dr->dr_numslots - 1)
4133 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4134 	if (start)
4135 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4136 	if (end)
4137 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4138 	if (irq)
4139 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4140 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4141 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4142 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4143 
4144 	desc->dma.dma64.control0 = htole32(ctl0);
4145 	desc->dma.dma64.control1 = htole32(ctl1);
4146 	desc->dma.dma64.address_low = htole32(addrlo);
4147 	desc->dma.dma64.address_high = htole32(addrhi);
4148 }
4149 
4150 static void
4151 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4152 {
4153 
4154 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4155 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4156 }
4157 
4158 static void
4159 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4160 {
4161 
4162 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4163 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4164 }
4165 
4166 static void
4167 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4168 {
4169 
4170 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4171 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4172 }
4173 
4174 static int
4175 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4176 {
4177 	uint32_t val;
4178 
4179 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4180 	val &= BWN_DMA64_RXSTATDPTR;
4181 
4182 	return (val / sizeof(struct bwn_dmadesc64));
4183 }
4184 
4185 static void
4186 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4187 {
4188 
4189 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4190 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4191 }
4192 
4193 static int
4194 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4195 {
4196 	struct bwn_mac *mac = dr->dr_mac;
4197 	struct bwn_dma *dma = &mac->mac_method.dma;
4198 	struct bwn_softc *sc = mac->mac_sc;
4199 	int error;
4200 
4201 	error = bus_dma_tag_create(dma->parent_dtag,
4202 			    BWN_ALIGN, 0,
4203 			    BUS_SPACE_MAXADDR,
4204 			    BUS_SPACE_MAXADDR,
4205 			    NULL, NULL,
4206 			    BWN_DMA_RINGMEMSIZE,
4207 			    1,
4208 			    BUS_SPACE_MAXSIZE_32BIT,
4209 			    0,
4210 			    NULL, NULL,
4211 			    &dr->dr_ring_dtag);
4212 	if (error) {
4213 		device_printf(sc->sc_dev,
4214 		    "can't create TX ring DMA tag: TODO frees\n");
4215 		return (-1);
4216 	}
4217 
4218 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4219 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4220 	    &dr->dr_ring_dmap);
4221 	if (error) {
4222 		device_printf(sc->sc_dev,
4223 		    "can't allocate DMA mem: TODO frees\n");
4224 		return (-1);
4225 	}
4226 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4227 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4228 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4229 	if (error) {
4230 		device_printf(sc->sc_dev,
4231 		    "can't load DMA mem: TODO free\n");
4232 		return (-1);
4233 	}
4234 
4235 	return (0);
4236 }
4237 
4238 static void
4239 bwn_dma_setup(struct bwn_dma_ring *dr)
4240 {
4241 	uint64_t ring64;
4242 	uint32_t addrext, ring32, value;
4243 	uint32_t trans = siba_dma_translation(dr->dr_mac->mac_sd);
4244 
4245 	if (dr->dr_tx) {
4246 		dr->dr_curslot = -1;
4247 
4248 		if (dr->dr_type == BWN_DMA_64BIT) {
4249 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4250 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4251 			    >> 30;
4252 			value = BWN_DMA64_TXENABLE;
4253 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4254 			    & BWN_DMA64_TXADDREXT_MASK;
4255 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4256 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4257 			    (ring64 & 0xffffffff));
4258 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4259 			    ((ring64 >> 32) &
4260 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4261 		} else {
4262 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4263 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4264 			value = BWN_DMA32_TXENABLE;
4265 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4266 			    & BWN_DMA32_TXADDREXT_MASK;
4267 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4268 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4269 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4270 		}
4271 		return;
4272 	}
4273 
4274 	/*
4275 	 * set for RX
4276 	 */
4277 	dr->dr_usedslot = dr->dr_numslots;
4278 
4279 	if (dr->dr_type == BWN_DMA_64BIT) {
4280 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4281 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4282 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4283 		value |= BWN_DMA64_RXENABLE;
4284 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4285 		    & BWN_DMA64_RXADDREXT_MASK;
4286 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4287 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4288 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4289 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4290 		    | (trans << 1));
4291 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4292 		    sizeof(struct bwn_dmadesc64));
4293 	} else {
4294 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4295 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4296 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4297 		value |= BWN_DMA32_RXENABLE;
4298 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4299 		    & BWN_DMA32_RXADDREXT_MASK;
4300 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4301 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4302 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4303 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4304 		    sizeof(struct bwn_dmadesc32));
4305 	}
4306 }
4307 
4308 static void
4309 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4310 {
4311 
4312 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4313 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4314 	    dr->dr_ring_dmap);
4315 }
4316 
4317 static void
4318 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4319 {
4320 
4321 	if (dr->dr_tx) {
4322 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4323 		if (dr->dr_type == BWN_DMA_64BIT) {
4324 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4325 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4326 		} else
4327 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4328 	} else {
4329 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4330 		if (dr->dr_type == BWN_DMA_64BIT) {
4331 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4332 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4333 		} else
4334 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4335 	}
4336 }
4337 
4338 static void
4339 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4340 {
4341 	struct bwn_dmadesc_generic *desc;
4342 	struct bwn_dmadesc_meta *meta;
4343 	struct bwn_mac *mac = dr->dr_mac;
4344 	struct bwn_dma *dma = &mac->mac_method.dma;
4345 	struct bwn_softc *sc = mac->mac_sc;
4346 	int i;
4347 
4348 	if (!dr->dr_usedslot)
4349 		return;
4350 	for (i = 0; i < dr->dr_numslots; i++) {
4351 		dr->getdesc(dr, i, &desc, &meta);
4352 
4353 		if (meta->mt_m == NULL) {
4354 			if (!dr->dr_tx)
4355 				device_printf(sc->sc_dev, "%s: not TX?\n",
4356 				    __func__);
4357 			continue;
4358 		}
4359 		if (dr->dr_tx) {
4360 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4361 				bus_dmamap_unload(dr->dr_txring_dtag,
4362 				    meta->mt_dmap);
4363 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4364 				bus_dmamap_unload(dma->txbuf_dtag,
4365 				    meta->mt_dmap);
4366 		} else
4367 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4368 		bwn_dma_free_descbuf(dr, meta);
4369 	}
4370 }
4371 
4372 static int
4373 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4374     int type)
4375 {
4376 	struct bwn_softc *sc = mac->mac_sc;
4377 	uint32_t value;
4378 	int i;
4379 	uint16_t offset;
4380 
4381 	for (i = 0; i < 10; i++) {
4382 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4383 		    BWN_DMA32_TXSTATUS;
4384 		value = BWN_READ_4(mac, base + offset);
4385 		if (type == BWN_DMA_64BIT) {
4386 			value &= BWN_DMA64_TXSTAT;
4387 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4388 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4389 			    value == BWN_DMA64_TXSTAT_STOPPED)
4390 				break;
4391 		} else {
4392 			value &= BWN_DMA32_TXSTATE;
4393 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4394 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4395 			    value == BWN_DMA32_TXSTAT_STOPPED)
4396 				break;
4397 		}
4398 		DELAY(1000);
4399 	}
4400 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4401 	BWN_WRITE_4(mac, base + offset, 0);
4402 	for (i = 0; i < 10; i++) {
4403 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4404 						   BWN_DMA32_TXSTATUS;
4405 		value = BWN_READ_4(mac, base + offset);
4406 		if (type == BWN_DMA_64BIT) {
4407 			value &= BWN_DMA64_TXSTAT;
4408 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4409 				i = -1;
4410 				break;
4411 			}
4412 		} else {
4413 			value &= BWN_DMA32_TXSTATE;
4414 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4415 				i = -1;
4416 				break;
4417 			}
4418 		}
4419 		DELAY(1000);
4420 	}
4421 	if (i != -1) {
4422 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4423 		return (ENODEV);
4424 	}
4425 	DELAY(1000);
4426 
4427 	return (0);
4428 }
4429 
4430 static int
4431 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4432     int type)
4433 {
4434 	struct bwn_softc *sc = mac->mac_sc;
4435 	uint32_t value;
4436 	int i;
4437 	uint16_t offset;
4438 
4439 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4440 	BWN_WRITE_4(mac, base + offset, 0);
4441 	for (i = 0; i < 10; i++) {
4442 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4443 		    BWN_DMA32_RXSTATUS;
4444 		value = BWN_READ_4(mac, base + offset);
4445 		if (type == BWN_DMA_64BIT) {
4446 			value &= BWN_DMA64_RXSTAT;
4447 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4448 				i = -1;
4449 				break;
4450 			}
4451 		} else {
4452 			value &= BWN_DMA32_RXSTATE;
4453 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4454 				i = -1;
4455 				break;
4456 			}
4457 		}
4458 		DELAY(1000);
4459 	}
4460 	if (i != -1) {
4461 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4462 		return (ENODEV);
4463 	}
4464 
4465 	return (0);
4466 }
4467 
4468 static void
4469 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4470     struct bwn_dmadesc_meta *meta)
4471 {
4472 
4473 	if (meta->mt_m != NULL) {
4474 		m_freem(meta->mt_m);
4475 		meta->mt_m = NULL;
4476 	}
4477 	if (meta->mt_ni != NULL) {
4478 		ieee80211_free_node(meta->mt_ni);
4479 		meta->mt_ni = NULL;
4480 	}
4481 }
4482 
4483 static void
4484 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4485 {
4486 	struct bwn_rxhdr4 *rxhdr;
4487 	unsigned char *frame;
4488 
4489 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4490 	rxhdr->frame_len = 0;
4491 
4492 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4493 	    sizeof(struct bwn_plcp6) + 2,
4494 	    ("%s:%d: fail", __func__, __LINE__));
4495 	frame = mtod(m, char *) + dr->dr_frameoffset;
4496 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4497 }
4498 
4499 static uint8_t
4500 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4501 {
4502 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4503 
4504 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4505 	    == 0xff);
4506 }
4507 
4508 static void
4509 bwn_wme_init(struct bwn_mac *mac)
4510 {
4511 
4512 	bwn_wme_load(mac);
4513 
4514 	/* enable WME support. */
4515 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4516 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4517 	    BWN_IFSCTL_USE_EDCF);
4518 }
4519 
4520 static void
4521 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4522 {
4523 	struct bwn_softc *sc = mac->mac_sc;
4524 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4525 	uint16_t delay;	/* microsec */
4526 
4527 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4528 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4529 		delay = 500;
4530 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4531 		delay = max(delay, (uint16_t)2400);
4532 
4533 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4534 }
4535 
4536 static void
4537 bwn_bt_enable(struct bwn_mac *mac)
4538 {
4539 	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
4540 	uint64_t hf;
4541 
4542 	if (bwn_bluetooth == 0)
4543 		return;
4544 	if ((sprom->bf_lo & BWN_BFL_BTCOEXIST) == 0)
4545 		return;
4546 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4547 		return;
4548 
4549 	hf = bwn_hf_read(mac);
4550 	if (sprom->bf_lo & BWN_BFL_BTCMOD)
4551 		hf |= BWN_HF_BT_COEXISTALT;
4552 	else
4553 		hf |= BWN_HF_BT_COEXIST;
4554 	bwn_hf_write(mac, hf);
4555 }
4556 
4557 static void
4558 bwn_set_macaddr(struct bwn_mac *mac)
4559 {
4560 
4561 	bwn_mac_write_bssid(mac);
4562 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4563 }
4564 
4565 static void
4566 bwn_clear_keys(struct bwn_mac *mac)
4567 {
4568 	int i;
4569 
4570 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4571 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4572 		    ("%s:%d: fail", __func__, __LINE__));
4573 
4574 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4575 		    NULL, BWN_SEC_KEYSIZE, NULL);
4576 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4577 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4578 			    NULL, BWN_SEC_KEYSIZE, NULL);
4579 		}
4580 		mac->mac_key[i].keyconf = NULL;
4581 	}
4582 }
4583 
4584 static void
4585 bwn_crypt_init(struct bwn_mac *mac)
4586 {
4587 
4588 	mac->mac_max_nr_keys = (mac->mac_sd->sd_id.sd_rev >= 5) ? 58 : 20;
4589 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4590 	    ("%s:%d: fail", __func__, __LINE__));
4591 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4592 	mac->mac_ktp *= 2;
4593 	if (mac->mac_sd->sd_id.sd_rev >= 5) {
4594 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT,
4595 		    mac->mac_max_nr_keys - 8);
4596 	}
4597 	bwn_clear_keys(mac);
4598 }
4599 
4600 static void
4601 bwn_chip_exit(struct bwn_mac *mac)
4602 {
4603 
4604 	bwn_phy_exit(mac);
4605 	bwn_gpio_cleanup(mac);
4606 }
4607 
4608 static int
4609 bwn_fw_fillinfo(struct bwn_mac *mac)
4610 {
4611 	int error;
4612 
4613 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4614 	if (error == 0)
4615 		return (0);
4616 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4617 	if (error == 0)
4618 		return (0);
4619 	return (error);
4620 }
4621 
4622 static int
4623 bwn_gpio_init(struct bwn_mac *mac)
4624 {
4625 	struct siba_softc *bus = mac->mac_sd->sd_bus;
4626 	struct siba_dev_softc *sd;
4627 	uint32_t mask = 0x0000001f, set = 0x0000000f;
4628 
4629 	BWN_WRITE_4(mac, BWN_MACCTL,
4630 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4631 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4632 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4633 
4634 	if (bus->siba_chipid == 0x4301) {
4635 		mask |= 0x0060;
4636 		set |= 0x0060;
4637 	}
4638 	if (bus->siba_sprom.bf_lo & BWN_BFL_PACTRL) {
4639 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4640 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4641 		mask |= 0x0200;
4642 		set |= 0x0200;
4643 	}
4644 	if (mac->mac_sd->sd_id.sd_rev >= 2)
4645 		mask |= 0x0010;
4646 	sd = (bus->siba_cc.scc_dev != NULL) ? bus->siba_cc.scc_dev :
4647 	    bus->siba_pci.spc_dev;
4648 	if (sd == NULL)
4649 		return (0);
4650 	siba_write_4(sd, BWN_GPIOCTL,
4651 	    (siba_read_4(sd, BWN_GPIOCTL) & mask) | set);
4652 
4653 	return (0);
4654 }
4655 
4656 static int
4657 bwn_fw_loadinitvals(struct bwn_mac *mac)
4658 {
4659 #define	GETFWOFFSET(fwp, offset)				\
4660 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4661 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4662 	const struct bwn_fwhdr *hdr;
4663 	struct bwn_fw *fw = &mac->mac_fw;
4664 	int error;
4665 
4666 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4667 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4668 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4669 	if (error)
4670 		return (error);
4671 	if (fw->initvals_band.fw) {
4672 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4673 		error = bwn_fwinitvals_write(mac,
4674 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4675 		    be32toh(hdr->size),
4676 		    fw->initvals_band.fw->datasize - hdr_len);
4677 	}
4678 	return (error);
4679 #undef GETFWOFFSET
4680 }
4681 
4682 static int
4683 bwn_phy_init(struct bwn_mac *mac)
4684 {
4685 	struct bwn_softc *sc = mac->mac_sc;
4686 	int error;
4687 
4688 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4689 	mac->mac_phy.rf_onoff(mac, 1);
4690 	error = mac->mac_phy.init(mac);
4691 	if (error) {
4692 		device_printf(sc->sc_dev, "PHY init failed\n");
4693 		goto fail0;
4694 	}
4695 	error = bwn_switch_channel(mac,
4696 	    mac->mac_phy.get_default_chan(mac));
4697 	if (error) {
4698 		device_printf(sc->sc_dev,
4699 		    "failed to switch default channel\n");
4700 		goto fail1;
4701 	}
4702 	return (0);
4703 fail1:
4704 	if (mac->mac_phy.exit)
4705 		mac->mac_phy.exit(mac);
4706 fail0:
4707 	mac->mac_phy.rf_onoff(mac, 0);
4708 
4709 	return (error);
4710 }
4711 
4712 static void
4713 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4714 {
4715 	uint16_t ant;
4716 	uint16_t tmp;
4717 
4718 	ant = bwn_ant2phy(antenna);
4719 
4720 	/* For ACK/CTS */
4721 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4722 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4723 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4724 	/* For Probe Resposes */
4725 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4726 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4727 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4728 }
4729 
4730 static void
4731 bwn_set_opmode(struct bwn_mac *mac)
4732 {
4733 	struct bwn_softc *sc = mac->mac_sc;
4734 	struct ifnet *ifp = sc->sc_ifp;
4735 	struct ieee80211com *ic = ifp->if_l2com;
4736 	uint32_t ctl;
4737 	uint16_t cfp_pretbtt;
4738 
4739 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4740 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4741 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4742 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4743 	ctl |= BWN_MACCTL_STA;
4744 
4745 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4746 	    ic->ic_opmode == IEEE80211_M_MBSS)
4747 		ctl |= BWN_MACCTL_HOSTAP;
4748 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4749 		ctl &= ~BWN_MACCTL_STA;
4750 	ctl |= sc->sc_filters;
4751 
4752 	if (mac->mac_sd->sd_id.sd_rev <= 4)
4753 		ctl |= BWN_MACCTL_PROMISC;
4754 
4755 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4756 
4757 	cfp_pretbtt = 2;
4758 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4759 		if (mac->mac_sd->sd_bus->siba_chipid == 0x4306 &&
4760 		    mac->mac_sd->sd_bus->siba_chiprev == 3)
4761 			cfp_pretbtt = 100;
4762 		else
4763 			cfp_pretbtt = 50;
4764 	}
4765 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4766 }
4767 
4768 static void
4769 bwn_gpio_cleanup(struct bwn_mac *mac)
4770 {
4771 	struct siba_softc *bus = mac->mac_sd->sd_bus;
4772 	struct siba_dev_softc *gpiodev, *pcidev = NULL;
4773 
4774 	pcidev = bus->siba_pci.spc_dev;
4775 	gpiodev = bus->siba_cc.scc_dev ? bus->siba_cc.scc_dev : pcidev;
4776 	if (!gpiodev)
4777 		return;
4778 	siba_write_4(gpiodev, BWN_GPIOCTL, 0);
4779 }
4780 
4781 static int
4782 bwn_dma_gettype(struct bwn_mac *mac)
4783 {
4784 	uint32_t tmp;
4785 	uint16_t base;
4786 
4787 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4788 	if (tmp & SIBA_TGSHIGH_DMA64)
4789 		return (BWN_DMA_64BIT);
4790 	base = bwn_dma_base(0, 0);
4791 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4792 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4793 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4794 		return (BWN_DMA_32BIT);
4795 
4796 	return (BWN_DMA_30BIT);
4797 }
4798 
4799 static void
4800 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4801 {
4802 	if (!error) {
4803 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4804 		*((bus_addr_t *)arg) = seg->ds_addr;
4805 	}
4806 }
4807 
4808 static void
4809 bwn_phy_g_init_sub(struct bwn_mac *mac)
4810 {
4811 	struct bwn_phy *phy = &mac->mac_phy;
4812 	struct bwn_phy_g *pg = &phy->phy_g;
4813 	uint16_t i, tmp;
4814 
4815 	if (phy->rev == 1)
4816 		bwn_phy_init_b5(mac);
4817 	else
4818 		bwn_phy_init_b6(mac);
4819 
4820 	if (phy->rev >= 2 || phy->gmode)
4821 		bwn_phy_init_a(mac);
4822 
4823 	if (phy->rev >= 2) {
4824 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4825 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4826 	}
4827 	if (phy->rev == 2) {
4828 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4829 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4830 	}
4831 	if (phy->rev > 5) {
4832 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4833 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4834 	}
4835 	if (phy->gmode || phy->rev >= 2) {
4836 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4837 		tmp &= BWN_PHYVER_VERSION;
4838 		if (tmp == 3 || tmp == 5) {
4839 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4840 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4841 		}
4842 		if (tmp == 5) {
4843 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4844 			    0x1f00);
4845 		}
4846 	}
4847 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4848 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4849 	if (phy->rf_rev == 8) {
4850 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4851 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4852 	}
4853 	if (BWN_HAS_LOOPBACK(phy))
4854 		bwn_loopback_calcgain(mac);
4855 
4856 	if (phy->rf_rev != 8) {
4857 		if (pg->pg_initval == 0xffff)
4858 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4859 		else
4860 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4861 	}
4862 	bwn_lo_g_init(mac);
4863 	if (BWN_HAS_TXMAG(phy)) {
4864 		BWN_RF_WRITE(mac, 0x52,
4865 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4866 		    | pg->pg_loctl.tx_bias |
4867 		    pg->pg_loctl.tx_magn);
4868 	} else {
4869 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4870 	}
4871 	if (phy->rev >= 6) {
4872 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4873 		    (pg->pg_loctl.tx_bias << 12));
4874 	}
4875 	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL)
4876 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4877 	else
4878 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4879 	if (phy->rev < 2)
4880 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4881 	else
4882 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4883 	if (phy->gmode || phy->rev >= 2) {
4884 		bwn_lo_g_adjust(mac);
4885 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4886 	}
4887 
4888 	if (!(mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
4889 		for (i = 0; i < 64; i++) {
4890 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4891 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4892 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4893 			    -32), 31));
4894 		}
4895 		bwn_nrssi_threshold(mac);
4896 	} else if (phy->gmode || phy->rev >= 2) {
4897 		if (pg->pg_nrssi[0] == -1000) {
4898 			KASSERT(pg->pg_nrssi[1] == -1000,
4899 			    ("%s:%d: fail", __func__, __LINE__));
4900 			bwn_nrssi_slope_11g(mac);
4901 		} else
4902 			bwn_nrssi_threshold(mac);
4903 	}
4904 	if (phy->rf_rev == 8)
4905 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4906 	bwn_phy_hwpctl_init(mac);
4907 	if ((mac->mac_sd->sd_bus->siba_chipid == 0x4306
4908 	     && mac->mac_sd->sd_bus->siba_chippkg == 2) || 0) {
4909 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4910 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4911 	}
4912 }
4913 
4914 static uint8_t
4915 bwn_has_hwpctl(struct bwn_mac *mac)
4916 {
4917 
4918 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4919 		return (0);
4920 	return (mac->mac_phy.use_hwpctl(mac));
4921 }
4922 
4923 static void
4924 bwn_phy_init_b5(struct bwn_mac *mac)
4925 {
4926 	struct siba_softc *bus = mac->mac_sd->sd_bus;
4927 	struct bwn_phy *phy = &mac->mac_phy;
4928 	struct bwn_phy_g *pg = &phy->phy_g;
4929 	uint16_t offset, value;
4930 	uint8_t old_channel;
4931 
4932 	if (phy->analog == 1)
4933 		BWN_RF_SET(mac, 0x007a, 0x0050);
4934 	if ((bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM) &&
4935 	    (bus->siba_board_type != SIBA_BOARD_BU4306)) {
4936 		value = 0x2120;
4937 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4938 			BWN_PHY_WRITE(mac, offset, value);
4939 			value += 0x202;
4940 		}
4941 	}
4942 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4943 	if (phy->rf_ver == 0x2050)
4944 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4945 
4946 	if (phy->gmode || phy->rev >= 2) {
4947 		if (phy->rf_ver == 0x2050) {
4948 			BWN_RF_SET(mac, 0x007a, 0x0020);
4949 			BWN_RF_SET(mac, 0x0051, 0x0004);
4950 		}
4951 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4952 
4953 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4954 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4955 
4956 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4957 
4958 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4959 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4960 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4961 	}
4962 
4963 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4964 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4965 
4966 	if (phy->analog == 1) {
4967 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4968 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4969 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4970 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4971 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4972 	} else
4973 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4974 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4975 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4976 
4977 	if (phy->analog == 1)
4978 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4979 	else
4980 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4981 
4982 	if (phy->analog == 0)
4983 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4984 
4985 	old_channel = phy->chan;
4986 	bwn_phy_g_switch_chan(mac, 7, 0);
4987 
4988 	if (phy->rf_ver != 0x2050) {
4989 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4990 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4991 	}
4992 
4993 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4994 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4995 
4996 	if (phy->rf_ver == 0x2050) {
4997 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4998 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4999 	}
5000 
5001 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
5002 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
5003 	BWN_RF_SET(mac, 0x007a, 0x0007);
5004 
5005 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5006 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
5007 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
5008 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
5009 
5010 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5011 	    pg->pg_txctl);
5012 
5013 	if (phy->rf_ver == 0x2050)
5014 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5015 
5016 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
5017 }
5018 
5019 static void
5020 bwn_loopback_calcgain(struct bwn_mac *mac)
5021 {
5022 	struct bwn_phy *phy = &mac->mac_phy;
5023 	struct bwn_phy_g *pg = &phy->phy_g;
5024 	uint16_t backup_phy[16] = { 0 };
5025 	uint16_t backup_radio[3];
5026 	uint16_t backup_bband;
5027 	uint16_t i, j, loop_i_max;
5028 	uint16_t trsw_rx;
5029 	uint16_t loop1_outer_done, loop1_inner_done;
5030 
5031 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5032 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
5033 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5034 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5035 	if (phy->rev != 1) {
5036 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5037 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5038 	}
5039 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5040 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5041 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5042 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
5043 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
5044 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5045 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5046 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
5047 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5048 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5049 	backup_bband = pg->pg_bbatt.att;
5050 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
5051 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
5052 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
5053 
5054 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
5055 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
5056 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
5057 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
5058 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
5059 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
5060 	if (phy->rev != 1) {
5061 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
5062 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
5063 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
5064 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
5065 	}
5066 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
5067 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
5068 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
5069 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
5070 
5071 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
5072 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5073 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5074 
5075 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
5076 	if (phy->rev != 1) {
5077 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
5078 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
5079 	}
5080 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
5081 
5082 	if (phy->rf_rev == 8)
5083 		BWN_RF_WRITE(mac, 0x43, 0x000f);
5084 	else {
5085 		BWN_RF_WRITE(mac, 0x52, 0);
5086 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
5087 	}
5088 	bwn_phy_g_set_bbatt(mac, 11);
5089 
5090 	if (phy->rev >= 3)
5091 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5092 	else
5093 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5094 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5095 
5096 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5097 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5098 
5099 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5100 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5101 
5102 	if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) {
5103 		if (phy->rev >= 7) {
5104 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5105 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5106 		}
5107 	}
5108 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5109 
5110 	j = 0;
5111 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5112 	for (i = 0; i < loop_i_max; i++) {
5113 		for (j = 0; j < 16; j++) {
5114 			BWN_RF_WRITE(mac, 0x43, i);
5115 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5116 			    (j << 8));
5117 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5118 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5119 			DELAY(20);
5120 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5121 				goto done0;
5122 		}
5123 	}
5124 done0:
5125 	loop1_outer_done = i;
5126 	loop1_inner_done = j;
5127 	if (j >= 8) {
5128 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5129 		trsw_rx = 0x1b;
5130 		for (j = j - 8; j < 16; j++) {
5131 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5132 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5133 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5134 			DELAY(20);
5135 			trsw_rx -= 3;
5136 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5137 				goto done1;
5138 		}
5139 	} else
5140 		trsw_rx = 0x18;
5141 done1:
5142 
5143 	if (phy->rev != 1) {
5144 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5145 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5146 	}
5147 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5148 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5149 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5150 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5151 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5152 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5153 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5154 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5155 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5156 
5157 	bwn_phy_g_set_bbatt(mac, backup_bband);
5158 
5159 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5160 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5161 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5162 
5163 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5164 	DELAY(10);
5165 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5166 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5167 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5168 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5169 
5170 	pg->pg_max_lb_gain =
5171 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5172 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5173 }
5174 
5175 static uint16_t
5176 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5177 {
5178 	struct bwn_phy *phy = &mac->mac_phy;
5179 	uint32_t tmp1 = 0, tmp2 = 0;
5180 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5181 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5182 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5183 	static const uint8_t rcc_table[] = {
5184 		0x02, 0x03, 0x01, 0x0f,
5185 		0x06, 0x07, 0x05, 0x0f,
5186 		0x0a, 0x0b, 0x09, 0x0f,
5187 		0x0e, 0x0f, 0x0d, 0x0f,
5188 	};
5189 
5190 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5191 	    rfoverval = rfover = cck3 = 0;
5192 	radio0 = BWN_RF_READ(mac, 0x43);
5193 	radio1 = BWN_RF_READ(mac, 0x51);
5194 	radio2 = BWN_RF_READ(mac, 0x52);
5195 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5196 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5197 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5198 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5199 
5200 	if (phy->type == BWN_PHYTYPE_B) {
5201 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5202 		reg0 = BWN_READ_2(mac, 0x3ec);
5203 
5204 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5205 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5206 	} else if (phy->gmode || phy->rev >= 2) {
5207 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5208 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5209 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5210 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5211 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5212 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5213 
5214 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5215 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5216 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5217 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5218 		if (BWN_HAS_LOOPBACK(phy)) {
5219 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5220 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5221 			if (phy->rev >= 3)
5222 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5223 			else
5224 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5225 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5226 		}
5227 
5228 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5229 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5230 			BWN_LPD(0, 1, 1)));
5231 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5232 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5233 	}
5234 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5235 
5236 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5237 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5238 	reg1 = BWN_READ_2(mac, 0x3e6);
5239 	reg2 = BWN_READ_2(mac, 0x3f4);
5240 
5241 	if (phy->analog == 0)
5242 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5243 	else {
5244 		if (phy->analog >= 2)
5245 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5246 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5247 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5248 	}
5249 
5250 	reg = BWN_RF_READ(mac, 0x60);
5251 	index = (reg & 0x001e) >> 1;
5252 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5253 
5254 	if (phy->type == BWN_PHYTYPE_B)
5255 		BWN_RF_WRITE(mac, 0x78, 0x26);
5256 	if (phy->gmode || phy->rev >= 2) {
5257 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5258 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5259 			BWN_LPD(0, 1, 1)));
5260 	}
5261 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5262 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5263 	if (phy->gmode || phy->rev >= 2) {
5264 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5265 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5266 			BWN_LPD(0, 0, 1)));
5267 	}
5268 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5269 	BWN_RF_SET(mac, 0x51, 0x0004);
5270 	if (phy->rf_rev == 8)
5271 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5272 	else {
5273 		BWN_RF_WRITE(mac, 0x52, 0);
5274 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5275 	}
5276 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5277 
5278 	for (i = 0; i < 16; i++) {
5279 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5280 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5281 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5282 		if (phy->gmode || phy->rev >= 2) {
5283 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5284 			    bwn_rf_2050_rfoverval(mac,
5285 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5286 		}
5287 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5288 		DELAY(10);
5289 		if (phy->gmode || phy->rev >= 2) {
5290 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5291 			    bwn_rf_2050_rfoverval(mac,
5292 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5293 		}
5294 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5295 		DELAY(10);
5296 		if (phy->gmode || phy->rev >= 2) {
5297 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5298 			    bwn_rf_2050_rfoverval(mac,
5299 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5300 		}
5301 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5302 		DELAY(20);
5303 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5304 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5305 		if (phy->gmode || phy->rev >= 2) {
5306 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5307 			    bwn_rf_2050_rfoverval(mac,
5308 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5309 		}
5310 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5311 	}
5312 	DELAY(10);
5313 
5314 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5315 	tmp1++;
5316 	tmp1 >>= 9;
5317 
5318 	for (i = 0; i < 16; i++) {
5319 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5320 		BWN_RF_WRITE(mac, 0x78, radio78);
5321 		DELAY(10);
5322 		for (j = 0; j < 16; j++) {
5323 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5324 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5325 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5326 			if (phy->gmode || phy->rev >= 2) {
5327 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5328 				    bwn_rf_2050_rfoverval(mac,
5329 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5330 			}
5331 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5332 			DELAY(10);
5333 			if (phy->gmode || phy->rev >= 2) {
5334 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5335 				    bwn_rf_2050_rfoverval(mac,
5336 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5337 			}
5338 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5339 			DELAY(10);
5340 			if (phy->gmode || phy->rev >= 2) {
5341 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5342 				    bwn_rf_2050_rfoverval(mac,
5343 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5344 			}
5345 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5346 			DELAY(10);
5347 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5348 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5349 			if (phy->gmode || phy->rev >= 2) {
5350 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5351 				    bwn_rf_2050_rfoverval(mac,
5352 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5353 			}
5354 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5355 		}
5356 		tmp2++;
5357 		tmp2 >>= 8;
5358 		if (tmp1 < tmp2)
5359 			break;
5360 	}
5361 
5362 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5363 	BWN_RF_WRITE(mac, 0x51, radio1);
5364 	BWN_RF_WRITE(mac, 0x52, radio2);
5365 	BWN_RF_WRITE(mac, 0x43, radio0);
5366 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5367 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5368 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5369 	BWN_WRITE_2(mac, 0x3e6, reg1);
5370 	if (phy->analog != 0)
5371 		BWN_WRITE_2(mac, 0x3f4, reg2);
5372 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5373 	bwn_spu_workaround(mac, phy->chan);
5374 	if (phy->type == BWN_PHYTYPE_B) {
5375 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5376 		BWN_WRITE_2(mac, 0x3ec, reg0);
5377 	} else if (phy->gmode) {
5378 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5379 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5380 			    & 0x7fff);
5381 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5382 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5383 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5384 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5385 			      analogoverval);
5386 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5387 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5388 		if (BWN_HAS_LOOPBACK(phy)) {
5389 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5390 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5391 		}
5392 	}
5393 
5394 	return ((i > 15) ? radio78 : rcc);
5395 }
5396 
5397 static void
5398 bwn_phy_init_b6(struct bwn_mac *mac)
5399 {
5400 	struct bwn_phy *phy = &mac->mac_phy;
5401 	struct bwn_phy_g *pg = &phy->phy_g;
5402 	uint16_t offset, val;
5403 	uint8_t old_channel;
5404 
5405 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5406 	    ("%s:%d: fail", __func__, __LINE__));
5407 
5408 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5409 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5410 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5411 		BWN_RF_WRITE(mac, 0x51, 0x37);
5412 		BWN_RF_WRITE(mac, 0x52, 0x70);
5413 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5414 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5415 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5416 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5417 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5418 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5419 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5420 		bwn_hf_write(mac,
5421 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5422 	}
5423 	if (phy->rf_rev == 8) {
5424 		BWN_RF_WRITE(mac, 0x51, 0);
5425 		BWN_RF_WRITE(mac, 0x52, 0x40);
5426 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5427 		BWN_RF_WRITE(mac, 0x54, 0x98);
5428 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5429 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5430 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5431 		if (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_ALTIQ) {
5432 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5433 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5434 		} else {
5435 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5436 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5437 		}
5438 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5439 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5440 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5441 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5442 	}
5443 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5444 		BWN_PHY_WRITE(mac, offset, val);
5445 		val -= 0x0202;
5446 	}
5447 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5448 		BWN_PHY_WRITE(mac, offset, val);
5449 		val -= 0x0202;
5450 	}
5451 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5452 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5453 		val += 0x0202;
5454 	}
5455 	if (phy->type == BWN_PHYTYPE_G) {
5456 		BWN_RF_SET(mac, 0x007a, 0x0020);
5457 		BWN_RF_SET(mac, 0x0051, 0x0004);
5458 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5459 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5460 		BWN_PHY_WRITE(mac, 0x5b, 0);
5461 		BWN_PHY_WRITE(mac, 0x5c, 0);
5462 	}
5463 
5464 	old_channel = phy->chan;
5465 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5466 
5467 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5468 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5469 	DELAY(40);
5470 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5471 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5472 		BWN_RF_WRITE(mac, 0x50, 0x20);
5473 	}
5474 	if (phy->rf_rev <= 2) {
5475 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5476 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5477 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5478 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5479 	}
5480 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5481 
5482 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5483 
5484 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5485 	if (phy->rf_rev >= 6)
5486 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5487 	else
5488 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5489 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5490 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5491 	    pg->pg_txctl);
5492 	if (phy->rf_rev <= 5)
5493 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5494 	if (phy->rf_rev <= 2)
5495 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5496 
5497 	if (phy->analog == 4) {
5498 		BWN_WRITE_2(mac, 0x3e4, 9);
5499 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5500 	} else
5501 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5502 	if (phy->type == BWN_PHYTYPE_B)
5503 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5504 	else if (phy->type == BWN_PHYTYPE_G)
5505 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5506 }
5507 
5508 static void
5509 bwn_phy_init_a(struct bwn_mac *mac)
5510 {
5511 	struct bwn_phy *phy = &mac->mac_phy;
5512 
5513 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5514 	    ("%s:%d: fail", __func__, __LINE__));
5515 
5516 	if (phy->rev >= 6) {
5517 		if (phy->type == BWN_PHYTYPE_A)
5518 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5519 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5520 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5521 		else
5522 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5523 	}
5524 
5525 	bwn_wa_init(mac);
5526 
5527 	if (phy->type == BWN_PHYTYPE_G &&
5528 	    (mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_PACTRL))
5529 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5530 }
5531 
5532 static void
5533 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5534 {
5535 	int i;
5536 
5537 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5538 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5539 }
5540 
5541 static void
5542 bwn_wa_agc(struct bwn_mac *mac)
5543 {
5544 	struct bwn_phy *phy = &mac->mac_phy;
5545 
5546 	if (phy->rev == 1) {
5547 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5548 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5549 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5550 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5551 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5552 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5553 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5554 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5555 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5556 	} else {
5557 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5558 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5559 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5560 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5561 	}
5562 
5563 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5564 	    0x5700);
5565 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5566 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5567 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5568 	BWN_RF_SET(mac, 0x7a, 0x0008);
5569 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5570 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5571 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5572 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5573 	if (phy->rev == 1)
5574 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5575 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5576 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5577 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5578 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5579 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5580 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5581 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5582 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5583 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5584 	if (phy->rev == 1) {
5585 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5586 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5587 	} else {
5588 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5589 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5590 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5591 		if (phy->rev >= 6) {
5592 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5593 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5594 			    (uint16_t)~0xf000, 0x3000);
5595 		}
5596 	}
5597 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5598 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5599 	if (phy->rev == 1) {
5600 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5601 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5602 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5603 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5604 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5605 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5606 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5607 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5608 	} else {
5609 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5610 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5611 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5612 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5613 	}
5614 	if (phy->rev >= 6) {
5615 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5616 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5617 	}
5618 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5619 }
5620 
5621 static void
5622 bwn_wa_grev1(struct bwn_mac *mac)
5623 {
5624 	struct bwn_phy *phy = &mac->mac_phy;
5625 	int i;
5626 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5627 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5628 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5629 
5630 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5631 
5632 	/* init CRSTHRES and ANTDWELL */
5633 	if (phy->rev == 1) {
5634 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5635 	} else if (phy->rev == 2) {
5636 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5637 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5638 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5639 	} else {
5640 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5641 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5642 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5643 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5644 	}
5645 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5646 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5647 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5648 
5649 	/* XXX support PHY-A??? */
5650 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5651 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5652 		    bwn_tab_finefreqg[i]);
5653 
5654 	/* XXX support PHY-A??? */
5655 	if (phy->rev == 1)
5656 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5657 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5658 			    bwn_tab_noise_g1[i]);
5659 	else
5660 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5661 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5662 			    bwn_tab_noise_g2[i]);
5663 
5664 
5665 	for (i = 0; i < N(bwn_tab_rotor); i++)
5666 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5667 		    bwn_tab_rotor[i]);
5668 
5669 	/* XXX support PHY-A??? */
5670 	if (phy->rev >= 6) {
5671 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5672 		    BWN_PHY_ENCORE_EN)
5673 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5674 		else
5675 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5676 	} else
5677 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5678 
5679 	for (i = 0; i < N(bwn_tab_retard); i++)
5680 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5681 		    bwn_tab_retard[i]);
5682 
5683 	if (phy->rev == 1) {
5684 		for (i = 0; i < 16; i++)
5685 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5686 			    i, 0x0020);
5687 	} else {
5688 		for (i = 0; i < 32; i++)
5689 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5690 	}
5691 
5692 	bwn_wa_agc(mac);
5693 }
5694 
5695 static void
5696 bwn_wa_grev26789(struct bwn_mac *mac)
5697 {
5698 	struct bwn_phy *phy = &mac->mac_phy;
5699 	int i;
5700 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5701 	uint16_t ofdmrev;
5702 
5703 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5704 
5705 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5706 
5707 	/* init CRSTHRES and ANTDWELL */
5708 	if (phy->rev == 1)
5709 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5710 	else if (phy->rev == 2) {
5711 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5712 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5713 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5714 	} else {
5715 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5716 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5717 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5718 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5719 	}
5720 
5721 	for (i = 0; i < 64; i++)
5722 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5723 
5724 	/* XXX support PHY-A??? */
5725 	if (phy->rev == 1)
5726 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5727 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5728 			    bwn_tab_noise_g1[i]);
5729 	else
5730 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5731 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5732 			    bwn_tab_noise_g2[i]);
5733 
5734 	/* XXX support PHY-A??? */
5735 	if (phy->rev >= 6) {
5736 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5737 		    BWN_PHY_ENCORE_EN)
5738 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5739 		else
5740 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5741 	} else
5742 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5743 
5744 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5745 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5746 		    bwn_tab_sigmasqr2[i]);
5747 
5748 	if (phy->rev == 1) {
5749 		for (i = 0; i < 16; i++)
5750 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5751 			    0x0020);
5752 	} else {
5753 		for (i = 0; i < 32; i++)
5754 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5755 	}
5756 
5757 	bwn_wa_agc(mac);
5758 
5759 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5760 	if (ofdmrev > 2) {
5761 		if (phy->type == BWN_PHYTYPE_A)
5762 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5763 		else
5764 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5765 	} else {
5766 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5767 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5768 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5769 	}
5770 
5771 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5772 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5773 }
5774 
5775 static void
5776 bwn_wa_init(struct bwn_mac *mac)
5777 {
5778 	struct bwn_phy *phy = &mac->mac_phy;
5779 	struct siba_softc *bus = mac->mac_sd->sd_bus;
5780 
5781 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5782 
5783 	switch (phy->rev) {
5784 	case 1:
5785 		bwn_wa_grev1(mac);
5786 		break;
5787 	case 2:
5788 	case 6:
5789 	case 7:
5790 	case 8:
5791 	case 9:
5792 		bwn_wa_grev26789(mac);
5793 		break;
5794 	default:
5795 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5796 	}
5797 
5798 	if (bus->siba_board_vendor != SIBA_BOARDVENDOR_BCM ||
5799 	    bus->siba_board_type != SIBA_BOARD_BU4306 ||
5800 	    bus->siba_board_rev != 0x17) {
5801 		if (phy->rev < 2) {
5802 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5803 			    0x0002);
5804 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5805 			    0x0001);
5806 		} else {
5807 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5808 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5809 			if ((bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA) &&
5810 			    (phy->rev >= 7)) {
5811 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5812 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5813 				    0x0020, 0x0001);
5814 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5815 				    0x0021, 0x0001);
5816 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5817 				    0x0022, 0x0001);
5818 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5819 				    0x0023, 0x0000);
5820 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5821 				    0x0000, 0x0000);
5822 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5823 				    0x0003, 0x0002);
5824 			}
5825 		}
5826 	}
5827 	if (bus->siba_sprom.bf_lo & BWN_BFL_FEM) {
5828 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5829 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5830 	}
5831 
5832 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5833 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5834 }
5835 
5836 static void
5837 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5838     uint16_t value)
5839 {
5840 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5841 	uint16_t addr;
5842 
5843 	addr = table + offset;
5844 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5845 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5846 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5847 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5848 	}
5849 	pg->pg_ofdmtab_addr = addr;
5850 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5851 }
5852 
5853 static void
5854 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5855     uint32_t value)
5856 {
5857 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5858 	uint16_t addr;
5859 
5860 	addr = table + offset;
5861 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5862 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5863 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5864 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5865 	}
5866 	pg->pg_ofdmtab_addr = addr;
5867 
5868 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5869 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5870 }
5871 
5872 static void
5873 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5874     uint16_t value)
5875 {
5876 
5877 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5878 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5879 }
5880 
5881 static void
5882 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5883 {
5884 	struct bwn_phy *phy = &mac->mac_phy;
5885 	unsigned int i, max_loop;
5886 	uint16_t value;
5887 	uint32_t buffer[5] = {
5888 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5889 	};
5890 
5891 	if (ofdm) {
5892 		max_loop = 0x1e;
5893 		buffer[0] = 0x000201cc;
5894 	} else {
5895 		max_loop = 0xfa;
5896 		buffer[0] = 0x000b846e;
5897 	}
5898 
5899 	BWN_ASSERT_LOCKED(mac->mac_sc);
5900 
5901 	for (i = 0; i < 5; i++)
5902 		bwn_ram_write(mac, i * 4, buffer[i]);
5903 
5904 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5905 	BWN_WRITE_2(mac, 0x07c0,
5906 	    (mac->mac_sd->sd_id.sd_rev < 11) ? 0x0000 : 0x0100);
5907 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5908 	BWN_WRITE_2(mac, 0x050c, value);
5909 	if (phy->type == BWN_PHYTYPE_LP)
5910 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5911 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5912 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5913 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5914 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5915 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5916 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5917 	if (phy->type == BWN_PHYTYPE_LP)
5918 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5919 	else
5920 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5921 
5922 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5923 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5924 	for (i = 0x00; i < max_loop; i++) {
5925 		value = BWN_READ_2(mac, 0x050e);
5926 		if (value & 0x0080)
5927 			break;
5928 		DELAY(10);
5929 	}
5930 	for (i = 0x00; i < 0x0a; i++) {
5931 		value = BWN_READ_2(mac, 0x050e);
5932 		if (value & 0x0400)
5933 			break;
5934 		DELAY(10);
5935 	}
5936 	for (i = 0x00; i < 0x19; i++) {
5937 		value = BWN_READ_2(mac, 0x0690);
5938 		if (!(value & 0x0100))
5939 			break;
5940 		DELAY(10);
5941 	}
5942 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5943 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5944 }
5945 
5946 static void
5947 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5948 {
5949 	uint32_t macctl;
5950 
5951 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5952 
5953 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5954 	if (macctl & BWN_MACCTL_BIGENDIAN)
5955 		printf("TODO: need swap\n");
5956 
5957 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5958 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5959 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5960 }
5961 
5962 static void
5963 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5964 {
5965 	uint16_t value;
5966 
5967 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5968 	    ("%s:%d: fail", __func__, __LINE__));
5969 
5970 	value = (uint8_t) (ctl->q);
5971 	value |= ((uint8_t) (ctl->i)) << 8;
5972 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5973 }
5974 
5975 static uint16_t
5976 bwn_lo_calcfeed(struct bwn_mac *mac,
5977     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5978 {
5979 	struct bwn_phy *phy = &mac->mac_phy;
5980 	uint16_t rfover;
5981 	uint16_t feedthrough;
5982 
5983 	if (phy->gmode) {
5984 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5985 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5986 
5987 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5988 		    ("%s:%d: fail", __func__, __LINE__));
5989 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5990 		    ("%s:%d: fail", __func__, __LINE__));
5991 
5992 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5993 
5994 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5995 		if ((mac->mac_sd->sd_bus->siba_sprom.bf_lo & BWN_BFL_EXTLNA)
5996 		    && phy->rev > 6)
5997 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5998 
5999 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6000 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6001 		DELAY(10);
6002 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
6003 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6004 		DELAY(10);
6005 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
6006 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
6007 		DELAY(10);
6008 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
6009 	} else {
6010 		pga |= BWN_PHY_PGACTL_UNKNOWN;
6011 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6012 		DELAY(10);
6013 		pga |= BWN_PHY_PGACTL_LOWBANDW;
6014 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6015 		DELAY(10);
6016 		pga |= BWN_PHY_PGACTL_LPF;
6017 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
6018 	}
6019 	DELAY(21);
6020 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
6021 
6022 	return (feedthrough);
6023 }
6024 
6025 static uint16_t
6026 bwn_lo_txctl_regtable(struct bwn_mac *mac,
6027     uint16_t *value, uint16_t *pad_mix_gain)
6028 {
6029 	struct bwn_phy *phy = &mac->mac_phy;
6030 	uint16_t reg, v, padmix;
6031 
6032 	if (phy->type == BWN_PHYTYPE_B) {
6033 		v = 0x30;
6034 		if (phy->rf_rev <= 5) {
6035 			reg = 0x43;
6036 			padmix = 0;
6037 		} else {
6038 			reg = 0x52;
6039 			padmix = 5;
6040 		}
6041 	} else {
6042 		if (phy->rev >= 2 && phy->rf_rev == 8) {
6043 			reg = 0x43;
6044 			v = 0x10;
6045 			padmix = 2;
6046 		} else {
6047 			reg = 0x52;
6048 			v = 0x30;
6049 			padmix = 5;
6050 		}
6051 	}
6052 	if (value)
6053 		*value = v;
6054 	if (pad_mix_gain)
6055 		*pad_mix_gain = padmix;
6056 
6057 	return (reg);
6058 }
6059 
6060 static void
6061 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
6062 {
6063 	struct bwn_phy *phy = &mac->mac_phy;
6064 	struct bwn_phy_g *pg = &phy->phy_g;
6065 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6066 	uint16_t reg, mask;
6067 	uint16_t trsw_rx, pga;
6068 	uint16_t rf_pctl_reg;
6069 
6070 	static const uint8_t tx_bias_values[] = {
6071 		0x09, 0x08, 0x0a, 0x01, 0x00,
6072 		0x02, 0x05, 0x04, 0x06,
6073 	};
6074 	static const uint8_t tx_magn_values[] = {
6075 		0x70, 0x40,
6076 	};
6077 
6078 	if (!BWN_HAS_LOOPBACK(phy)) {
6079 		rf_pctl_reg = 6;
6080 		trsw_rx = 2;
6081 		pga = 0;
6082 	} else {
6083 		int lb_gain;
6084 
6085 		trsw_rx = 0;
6086 		lb_gain = pg->pg_max_lb_gain / 2;
6087 		if (lb_gain > 10) {
6088 			rf_pctl_reg = 0;
6089 			pga = abs(10 - lb_gain) / 6;
6090 			pga = MIN(MAX(pga, 0), 15);
6091 		} else {
6092 			int cmp_val;
6093 			int tmp;
6094 
6095 			pga = 0;
6096 			cmp_val = 0x24;
6097 			if ((phy->rev >= 2) &&
6098 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6099 				cmp_val = 0x3c;
6100 			tmp = lb_gain;
6101 			if ((10 - lb_gain) < cmp_val)
6102 				tmp = (10 - lb_gain);
6103 			if (tmp < 0)
6104 				tmp += 6;
6105 			else
6106 				tmp += 3;
6107 			cmp_val /= 4;
6108 			tmp /= 4;
6109 			if (tmp >= cmp_val)
6110 				rf_pctl_reg = cmp_val;
6111 			else
6112 				rf_pctl_reg = tmp;
6113 		}
6114 	}
6115 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6116 	bwn_phy_g_set_bbatt(mac, 2);
6117 
6118 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6119 	mask = ~mask;
6120 	BWN_RF_MASK(mac, reg, mask);
6121 
6122 	if (BWN_HAS_TXMAG(phy)) {
6123 		int i, j;
6124 		int feedthrough;
6125 		int min_feedth = 0xffff;
6126 		uint8_t tx_magn, tx_bias;
6127 
6128 		for (i = 0; i < N(tx_magn_values); i++) {
6129 			tx_magn = tx_magn_values[i];
6130 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6131 			for (j = 0; j < N(tx_bias_values); j++) {
6132 				tx_bias = tx_bias_values[j];
6133 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6134 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6135 				    trsw_rx);
6136 				if (feedthrough < min_feedth) {
6137 					lo->tx_bias = tx_bias;
6138 					lo->tx_magn = tx_magn;
6139 					min_feedth = feedthrough;
6140 				}
6141 				if (lo->tx_bias == 0)
6142 					break;
6143 			}
6144 			BWN_RF_WRITE(mac, 0x52,
6145 					  (BWN_RF_READ(mac, 0x52)
6146 					   & 0xff00) | lo->tx_bias | lo->
6147 					  tx_magn);
6148 		}
6149 	} else {
6150 		lo->tx_magn = 0;
6151 		lo->tx_bias = 0;
6152 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6153 	}
6154 
6155 	BWN_GETTIME(lo->txctl_measured_time);
6156 }
6157 
6158 static void
6159 bwn_lo_get_powervector(struct bwn_mac *mac)
6160 {
6161 	struct bwn_phy *phy = &mac->mac_phy;
6162 	struct bwn_phy_g *pg = &phy->phy_g;
6163 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6164 	int i;
6165 	uint64_t tmp;
6166 	uint64_t power_vector = 0;
6167 
6168 	for (i = 0; i < 8; i += 2) {
6169 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6170 		power_vector |= (tmp << (i * 8));
6171 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6172 	}
6173 	if (power_vector)
6174 		lo->power_vector = power_vector;
6175 
6176 	BWN_GETTIME(lo->pwr_vec_read_time);
6177 }
6178 
6179 static void
6180 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6181     int use_trsw_rx)
6182 {
6183 	struct bwn_phy *phy = &mac->mac_phy;
6184 	struct bwn_phy_g *pg = &phy->phy_g;
6185 	uint16_t tmp;
6186 
6187 	if (max_rx_gain < 0)
6188 		max_rx_gain = 0;
6189 
6190 	if (BWN_HAS_LOOPBACK(phy)) {
6191 		int trsw_rx = 0;
6192 		int trsw_rx_gain;
6193 
6194 		if (use_trsw_rx) {
6195 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6196 			if (max_rx_gain >= trsw_rx_gain) {
6197 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6198 				trsw_rx = 0x20;
6199 			}
6200 		} else
6201 			trsw_rx_gain = max_rx_gain;
6202 		if (trsw_rx_gain < 9) {
6203 			pg->pg_lna_lod_gain = 0;
6204 		} else {
6205 			pg->pg_lna_lod_gain = 1;
6206 			trsw_rx_gain -= 8;
6207 		}
6208 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6209 		pg->pg_pga_gain = trsw_rx_gain / 3;
6210 		if (pg->pg_pga_gain >= 5) {
6211 			pg->pg_pga_gain -= 5;
6212 			pg->pg_lna_gain = 2;
6213 		} else
6214 			pg->pg_lna_gain = 0;
6215 	} else {
6216 		pg->pg_lna_gain = 0;
6217 		pg->pg_trsw_rx_gain = 0x20;
6218 		if (max_rx_gain >= 0x14) {
6219 			pg->pg_lna_lod_gain = 1;
6220 			pg->pg_pga_gain = 2;
6221 		} else if (max_rx_gain >= 0x12) {
6222 			pg->pg_lna_lod_gain = 1;
6223 			pg->pg_pga_gain = 1;
6224 		} else if (max_rx_gain >= 0xf) {
6225 			pg->pg_lna_lod_gain = 1;
6226 			pg->pg_pga_gain = 0;
6227 		} else {
6228 			pg->pg_lna_lod_gain = 0;
6229 			pg->pg_pga_gain = 0;
6230 		}
6231 	}
6232 
6233 	tmp = BWN_RF_READ(mac, 0x7a);
6234 	if (pg->pg_lna_lod_gain == 0)
6235 		tmp &= ~0x0008;
6236 	else
6237 		tmp |= 0x0008;
6238 	BWN_RF_WRITE(mac, 0x7a, tmp);
6239 }
6240 
6241 static void
6242 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6243 {
6244 	struct siba_sprom *sprom = &mac->mac_sd->sd_bus->siba_sprom;
6245 	struct bwn_phy *phy = &mac->mac_phy;
6246 	struct bwn_phy_g *pg = &phy->phy_g;
6247 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6248 	struct timespec ts;
6249 	uint16_t tmp;
6250 
6251 	if (bwn_has_hwpctl(mac)) {
6252 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6253 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6254 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6255 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6256 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6257 
6258 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6259 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6260 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6261 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6262 	}
6263 	if (phy->type == BWN_PHYTYPE_B &&
6264 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6265 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6266 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6267 	}
6268 	if (phy->rev >= 2) {
6269 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6270 		sav->phy_analogoverval =
6271 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6272 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6273 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6274 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6275 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6276 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6277 
6278 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6279 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6280 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6281 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6282 		if (phy->type == BWN_PHYTYPE_G) {
6283 			if ((phy->rev >= 7) &&
6284 			    (sprom->bf_lo & BWN_BFL_EXTLNA)) {
6285 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6286 			} else {
6287 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6288 			}
6289 		} else {
6290 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6291 		}
6292 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6293 	}
6294 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6295 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6296 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6297 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6298 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6299 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6300 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6301 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6302 
6303 	if (!BWN_HAS_TXMAG(phy)) {
6304 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6305 		sav->rf2 &= 0x00f0;
6306 	}
6307 	if (phy->type == BWN_PHYTYPE_B) {
6308 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6309 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6310 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6311 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6312 	} else {
6313 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6314 			    | 0x8000);
6315 	}
6316 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6317 		    & 0xf000);
6318 
6319 	tmp =
6320 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6321 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6322 
6323 	tmp = sav->phy_syncctl;
6324 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6325 	tmp = sav->rf1;
6326 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6327 
6328 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6329 	if (phy->type == BWN_PHYTYPE_G ||
6330 	    (phy->type == BWN_PHYTYPE_B &&
6331 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6332 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6333 	} else
6334 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6335 	if (phy->rev >= 2)
6336 		bwn_dummy_transmission(mac, 0, 1);
6337 	bwn_phy_g_switch_chan(mac, 6, 0);
6338 	BWN_RF_READ(mac, 0x51);
6339 	if (phy->type == BWN_PHYTYPE_G)
6340 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6341 
6342 	nanouptime(&ts);
6343 	if (time_before(lo->txctl_measured_time,
6344 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6345 		bwn_lo_measure_txctl_values(mac);
6346 
6347 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6348 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6349 	else {
6350 		if (phy->type == BWN_PHYTYPE_B)
6351 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6352 		else
6353 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6354 	}
6355 }
6356 
6357 static void
6358 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6359 {
6360 	struct bwn_phy *phy = &mac->mac_phy;
6361 	struct bwn_phy_g *pg = &phy->phy_g;
6362 	uint16_t tmp;
6363 
6364 	if (phy->rev >= 2) {
6365 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6366 		tmp = (pg->pg_pga_gain << 8);
6367 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6368 		DELAY(5);
6369 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6370 		DELAY(2);
6371 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6372 	} else {
6373 		tmp = (pg->pg_pga_gain | 0xefa0);
6374 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6375 	}
6376 	if (phy->type == BWN_PHYTYPE_G) {
6377 		if (phy->rev >= 3)
6378 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6379 		else
6380 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6381 		if (phy->rev >= 2)
6382 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6383 		else
6384 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6385 	}
6386 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6387 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6388 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6389 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6390 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6391 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6392 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6393 	if (!BWN_HAS_TXMAG(phy)) {
6394 		tmp = sav->rf2;
6395 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6396 	}
6397 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6398 	if (phy->type == BWN_PHYTYPE_B &&
6399 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6400 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6401 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6402 	}
6403 	if (phy->rev >= 2) {
6404 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6405 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6406 			      sav->phy_analogoverval);
6407 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6408 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6409 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6410 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6411 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6412 	}
6413 	if (bwn_has_hwpctl(mac)) {
6414 		tmp = (sav->phy_lomask & 0xbfff);
6415 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6416 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6417 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6418 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6419 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6420 	}
6421 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6422 }
6423 
6424 static int
6425 bwn_lo_probe_loctl(struct bwn_mac *mac,
6426     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6427 {
6428 	struct bwn_phy *phy = &mac->mac_phy;
6429 	struct bwn_phy_g *pg = &phy->phy_g;
6430 	struct bwn_loctl orig, test;
6431 	struct bwn_loctl prev = { -100, -100 };
6432 	static const struct bwn_loctl modifiers[] = {
6433 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6434 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6435 	};
6436 	int begin, end, lower = 0, i;
6437 	uint16_t feedth;
6438 
6439 	if (d->curstate == 0) {
6440 		begin = 1;
6441 		end = 8;
6442 	} else if (d->curstate % 2 == 0) {
6443 		begin = d->curstate - 1;
6444 		end = d->curstate + 1;
6445 	} else {
6446 		begin = d->curstate - 2;
6447 		end = d->curstate + 2;
6448 	}
6449 	if (begin < 1)
6450 		begin += 8;
6451 	if (end > 8)
6452 		end -= 8;
6453 
6454 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6455 	i = begin;
6456 	d->curstate = i;
6457 	while (1) {
6458 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6459 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6460 		test.i += modifiers[i - 1].i * d->multipler;
6461 		test.q += modifiers[i - 1].q * d->multipler;
6462 		if ((test.i != prev.i || test.q != prev.q) &&
6463 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6464 			bwn_lo_write(mac, &test);
6465 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6466 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6467 			if (feedth < d->feedth) {
6468 				memcpy(probe, &test,
6469 				    sizeof(struct bwn_loctl));
6470 				lower = 1;
6471 				d->feedth = feedth;
6472 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6473 					break;
6474 			}
6475 		}
6476 		memcpy(&prev, &test, sizeof(prev));
6477 		if (i == end)
6478 			break;
6479 		if (i == 8)
6480 			i = 1;
6481 		else
6482 			i++;
6483 		d->curstate = i;
6484 	}
6485 
6486 	return (lower);
6487 }
6488 
6489 static void
6490 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6491 {
6492 	struct bwn_phy *phy = &mac->mac_phy;
6493 	struct bwn_phy_g *pg = &phy->phy_g;
6494 	struct bwn_lo_g_sm d;
6495 	struct bwn_loctl probe;
6496 	int lower, repeat, cnt = 0;
6497 	uint16_t feedth;
6498 
6499 	d.nmeasure = 0;
6500 	d.multipler = 1;
6501 	if (BWN_HAS_LOOPBACK(phy))
6502 		d.multipler = 3;
6503 
6504 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6505 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6506 
6507 	do {
6508 		bwn_lo_write(mac, &d.loctl);
6509 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6510 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6511 		if (feedth < 0x258) {
6512 			if (feedth >= 0x12c)
6513 				*rxgain += 6;
6514 			else
6515 				*rxgain += 3;
6516 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6517 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6518 		}
6519 		d.feedth = feedth;
6520 		d.curstate = 0;
6521 		do {
6522 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6523 			    ("%s:%d: fail", __func__, __LINE__));
6524 			memcpy(&probe, &d.loctl,
6525 			       sizeof(struct bwn_loctl));
6526 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6527 			if (!lower)
6528 				break;
6529 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6530 				break;
6531 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6532 			d.nmeasure++;
6533 		} while (d.nmeasure < 24);
6534 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6535 
6536 		if (BWN_HAS_LOOPBACK(phy)) {
6537 			if (d.feedth > 0x1194)
6538 				*rxgain -= 6;
6539 			else if (d.feedth < 0x5dc)
6540 				*rxgain += 3;
6541 			if (cnt == 0) {
6542 				if (d.feedth <= 0x5dc) {
6543 					d.multipler = 1;
6544 					cnt++;
6545 				} else
6546 					d.multipler = 2;
6547 			} else if (cnt == 2)
6548 				d.multipler = 1;
6549 		}
6550 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6551 	} while (++cnt < repeat);
6552 }
6553 
6554 static struct bwn_lo_calib *
6555 bwn_lo_calibset(struct bwn_mac *mac,
6556     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6557 {
6558 	struct bwn_phy *phy = &mac->mac_phy;
6559 	struct bwn_phy_g *pg = &phy->phy_g;
6560 	struct bwn_loctl loctl = { 0, 0 };
6561 	struct bwn_lo_calib *cal;
6562 	struct bwn_lo_g_value sval = { 0 };
6563 	int rxgain;
6564 	uint16_t pad, reg, value;
6565 
6566 	sval.old_channel = phy->chan;
6567 	bwn_mac_suspend(mac);
6568 	bwn_lo_save(mac, &sval);
6569 
6570 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6571 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6572 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6573 
6574 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6575 	if (rfatt->padmix)
6576 		rxgain -= pad;
6577 	if (BWN_HAS_LOOPBACK(phy))
6578 		rxgain += pg->pg_max_lb_gain;
6579 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6580 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6581 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6582 
6583 	bwn_lo_restore(mac, &sval);
6584 	bwn_mac_enable(mac);
6585 
6586 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6587 	if (!cal) {
6588 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6589 		return (NULL);
6590 	}
6591 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6592 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6593 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6594 
6595 	BWN_GETTIME(cal->calib_time);
6596 
6597 	return (cal);
6598 }
6599 
6600 static struct bwn_lo_calib *
6601 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6602     const struct bwn_rfatt *rfatt)
6603 {
6604 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6605 	struct bwn_lo_calib *c;
6606 
6607 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6608 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6609 			continue;
6610 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6611 			continue;
6612 		return (c);
6613 	}
6614 
6615 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6616 	if (!c)
6617 		return (NULL);
6618 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6619 
6620 	return (c);
6621 }
6622 
6623 static void
6624 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6625 {
6626 	struct bwn_phy *phy = &mac->mac_phy;
6627 	struct bwn_phy_g *pg = &phy->phy_g;
6628 	struct bwn_softc *sc = mac->mac_sc;
6629 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6630 	const struct bwn_rfatt *rfatt;
6631 	const struct bwn_bbatt *bbatt;
6632 	uint64_t pvector;
6633 	int i;
6634 	int rf_offset, bb_offset;
6635 	uint8_t changed = 0;
6636 
6637 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6638 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6639 	    ("%s:%d: fail", __func__, __LINE__));
6640 
6641 	pvector = lo->power_vector;
6642 	if (!update && !pvector)
6643 		return;
6644 
6645 	bwn_mac_suspend(mac);
6646 
6647 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6648 		struct bwn_lo_calib *cal;
6649 		int idx;
6650 		uint16_t val;
6651 
6652 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6653 			continue;
6654 		bb_offset = i / lo->rfatt.len;
6655 		rf_offset = i % lo->rfatt.len;
6656 		bbatt = &(lo->bbatt.array[bb_offset]);
6657 		rfatt = &(lo->rfatt.array[rf_offset]);
6658 
6659 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6660 		if (!cal) {
6661 			device_printf(sc->sc_dev, "LO: Could not "
6662 			    "calibrate DC table entry\n");
6663 			continue;
6664 		}
6665 		val = (uint8_t)(cal->ctl.q);
6666 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6667 		free(cal, M_DEVBUF);
6668 
6669 		idx = i / 2;
6670 		if (i % 2)
6671 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6672 			    | ((val & 0x00ff) << 8);
6673 		else
6674 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6675 			    | (val & 0x00ff);
6676 		changed = 1;
6677 	}
6678 	if (changed) {
6679 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6680 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6681 	}
6682 	bwn_mac_enable(mac);
6683 }
6684 
6685 static void
6686 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6687 {
6688 
6689 	if (!rf->padmix)
6690 		return;
6691 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6692 		rf->att = 4;
6693 }
6694 
6695 static void
6696 bwn_lo_g_adjust(struct bwn_mac *mac)
6697 {
6698 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6699 	struct bwn_lo_calib *cal;
6700 	struct bwn_rfatt rf;
6701 
6702 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6703 	bwn_lo_fixup_rfatt(&rf);
6704 
6705 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6706 	if (!cal)
6707 		return;
6708 	bwn_lo_write(mac, &cal->ctl);
6709 }
6710 
6711 static void
6712 bwn_lo_g_init(struct bwn_mac *mac)
6713 {
6714 
6715 	if (!bwn_has_hwpctl(mac))
6716 		return;
6717 
6718 	bwn_lo_get_powervector(mac);
6719 	bwn_phy_g_dc_lookup_init(mac, 1);
6720 }
6721 
6722 static void
6723 bwn_mac_suspend(struct bwn_mac *mac)
6724 {
6725 	struct bwn_softc *sc = mac->mac_sc;
6726 	int i;
6727 	uint32_t tmp;
6728 
6729 	KASSERT(mac->mac_suspended >= 0,
6730 	    ("%s:%d: fail", __func__, __LINE__));
6731 
6732 	if (mac->mac_suspended == 0) {
6733 		bwn_psctl(mac, BWN_PS_AWAKE);
6734 		BWN_WRITE_4(mac, BWN_MACCTL,
6735 			    BWN_READ_4(mac, BWN_MACCTL)
6736 			    & ~BWN_MACCTL_ON);
6737 		BWN_READ_4(mac, BWN_MACCTL);
6738 		for (i = 35; i; i--) {
6739 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6740 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6741 				goto out;
6742 			DELAY(10);
6743 		}
6744 		for (i = 40; i; i--) {
6745 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6746 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6747 				goto out;
6748 			DELAY(1000);
6749 		}
6750 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6751 	}
6752 out:
6753 	mac->mac_suspended++;
6754 }
6755 
6756 static void
6757 bwn_mac_enable(struct bwn_mac *mac)
6758 {
6759 	struct bwn_softc *sc = mac->mac_sc;
6760 	uint16_t state;
6761 
6762 	state = bwn_shm_read_2(mac, BWN_SHARED,
6763 	    BWN_SHARED_UCODESTAT);
6764 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6765 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6766 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6767 
6768 	mac->mac_suspended--;
6769 	KASSERT(mac->mac_suspended >= 0,
6770 	    ("%s:%d: fail", __func__, __LINE__));
6771 	if (mac->mac_suspended == 0) {
6772 		BWN_WRITE_4(mac, BWN_MACCTL,
6773 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6774 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6775 		BWN_READ_4(mac, BWN_MACCTL);
6776 		BWN_READ_4(mac, BWN_INTR_REASON);
6777 		bwn_psctl(mac, 0);
6778 	}
6779 }
6780 
6781 static void
6782 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6783 {
6784 	int i;
6785 	uint16_t ucstat;
6786 
6787 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6788 	    ("%s:%d: fail", __func__, __LINE__));
6789 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6790 	    ("%s:%d: fail", __func__, __LINE__));
6791 
6792 	/* XXX forcibly awake and hwps-off */
6793 
6794 	BWN_WRITE_4(mac, BWN_MACCTL,
6795 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6796 	    ~BWN_MACCTL_HWPS);
6797 	BWN_READ_4(mac, BWN_MACCTL);
6798 	if (mac->mac_sd->sd_id.sd_rev >= 5) {
6799 		for (i = 0; i < 100; i++) {
6800 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6801 			    BWN_SHARED_UCODESTAT);
6802 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6803 				break;
6804 			DELAY(10);
6805 		}
6806 	}
6807 }
6808 
6809 static int16_t
6810 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6811 {
6812 
6813 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6814 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6815 }
6816 
6817 static void
6818 bwn_nrssi_threshold(struct bwn_mac *mac)
6819 {
6820 	struct bwn_phy *phy = &mac->mac_phy;
6821 	struct bwn_phy_g *pg = &phy->phy_g;
6822 	struct siba_softc *siba = mac->mac_sd->sd_bus;
6823 	int32_t a, b;
6824 	int16_t tmp16;
6825 	uint16_t tmpu16;
6826 
6827 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6828 
6829 	if (phy->gmode && (siba->siba_sprom.bf_lo & BWN_BFL_RSSI)) {
6830 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6831 			a = 0x13;
6832 			b = 0x12;
6833 		} else {
6834 			a = 0xe;
6835 			b = 0x11;
6836 		}
6837 
6838 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6839 		a += (pg->pg_nrssi[0] << 6);
6840 		a += (a < 32) ? 31 : 32;
6841 		a = a >> 6;
6842 		a = MIN(MAX(a, -31), 31);
6843 
6844 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6845 		b += (pg->pg_nrssi[0] << 6);
6846 		if (b < 32)
6847 			b += 31;
6848 		else
6849 			b += 32;
6850 		b = b >> 6;
6851 		b = MIN(MAX(b, -31), 31);
6852 
6853 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6854 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6855 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6856 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6857 		return;
6858 	}
6859 
6860 	tmp16 = bwn_nrssi_read(mac, 0x20);
6861 	if (tmp16 >= 0x20)
6862 		tmp16 -= 0x40;
6863 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6864 }
6865 
6866 static void
6867 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6868 {
6869 #define	SAVE_RF_MAX		3
6870 #define	SAVE_PHY_COMM_MAX	4
6871 #define	SAVE_PHY3_MAX		8
6872 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6873 		{ 0x7a, 0x52, 0x43 };
6874 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6875 		{ 0x15, 0x5a, 0x59, 0x58 };
6876 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6877 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6878 		0x0801, 0x0060, 0x0014, 0x0478
6879 	};
6880 	struct bwn_phy *phy = &mac->mac_phy;
6881 	struct bwn_phy_g *pg = &phy->phy_g;
6882 	int32_t i, tmp32, phy3_idx = 0;
6883 	uint16_t delta, tmp;
6884 	uint16_t save_rf[SAVE_RF_MAX];
6885 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6886 	uint16_t save_phy3[SAVE_PHY3_MAX];
6887 	uint16_t ant_div, phy0, chan_ex;
6888 	int16_t nrssi0, nrssi1;
6889 
6890 	KASSERT(phy->type == BWN_PHYTYPE_G,
6891 	    ("%s:%d: fail", __func__, __LINE__));
6892 
6893 	if (phy->rf_rev >= 9)
6894 		return;
6895 	if (phy->rf_rev == 8)
6896 		bwn_nrssi_offset(mac);
6897 
6898 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6899 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6900 
6901 	/*
6902 	 * Save RF/PHY registers for later restoration
6903 	 */
6904 	ant_div = BWN_READ_2(mac, 0x03e2);
6905 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6906 	for (i = 0; i < SAVE_RF_MAX; ++i)
6907 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6908 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6909 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6910 
6911 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6912 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6913 	if (phy->rev >= 3) {
6914 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6915 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6916 		BWN_PHY_WRITE(mac, 0x002e, 0);
6917 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6918 		switch (phy->rev) {
6919 		case 4:
6920 		case 6:
6921 		case 7:
6922 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6923 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6924 			break;
6925 		case 3:
6926 		case 5:
6927 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6928 			break;
6929 		}
6930 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6931 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6932 	}
6933 	/*
6934 	 * Calculate nrssi0
6935 	 */
6936 	BWN_RF_SET(mac, 0x007a, 0x0070);
6937 	bwn_set_all_gains(mac, 0, 8, 0);
6938 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6939 	if (phy->rev >= 2) {
6940 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6941 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6942 	}
6943 	BWN_RF_SET(mac, 0x007a, 0x0080);
6944 	DELAY(20);
6945 
6946 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6947 	if (nrssi0 >= 0x0020)
6948 		nrssi0 -= 0x0040;
6949 
6950 	/*
6951 	 * Calculate nrssi1
6952 	 */
6953 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6954 	if (phy->rev >= 2)
6955 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6956 
6957 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6958 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6959 	BWN_RF_SET(mac, 0x007a, 0x000f);
6960 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6961 	if (phy->rev >= 2) {
6962 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6963 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6964 	}
6965 
6966 	bwn_set_all_gains(mac, 3, 0, 1);
6967 	if (phy->rf_rev == 8) {
6968 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6969 	} else {
6970 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6971 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6972 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6973 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6974 	}
6975 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6976 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6977 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6978 	DELAY(20);
6979 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6980 
6981 	/*
6982 	 * Install calculated narrow RSSI values
6983 	 */
6984 	if (nrssi1 >= 0x0020)
6985 		nrssi1 -= 0x0040;
6986 	if (nrssi0 == nrssi1)
6987 		pg->pg_nrssi_slope = 0x00010000;
6988 	else
6989 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6990 	if (nrssi0 >= -4) {
6991 		pg->pg_nrssi[0] = nrssi1;
6992 		pg->pg_nrssi[1] = nrssi0;
6993 	}
6994 
6995 	/*
6996 	 * Restore saved RF/PHY registers
6997 	 */
6998 	if (phy->rev >= 3) {
6999 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
7000 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7001 			    save_phy3[phy3_idx]);
7002 		}
7003 	}
7004 	if (phy->rev >= 2) {
7005 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
7006 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
7007 	}
7008 
7009 	for (i = 0; i < SAVE_RF_MAX; ++i)
7010 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7011 
7012 	BWN_WRITE_2(mac, 0x03e2, ant_div);
7013 	BWN_WRITE_2(mac, 0x03e6, phy0);
7014 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
7015 
7016 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7017 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7018 
7019 	bwn_spu_workaround(mac, phy->chan);
7020 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
7021 	bwn_set_original_gains(mac);
7022 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
7023 	if (phy->rev >= 3) {
7024 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
7025 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
7026 			    save_phy3[phy3_idx]);
7027 		}
7028 	}
7029 
7030 	delta = 0x1f - pg->pg_nrssi[0];
7031 	for (i = 0; i < 64; i++) {
7032 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
7033 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
7034 		pg->pg_nrssi_lt[i] = tmp32;
7035 	}
7036 
7037 	bwn_nrssi_threshold(mac);
7038 #undef SAVE_RF_MAX
7039 #undef SAVE_PHY_COMM_MAX
7040 #undef SAVE_PHY3_MAX
7041 }
7042 
7043 static void
7044 bwn_nrssi_offset(struct bwn_mac *mac)
7045 {
7046 #define	SAVE_RF_MAX		2
7047 #define	SAVE_PHY_COMM_MAX	10
7048 #define	SAVE_PHY6_MAX		8
7049 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
7050 		{ 0x7a, 0x43 };
7051 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
7052 		0x0001, 0x0811, 0x0812, 0x0814,
7053 		0x0815, 0x005a, 0x0059, 0x0058,
7054 		0x000a, 0x0003
7055 	};
7056 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
7057 		0x002e, 0x002f, 0x080f, 0x0810,
7058 		0x0801, 0x0060, 0x0014, 0x0478
7059 	};
7060 	struct bwn_phy *phy = &mac->mac_phy;
7061 	int i, phy6_idx = 0;
7062 	uint16_t save_rf[SAVE_RF_MAX];
7063 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
7064 	uint16_t save_phy6[SAVE_PHY6_MAX];
7065 	int16_t nrssi;
7066 	uint16_t saved = 0xffff;
7067 
7068 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
7069 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
7070 	for (i = 0; i < SAVE_RF_MAX; ++i)
7071 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
7072 
7073 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
7074 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
7075 	BWN_PHY_SET(mac, 0x0811, 0x000c);
7076 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
7077 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
7078 	if (phy->rev >= 6) {
7079 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
7080 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
7081 
7082 		BWN_PHY_WRITE(mac, 0x002e, 0);
7083 		BWN_PHY_WRITE(mac, 0x002f, 0);
7084 		BWN_PHY_WRITE(mac, 0x080f, 0);
7085 		BWN_PHY_WRITE(mac, 0x0810, 0);
7086 		BWN_PHY_SET(mac, 0x0478, 0x0100);
7087 		BWN_PHY_SET(mac, 0x0801, 0x0040);
7088 		BWN_PHY_SET(mac, 0x0060, 0x0040);
7089 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7090 	}
7091 	BWN_RF_SET(mac, 0x007a, 0x0070);
7092 	BWN_RF_SET(mac, 0x007a, 0x0080);
7093 	DELAY(30);
7094 
7095 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7096 	if (nrssi >= 0x20)
7097 		nrssi -= 0x40;
7098 	if (nrssi == 31) {
7099 		for (i = 7; i >= 4; i--) {
7100 			BWN_RF_WRITE(mac, 0x007b, i);
7101 			DELAY(20);
7102 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7103 			    0x003f);
7104 			if (nrssi >= 0x20)
7105 				nrssi -= 0x40;
7106 			if (nrssi < 31 && saved == 0xffff)
7107 				saved = i;
7108 		}
7109 		if (saved == 0xffff)
7110 			saved = 4;
7111 	} else {
7112 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7113 		if (phy->rev != 1) {
7114 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7115 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7116 		}
7117 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7118 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7119 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7120 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7121 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7122 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7123 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7124 		if (phy->rev == 0)
7125 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7126 		else
7127 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7128 		if (phy->rev != 1) {
7129 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7130 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7131 		}
7132 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7133 		BWN_RF_SET(mac, 0x007a, 0x000f);
7134 		bwn_set_all_gains(mac, 3, 0, 1);
7135 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7136 		DELAY(30);
7137 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7138 		if (nrssi >= 0x20)
7139 			nrssi -= 0x40;
7140 		if (nrssi == -32) {
7141 			for (i = 0; i < 4; i++) {
7142 				BWN_RF_WRITE(mac, 0x007b, i);
7143 				DELAY(20);
7144 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7145 				    0x047f) >> 8) & 0x003f);
7146 				if (nrssi >= 0x20)
7147 					nrssi -= 0x40;
7148 				if (nrssi > -31 && saved == 0xffff)
7149 					saved = i;
7150 			}
7151 			if (saved == 0xffff)
7152 				saved = 3;
7153 		} else
7154 			saved = 0;
7155 	}
7156 	BWN_RF_WRITE(mac, 0x007b, saved);
7157 
7158 	/*
7159 	 * Restore saved RF/PHY registers
7160 	 */
7161 	if (phy->rev >= 6) {
7162 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7163 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7164 			    save_phy6[phy6_idx]);
7165 		}
7166 	}
7167 	if (phy->rev != 1) {
7168 		for (i = 3; i < 5; i++)
7169 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7170 			    save_phy_comm[i]);
7171 	}
7172 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7173 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7174 
7175 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7176 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7177 
7178 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7179 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7180 	bwn_set_original_gains(mac);
7181 	if (phy->rev >= 6) {
7182 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7183 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7184 			    save_phy6[phy6_idx]);
7185 		}
7186 	}
7187 
7188 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7189 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7190 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7191 }
7192 
7193 static void
7194 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7195     int16_t third)
7196 {
7197 	struct bwn_phy *phy = &mac->mac_phy;
7198 	uint16_t i;
7199 	uint16_t start = 0x08, end = 0x18;
7200 	uint16_t tmp;
7201 	uint16_t table;
7202 
7203 	if (phy->rev <= 1) {
7204 		start = 0x10;
7205 		end = 0x20;
7206 	}
7207 
7208 	table = BWN_OFDMTAB_GAINX;
7209 	if (phy->rev <= 1)
7210 		table = BWN_OFDMTAB_GAINX_R1;
7211 	for (i = 0; i < 4; i++)
7212 		bwn_ofdmtab_write_2(mac, table, i, first);
7213 
7214 	for (i = start; i < end; i++)
7215 		bwn_ofdmtab_write_2(mac, table, i, second);
7216 
7217 	if (third != -1) {
7218 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7219 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7220 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7221 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7222 	}
7223 	bwn_dummy_transmission(mac, 0, 1);
7224 }
7225 
7226 static void
7227 bwn_set_original_gains(struct bwn_mac *mac)
7228 {
7229 	struct bwn_phy *phy = &mac->mac_phy;
7230 	uint16_t i, tmp;
7231 	uint16_t table;
7232 	uint16_t start = 0x0008, end = 0x0018;
7233 
7234 	if (phy->rev <= 1) {
7235 		start = 0x0010;
7236 		end = 0x0020;
7237 	}
7238 
7239 	table = BWN_OFDMTAB_GAINX;
7240 	if (phy->rev <= 1)
7241 		table = BWN_OFDMTAB_GAINX_R1;
7242 	for (i = 0; i < 4; i++) {
7243 		tmp = (i & 0xfffc);
7244 		tmp |= (i & 0x0001) << 1;
7245 		tmp |= (i & 0x0002) >> 1;
7246 
7247 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7248 	}
7249 
7250 	for (i = start; i < end; i++)
7251 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7252 
7253 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7254 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7255 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7256 	bwn_dummy_transmission(mac, 0, 1);
7257 }
7258 
7259 static void
7260 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7261 {
7262 	struct siba_softc *bus = mac->mac_sd->sd_bus;
7263 	struct bwn_phy *phy = &mac->mac_phy;
7264 	struct bwn_phy_g *pg = &phy->phy_g;
7265 	struct bwn_rfatt old_rfatt, rfatt;
7266 	struct bwn_bbatt old_bbatt, bbatt;
7267 	uint8_t old_txctl = 0;
7268 
7269 	KASSERT(phy->type == BWN_PHYTYPE_G,
7270 	    ("%s:%d: fail", __func__, __LINE__));
7271 
7272 	if ((bus->siba_board_vendor == SIBA_BOARDVENDOR_BCM) &&
7273 	    (bus->siba_board_type == SIBA_BOARD_BU4306))
7274 		return;
7275 
7276 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7277 
7278 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7279 
7280 	if (!phy->gmode)
7281 		return;
7282 	bwn_hwpctl_early_init(mac);
7283 	if (pg->pg_curtssi == 0) {
7284 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7285 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7286 		} else {
7287 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7288 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7289 			old_txctl = pg->pg_txctl;
7290 
7291 			bbatt.att = 11;
7292 			if (phy->rf_rev == 8) {
7293 				rfatt.att = 15;
7294 				rfatt.padmix = 1;
7295 			} else {
7296 				rfatt.att = 9;
7297 				rfatt.padmix = 0;
7298 			}
7299 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7300 		}
7301 		bwn_dummy_transmission(mac, 0, 1);
7302 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7303 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7304 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7305 		else
7306 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7307 			    &old_rfatt, old_txctl);
7308 	}
7309 	bwn_hwpctl_init_gphy(mac);
7310 
7311 	/* clear TSSI */
7312 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7313 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7314 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7315 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7316 }
7317 
7318 static void
7319 bwn_hwpctl_early_init(struct bwn_mac *mac)
7320 {
7321 	struct bwn_phy *phy = &mac->mac_phy;
7322 
7323 	if (!bwn_has_hwpctl(mac)) {
7324 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7325 		return;
7326 	}
7327 
7328 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7329 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7330 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7331 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7332 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7333 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7334 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7335 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7336 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7337 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7338 	} else {
7339 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7340 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7341 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7342 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7343 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7344 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7345 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7346 	}
7347 }
7348 
7349 static void
7350 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7351 {
7352 	struct bwn_phy *phy = &mac->mac_phy;
7353 	struct bwn_phy_g *pg = &phy->phy_g;
7354 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7355 	int i;
7356 	uint16_t nr_written = 0, tmp, value;
7357 	uint8_t rf, bb;
7358 
7359 	if (!bwn_has_hwpctl(mac)) {
7360 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7361 		return;
7362 	}
7363 
7364 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7365 	    (pg->pg_idletssi - pg->pg_curtssi));
7366 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7367 	    (pg->pg_idletssi - pg->pg_curtssi));
7368 
7369 	for (i = 0; i < 32; i++)
7370 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7371 	for (i = 32; i < 64; i++)
7372 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7373 	for (i = 0; i < 64; i += 2) {
7374 		value = (uint16_t) pg->pg_tssi2dbm[i];
7375 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7376 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7377 	}
7378 
7379 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7380 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7381 			if (nr_written >= 0x40)
7382 				return;
7383 			tmp = lo->bbatt.array[bb].att;
7384 			tmp <<= 8;
7385 			if (phy->rf_rev == 8)
7386 				tmp |= 0x50;
7387 			else
7388 				tmp |= 0x40;
7389 			tmp |= lo->rfatt.array[rf].att;
7390 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7391 			nr_written++;
7392 		}
7393 	}
7394 
7395 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7396 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7397 
7398 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7399 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7400 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7401 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7402 
7403 	bwn_phy_g_dc_lookup_init(mac, 1);
7404 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7405 }
7406 
7407 static void
7408 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7409 {
7410 	struct siba_softc *siba = mac->mac_sd->sd_bus;
7411 
7412 	if (spu != 0)
7413 		bwn_spu_workaround(mac, channel);
7414 
7415 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7416 
7417 	if (channel == 14) {
7418 		if (siba->siba_sprom.ccode == SIBA_CCODE_JAPAN)
7419 			bwn_hf_write(mac,
7420 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7421 		else
7422 			bwn_hf_write(mac,
7423 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7424 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7425 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7426 		return;
7427 	}
7428 
7429 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7430 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7431 }
7432 
7433 static uint16_t
7434 bwn_phy_g_chan2freq(uint8_t channel)
7435 {
7436 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7437 
7438 	KASSERT(channel >= 1 && channel <= 14,
7439 	    ("%s:%d: fail", __func__, __LINE__));
7440 
7441 	return (bwn_phy_g_rf_channels[channel - 1]);
7442 }
7443 
7444 static void
7445 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7446     const struct bwn_rfatt *rfatt, uint8_t txctl)
7447 {
7448 	struct bwn_phy *phy = &mac->mac_phy;
7449 	struct bwn_phy_g *pg = &phy->phy_g;
7450 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7451 	uint16_t bb, rf;
7452 	uint16_t tx_bias, tx_magn;
7453 
7454 	bb = bbatt->att;
7455 	rf = rfatt->att;
7456 	tx_bias = lo->tx_bias;
7457 	tx_magn = lo->tx_magn;
7458 	if (tx_bias == 0xff)
7459 		tx_bias = 0;
7460 
7461 	pg->pg_txctl = txctl;
7462 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7463 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7464 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7465 	bwn_phy_g_set_bbatt(mac, bb);
7466 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7467 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7468 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7469 	else {
7470 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7471 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7472 	}
7473 	if (BWN_HAS_TXMAG(phy))
7474 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7475 	else
7476 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7477 	bwn_lo_g_adjust(mac);
7478 }
7479 
7480 static void
7481 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7482     uint16_t bbatt)
7483 {
7484 	struct bwn_phy *phy = &mac->mac_phy;
7485 
7486 	if (phy->analog == 0) {
7487 		BWN_WRITE_2(mac, BWN_PHY0,
7488 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7489 		return;
7490 	}
7491 	if (phy->analog > 1) {
7492 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7493 		return;
7494 	}
7495 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7496 }
7497 
7498 static uint16_t
7499 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7500 {
7501 	struct bwn_phy *phy = &mac->mac_phy;
7502 	struct bwn_phy_g *pg = &phy->phy_g;
7503 	struct siba_sprom *sprom = &(mac->mac_sd->sd_bus->siba_sprom);
7504 	int max_lb_gain;
7505 	uint16_t extlna;
7506 	uint16_t i;
7507 
7508 	if (phy->gmode == 0)
7509 		return (0);
7510 
7511 	if (BWN_HAS_LOOPBACK(phy)) {
7512 		max_lb_gain = pg->pg_max_lb_gain;
7513 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7514 		if (max_lb_gain >= 0x46) {
7515 			extlna = 0x3000;
7516 			max_lb_gain -= 0x46;
7517 		} else if (max_lb_gain >= 0x3a) {
7518 			extlna = 0x1000;
7519 			max_lb_gain -= 0x3a;
7520 		} else if (max_lb_gain >= 0x2e) {
7521 			extlna = 0x2000;
7522 			max_lb_gain -= 0x2e;
7523 		} else {
7524 			extlna = 0;
7525 			max_lb_gain -= 0x10;
7526 		}
7527 
7528 		for (i = 0; i < 16; i++) {
7529 			max_lb_gain -= (i * 6);
7530 			if (max_lb_gain < 6)
7531 				break;
7532 		}
7533 
7534 		if ((phy->rev < 7) || !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7535 			if (reg == BWN_PHY_RFOVER) {
7536 				return (0x1b3);
7537 			} else if (reg == BWN_PHY_RFOVERVAL) {
7538 				extlna |= (i << 8);
7539 				switch (lpd) {
7540 				case BWN_LPD(0, 1, 1):
7541 					return (0x0f92);
7542 				case BWN_LPD(0, 0, 1):
7543 				case BWN_LPD(1, 0, 1):
7544 					return (0x0092 | extlna);
7545 				case BWN_LPD(1, 0, 0):
7546 					return (0x0093 | extlna);
7547 				}
7548 				KASSERT(0 == 1,
7549 				    ("%s:%d: fail", __func__, __LINE__));
7550 			}
7551 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7552 		} else {
7553 			if (reg == BWN_PHY_RFOVER)
7554 				return (0x9b3);
7555 			if (reg == BWN_PHY_RFOVERVAL) {
7556 				if (extlna)
7557 					extlna |= 0x8000;
7558 				extlna |= (i << 8);
7559 				switch (lpd) {
7560 				case BWN_LPD(0, 1, 1):
7561 					return (0x8f92);
7562 				case BWN_LPD(0, 0, 1):
7563 					return (0x8092 | extlna);
7564 				case BWN_LPD(1, 0, 1):
7565 					return (0x2092 | extlna);
7566 				case BWN_LPD(1, 0, 0):
7567 					return (0x2093 | extlna);
7568 				}
7569 				KASSERT(0 == 1,
7570 				    ("%s:%d: fail", __func__, __LINE__));
7571 			}
7572 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7573 		}
7574 		return (0);
7575 	}
7576 
7577 	if ((phy->rev < 7) ||
7578 	    !(sprom->bf_lo & BWN_BFL_EXTLNA)) {
7579 		if (reg == BWN_PHY_RFOVER) {
7580 			return (0x1b3);
7581 		} else if (reg == BWN_PHY_RFOVERVAL) {
7582 			switch (lpd) {
7583 			case BWN_LPD(0, 1, 1):
7584 				return (0x0fb2);
7585 			case BWN_LPD(0, 0, 1):
7586 				return (0x00b2);
7587 			case BWN_LPD(1, 0, 1):
7588 				return (0x30b2);
7589 			case BWN_LPD(1, 0, 0):
7590 				return (0x30b3);
7591 			}
7592 			KASSERT(0 == 1,
7593 			    ("%s:%d: fail", __func__, __LINE__));
7594 		}
7595 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7596 	} else {
7597 		if (reg == BWN_PHY_RFOVER) {
7598 			return (0x9b3);
7599 		} else if (reg == BWN_PHY_RFOVERVAL) {
7600 			switch (lpd) {
7601 			case BWN_LPD(0, 1, 1):
7602 				return (0x8fb2);
7603 			case BWN_LPD(0, 0, 1):
7604 				return (0x80b2);
7605 			case BWN_LPD(1, 0, 1):
7606 				return (0x20b2);
7607 			case BWN_LPD(1, 0, 0):
7608 				return (0x20b3);
7609 			}
7610 			KASSERT(0 == 1,
7611 			    ("%s:%d: fail", __func__, __LINE__));
7612 		}
7613 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7614 	}
7615 	return (0);
7616 }
7617 
7618 static void
7619 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7620 {
7621 
7622 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7623 		return;
7624 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7625 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7626 	DELAY(1000);
7627 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7628 }
7629 
7630 static int
7631 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7632 {
7633 	struct bwn_softc *sc = mac->mac_sc;
7634 	struct bwn_fw *fw = &mac->mac_fw;
7635 	const uint8_t rev = mac->mac_sd->sd_id.sd_rev;
7636 	const char *filename;
7637 	uint32_t high;
7638 	int error;
7639 
7640 	/* microcode */
7641 	if (rev >= 5 && rev <= 10)
7642 		filename = "ucode5";
7643 	else if (rev >= 11 && rev <= 12)
7644 		filename = "ucode11";
7645 	else if (rev == 13)
7646 		filename = "ucode13";
7647 	else if (rev == 14)
7648 		filename = "ucode14";
7649 	else if (rev >= 15)
7650 		filename = "ucode15";
7651 	else {
7652 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7653 		bwn_release_firmware(mac);
7654 		return (EOPNOTSUPP);
7655 	}
7656 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7657 	if (error) {
7658 		bwn_release_firmware(mac);
7659 		return (error);
7660 	}
7661 
7662 	/* PCM */
7663 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7664 	if (rev >= 5 && rev <= 10) {
7665 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7666 		if (error == ENOENT)
7667 			fw->no_pcmfile = 1;
7668 		else if (error) {
7669 			bwn_release_firmware(mac);
7670 			return (error);
7671 		}
7672 	} else if (rev < 11) {
7673 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7674 		return (EOPNOTSUPP);
7675 	}
7676 
7677 	/* initvals */
7678 	high = siba_read_4(mac->mac_sd, SIBA_TGSHIGH);
7679 	switch (mac->mac_phy.type) {
7680 	case BWN_PHYTYPE_A:
7681 		if (rev < 5 || rev > 10)
7682 			goto fail1;
7683 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7684 			filename = "a0g1initvals5";
7685 		else
7686 			filename = "a0g0initvals5";
7687 		break;
7688 	case BWN_PHYTYPE_G:
7689 		if (rev >= 5 && rev <= 10)
7690 			filename = "b0g0initvals5";
7691 		else if (rev >= 13)
7692 			filename = "b0g0initvals13";
7693 		else
7694 			goto fail1;
7695 		break;
7696 	case BWN_PHYTYPE_LP:
7697 		if (rev == 13)
7698 			filename = "lp0initvals13";
7699 		else if (rev == 14)
7700 			filename = "lp0initvals14";
7701 		else if (rev >= 15)
7702 			filename = "lp0initvals15";
7703 		else
7704 			goto fail1;
7705 		break;
7706 	case BWN_PHYTYPE_N:
7707 		if (rev >= 11 && rev <= 12)
7708 			filename = "n0initvals11";
7709 		else
7710 			goto fail1;
7711 		break;
7712 	default:
7713 		goto fail1;
7714 	}
7715 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7716 	if (error) {
7717 		bwn_release_firmware(mac);
7718 		return (error);
7719 	}
7720 
7721 	/* bandswitch initvals */
7722 	switch (mac->mac_phy.type) {
7723 	case BWN_PHYTYPE_A:
7724 		if (rev >= 5 && rev <= 10) {
7725 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7726 				filename = "a0g1bsinitvals5";
7727 			else
7728 				filename = "a0g0bsinitvals5";
7729 		} else if (rev >= 11)
7730 			filename = NULL;
7731 		else
7732 			goto fail1;
7733 		break;
7734 	case BWN_PHYTYPE_G:
7735 		if (rev >= 5 && rev <= 10)
7736 			filename = "b0g0bsinitvals5";
7737 		else if (rev >= 11)
7738 			filename = NULL;
7739 		else
7740 			goto fail1;
7741 		break;
7742 	case BWN_PHYTYPE_LP:
7743 		if (rev == 13)
7744 			filename = "lp0bsinitvals13";
7745 		else if (rev == 14)
7746 			filename = "lp0bsinitvals14";
7747 		else if (rev >= 15)
7748 			filename = "lp0bsinitvals15";
7749 		else
7750 			goto fail1;
7751 		break;
7752 	case BWN_PHYTYPE_N:
7753 		if (rev >= 11 && rev <= 12)
7754 			filename = "n0bsinitvals11";
7755 		else
7756 			goto fail1;
7757 		break;
7758 	default:
7759 		goto fail1;
7760 	}
7761 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7762 	if (error) {
7763 		bwn_release_firmware(mac);
7764 		return (error);
7765 	}
7766 	return (0);
7767 fail1:
7768 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7769 	bwn_release_firmware(mac);
7770 	return (EOPNOTSUPP);
7771 }
7772 
7773 static int
7774 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7775     const char *name, struct bwn_fwfile *bfw)
7776 {
7777 	const struct bwn_fwhdr *hdr;
7778 	struct bwn_softc *sc = mac->mac_sc;
7779 	const struct firmware *fw;
7780 	char namebuf[64];
7781 
7782 	if (name == NULL) {
7783 		bwn_do_release_fw(bfw);
7784 		return (0);
7785 	}
7786 	if (bfw->filename != NULL) {
7787 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7788 			return (0);
7789 		bwn_do_release_fw(bfw);
7790 	}
7791 
7792 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7793 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7794 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7795 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7796 	fw = firmware_get(namebuf);
7797 	if (fw == NULL) {
7798 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7799 		    namebuf);
7800 		return (ENOENT);
7801 	}
7802 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7803 		goto fail;
7804 	hdr = (const struct bwn_fwhdr *)(fw->data);
7805 	switch (hdr->type) {
7806 	case BWN_FWTYPE_UCODE:
7807 	case BWN_FWTYPE_PCM:
7808 		if (be32toh(hdr->size) !=
7809 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7810 			goto fail;
7811 		/* FALLTHROUGH */
7812 	case BWN_FWTYPE_IV:
7813 		if (hdr->ver != 1)
7814 			goto fail;
7815 		break;
7816 	default:
7817 		goto fail;
7818 	}
7819 	bfw->filename = name;
7820 	bfw->fw = fw;
7821 	bfw->type = type;
7822 	return (0);
7823 fail:
7824 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7825 	if (fw != NULL)
7826 		firmware_put(fw, FIRMWARE_UNLOAD);
7827 	return (EPROTO);
7828 }
7829 
7830 static void
7831 bwn_release_firmware(struct bwn_mac *mac)
7832 {
7833 
7834 	bwn_do_release_fw(&mac->mac_fw.ucode);
7835 	bwn_do_release_fw(&mac->mac_fw.pcm);
7836 	bwn_do_release_fw(&mac->mac_fw.initvals);
7837 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7838 }
7839 
7840 static void
7841 bwn_do_release_fw(struct bwn_fwfile *bfw)
7842 {
7843 
7844 	if (bfw->fw != NULL)
7845 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7846 	bfw->fw = NULL;
7847 	bfw->filename = NULL;
7848 }
7849 
7850 static int
7851 bwn_fw_loaducode(struct bwn_mac *mac)
7852 {
7853 #define	GETFWOFFSET(fwp, offset)	\
7854 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7855 #define	GETFWSIZE(fwp, offset)	\
7856 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7857 	struct bwn_softc *sc = mac->mac_sc;
7858 	const uint32_t *data;
7859 	unsigned int i;
7860 	uint32_t ctl;
7861 	uint16_t date, fwcaps, time;
7862 	int error = 0;
7863 
7864 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7865 	ctl |= BWN_MACCTL_MCODE_JMP0;
7866 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7867 	    __LINE__));
7868 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7869 	for (i = 0; i < 64; i++)
7870 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7871 	for (i = 0; i < 4096; i += 2)
7872 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7873 
7874 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7875 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7876 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7877 	     i++) {
7878 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7879 		DELAY(10);
7880 	}
7881 
7882 	if (mac->mac_fw.pcm.fw) {
7883 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7884 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7885 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7886 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7887 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7888 		    sizeof(struct bwn_fwhdr)); i++) {
7889 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7890 			DELAY(10);
7891 		}
7892 	}
7893 
7894 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7895 	BWN_WRITE_4(mac, BWN_MACCTL,
7896 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7897 	    BWN_MACCTL_MCODE_RUN);
7898 
7899 	for (i = 0; i < 21; i++) {
7900 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7901 			break;
7902 		if (i >= 20) {
7903 			device_printf(sc->sc_dev, "ucode timeout\n");
7904 			error = ENXIO;
7905 			goto error;
7906 		}
7907 		DELAY(50000);
7908 	}
7909 	BWN_READ_4(mac, BWN_INTR_REASON);
7910 
7911 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7912 	if (mac->mac_fw.rev <= 0x128) {
7913 		device_printf(sc->sc_dev, "the firmware is too old\n");
7914 		error = EOPNOTSUPP;
7915 		goto error;
7916 	}
7917 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7918 	    BWN_SHARED_UCODE_PATCH);
7919 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7920 	mac->mac_fw.opensource = (date == 0xffff);
7921 	if (bwn_wme != 0)
7922 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7923 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7924 
7925 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7926 	if (mac->mac_fw.opensource == 0) {
7927 		device_printf(sc->sc_dev,
7928 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7929 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7930 		if (mac->mac_fw.no_pcmfile)
7931 			device_printf(sc->sc_dev,
7932 			    "no HW crypto acceleration due to pcm5\n");
7933 	} else {
7934 		mac->mac_fw.patch = time;
7935 		fwcaps = bwn_fwcaps_read(mac);
7936 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7937 			device_printf(sc->sc_dev,
7938 			    "disabling HW crypto acceleration\n");
7939 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7940 		}
7941 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7942 			device_printf(sc->sc_dev, "disabling WME support\n");
7943 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7944 		}
7945 	}
7946 
7947 	if (BWN_ISOLDFMT(mac))
7948 		device_printf(sc->sc_dev, "using old firmware image\n");
7949 
7950 	return (0);
7951 
7952 error:
7953 	BWN_WRITE_4(mac, BWN_MACCTL,
7954 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7955 	    BWN_MACCTL_MCODE_JMP0);
7956 
7957 	return (error);
7958 #undef GETFWSIZE
7959 #undef GETFWOFFSET
7960 }
7961 
7962 /* OpenFirmware only */
7963 static uint16_t
7964 bwn_fwcaps_read(struct bwn_mac *mac)
7965 {
7966 
7967 	KASSERT(mac->mac_fw.opensource == 1,
7968 	    ("%s:%d: fail", __func__, __LINE__));
7969 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7970 }
7971 
7972 static int
7973 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7974     size_t count, size_t array_size)
7975 {
7976 #define	GET_NEXTIV16(iv)						\
7977 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7978 	    sizeof(uint16_t) + sizeof(uint16_t)))
7979 #define	GET_NEXTIV32(iv)						\
7980 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7981 	    sizeof(uint16_t) + sizeof(uint32_t)))
7982 	struct bwn_softc *sc = mac->mac_sc;
7983 	const struct bwn_fwinitvals *iv;
7984 	uint16_t offset;
7985 	size_t i;
7986 	uint8_t bit32;
7987 
7988 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7989 	    ("%s:%d: fail", __func__, __LINE__));
7990 	iv = ivals;
7991 	for (i = 0; i < count; i++) {
7992 		if (array_size < sizeof(iv->offset_size))
7993 			goto fail;
7994 		array_size -= sizeof(iv->offset_size);
7995 		offset = be16toh(iv->offset_size);
7996 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7997 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7998 		if (offset >= 0x1000)
7999 			goto fail;
8000 		if (bit32) {
8001 			if (array_size < sizeof(iv->data.d32))
8002 				goto fail;
8003 			array_size -= sizeof(iv->data.d32);
8004 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
8005 			iv = GET_NEXTIV32(iv);
8006 		} else {
8007 
8008 			if (array_size < sizeof(iv->data.d16))
8009 				goto fail;
8010 			array_size -= sizeof(iv->data.d16);
8011 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
8012 
8013 			iv = GET_NEXTIV16(iv);
8014 		}
8015 	}
8016 	if (array_size != 0)
8017 		goto fail;
8018 	return (0);
8019 fail:
8020 	device_printf(sc->sc_dev, "initvals: invalid format\n");
8021 	return (EPROTO);
8022 #undef GET_NEXTIV16
8023 #undef GET_NEXTIV32
8024 }
8025 
8026 static int
8027 bwn_switch_channel(struct bwn_mac *mac, int chan)
8028 {
8029 	struct bwn_phy *phy = &(mac->mac_phy);
8030 	struct bwn_softc *sc = mac->mac_sc;
8031 	struct ifnet *ifp = sc->sc_ifp;
8032 	struct ieee80211com *ic = ifp->if_l2com;
8033 	uint16_t channelcookie, savedcookie;
8034 	int error;
8035 
8036 	if (chan == 0xffff)
8037 		chan = phy->get_default_chan(mac);
8038 
8039 	channelcookie = chan;
8040 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
8041 		channelcookie |= 0x100;
8042 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
8043 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
8044 	error = phy->switch_channel(mac, chan);
8045 	if (error)
8046 		goto fail;
8047 
8048 	mac->mac_phy.chan = chan;
8049 	DELAY(8000);
8050 	return (0);
8051 fail:
8052 	device_printf(sc->sc_dev, "failed to switch channel\n");
8053 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
8054 	return (error);
8055 }
8056 
8057 static uint16_t
8058 bwn_ant2phy(int antenna)
8059 {
8060 
8061 	switch (antenna) {
8062 	case BWN_ANT0:
8063 		return (BWN_TX_PHY_ANT0);
8064 	case BWN_ANT1:
8065 		return (BWN_TX_PHY_ANT1);
8066 	case BWN_ANT2:
8067 		return (BWN_TX_PHY_ANT2);
8068 	case BWN_ANT3:
8069 		return (BWN_TX_PHY_ANT3);
8070 	case BWN_ANTAUTO:
8071 		return (BWN_TX_PHY_ANT01AUTO);
8072 	}
8073 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8074 	return (0);
8075 }
8076 
8077 static void
8078 bwn_wme_load(struct bwn_mac *mac)
8079 {
8080 	struct bwn_softc *sc = mac->mac_sc;
8081 	int i;
8082 
8083 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
8084 	    ("%s:%d: fail", __func__, __LINE__));
8085 
8086 	bwn_mac_suspend(mac);
8087 	for (i = 0; i < N(sc->sc_wmeParams); i++)
8088 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8089 		    bwn_wme_shm_offsets[i]);
8090 	bwn_mac_enable(mac);
8091 }
8092 
8093 static void
8094 bwn_wme_loadparams(struct bwn_mac *mac,
8095     const struct wmeParams *p, uint16_t shm_offset)
8096 {
8097 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8098 	struct bwn_softc *sc = mac->mac_sc;
8099 	uint16_t params[BWN_NR_WMEPARAMS];
8100 	int slot, tmp;
8101 	unsigned int i;
8102 
8103 	slot = BWN_READ_2(mac, BWN_RNG) &
8104 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8105 
8106 	memset(&params, 0, sizeof(params));
8107 
8108 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8109 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8110 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8111 
8112 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8113 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8114 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8115 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8116 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8117 	params[BWN_WMEPARAM_BSLOTS] = slot;
8118 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8119 
8120 	for (i = 0; i < N(params); i++) {
8121 		if (i == BWN_WMEPARAM_STATUS) {
8122 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8123 			    shm_offset + (i * 2));
8124 			tmp |= 0x100;
8125 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8126 			    tmp);
8127 		} else {
8128 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8129 			    params[i]);
8130 		}
8131 	}
8132 }
8133 
8134 static void
8135 bwn_mac_write_bssid(struct bwn_mac *mac)
8136 {
8137 	struct bwn_softc *sc = mac->mac_sc;
8138 	uint32_t tmp;
8139 	int i;
8140 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8141 
8142 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8143 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8144 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8145 	    IEEE80211_ADDR_LEN);
8146 
8147 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8148 		tmp = (uint32_t) (mac_bssid[i + 0]);
8149 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8150 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8151 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8152 		bwn_ram_write(mac, 0x20 + i, tmp);
8153 	}
8154 }
8155 
8156 static void
8157 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8158     const uint8_t *macaddr)
8159 {
8160 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8161 	uint16_t data;
8162 
8163 	if (!mac)
8164 		macaddr = zero;
8165 
8166 	offset |= 0x0020;
8167 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8168 
8169 	data = macaddr[0];
8170 	data |= macaddr[1] << 8;
8171 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8172 	data = macaddr[2];
8173 	data |= macaddr[3] << 8;
8174 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8175 	data = macaddr[4];
8176 	data |= macaddr[5] << 8;
8177 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8178 }
8179 
8180 static void
8181 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8182     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8183 {
8184 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8185 	uint8_t per_sta_keys_start = 8;
8186 
8187 	if (BWN_SEC_NEWAPI(mac))
8188 		per_sta_keys_start = 4;
8189 
8190 	KASSERT(index < mac->mac_max_nr_keys,
8191 	    ("%s:%d: fail", __func__, __LINE__));
8192 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8193 	    ("%s:%d: fail", __func__, __LINE__));
8194 
8195 	if (index >= per_sta_keys_start)
8196 		bwn_key_macwrite(mac, index, NULL);
8197 	if (key)
8198 		memcpy(buf, key, key_len);
8199 	bwn_key_write(mac, index, algorithm, buf);
8200 	if (index >= per_sta_keys_start)
8201 		bwn_key_macwrite(mac, index, mac_addr);
8202 
8203 	mac->mac_key[index].algorithm = algorithm;
8204 }
8205 
8206 static void
8207 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8208 {
8209 	uint32_t addrtmp[2] = { 0, 0 };
8210 	uint8_t start = 8;
8211 
8212 	if (BWN_SEC_NEWAPI(mac))
8213 		start = 4;
8214 
8215 	KASSERT(index >= start,
8216 	    ("%s:%d: fail", __func__, __LINE__));
8217 	index -= start;
8218 
8219 	if (addr) {
8220 		addrtmp[0] = addr[0];
8221 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8222 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8223 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8224 		addrtmp[1] = addr[4];
8225 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8226 	}
8227 
8228 	if (mac->mac_sd->sd_id.sd_rev >= 5) {
8229 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8230 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8231 	} else {
8232 		if (index >= 8) {
8233 			bwn_shm_write_4(mac, BWN_SHARED,
8234 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8235 			bwn_shm_write_2(mac, BWN_SHARED,
8236 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8237 		}
8238 	}
8239 }
8240 
8241 static void
8242 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8243     const uint8_t *key)
8244 {
8245 	unsigned int i;
8246 	uint32_t offset;
8247 	uint16_t kidx, value;
8248 
8249 	kidx = BWN_SEC_KEY2FW(mac, index);
8250 	bwn_shm_write_2(mac, BWN_SHARED,
8251 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8252 
8253 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8254 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8255 		value = key[i];
8256 		value |= (uint16_t)(key[i + 1]) << 8;
8257 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8258 	}
8259 }
8260 
8261 static void
8262 bwn_phy_exit(struct bwn_mac *mac)
8263 {
8264 
8265 	mac->mac_phy.rf_onoff(mac, 0);
8266 	if (mac->mac_phy.exit != NULL)
8267 		mac->mac_phy.exit(mac);
8268 }
8269 
8270 static void
8271 bwn_dma_free(struct bwn_mac *mac)
8272 {
8273 	struct bwn_dma *dma;
8274 
8275 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8276 		return;
8277 	dma = &mac->mac_method.dma;
8278 
8279 	bwn_dma_ringfree(&dma->rx);
8280 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8281 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8282 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8283 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8284 	bwn_dma_ringfree(&dma->mcast);
8285 }
8286 
8287 static void
8288 bwn_core_stop(struct bwn_mac *mac)
8289 {
8290 	struct bwn_softc *sc = mac->mac_sc;
8291 
8292 	BWN_ASSERT_LOCKED(sc);
8293 
8294 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8295 		return;
8296 
8297 	callout_stop(&sc->sc_rfswitch_ch);
8298 	callout_stop(&sc->sc_task_ch);
8299 	callout_stop(&sc->sc_watchdog_ch);
8300 	sc->sc_watchdog_timer = 0;
8301 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8302 	BWN_READ_4(mac, BWN_INTR_MASK);
8303 	bwn_mac_suspend(mac);
8304 
8305 	mac->mac_status = BWN_MAC_STATUS_INITED;
8306 }
8307 
8308 static int
8309 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8310 {
8311 	struct bwn_mac *up_dev = NULL;
8312 	struct bwn_mac *down_dev;
8313 	struct bwn_mac *mac;
8314 	int err, status;
8315 	uint8_t gmode;
8316 
8317 	BWN_ASSERT_LOCKED(sc);
8318 
8319 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8320 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8321 		    mac->mac_phy.supports_2ghz) {
8322 			up_dev = mac;
8323 			gmode = 1;
8324 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8325 		    mac->mac_phy.supports_5ghz) {
8326 			up_dev = mac;
8327 			gmode = 0;
8328 		} else {
8329 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8330 			return (EINVAL);
8331 		}
8332 		if (up_dev != NULL)
8333 			break;
8334 	}
8335 	if (up_dev == NULL) {
8336 		device_printf(sc->sc_dev, "Could not find a device\n");
8337 		return (ENODEV);
8338 	}
8339 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8340 		return (0);
8341 
8342 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8343 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8344 
8345 	down_dev = sc->sc_curmac;;
8346 	status = down_dev->mac_status;
8347 	if (status >= BWN_MAC_STATUS_STARTED)
8348 		bwn_core_stop(down_dev);
8349 	if (status >= BWN_MAC_STATUS_INITED)
8350 		bwn_core_exit(down_dev);
8351 
8352 	if (down_dev != up_dev)
8353 		bwn_phy_reset(down_dev);
8354 
8355 	up_dev->mac_phy.gmode = gmode;
8356 	if (status >= BWN_MAC_STATUS_INITED) {
8357 		err = bwn_core_init(up_dev);
8358 		if (err) {
8359 			device_printf(sc->sc_dev,
8360 			    "fatal: failed to initialize for %s-GHz\n",
8361 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8362 			goto fail;
8363 		}
8364 	}
8365 	if (status >= BWN_MAC_STATUS_STARTED)
8366 		bwn_core_start(up_dev);
8367 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8368 	sc->sc_curmac = up_dev;
8369 
8370 	return (0);
8371 fail:
8372 	sc->sc_curmac = NULL;
8373 	return (err);
8374 }
8375 
8376 static void
8377 bwn_rf_turnon(struct bwn_mac *mac)
8378 {
8379 
8380 	bwn_mac_suspend(mac);
8381 	mac->mac_phy.rf_onoff(mac, 1);
8382 	mac->mac_phy.rf_on = 1;
8383 	bwn_mac_enable(mac);
8384 }
8385 
8386 static void
8387 bwn_rf_turnoff(struct bwn_mac *mac)
8388 {
8389 
8390 	bwn_mac_suspend(mac);
8391 	mac->mac_phy.rf_onoff(mac, 0);
8392 	mac->mac_phy.rf_on = 0;
8393 	bwn_mac_enable(mac);
8394 }
8395 
8396 static void
8397 bwn_phy_reset(struct bwn_mac *mac)
8398 {
8399 	struct siba_dev_softc *sd = mac->mac_sd;
8400 
8401 	siba_write_4(sd, SIBA_TGSLOW,
8402 	    ((siba_read_4(sd, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8403 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8404 	DELAY(1000);
8405 	siba_write_4(sd, SIBA_TGSLOW,
8406 	    (siba_read_4(sd, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8407 	    BWN_TGSLOW_PHYRESET);
8408 	DELAY(1000);
8409 }
8410 
8411 static int
8412 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8413 {
8414 	struct bwn_vap *bvp = BWN_VAP(vap);
8415 	struct ieee80211com *ic= vap->iv_ic;
8416 	struct ifnet *ifp = ic->ic_ifp;
8417 	enum ieee80211_state ostate = vap->iv_state;
8418 	struct bwn_softc *sc = ifp->if_softc;
8419 	struct bwn_mac *mac = sc->sc_curmac;
8420 	int error;
8421 
8422 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8423 	    ieee80211_state_name[vap->iv_state],
8424 	    ieee80211_state_name[nstate]);
8425 
8426 	error = bvp->bv_newstate(vap, nstate, arg);
8427 	if (error != 0)
8428 		return (error);
8429 
8430 	BWN_LOCK(sc);
8431 
8432 	bwn_led_newstate(mac, nstate);
8433 
8434 	/*
8435 	 * Clear the BSSID when we stop a STA
8436 	 */
8437 	if (vap->iv_opmode == IEEE80211_M_STA) {
8438 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8439 			/*
8440 			 * Clear out the BSSID.  If we reassociate to
8441 			 * the same AP, this will reinialize things
8442 			 * correctly...
8443 			 */
8444 			if (ic->ic_opmode == IEEE80211_M_STA &&
8445 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8446 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8447 				bwn_set_macaddr(mac);
8448 			}
8449 		}
8450 	}
8451 
8452 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8453 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8454 		/* XXX nothing to do? */
8455 	} else if (nstate == IEEE80211_S_RUN) {
8456 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8457 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8458 		bwn_set_opmode(mac);
8459 		bwn_set_pretbtt(mac);
8460 		bwn_spu_setdelay(mac, 0);
8461 		bwn_set_macaddr(mac);
8462 	}
8463 
8464 	BWN_UNLOCK(sc);
8465 
8466 	return (error);
8467 }
8468 
8469 static void
8470 bwn_set_pretbtt(struct bwn_mac *mac)
8471 {
8472 	struct bwn_softc *sc = mac->mac_sc;
8473 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8474 	uint16_t pretbtt;
8475 
8476 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8477 		pretbtt = 2;
8478 	else
8479 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8480 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8481 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8482 }
8483 
8484 static int
8485 bwn_intr(void *arg)
8486 {
8487 	struct bwn_mac *mac = arg;
8488 	struct bwn_softc *sc = mac->mac_sc;
8489 	struct siba_softc *siba = mac->mac_sd->sd_bus;
8490 	uint32_t reason;
8491 
8492 	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid)
8493 		return (FILTER_STRAY);
8494 
8495 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8496 	if (reason == 0xffffffff)	/* shared IRQ */
8497 		return (FILTER_STRAY);
8498 	reason &= mac->mac_intr_mask;
8499 	if (reason == 0)
8500 		return (FILTER_HANDLED);
8501 
8502 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8503 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8504 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8505 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8506 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8507 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8508 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8509 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8510 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8511 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8512 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8513 
8514 	/* Disable interrupts. */
8515 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8516 
8517 	mac->mac_reason_intr = reason;
8518 
8519 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8520 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8521 
8522 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8523 	return (FILTER_HANDLED);
8524 }
8525 
8526 static void
8527 bwn_intrtask(void *arg, int npending)
8528 {
8529 	struct bwn_mac *mac = arg;
8530 	struct bwn_softc *sc = mac->mac_sc;
8531 	struct ifnet *ifp = sc->sc_ifp;
8532 	struct siba_softc *siba = mac->mac_sd->sd_bus;
8533 	uint32_t merged = 0;
8534 	int i, tx = 0, rx = 0;
8535 
8536 	BWN_LOCK(sc);
8537 	if (mac->mac_status < BWN_MAC_STATUS_STARTED || siba->siba_invalid) {
8538 		BWN_UNLOCK(sc);
8539 		return;
8540 	}
8541 
8542 	for (i = 0; i < N(mac->mac_reason); i++)
8543 		merged |= mac->mac_reason[i];
8544 
8545 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8546 		device_printf(sc->sc_dev, "MAC trans error\n");
8547 
8548 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8549 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8550 		mac->mac_phy.txerrors--;
8551 		if (mac->mac_phy.txerrors == 0) {
8552 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8553 			bwn_restart(mac, "PHY TX errors");
8554 		}
8555 	}
8556 
8557 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8558 		if (merged & BWN_DMAINTR_FATALMASK) {
8559 			device_printf(sc->sc_dev,
8560 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8561 			    mac->mac_reason[0], mac->mac_reason[1],
8562 			    mac->mac_reason[2], mac->mac_reason[3],
8563 			    mac->mac_reason[4], mac->mac_reason[5]);
8564 			bwn_restart(mac, "DMA error");
8565 			BWN_UNLOCK(sc);
8566 			return;
8567 		}
8568 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8569 			device_printf(sc->sc_dev,
8570 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8571 			    mac->mac_reason[0], mac->mac_reason[1],
8572 			    mac->mac_reason[2], mac->mac_reason[3],
8573 			    mac->mac_reason[4], mac->mac_reason[5]);
8574 		}
8575 	}
8576 
8577 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8578 		bwn_intr_ucode_debug(mac);
8579 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8580 		bwn_intr_tbtt_indication(mac);
8581 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8582 		bwn_intr_atim_end(mac);
8583 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8584 		bwn_intr_beacon(mac);
8585 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8586 		bwn_intr_pmq(mac);
8587 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8588 		bwn_intr_noise(mac);
8589 
8590 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8591 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8592 			bwn_dma_rx(mac->mac_method.dma.rx);
8593 			rx = 1;
8594 		}
8595 	} else
8596 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8597 
8598 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8599 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8600 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8601 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8602 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8603 
8604 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8605 		bwn_intr_txeof(mac);
8606 		tx = 1;
8607 	}
8608 
8609 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8610 
8611 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8612 		int evt = BWN_LED_EVENT_NONE;
8613 
8614 		if (tx && rx) {
8615 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8616 				evt = BWN_LED_EVENT_RX;
8617 			else
8618 				evt = BWN_LED_EVENT_TX;
8619 		} else if (tx) {
8620 			evt = BWN_LED_EVENT_TX;
8621 		} else if (rx) {
8622 			evt = BWN_LED_EVENT_RX;
8623 		} else if (rx == 0) {
8624 			evt = BWN_LED_EVENT_POLL;
8625 		}
8626 
8627 		if (evt != BWN_LED_EVENT_NONE)
8628 			bwn_led_event(mac, evt);
8629        }
8630 
8631 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8632 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8633 			bwn_start_locked(ifp);
8634 	}
8635 
8636 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8637 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8638 
8639 	BWN_UNLOCK(sc);
8640 }
8641 
8642 static void
8643 bwn_restart(struct bwn_mac *mac, const char *msg)
8644 {
8645 	struct bwn_softc *sc = mac->mac_sc;
8646 	struct ifnet *ifp = sc->sc_ifp;
8647 	struct ieee80211com *ic = ifp->if_l2com;
8648 
8649 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8650 		return;
8651 
8652 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8653 	ieee80211_runtask(ic, &mac->mac_hwreset);
8654 }
8655 
8656 static void
8657 bwn_intr_ucode_debug(struct bwn_mac *mac)
8658 {
8659 	struct bwn_softc *sc = mac->mac_sc;
8660 	uint16_t reason;
8661 
8662 	if (mac->mac_fw.opensource == 0)
8663 		return;
8664 
8665 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8666 	switch (reason) {
8667 	case BWN_DEBUGINTR_PANIC:
8668 		bwn_handle_fwpanic(mac);
8669 		break;
8670 	case BWN_DEBUGINTR_DUMP_SHM:
8671 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8672 		break;
8673 	case BWN_DEBUGINTR_DUMP_REGS:
8674 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8675 		break;
8676 	case BWN_DEBUGINTR_MARKER:
8677 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8678 		break;
8679 	default:
8680 		device_printf(sc->sc_dev,
8681 		    "ucode debug unknown reason: %#x\n", reason);
8682 	}
8683 
8684 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8685 	    BWN_DEBUGINTR_ACK);
8686 }
8687 
8688 static void
8689 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8690 {
8691 	struct bwn_softc *sc = mac->mac_sc;
8692 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8693 
8694 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8695 		bwn_psctl(mac, 0);
8696 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8697 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8698 }
8699 
8700 static void
8701 bwn_intr_atim_end(struct bwn_mac *mac)
8702 {
8703 
8704 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8705 		BWN_WRITE_4(mac, BWN_MACCMD,
8706 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8707 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8708 	}
8709 }
8710 
8711 static void
8712 bwn_intr_beacon(struct bwn_mac *mac)
8713 {
8714 	struct bwn_softc *sc = mac->mac_sc;
8715 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8716 	uint32_t cmd, beacon0, beacon1;
8717 
8718 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8719 	    ic->ic_opmode == IEEE80211_M_MBSS)
8720 		return;
8721 
8722 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8723 
8724 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8725 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8726 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8727 
8728 	if (beacon0 && beacon1) {
8729 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8730 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8731 		return;
8732 	}
8733 
8734 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8735 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8736 		bwn_load_beacon0(mac);
8737 		bwn_load_beacon1(mac);
8738 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8739 		cmd |= BWN_MACCMD_BEACON0_VALID;
8740 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8741 	} else {
8742 		if (!beacon0) {
8743 			bwn_load_beacon0(mac);
8744 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8745 			cmd |= BWN_MACCMD_BEACON0_VALID;
8746 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8747 		} else if (!beacon1) {
8748 			bwn_load_beacon1(mac);
8749 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8750 			cmd |= BWN_MACCMD_BEACON1_VALID;
8751 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8752 		}
8753 	}
8754 }
8755 
8756 static void
8757 bwn_intr_pmq(struct bwn_mac *mac)
8758 {
8759 	uint32_t tmp;
8760 
8761 	while (1) {
8762 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8763 		if (!(tmp & 0x00000008))
8764 			break;
8765 	}
8766 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8767 }
8768 
8769 static void
8770 bwn_intr_noise(struct bwn_mac *mac)
8771 {
8772 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8773 	uint16_t tmp;
8774 	uint8_t noise[4];
8775 	uint8_t i, j;
8776 	int32_t average;
8777 
8778 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8779 		return;
8780 
8781 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8782 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8783 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8784 	    noise[3] == 0x7f)
8785 		goto new;
8786 
8787 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8788 	    ("%s:%d: fail", __func__, __LINE__));
8789 	i = mac->mac_noise.noi_nsamples;
8790 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8791 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8792 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8793 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8794 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8795 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8796 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8797 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8798 	mac->mac_noise.noi_nsamples++;
8799 	if (mac->mac_noise.noi_nsamples == 8) {
8800 		average = 0;
8801 		for (i = 0; i < 8; i++) {
8802 			for (j = 0; j < 4; j++)
8803 				average += mac->mac_noise.noi_samples[i][j];
8804 		}
8805 		average = (((average / 32) * 125) + 64) / 128;
8806 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8807 		if (tmp >= 8)
8808 			average += 2;
8809 		else
8810 			average -= 25;
8811 		average -= (tmp == 8) ? 72 : 48;
8812 
8813 		mac->mac_stats.link_noise = average;
8814 		mac->mac_noise.noi_running = 0;
8815 		return;
8816 	}
8817 new:
8818 	bwn_noise_gensample(mac);
8819 }
8820 
8821 static int
8822 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8823 {
8824 	struct bwn_mac *mac = prq->prq_mac;
8825 	struct bwn_softc *sc = mac->mac_sc;
8826 	unsigned int i;
8827 
8828 	BWN_ASSERT_LOCKED(sc);
8829 
8830 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8831 		return (0);
8832 
8833 	for (i = 0; i < 5000; i++) {
8834 		if (bwn_pio_rxeof(prq) == 0)
8835 			break;
8836 	}
8837 	if (i >= 5000)
8838 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8839 	return ((i > 0) ? 1 : 0);
8840 }
8841 
8842 static void
8843 bwn_dma_rx(struct bwn_dma_ring *dr)
8844 {
8845 	int slot, curslot;
8846 
8847 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8848 	curslot = dr->get_curslot(dr);
8849 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8850 	    ("%s:%d: fail", __func__, __LINE__));
8851 
8852 	slot = dr->dr_curslot;
8853 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8854 		bwn_dma_rxeof(dr, &slot);
8855 
8856 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8857 	    BUS_DMASYNC_PREWRITE);
8858 
8859 	dr->set_curslot(dr, slot);
8860 	dr->dr_curslot = slot;
8861 }
8862 
8863 static void
8864 bwn_intr_txeof(struct bwn_mac *mac)
8865 {
8866 	struct bwn_txstatus stat;
8867 	uint32_t stat0, stat1;
8868 	uint16_t tmp;
8869 
8870 	BWN_ASSERT_LOCKED(mac->mac_sc);
8871 
8872 	while (1) {
8873 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8874 		if (!(stat0 & 0x00000001))
8875 			break;
8876 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8877 
8878 		stat.cookie = (stat0 >> 16);
8879 		stat.seq = (stat1 & 0x0000ffff);
8880 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8881 		tmp = (stat0 & 0x0000ffff);
8882 		stat.framecnt = ((tmp & 0xf000) >> 12);
8883 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8884 		stat.sreason = ((tmp & 0x001c) >> 2);
8885 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8886 		stat.im = (tmp & 0x0040) ? 1 : 0;
8887 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8888 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8889 
8890 		bwn_handle_txeof(mac, &stat);
8891 	}
8892 }
8893 
8894 static void
8895 bwn_hwreset(void *arg, int npending)
8896 {
8897 	struct bwn_mac *mac = arg;
8898 	struct bwn_softc *sc = mac->mac_sc;
8899 	int error = 0;
8900 	int prev_status;
8901 
8902 	BWN_LOCK(sc);
8903 
8904 	prev_status = mac->mac_status;
8905 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8906 		bwn_core_stop(mac);
8907 	if (prev_status >= BWN_MAC_STATUS_INITED)
8908 		bwn_core_exit(mac);
8909 
8910 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8911 		error = bwn_core_init(mac);
8912 		if (error)
8913 			goto out;
8914 	}
8915 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8916 		bwn_core_start(mac);
8917 out:
8918 	if (error) {
8919 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8920 		sc->sc_curmac = NULL;
8921 	}
8922 	BWN_UNLOCK(sc);
8923 }
8924 
8925 static void
8926 bwn_handle_fwpanic(struct bwn_mac *mac)
8927 {
8928 	struct bwn_softc *sc = mac->mac_sc;
8929 	uint16_t reason;
8930 
8931 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8932 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8933 
8934 	if (reason == BWN_FWPANIC_RESTART)
8935 		bwn_restart(mac, "ucode panic");
8936 }
8937 
8938 static void
8939 bwn_load_beacon0(struct bwn_mac *mac)
8940 {
8941 
8942 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8943 }
8944 
8945 static void
8946 bwn_load_beacon1(struct bwn_mac *mac)
8947 {
8948 
8949 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8950 }
8951 
8952 static uint32_t
8953 bwn_jssi_read(struct bwn_mac *mac)
8954 {
8955 	uint32_t val = 0;
8956 
8957 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8958 	val <<= 16;
8959 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8960 
8961 	return (val);
8962 }
8963 
8964 static void
8965 bwn_noise_gensample(struct bwn_mac *mac)
8966 {
8967 	uint32_t jssi = 0x7f7f7f7f;
8968 
8969 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8970 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8971 	BWN_WRITE_4(mac, BWN_MACCMD,
8972 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8973 }
8974 
8975 static int
8976 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8977 {
8978 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8979 
8980 	return (dr->dr_numslots - dr->dr_usedslot);
8981 }
8982 
8983 static int
8984 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8985 {
8986 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8987 
8988 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8989 	    ("%s:%d: fail", __func__, __LINE__));
8990 	if (slot == dr->dr_numslots - 1)
8991 		return (0);
8992 	return (slot + 1);
8993 }
8994 
8995 static void
8996 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8997 {
8998 	struct bwn_mac *mac = dr->dr_mac;
8999 	struct bwn_softc *sc = mac->mac_sc;
9000 	struct bwn_dma *dma = &mac->mac_method.dma;
9001 	struct bwn_dmadesc_generic *desc;
9002 	struct bwn_dmadesc_meta *meta;
9003 	struct bwn_rxhdr4 *rxhdr;
9004 	struct ifnet *ifp = sc->sc_ifp;
9005 	struct mbuf *m;
9006 	uint32_t macstat;
9007 	int32_t tmp;
9008 	int cnt = 0;
9009 	uint16_t len;
9010 
9011 	dr->getdesc(dr, *slot, &desc, &meta);
9012 
9013 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
9014 	m = meta->mt_m;
9015 
9016 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
9017 		ifp->if_ierrors++;
9018 		return;
9019 	}
9020 
9021 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
9022 	len = le16toh(rxhdr->frame_len);
9023 	if (len <= 0) {
9024 		ifp->if_ierrors++;
9025 		return;
9026 	}
9027 	if (bwn_dma_check_redzone(dr, m)) {
9028 		device_printf(sc->sc_dev, "redzone error.\n");
9029 		bwn_dma_set_redzone(dr, m);
9030 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9031 		    BUS_DMASYNC_PREWRITE);
9032 		return;
9033 	}
9034 	if (len > dr->dr_rx_bufsize) {
9035 		tmp = len;
9036 		while (1) {
9037 			dr->getdesc(dr, *slot, &desc, &meta);
9038 			bwn_dma_set_redzone(dr, meta->mt_m);
9039 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9040 			    BUS_DMASYNC_PREWRITE);
9041 			*slot = bwn_dma_nextslot(dr, *slot);
9042 			cnt++;
9043 			tmp -= dr->dr_rx_bufsize;
9044 			if (tmp <= 0)
9045 				break;
9046 		}
9047 		device_printf(sc->sc_dev, "too small buffer "
9048 		       "(len %u buffer %u dropped %d)\n",
9049 		       len, dr->dr_rx_bufsize, cnt);
9050 		return;
9051 	}
9052 	macstat = le32toh(rxhdr->mac_status);
9053 	if (macstat & BWN_RX_MAC_FCSERR) {
9054 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9055 			device_printf(sc->sc_dev, "RX drop\n");
9056 			return;
9057 		}
9058 	}
9059 
9060 	m->m_pkthdr.rcvif = ifp;
9061 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
9062 	m_adj(m, dr->dr_frameoffset);
9063 
9064 	bwn_rxeof(dr->dr_mac, m, rxhdr);
9065 }
9066 
9067 static void
9068 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
9069 {
9070 	struct bwn_dma_ring *dr;
9071 	struct bwn_dmadesc_generic *desc;
9072 	struct bwn_dmadesc_meta *meta;
9073 	struct bwn_node *bn;
9074 	struct bwn_pio_txqueue *tq;
9075 	struct bwn_pio_txpkt *tp = NULL;
9076 	struct bwn_softc *sc = mac->mac_sc;
9077 	struct bwn_stats *stats = &mac->mac_stats;
9078 	struct ieee80211_node *ni;
9079 	int slot;
9080 
9081 	BWN_ASSERT_LOCKED(mac->mac_sc);
9082 
9083 	if (status->im)
9084 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9085 	if (status->ampdu)
9086 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9087 	if (status->rtscnt) {
9088 		if (status->rtscnt == 0xf)
9089 			stats->rtsfail++;
9090 		else
9091 			stats->rts++;
9092 	}
9093 
9094 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9095 		if (status->ack) {
9096 			dr = bwn_dma_parse_cookie(mac, status,
9097 			    status->cookie, &slot);
9098 			if (dr == NULL) {
9099 				device_printf(sc->sc_dev,
9100 				    "failed to parse cookie\n");
9101 				return;
9102 			}
9103 			while (1) {
9104 				dr->getdesc(dr, slot, &desc, &meta);
9105 				if (meta->mt_islast) {
9106 					ni = meta->mt_ni;
9107 					bn = (struct bwn_node *)ni;
9108 					ieee80211_amrr_tx_complete(&bn->bn_amn,
9109 					    status->ack, 0);
9110 					break;
9111 				}
9112 				slot = bwn_dma_nextslot(dr, slot);
9113 			}
9114 		}
9115 		bwn_dma_handle_txeof(mac, status);
9116 	} else {
9117 		if (status->ack) {
9118 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9119 			if (tq == NULL) {
9120 				device_printf(sc->sc_dev,
9121 				    "failed to parse cookie\n");
9122 				return;
9123 			}
9124 			ni = tp->tp_ni;
9125 			bn = (struct bwn_node *)ni;
9126 			ieee80211_amrr_tx_complete(&bn->bn_amn, status->ack, 0);
9127 		}
9128 		bwn_pio_handle_txeof(mac, status);
9129 	}
9130 
9131 	bwn_phy_txpower_check(mac, 0);
9132 }
9133 
9134 static uint8_t
9135 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9136 {
9137 	struct bwn_mac *mac = prq->prq_mac;
9138 	struct bwn_softc *sc = mac->mac_sc;
9139 	struct bwn_rxhdr4 rxhdr;
9140 	struct ifnet *ifp = sc->sc_ifp;
9141 	struct mbuf *m;
9142 	uint32_t ctl32, macstat, v32;
9143 	unsigned int i, padding;
9144 	uint16_t ctl16, len, v16;
9145 	unsigned char *mp;
9146 	char *data;
9147 
9148 	memset(&rxhdr, 0, sizeof(rxhdr));
9149 
9150 	if (prq->prq_rev >= 8) {
9151 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9152 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9153 			return (0);
9154 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9155 		    BWN_PIO8_RXCTL_FRAMEREADY);
9156 		for (i = 0; i < 10; i++) {
9157 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9158 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9159 				goto ready;
9160 			DELAY(10);
9161 		}
9162 	} else {
9163 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9164 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9165 			return (0);
9166 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9167 		    BWN_PIO_RXCTL_FRAMEREADY);
9168 		for (i = 0; i < 10; i++) {
9169 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9170 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9171 				goto ready;
9172 			DELAY(10);
9173 		}
9174 	}
9175 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9176 	return (1);
9177 ready:
9178 	if (prq->prq_rev >= 8)
9179 		siba_read_multi_4(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9180 		    prq->prq_base + BWN_PIO8_RXDATA);
9181 	else
9182 		siba_read_multi_2(mac->mac_sd, &rxhdr, sizeof(rxhdr),
9183 		    prq->prq_base + BWN_PIO_RXDATA);
9184 	len = le16toh(rxhdr.frame_len);
9185 	if (len > 0x700) {
9186 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9187 		goto error;
9188 	}
9189 	if (len == 0) {
9190 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9191 		goto error;
9192 	}
9193 
9194 	macstat = le32toh(rxhdr.mac_status);
9195 	if (macstat & BWN_RX_MAC_FCSERR) {
9196 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9197 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9198 			goto error;
9199 		}
9200 	}
9201 
9202 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9203 	KASSERT(len + padding <= MCLBYTES, ("too big..\n"));
9204 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9205 	if (m == NULL) {
9206 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9207 		goto error;
9208 	}
9209 	mp = mtod(m, unsigned char *);
9210 	if (prq->prq_rev >= 8) {
9211 		siba_read_multi_4(mac->mac_sd, mp + padding, (len & ~3),
9212 		    prq->prq_base + BWN_PIO8_RXDATA);
9213 		if (len & 3) {
9214 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9215 			data = &(mp[len + padding - 1]);
9216 			switch (len & 3) {
9217 			case 3:
9218 				*data = (v32 >> 16);
9219 				data--;
9220 			case 2:
9221 				*data = (v32 >> 8);
9222 				data--;
9223 			case 1:
9224 				*data = v32;
9225 			}
9226 		}
9227 	} else {
9228 		siba_read_multi_2(mac->mac_sd, mp + padding, (len & ~1),
9229 		    prq->prq_base + BWN_PIO_RXDATA);
9230 		if (len & 1) {
9231 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9232 			mp[len + padding - 1] = v16;
9233 		}
9234 	}
9235 
9236 	m->m_pkthdr.rcvif = ifp;
9237 	m->m_len = m->m_pkthdr.len = len + padding;
9238 
9239 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9240 
9241 	return (1);
9242 error:
9243 	if (prq->prq_rev >= 8)
9244 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9245 		    BWN_PIO8_RXCTL_DATAREADY);
9246 	else
9247 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9248 	return (1);
9249 }
9250 
9251 static int
9252 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9253     struct bwn_dmadesc_meta *meta, int init)
9254 {
9255 	struct bwn_mac *mac = dr->dr_mac;
9256 	struct bwn_dma *dma = &mac->mac_method.dma;
9257 	struct bwn_rxhdr4 *hdr;
9258 	bus_dmamap_t map;
9259 	bus_addr_t paddr;
9260 	struct mbuf *m;
9261 	int error;
9262 
9263 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9264 	if (m == NULL) {
9265 		error = ENOBUFS;
9266 
9267 		/*
9268 		 * If the NIC is up and running, we need to:
9269 		 * - Clear RX buffer's header.
9270 		 * - Restore RX descriptor settings.
9271 		 */
9272 		if (init)
9273 			return (error);
9274 		else
9275 			goto back;
9276 	}
9277 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9278 
9279 	bwn_dma_set_redzone(dr, m);
9280 
9281 	/*
9282 	 * Try to load RX buf into temporary DMA map
9283 	 */
9284 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9285 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9286 	if (error) {
9287 		m_freem(m);
9288 
9289 		/*
9290 		 * See the comment above
9291 		 */
9292 		if (init)
9293 			return (error);
9294 		else
9295 			goto back;
9296 	}
9297 
9298 	if (!init)
9299 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9300 	meta->mt_m = m;
9301 	meta->mt_paddr = paddr;
9302 
9303 	/*
9304 	 * Swap RX buf's DMA map with the loaded temporary one
9305 	 */
9306 	map = meta->mt_dmap;
9307 	meta->mt_dmap = dr->dr_spare_dmap;
9308 	dr->dr_spare_dmap = map;
9309 
9310 back:
9311 	/*
9312 	 * Clear RX buf header
9313 	 */
9314 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9315 	bzero(hdr, sizeof(*hdr));
9316 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9317 	    BUS_DMASYNC_PREWRITE);
9318 
9319 	/*
9320 	 * Setup RX buf descriptor
9321 	 */
9322 	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9323 	    sizeof(*hdr), 0, 0, 0);
9324 	return (error);
9325 }
9326 
9327 static void
9328 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9329 		 bus_size_t mapsz __unused, int error)
9330 {
9331 
9332 	if (!error) {
9333 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9334 		*((bus_addr_t *)arg) = seg->ds_addr;
9335 	}
9336 }
9337 
9338 static int
9339 bwn_hwrate2ieeerate(int rate)
9340 {
9341 
9342 	switch (rate) {
9343 	case BWN_CCK_RATE_1MB:
9344 		return (2);
9345 	case BWN_CCK_RATE_2MB:
9346 		return (4);
9347 	case BWN_CCK_RATE_5MB:
9348 		return (11);
9349 	case BWN_CCK_RATE_11MB:
9350 		return (22);
9351 	case BWN_OFDM_RATE_6MB:
9352 		return (12);
9353 	case BWN_OFDM_RATE_9MB:
9354 		return (18);
9355 	case BWN_OFDM_RATE_12MB:
9356 		return (24);
9357 	case BWN_OFDM_RATE_18MB:
9358 		return (36);
9359 	case BWN_OFDM_RATE_24MB:
9360 		return (48);
9361 	case BWN_OFDM_RATE_36MB:
9362 		return (72);
9363 	case BWN_OFDM_RATE_48MB:
9364 		return (96);
9365 	case BWN_OFDM_RATE_54MB:
9366 		return (108);
9367 	default:
9368 		printf("Ooops\n");
9369 		return (0);
9370 	}
9371 }
9372 
9373 static void
9374 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9375 {
9376 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9377 	struct bwn_plcp6 *plcp;
9378 	struct bwn_softc *sc = mac->mac_sc;
9379 	struct ieee80211_frame_min *wh;
9380 	struct ieee80211_node *ni;
9381 	struct ifnet *ifp = sc->sc_ifp;
9382 	struct ieee80211com *ic = ifp->if_l2com;
9383 	uint32_t macstat;
9384 	int padding, rate, rssi = 0, noise = 0, type;
9385 	uint16_t phytype, phystat0, phystat3, chanstat;
9386 	unsigned char *mp = mtod(m, unsigned char *);
9387 	static int rx_mac_dec_rpt = 0;
9388 
9389 	BWN_ASSERT_LOCKED(sc);
9390 
9391 	phystat0 = le16toh(rxhdr->phy_status0);
9392 	phystat3 = le16toh(rxhdr->phy_status3);
9393 	macstat = le32toh(rxhdr->mac_status);
9394 	chanstat = le16toh(rxhdr->channel);
9395 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9396 
9397 	if (macstat & BWN_RX_MAC_FCSERR)
9398 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9399 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9400 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9401 	if (macstat & BWN_RX_MAC_DECERR)
9402 		goto drop;
9403 
9404 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9405 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9406 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9407 		    m->m_pkthdr.len);
9408 		goto drop;
9409 	}
9410 	plcp = (struct bwn_plcp6 *)(mp + padding);
9411 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9412 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9413 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9414 		    m->m_pkthdr.len);
9415 		goto drop;
9416 	}
9417 	wh = mtod(m, struct ieee80211_frame_min *);
9418 
9419 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9420 		device_printf(sc->sc_dev,
9421 		    "RX decryption attempted (old %d keyidx %#x)\n",
9422 		    BWN_ISOLDFMT(mac),
9423 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9424 
9425 	/* XXX calculating RSSI & noise & antenna */
9426 
9427 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9428 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9429 		    phytype == BWN_PHYTYPE_A);
9430 	else
9431 		rate = bwn_plcp_get_cckrate(mac, plcp);
9432 	if (rate == -1) {
9433 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9434 			goto drop;
9435 	}
9436 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9437 
9438 	/* RX radio tap */
9439 	if (ieee80211_radiotap_active(ic))
9440 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9441 	m_adj(m, -IEEE80211_CRC_LEN);
9442 
9443 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9444 	noise = mac->mac_stats.link_noise;
9445 
9446 	BWN_UNLOCK(sc);
9447 
9448 	ni = ieee80211_find_rxnode(ic, wh);
9449 	if (ni != NULL) {
9450 		type = ieee80211_input(ni, m, rssi, noise);
9451 		ieee80211_free_node(ni);
9452 	} else
9453 		type = ieee80211_input_all(ic, m, rssi, noise);
9454 
9455 	BWN_LOCK(sc);
9456 	return;
9457 drop:
9458 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9459 }
9460 
9461 static void
9462 bwn_dma_handle_txeof(struct bwn_mac *mac,
9463     const struct bwn_txstatus *status)
9464 {
9465 	struct bwn_dma *dma = &mac->mac_method.dma;
9466 	struct bwn_dma_ring *dr;
9467 	struct bwn_dmadesc_generic *desc;
9468 	struct bwn_dmadesc_meta *meta;
9469 	struct bwn_softc *sc = mac->mac_sc;
9470 	struct ieee80211_node *ni;
9471 	struct ifnet *ifp = sc->sc_ifp;
9472 	struct mbuf *m;
9473 	int slot;
9474 
9475 	BWN_ASSERT_LOCKED(sc);
9476 
9477 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9478 	if (dr == NULL) {
9479 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9480 		return;
9481 	}
9482 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9483 
9484 	while (1) {
9485 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9486 		    ("%s:%d: fail", __func__, __LINE__));
9487 		dr->getdesc(dr, slot, &desc, &meta);
9488 
9489 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9490 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9491 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9492 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9493 
9494 		if (meta->mt_islast) {
9495 			KASSERT(meta->mt_m != NULL,
9496 			    ("%s:%d: fail", __func__, __LINE__));
9497 
9498 			ni = meta->mt_ni;
9499 			m = meta->mt_m;
9500 			if (ni != NULL) {
9501 				/*
9502 				 * Do any tx complete callback. Note this must
9503 				 * be done before releasing the node reference.
9504 				 */
9505 				if (m->m_flags & M_TXCB)
9506 					ieee80211_process_callback(ni, m, 0);
9507 				ieee80211_free_node(ni);
9508 				meta->mt_ni = NULL;
9509 			}
9510 			m_freem(m);
9511 			meta->mt_m = NULL;
9512 		} else {
9513 			KASSERT(meta->mt_m == NULL,
9514 			    ("%s:%d: fail", __func__, __LINE__));
9515 		}
9516 
9517 		dr->dr_usedslot--;
9518 		if (meta->mt_islast) {
9519 			ifp->if_opackets++;
9520 			break;
9521 		}
9522 		slot = bwn_dma_nextslot(dr, slot);
9523 	}
9524 	sc->sc_watchdog_timer = 0;
9525 	if (dr->dr_stop) {
9526 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9527 		    ("%s:%d: fail", __func__, __LINE__));
9528 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9529 		dr->dr_stop = 0;
9530 	}
9531 }
9532 
9533 static void
9534 bwn_pio_handle_txeof(struct bwn_mac *mac,
9535     const struct bwn_txstatus *status)
9536 {
9537 	struct bwn_pio_txqueue *tq;
9538 	struct bwn_pio_txpkt *tp = NULL;
9539 	struct bwn_softc *sc = mac->mac_sc;
9540 	struct ifnet *ifp = sc->sc_ifp;
9541 
9542 	BWN_ASSERT_LOCKED(sc);
9543 
9544 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9545 	if (tq == NULL)
9546 		return;
9547 
9548 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9549 	tq->tq_free++;
9550 
9551 	if (tp->tp_ni != NULL) {
9552 		/*
9553 		 * Do any tx complete callback.  Note this must
9554 		 * be done before releasing the node reference.
9555 		 */
9556 		if (tp->tp_m->m_flags & M_TXCB)
9557 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9558 		ieee80211_free_node(tp->tp_ni);
9559 		tp->tp_ni = NULL;
9560 	}
9561 	m_freem(tp->tp_m);
9562 	tp->tp_m = NULL;
9563 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9564 
9565 	ifp->if_opackets++;
9566 
9567 	sc->sc_watchdog_timer = 0;
9568 	if (tq->tq_stop) {
9569 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9570 		tq->tq_stop = 0;
9571 	}
9572 }
9573 
9574 static void
9575 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9576 {
9577 	struct bwn_softc *sc = mac->mac_sc;
9578 	struct bwn_phy *phy = &mac->mac_phy;
9579 	struct ifnet *ifp = sc->sc_ifp;
9580 	struct ieee80211com *ic = ifp->if_l2com;
9581 	struct siba_softc *siba = mac->mac_sd->sd_bus;
9582 	unsigned long now;
9583 	int result;
9584 
9585 	BWN_GETTIME(now);
9586 
9587 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9588 		return;
9589 	phy->nexttime = now + 2 * 1000;
9590 
9591 	if (siba->siba_board_vendor == SIBA_BOARDVENDOR_BCM &&
9592 	    siba->siba_board_type == SIBA_BOARD_BU4306)
9593 		return;
9594 
9595 	if (phy->recalc_txpwr != NULL) {
9596 		result = phy->recalc_txpwr(mac,
9597 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9598 		if (result == BWN_TXPWR_RES_DONE)
9599 			return;
9600 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9601 		    ("%s: fail", __func__));
9602 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9603 
9604 		ieee80211_runtask(ic, &mac->mac_txpower);
9605 	}
9606 }
9607 
9608 static uint16_t
9609 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9610 {
9611 
9612 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9613 }
9614 
9615 static uint32_t
9616 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9617 {
9618 
9619 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9620 }
9621 
9622 static void
9623 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9624 {
9625 
9626 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9627 }
9628 
9629 static void
9630 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9631 {
9632 
9633 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9634 }
9635 
9636 static int
9637 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9638 {
9639 
9640 	switch (rate) {
9641 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9642 	case 12:
9643 		return (BWN_OFDM_RATE_6MB);
9644 	case 18:
9645 		return (BWN_OFDM_RATE_9MB);
9646 	case 24:
9647 		return (BWN_OFDM_RATE_12MB);
9648 	case 36:
9649 		return (BWN_OFDM_RATE_18MB);
9650 	case 48:
9651 		return (BWN_OFDM_RATE_24MB);
9652 	case 72:
9653 		return (BWN_OFDM_RATE_36MB);
9654 	case 96:
9655 		return (BWN_OFDM_RATE_48MB);
9656 	case 108:
9657 		return (BWN_OFDM_RATE_54MB);
9658 	/* CCK rates (NB: not IEEE std, device-specific) */
9659 	case 2:
9660 		return (BWN_CCK_RATE_1MB);
9661 	case 4:
9662 		return (BWN_CCK_RATE_2MB);
9663 	case 11:
9664 		return (BWN_CCK_RATE_5MB);
9665 	case 22:
9666 		return (BWN_CCK_RATE_11MB);
9667 	}
9668 
9669 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9670 	return (BWN_CCK_RATE_1MB);
9671 }
9672 
9673 static int
9674 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9675     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9676 {
9677 	const struct bwn_phy *phy = &mac->mac_phy;
9678 	struct bwn_softc *sc = mac->mac_sc;
9679 	struct ieee80211_frame *wh;
9680 	struct ieee80211_frame *protwh;
9681 	struct ieee80211_frame_cts *cts;
9682 	struct ieee80211_frame_rts *rts;
9683 	const struct ieee80211_txparam *tp;
9684 	struct ieee80211vap *vap = ni->ni_vap;
9685 	struct ifnet *ifp = sc->sc_ifp;
9686 	struct ieee80211com *ic = ifp->if_l2com;
9687 	struct mbuf *mprot;
9688 	unsigned int len;
9689 	uint32_t macctl = 0;
9690 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9691 	uint16_t phyctl = 0;
9692 	uint8_t rate, rate_fb;
9693 
9694 	wh = mtod(m, struct ieee80211_frame *);
9695 	memset(txhdr, 0, sizeof(*txhdr));
9696 
9697 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9698 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9699 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9700 
9701 	/*
9702 	 * Find TX rate
9703 	 */
9704 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9705 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9706 		rate = rate_fb = tp->mgmtrate;
9707 	else if (ismcast)
9708 		rate = rate_fb = tp->mcastrate;
9709 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9710 		rate = rate_fb = tp->ucastrate;
9711 	else {
9712 		rix = ieee80211_amrr_choose(ni, &BWN_NODE(ni)->bn_amn);
9713 		rate = ni->ni_txrate;
9714 
9715 		if (rix > 0)
9716 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9717 			    IEEE80211_RATE_VAL;
9718 		else
9719 			rate_fb = rate;
9720 	}
9721 
9722 	sc->sc_tx_rate = rate;
9723 
9724 	rate = bwn_ieeerate2hwrate(sc, rate);
9725 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9726 
9727 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9728 	    bwn_plcp_getcck(rate);
9729 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9730 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9731 
9732 	if ((rate_fb == rate) ||
9733 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9734 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9735 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9736 	else
9737 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9738 		    m->m_pkthdr.len, rate, isshort);
9739 
9740 	/* XXX TX encryption */
9741 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9742 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9743 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9744 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9745 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9746 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9747 
9748 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9749 	    BWN_TX_EFT_FB_CCK;
9750 	txhdr->chan = phy->chan;
9751 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9752 	    BWN_TX_PHY_ENC_CCK;
9753 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9754 	     rate == BWN_CCK_RATE_11MB))
9755 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9756 
9757 	/* XXX TX antenna selection */
9758 
9759 	switch (bwn_antenna_sanitize(mac, 0)) {
9760 	case 0:
9761 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9762 		break;
9763 	case 1:
9764 		phyctl |= BWN_TX_PHY_ANT0;
9765 		break;
9766 	case 2:
9767 		phyctl |= BWN_TX_PHY_ANT1;
9768 		break;
9769 	case 3:
9770 		phyctl |= BWN_TX_PHY_ANT2;
9771 		break;
9772 	case 4:
9773 		phyctl |= BWN_TX_PHY_ANT3;
9774 		break;
9775 	default:
9776 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9777 	}
9778 
9779 	if (!ismcast)
9780 		macctl |= BWN_TX_MAC_ACK;
9781 
9782 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9783 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9784 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9785 		macctl |= BWN_TX_MAC_LONGFRAME;
9786 
9787 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9788 		/* XXX RTS rate is always 1MB??? */
9789 		rts_rate = BWN_CCK_RATE_1MB;
9790 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9791 
9792 		protdur = ieee80211_compute_duration(ic->ic_rt,
9793 		    m->m_pkthdr.len, rate, isshort) +
9794 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9795 
9796 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9797 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9798 			    (txhdr->body.old.rts_frame) :
9799 			    (txhdr->body.new.rts_frame));
9800 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9801 			    protdur);
9802 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9803 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9804 			    mprot->m_pkthdr.len);
9805 			m_freem(mprot);
9806 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9807 			len = sizeof(struct ieee80211_frame_cts);
9808 		} else {
9809 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9810 			    (txhdr->body.old.rts_frame) :
9811 			    (txhdr->body.new.rts_frame));
9812 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9813 			    isshort);
9814 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9815 			    wh->i_addr2, protdur);
9816 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9817 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9818 			    mprot->m_pkthdr.len);
9819 			m_freem(mprot);
9820 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9821 			len = sizeof(struct ieee80211_frame_rts);
9822 		}
9823 		len += IEEE80211_CRC_LEN;
9824 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9825 		    &txhdr->body.old.rts_plcp :
9826 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9827 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9828 		    rts_rate_fb);
9829 
9830 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9831 		    (&txhdr->body.old.rts_frame) :
9832 		    (&txhdr->body.new.rts_frame));
9833 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9834 
9835 		if (BWN_ISOFDMRATE(rts_rate)) {
9836 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9837 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9838 		} else {
9839 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9840 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9841 		}
9842 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9843 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9844 	}
9845 
9846 	if (BWN_ISOLDFMT(mac))
9847 		txhdr->body.old.cookie = htole16(cookie);
9848 	else
9849 		txhdr->body.new.cookie = htole16(cookie);
9850 
9851 	txhdr->macctl = htole32(macctl);
9852 	txhdr->phyctl = htole16(phyctl);
9853 
9854 	/*
9855 	 * TX radio tap
9856 	 */
9857 	if (ieee80211_radiotap_active_vap(vap)) {
9858 		sc->sc_tx_th.wt_flags = 0;
9859 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9860 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9861 		if (isshort &&
9862 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9863 		     rate == BWN_CCK_RATE_11MB))
9864 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9865 		sc->sc_tx_th.wt_rate = rate;
9866 
9867 		ieee80211_radiotap_tx(vap, m);
9868 	}
9869 
9870 	return (0);
9871 }
9872 
9873 static void
9874 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9875     const uint8_t rate)
9876 {
9877 	uint32_t d, plen;
9878 	uint8_t *raw = plcp->o.raw;
9879 
9880 	if (BWN_ISOFDMRATE(rate)) {
9881 		d = bwn_plcp_getofdm(rate);
9882 		KASSERT(!(octets & 0xf000),
9883 		    ("%s:%d: fail", __func__, __LINE__));
9884 		d |= (octets << 5);
9885 		plcp->o.data = htole32(d);
9886 	} else {
9887 		plen = octets * 16 / rate;
9888 		if ((octets * 16 % rate) > 0) {
9889 			plen++;
9890 			if ((rate == BWN_CCK_RATE_11MB)
9891 			    && ((octets * 8 % 11) < 4)) {
9892 				raw[1] = 0x84;
9893 			} else
9894 				raw[1] = 0x04;
9895 		} else
9896 			raw[1] = 0x04;
9897 		plcp->o.data |= htole32(plen << 16);
9898 		raw[0] = bwn_plcp_getcck(rate);
9899 	}
9900 }
9901 
9902 static uint8_t
9903 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9904 {
9905 	uint8_t mask;
9906 
9907 	if (n == 0)
9908 		return (0);
9909 	if (mac->mac_phy.gmode)
9910 		mask = mac->mac_sd->sd_bus->siba_sprom.ant_bg;
9911 	else
9912 		mask = mac->mac_sd->sd_bus->siba_sprom.ant_a;
9913 	if (!(mask & (1 << (n - 1))))
9914 		return (0);
9915 	return (n);
9916 }
9917 
9918 static uint8_t
9919 bwn_get_fbrate(uint8_t bitrate)
9920 {
9921 	switch (bitrate) {
9922 	case BWN_CCK_RATE_1MB:
9923 		return (BWN_CCK_RATE_1MB);
9924 	case BWN_CCK_RATE_2MB:
9925 		return (BWN_CCK_RATE_1MB);
9926 	case BWN_CCK_RATE_5MB:
9927 		return (BWN_CCK_RATE_2MB);
9928 	case BWN_CCK_RATE_11MB:
9929 		return (BWN_CCK_RATE_5MB);
9930 	case BWN_OFDM_RATE_6MB:
9931 		return (BWN_CCK_RATE_5MB);
9932 	case BWN_OFDM_RATE_9MB:
9933 		return (BWN_OFDM_RATE_6MB);
9934 	case BWN_OFDM_RATE_12MB:
9935 		return (BWN_OFDM_RATE_9MB);
9936 	case BWN_OFDM_RATE_18MB:
9937 		return (BWN_OFDM_RATE_12MB);
9938 	case BWN_OFDM_RATE_24MB:
9939 		return (BWN_OFDM_RATE_18MB);
9940 	case BWN_OFDM_RATE_36MB:
9941 		return (BWN_OFDM_RATE_24MB);
9942 	case BWN_OFDM_RATE_48MB:
9943 		return (BWN_OFDM_RATE_36MB);
9944 	case BWN_OFDM_RATE_54MB:
9945 		return (BWN_OFDM_RATE_48MB);
9946 	}
9947 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9948 	return (0);
9949 }
9950 
9951 static uint32_t
9952 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9953     uint32_t ctl, const void *_data, int len)
9954 {
9955 	uint32_t value = 0;
9956 	const uint8_t *data = _data;
9957 
9958 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9959 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9960 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9961 
9962 	siba_write_multi_4(mac->mac_sd, data, (len & ~3),
9963 	    tq->tq_base + BWN_PIO8_TXDATA);
9964 	if (len & 3) {
9965 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9966 		    BWN_PIO8_TXCTL_24_31);
9967 		data = &(data[len - 1]);
9968 		switch (len & 3) {
9969 		case 3:
9970 			ctl |= BWN_PIO8_TXCTL_16_23;
9971 			value |= (uint32_t)(*data) << 16;
9972 			data--;
9973 		case 2:
9974 			ctl |= BWN_PIO8_TXCTL_8_15;
9975 			value |= (uint32_t)(*data) << 8;
9976 			data--;
9977 		case 1:
9978 			value |= (uint32_t)(*data);
9979 		}
9980 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9981 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9982 	}
9983 
9984 	return (ctl);
9985 }
9986 
9987 static void
9988 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9989     uint16_t offset, uint32_t value)
9990 {
9991 
9992 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9993 }
9994 
9995 static uint16_t
9996 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9997     uint16_t ctl, const void *_data, int len)
9998 {
9999 	const uint8_t *data = _data;
10000 
10001 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10002 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10003 
10004 	siba_write_multi_2(mac->mac_sd, data, (len & ~1),
10005 	    tq->tq_base + BWN_PIO_TXDATA);
10006 	if (len & 1) {
10007 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10008 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10009 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
10010 	}
10011 
10012 	return (ctl);
10013 }
10014 
10015 static uint16_t
10016 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
10017     uint16_t ctl, struct mbuf *m0)
10018 {
10019 	int i, j = 0;
10020 	uint16_t data = 0;
10021 	const uint8_t *buf;
10022 	struct mbuf *m = m0;
10023 
10024 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
10025 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10026 
10027 	for (; m != NULL; m = m->m_next) {
10028 		buf = mtod(m, const uint8_t *);
10029 		for (i = 0; i < m->m_len; i++) {
10030 			if (!((j++) % 2))
10031 				data |= buf[i];
10032 			else {
10033 				data |= (buf[i] << 8);
10034 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10035 				data = 0;
10036 			}
10037 		}
10038 	}
10039 	if (m0->m_pkthdr.len % 2) {
10040 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
10041 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
10042 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
10043 	}
10044 
10045 	return (ctl);
10046 }
10047 
10048 static void
10049 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
10050 {
10051 
10052 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
10053 		return;
10054 	BWN_WRITE_2(mac, 0x684, 510 + time);
10055 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
10056 }
10057 
10058 static struct bwn_dma_ring *
10059 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
10060 {
10061 
10062 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
10063 		return (mac->mac_method.dma.wme[WME_AC_BE]);
10064 
10065 	switch (prio) {
10066 	case 3:
10067 		return (mac->mac_method.dma.wme[WME_AC_VO]);
10068 	case 2:
10069 		return (mac->mac_method.dma.wme[WME_AC_VI]);
10070 	case 0:
10071 		return (mac->mac_method.dma.wme[WME_AC_BE]);
10072 	case 1:
10073 		return (mac->mac_method.dma.wme[WME_AC_BK]);
10074 	}
10075 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10076 	return (NULL);
10077 }
10078 
10079 static int
10080 bwn_dma_getslot(struct bwn_dma_ring *dr)
10081 {
10082 	int slot;
10083 
10084 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10085 
10086 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10087 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10088 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10089 
10090 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10091 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10092 	dr->dr_curslot = slot;
10093 	dr->dr_usedslot++;
10094 
10095 	return (slot);
10096 }
10097 
10098 static int
10099 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10100 {
10101 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10102 	unsigned int a, b, c, d;
10103 	unsigned int avg;
10104 	uint32_t tmp;
10105 
10106 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10107 	a = tmp & 0xff;
10108 	b = (tmp >> 8) & 0xff;
10109 	c = (tmp >> 16) & 0xff;
10110 	d = (tmp >> 24) & 0xff;
10111 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10112 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10113 		return (ENOENT);
10114 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10115 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10116 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10117 
10118 	if (ofdm) {
10119 		a = (a + 32) & 0x3f;
10120 		b = (b + 32) & 0x3f;
10121 		c = (c + 32) & 0x3f;
10122 		d = (d + 32) & 0x3f;
10123 	}
10124 
10125 	avg = (a + b + c + d + 2) / 4;
10126 	if (ofdm) {
10127 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10128 		    & BWN_HF_4DB_CCK_POWERBOOST)
10129 			avg = (avg >= 13) ? (avg - 13) : 0;
10130 	}
10131 	return (avg);
10132 }
10133 
10134 static void
10135 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10136 {
10137 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10138 	int rfatt = *rfattp;
10139 	int bbatt = *bbattp;
10140 
10141 	while (1) {
10142 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10143 			break;
10144 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10145 			break;
10146 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10147 			break;
10148 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10149 			break;
10150 		if (bbatt > lo->bbatt.max) {
10151 			bbatt -= 4;
10152 			rfatt += 1;
10153 			continue;
10154 		}
10155 		if (bbatt < lo->bbatt.min) {
10156 			bbatt += 4;
10157 			rfatt -= 1;
10158 			continue;
10159 		}
10160 		if (rfatt > lo->rfatt.max) {
10161 			rfatt -= 1;
10162 			bbatt += 4;
10163 			continue;
10164 		}
10165 		if (rfatt < lo->rfatt.min) {
10166 			rfatt += 1;
10167 			bbatt -= 4;
10168 			continue;
10169 		}
10170 		break;
10171 	}
10172 
10173 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10174 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10175 }
10176 
10177 static void
10178 bwn_phy_lock(struct bwn_mac *mac)
10179 {
10180 	struct bwn_softc *sc = mac->mac_sc;
10181 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10182 
10183 	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10184 	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10185 
10186 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10187 		bwn_psctl(mac, BWN_PS_AWAKE);
10188 }
10189 
10190 static void
10191 bwn_phy_unlock(struct bwn_mac *mac)
10192 {
10193 	struct bwn_softc *sc = mac->mac_sc;
10194 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10195 
10196 	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10197 	    ("%s: unsupported rev %d", __func__, mac->mac_sd->sd_id.sd_rev));
10198 
10199 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10200 		bwn_psctl(mac, 0);
10201 }
10202 
10203 static void
10204 bwn_rf_lock(struct bwn_mac *mac)
10205 {
10206 
10207 	BWN_WRITE_4(mac, BWN_MACCTL,
10208 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10209 	BWN_READ_4(mac, BWN_MACCTL);
10210 	DELAY(10);
10211 }
10212 
10213 static void
10214 bwn_rf_unlock(struct bwn_mac *mac)
10215 {
10216 
10217 	BWN_READ_2(mac, BWN_PHYVER);
10218 	BWN_WRITE_4(mac, BWN_MACCTL,
10219 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10220 }
10221 
10222 static struct bwn_pio_txqueue *
10223 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10224     struct bwn_pio_txpkt **pack)
10225 {
10226 	struct bwn_pio *pio = &mac->mac_method.pio;
10227 	struct bwn_pio_txqueue *tq = NULL;
10228 	unsigned int index;
10229 
10230 	switch (cookie & 0xf000) {
10231 	case 0x1000:
10232 		tq = &pio->wme[WME_AC_BK];
10233 		break;
10234 	case 0x2000:
10235 		tq = &pio->wme[WME_AC_BE];
10236 		break;
10237 	case 0x3000:
10238 		tq = &pio->wme[WME_AC_VI];
10239 		break;
10240 	case 0x4000:
10241 		tq = &pio->wme[WME_AC_VO];
10242 		break;
10243 	case 0x5000:
10244 		tq = &pio->mcast;
10245 		break;
10246 	}
10247 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10248 	if (tq == NULL)
10249 		return (NULL);
10250 	index = (cookie & 0x0fff);
10251 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10252 	if (index >= N(tq->tq_pkts))
10253 		return (NULL);
10254 	*pack = &tq->tq_pkts[index];
10255 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10256 	return (tq);
10257 }
10258 
10259 static void
10260 bwn_txpwr(void *arg, int npending)
10261 {
10262 	struct bwn_mac *mac = arg;
10263 	struct bwn_softc *sc = mac->mac_sc;
10264 
10265 	BWN_LOCK(sc);
10266 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10267 	    mac->mac_phy.set_txpwr != NULL)
10268 		mac->mac_phy.set_txpwr(mac);
10269 	BWN_UNLOCK(sc);
10270 }
10271 
10272 static void
10273 bwn_task_15s(struct bwn_mac *mac)
10274 {
10275 	uint16_t reg;
10276 
10277 	if (mac->mac_fw.opensource) {
10278 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10279 		if (reg) {
10280 			bwn_restart(mac, "fw watchdog");
10281 			return;
10282 		}
10283 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10284 	}
10285 	if (mac->mac_phy.task_15s)
10286 		mac->mac_phy.task_15s(mac);
10287 
10288 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10289 }
10290 
10291 static void
10292 bwn_task_30s(struct bwn_mac *mac)
10293 {
10294 
10295 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10296 		return;
10297 	mac->mac_noise.noi_running = 1;
10298 	mac->mac_noise.noi_nsamples = 0;
10299 
10300 	bwn_noise_gensample(mac);
10301 }
10302 
10303 static void
10304 bwn_task_60s(struct bwn_mac *mac)
10305 {
10306 
10307 	if (mac->mac_phy.task_60s)
10308 		mac->mac_phy.task_60s(mac);
10309 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10310 }
10311 
10312 static void
10313 bwn_tasks(void *arg)
10314 {
10315 	struct bwn_mac *mac = arg;
10316 	struct bwn_softc *sc = mac->mac_sc;
10317 
10318 	BWN_ASSERT_LOCKED(sc);
10319 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10320 		return;
10321 
10322 	if (mac->mac_task_state % 4 == 0)
10323 		bwn_task_60s(mac);
10324 	if (mac->mac_task_state % 2 == 0)
10325 		bwn_task_30s(mac);
10326 	bwn_task_15s(mac);
10327 
10328 	mac->mac_task_state++;
10329 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10330 }
10331 
10332 static int
10333 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10334 {
10335 	struct bwn_softc *sc = mac->mac_sc;
10336 
10337 	KASSERT(a == 0, ("not support APHY\n"));
10338 
10339 	switch (plcp->o.raw[0] & 0xf) {
10340 	case 0xb:
10341 		return (BWN_OFDM_RATE_6MB);
10342 	case 0xf:
10343 		return (BWN_OFDM_RATE_9MB);
10344 	case 0xa:
10345 		return (BWN_OFDM_RATE_12MB);
10346 	case 0xe:
10347 		return (BWN_OFDM_RATE_18MB);
10348 	case 0x9:
10349 		return (BWN_OFDM_RATE_24MB);
10350 	case 0xd:
10351 		return (BWN_OFDM_RATE_36MB);
10352 	case 0x8:
10353 		return (BWN_OFDM_RATE_48MB);
10354 	case 0xc:
10355 		return (BWN_OFDM_RATE_54MB);
10356 	}
10357 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10358 	    plcp->o.raw[0] & 0xf);
10359 	return (-1);
10360 }
10361 
10362 static int
10363 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10364 {
10365 	struct bwn_softc *sc = mac->mac_sc;
10366 
10367 	switch (plcp->o.raw[0]) {
10368 	case 0x0a:
10369 		return (BWN_CCK_RATE_1MB);
10370 	case 0x14:
10371 		return (BWN_CCK_RATE_2MB);
10372 	case 0x37:
10373 		return (BWN_CCK_RATE_5MB);
10374 	case 0x6e:
10375 		return (BWN_CCK_RATE_11MB);
10376 	}
10377 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10378 	return (-1);
10379 }
10380 
10381 static void
10382 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10383     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10384     int rssi, int noise)
10385 {
10386 	struct bwn_softc *sc = mac->mac_sc;
10387 	const struct ieee80211_frame_min *wh;
10388 	uint64_t tsf;
10389 	uint16_t low_mactime_now;
10390 
10391 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10392 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10393 
10394 	wh = mtod(m, const struct ieee80211_frame_min *);
10395 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10396 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10397 
10398 	bwn_tsf_read(mac, &tsf);
10399 	low_mactime_now = tsf;
10400 	tsf = tsf & ~0xffffULL;
10401 	tsf += le16toh(rxhdr->mac_time);
10402 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10403 		tsf -= 0x10000;
10404 
10405 	sc->sc_rx_th.wr_tsf = tsf;
10406 	sc->sc_rx_th.wr_rate = rate;
10407 	sc->sc_rx_th.wr_antsignal = rssi;
10408 	sc->sc_rx_th.wr_antnoise = noise;
10409 }
10410 
10411 static void
10412 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10413 {
10414 	uint32_t low, high;
10415 
10416 	KASSERT(mac->mac_sd->sd_id.sd_rev >= 3,
10417 	    ("%s:%d: fail", __func__, __LINE__));
10418 
10419 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10420 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10421 	*tsf = high;
10422 	*tsf <<= 32;
10423 	*tsf |= low;
10424 }
10425 
10426 static int
10427 bwn_dma_attach(struct bwn_mac *mac)
10428 {
10429 	struct bwn_dma *dma = &mac->mac_method.dma;
10430 	struct bwn_softc *sc = mac->mac_sc;
10431 	struct siba_dev_softc *sd = mac->mac_sd;
10432 	struct siba_softc *siba = sd->sd_bus;
10433 	bus_addr_t lowaddr = 0;
10434 	int error;
10435 
10436 	if (siba->siba_type == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10437 		return (0);
10438 
10439 	KASSERT(mac->mac_sd->sd_id.sd_rev >= 5, ("%s: fail", __func__));
10440 
10441 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10442 
10443 	dma->dmatype = bwn_dma_gettype(mac);
10444 	if (dma->dmatype == BWN_DMA_30BIT)
10445 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10446 	else if (dma->dmatype == BWN_DMA_32BIT)
10447 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10448 	else
10449 		lowaddr = BUS_SPACE_MAXADDR;
10450 
10451 	/*
10452 	 * Create top level DMA tag
10453 	 */
10454 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10455 			       BWN_ALIGN, 0,		/* alignment, bounds */
10456 			       lowaddr,			/* lowaddr */
10457 			       BUS_SPACE_MAXADDR,	/* highaddr */
10458 			       NULL, NULL,		/* filter, filterarg */
10459 			       MAXBSIZE,		/* maxsize */
10460 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10461 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10462 			       0,			/* flags */
10463 			       NULL, NULL,		/* lockfunc, lockarg */
10464 			       &dma->parent_dtag);
10465 	if (error) {
10466 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10467 		return (error);
10468 	}
10469 
10470 	/*
10471 	 * Create TX/RX mbuf DMA tag
10472 	 */
10473 	error = bus_dma_tag_create(dma->parent_dtag,
10474 				1,
10475 				0,
10476 				BUS_SPACE_MAXADDR,
10477 				BUS_SPACE_MAXADDR,
10478 				NULL, NULL,
10479 				MCLBYTES,
10480 				1,
10481 				BUS_SPACE_MAXSIZE_32BIT,
10482 				0,
10483 				NULL, NULL,
10484 				&dma->rxbuf_dtag);
10485 	if (error) {
10486 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10487 		goto fail0;
10488 	}
10489 	error = bus_dma_tag_create(dma->parent_dtag,
10490 				1,
10491 				0,
10492 				BUS_SPACE_MAXADDR,
10493 				BUS_SPACE_MAXADDR,
10494 				NULL, NULL,
10495 				MCLBYTES,
10496 				1,
10497 				BUS_SPACE_MAXSIZE_32BIT,
10498 				0,
10499 				NULL, NULL,
10500 				&dma->txbuf_dtag);
10501 	if (error) {
10502 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10503 		goto fail1;
10504 	}
10505 
10506 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10507 	if (!dma->wme[WME_AC_BK])
10508 		goto fail2;
10509 
10510 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10511 	if (!dma->wme[WME_AC_BE])
10512 		goto fail3;
10513 
10514 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10515 	if (!dma->wme[WME_AC_VI])
10516 		goto fail4;
10517 
10518 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10519 	if (!dma->wme[WME_AC_VO])
10520 		goto fail5;
10521 
10522 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10523 	if (!dma->mcast)
10524 		goto fail6;
10525 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10526 	if (!dma->rx)
10527 		goto fail7;
10528 
10529 	return (error);
10530 
10531 fail7:	bwn_dma_ringfree(&dma->mcast);
10532 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10533 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10534 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10535 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10536 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10537 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10538 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10539 	return (error);
10540 }
10541 
10542 static struct bwn_dma_ring *
10543 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10544     uint16_t cookie, int *slot)
10545 {
10546 	struct bwn_dma *dma = &mac->mac_method.dma;
10547 	struct bwn_dma_ring *dr;
10548 	struct bwn_softc *sc = mac->mac_sc;
10549 
10550 	BWN_ASSERT_LOCKED(mac->mac_sc);
10551 
10552 	switch (cookie & 0xf000) {
10553 	case 0x1000:
10554 		dr = dma->wme[WME_AC_BK];
10555 		break;
10556 	case 0x2000:
10557 		dr = dma->wme[WME_AC_BE];
10558 		break;
10559 	case 0x3000:
10560 		dr = dma->wme[WME_AC_VI];
10561 		break;
10562 	case 0x4000:
10563 		dr = dma->wme[WME_AC_VO];
10564 		break;
10565 	case 0x5000:
10566 		dr = dma->mcast;
10567 		break;
10568 	default:
10569 		dr = NULL;
10570 		KASSERT(0 == 1,
10571 		    ("invalid cookie value %d", cookie & 0xf000));
10572 	}
10573 	*slot = (cookie & 0x0fff);
10574 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10575 		/*
10576 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10577 		 * that it occurs events which have same H/W sequence numbers.
10578 		 * When it's occurred just prints a WARNING msgs and ignores.
10579 		 */
10580 		KASSERT(status->seq == dma->lastseq,
10581 		    ("%s:%d: fail", __func__, __LINE__));
10582 		device_printf(sc->sc_dev,
10583 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10584 		    dr->dr_numslots);
10585 		return (NULL);
10586 	}
10587 	dma->lastseq = status->seq;
10588 	return (dr);
10589 }
10590 
10591 static void
10592 bwn_dma_stop(struct bwn_mac *mac)
10593 {
10594 	struct bwn_dma *dma;
10595 
10596 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10597 		return;
10598 	dma = &mac->mac_method.dma;
10599 
10600 	bwn_dma_ringstop(&dma->rx);
10601 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10602 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10603 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10604 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10605 	bwn_dma_ringstop(&dma->mcast);
10606 }
10607 
10608 static void
10609 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10610 {
10611 
10612 	if (dr == NULL)
10613 		return;
10614 
10615 	bwn_dma_cleanup(*dr);
10616 }
10617 
10618 static void
10619 bwn_pio_stop(struct bwn_mac *mac)
10620 {
10621 	struct bwn_pio *pio;
10622 
10623 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10624 		return;
10625 	pio = &mac->mac_method.pio;
10626 
10627 	bwn_destroy_queue_tx(&pio->mcast);
10628 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10629 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10630 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10631 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10632 }
10633 
10634 static void
10635 bwn_led_attach(struct bwn_mac *mac)
10636 {
10637 	struct bwn_softc *sc = mac->mac_sc;
10638 	struct siba_softc *siba = mac->mac_sd->sd_bus;
10639 	const uint8_t *led_act = NULL;
10640 	uint16_t val[BWN_LED_MAX];
10641 	int i;
10642 
10643 	sc->sc_led_idle = (2350 * hz) / 1000;
10644 	sc->sc_led_blink = 1;
10645 
10646 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10647 		if (siba->siba_pci_subvid == bwn_vendor_led_act[i].vid) {
10648 			led_act = bwn_vendor_led_act[i].led_act;
10649 			break;
10650 		}
10651 	}
10652 	if (led_act == NULL)
10653 		led_act = bwn_default_led_act;
10654 
10655 	val[0] = siba->siba_sprom.gpio0;
10656 	val[1] = siba->siba_sprom.gpio1;
10657 	val[2] = siba->siba_sprom.gpio2;
10658 	val[3] = siba->siba_sprom.gpio3;
10659 
10660 	for (i = 0; i < BWN_LED_MAX; ++i) {
10661 		struct bwn_led *led = &sc->sc_leds[i];
10662 
10663 		if (val[i] == 0xff) {
10664 			led->led_act = led_act[i];
10665 		} else {
10666 			if (val[i] & BWN_LED_ACT_LOW)
10667 				led->led_flags |= BWN_LED_F_ACTLOW;
10668 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10669 		}
10670 		led->led_mask = (1 << i);
10671 
10672 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10673 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10674 		    led->led_act == BWN_LED_ACT_BLINK) {
10675 			led->led_flags |= BWN_LED_F_BLINK;
10676 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10677 				led->led_flags |= BWN_LED_F_POLLABLE;
10678 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10679 				led->led_flags |= BWN_LED_F_SLOW;
10680 
10681 			if (sc->sc_blink_led == NULL) {
10682 				sc->sc_blink_led = led;
10683 				if (led->led_flags & BWN_LED_F_SLOW)
10684 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10685 			}
10686 		}
10687 
10688 		DPRINTF(sc, BWN_DEBUG_LED,
10689 		    "%dth led, act %d, lowact %d\n", i,
10690 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10691 	}
10692 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10693 }
10694 
10695 static __inline uint16_t
10696 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10697 {
10698 
10699 	if (led->led_flags & BWN_LED_F_ACTLOW)
10700 		on = !on;
10701 	if (on)
10702 		val |= led->led_mask;
10703 	else
10704 		val &= ~led->led_mask;
10705 	return val;
10706 }
10707 
10708 static void
10709 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10710 {
10711 	struct bwn_softc *sc = mac->mac_sc;
10712 	struct ifnet *ifp = sc->sc_ifp;
10713 	struct ieee80211com *ic = ifp->if_l2com;
10714 	uint16_t val;
10715 	int i;
10716 
10717 	if (nstate == IEEE80211_S_INIT) {
10718 		callout_stop(&sc->sc_led_blink_ch);
10719 		sc->sc_led_blinking = 0;
10720 	}
10721 
10722 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10723 		return;
10724 
10725 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10726 	for (i = 0; i < BWN_LED_MAX; ++i) {
10727 		struct bwn_led *led = &sc->sc_leds[i];
10728 		int on;
10729 
10730 		if (led->led_act == BWN_LED_ACT_UNKN ||
10731 		    led->led_act == BWN_LED_ACT_NULL)
10732 			continue;
10733 
10734 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10735 		    nstate != IEEE80211_S_INIT)
10736 			continue;
10737 
10738 		switch (led->led_act) {
10739 		case BWN_LED_ACT_ON:    /* Always on */
10740 			on = 1;
10741 			break;
10742 		case BWN_LED_ACT_OFF:   /* Always off */
10743 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10744 			on = 0;
10745 			break;
10746 		default:
10747 			on = 1;
10748 			switch (nstate) {
10749 			case IEEE80211_S_INIT:
10750 				on = 0;
10751 				break;
10752 			case IEEE80211_S_RUN:
10753 				if (led->led_act == BWN_LED_ACT_11G &&
10754 				    ic->ic_curmode != IEEE80211_MODE_11G)
10755 					on = 0;
10756 				break;
10757 			default:
10758 				if (led->led_act == BWN_LED_ACT_ASSOC)
10759 					on = 0;
10760 				break;
10761 			}
10762 			break;
10763 		}
10764 
10765 		val = bwn_led_onoff(led, val, on);
10766 	}
10767 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10768 }
10769 
10770 static void
10771 bwn_led_event(struct bwn_mac *mac, int event)
10772 {
10773 	struct bwn_softc *sc = mac->mac_sc;
10774         struct bwn_led *led = sc->sc_blink_led;
10775         int rate;
10776 
10777         if (event == BWN_LED_EVENT_POLL) {
10778                 if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10779                         return;
10780                 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10781                         return;
10782         }
10783 
10784         sc->sc_led_ticks = ticks;
10785         if (sc->sc_led_blinking)
10786                 return;
10787 
10788         switch (event) {
10789         case BWN_LED_EVENT_RX:
10790                 rate = sc->sc_rx_rate;
10791                 break;
10792         case BWN_LED_EVENT_TX:
10793                 rate = sc->sc_tx_rate;
10794                 break;
10795         case BWN_LED_EVENT_POLL:
10796                 rate = 0;
10797                 break;
10798         default:
10799                 panic("unknown LED event %d\n", event);
10800                 break;
10801         }
10802         bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10803             bwn_led_duration[rate].off_dur);
10804 }
10805 
10806 static void
10807 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10808 {
10809 	struct bwn_softc *sc = mac->mac_sc;
10810         struct bwn_led *led = sc->sc_blink_led;
10811         uint16_t val;
10812 
10813         val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10814         val = bwn_led_onoff(led, val, 1);
10815         BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10816 
10817         if (led->led_flags & BWN_LED_F_SLOW) {
10818                 BWN_LED_SLOWDOWN(on_dur);
10819                 BWN_LED_SLOWDOWN(off_dur);
10820         }
10821 
10822         sc->sc_led_blinking = 1;
10823         sc->sc_led_blink_offdur = off_dur;
10824 
10825         callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10826 }
10827 
10828 static void
10829 bwn_led_blink_next(void *arg)
10830 {
10831 	struct bwn_mac *mac = arg;
10832         struct bwn_softc *sc = mac->mac_sc;
10833         uint16_t val;
10834 
10835         val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10836         val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10837         BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10838 
10839         callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10840             bwn_led_blink_end, mac);
10841 }
10842 
10843 static void
10844 bwn_led_blink_end(void *arg)
10845 {
10846 	struct bwn_mac *mac = arg;
10847         struct bwn_softc *sc = mac->mac_sc;
10848 
10849         sc->sc_led_blinking = 0;
10850 }
10851 
10852 static int
10853 bwn_suspend(device_t dev)
10854 {
10855 	struct bwn_softc *sc = device_get_softc(dev);
10856 
10857 	bwn_stop(sc, 1);
10858 	return (0);
10859 }
10860 
10861 static int
10862 bwn_resume(device_t dev)
10863 {
10864 	struct bwn_softc *sc = device_get_softc(dev);
10865 	struct ifnet *ifp = sc->sc_ifp;
10866 
10867 	if (ifp->if_flags & IFF_UP)
10868 		bwn_init(sc);
10869 	return (0);
10870 }
10871 
10872 static void
10873 bwn_rfswitch(void *arg)
10874 {
10875 	struct bwn_softc *sc = arg;
10876 	struct bwn_mac *mac = sc->sc_curmac;
10877 	int cur = 0, prev = 0;
10878 
10879 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10880 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10881 
10882 	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10883 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10884 			& BWN_RF_HWENABLED_HI_MASK))
10885 			cur = 1;
10886 	} else {
10887 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10888 		    & BWN_RF_HWENABLED_LO_MASK)
10889 			cur = 1;
10890 	}
10891 
10892 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10893 		prev = 1;
10894 
10895 	if (cur != prev) {
10896 		if (cur)
10897 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10898 		else
10899 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10900 
10901 		device_printf(sc->sc_dev,
10902 		    "status of RF switch is changed to %s\n",
10903 		    cur ? "ON" : "OFF");
10904 		if (cur != mac->mac_phy.rf_on) {
10905 			if (cur)
10906 				bwn_rf_turnon(mac);
10907 			else
10908 				bwn_rf_turnoff(mac);
10909 		}
10910 	}
10911 
10912 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10913 }
10914 
10915 static void
10916 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10917 {
10918 	struct bwn_phy *phy = &mac->mac_phy;
10919 	struct bwn_phy_lp *plp = &phy->phy_lp;
10920 
10921 	plp->plp_antenna = BWN_ANT_DEFAULT;
10922 }
10923 
10924 static int
10925 bwn_phy_lp_init(struct bwn_mac *mac)
10926 {
10927 	static const struct bwn_stxtable tables[] = {
10928 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10929 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10930 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10931 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10932 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10933 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10934 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10935 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10936 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10937 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10938 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10939 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10940 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10941 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10942 		{ 2, 11, 0x40, 0, 0x0f }
10943 	};
10944 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10945 	struct bwn_softc *sc = mac->mac_sc;
10946 	const struct bwn_stxtable *st;
10947 	struct ifnet *ifp = sc->sc_ifp;
10948 	struct ieee80211com *ic = ifp->if_l2com;
10949 	int i, error;
10950 	uint16_t tmp;
10951 
10952 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10953 	bwn_phy_lp_bbinit(mac);
10954 
10955 	/* initialize RF */
10956 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10957 	DELAY(1);
10958 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10959 	DELAY(1);
10960 
10961 	if (mac->mac_phy.rf_ver == 0x2062)
10962 		bwn_phy_lp_b2062_init(mac);
10963 	else {
10964 		bwn_phy_lp_b2063_init(mac);
10965 
10966 		/* synchronize stx table. */
10967 		for (i = 0; i < N(tables); i++) {
10968 			st = &tables[i];
10969 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10970 			tmp >>= st->st_rfshift;
10971 			tmp <<= st->st_physhift;
10972 			BWN_PHY_SETMASK(mac,
10973 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10974 			    ~(st->st_mask << st->st_physhift), tmp);
10975 		}
10976 
10977 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10978 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10979 	}
10980 
10981 	/* calibrate RC */
10982 	if (mac->mac_phy.rev >= 2)
10983 		bwn_phy_lp_rxcal_r2(mac);
10984 	else if (!plp->plp_rccap) {
10985 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10986 			bwn_phy_lp_rccal_r12(mac);
10987 	} else
10988 		bwn_phy_lp_set_rccap(mac);
10989 
10990 	error = bwn_phy_lp_switch_channel(mac, 7);
10991 	if (error)
10992 		device_printf(sc->sc_dev,
10993 		    "failed to change channel 7 (%d)\n", error);
10994 	bwn_phy_lp_txpctl_init(mac);
10995 	bwn_phy_lp_calib(mac);
10996 	return (0);
10997 }
10998 
10999 static uint16_t
11000 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
11001 {
11002 
11003 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11004 	return (BWN_READ_2(mac, BWN_PHYDATA));
11005 }
11006 
11007 static void
11008 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11009 {
11010 
11011 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11012 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
11013 }
11014 
11015 static void
11016 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
11017     uint16_t set)
11018 {
11019 
11020 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
11021 	BWN_WRITE_2(mac, BWN_PHYDATA,
11022 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
11023 }
11024 
11025 static uint16_t
11026 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
11027 {
11028 
11029 	KASSERT(reg != 1, ("unaccessible register %d", reg));
11030 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
11031 		reg |= 0x100;
11032 	if (mac->mac_phy.rev >= 2)
11033 		reg |= 0x200;
11034 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11035 	return BWN_READ_2(mac, BWN_RFDATALO);
11036 }
11037 
11038 static void
11039 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
11040 {
11041 
11042 	KASSERT(reg != 1, ("unaccessible register %d", reg));
11043 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
11044 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
11045 }
11046 
11047 static void
11048 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
11049 {
11050 
11051 	if (on) {
11052 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
11053 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
11054 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
11055 		return;
11056 	}
11057 
11058 	if (mac->mac_phy.rev >= 2) {
11059 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
11060 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11061 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
11062 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
11063 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
11064 		return;
11065 	}
11066 
11067 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
11068 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
11069 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
11070 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
11071 }
11072 
11073 static int
11074 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11075 {
11076 	struct bwn_phy *phy = &mac->mac_phy;
11077 	struct bwn_phy_lp *plp = &phy->phy_lp;
11078 	int error;
11079 
11080 	if (phy->rf_ver == 0x2063) {
11081 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11082 		if (error)
11083 			return (error);
11084 	} else {
11085 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11086 		if (error)
11087 			return (error);
11088 		bwn_phy_lp_set_anafilter(mac, chan);
11089 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11090 	}
11091 
11092 	plp->plp_chan = chan;
11093 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11094 	return (0);
11095 }
11096 
11097 static uint32_t
11098 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11099 {
11100 	struct bwn_softc *sc = mac->mac_sc;
11101 	struct ifnet *ifp = sc->sc_ifp;
11102 	struct ieee80211com *ic = ifp->if_l2com;
11103 
11104 	device_printf(sc->sc_dev, "correct?\n");
11105 
11106 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11107 }
11108 
11109 static void
11110 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11111 {
11112 	struct bwn_phy *phy = &mac->mac_phy;
11113 	struct bwn_phy_lp *plp = &phy->phy_lp;
11114 
11115 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11116 		return;
11117 
11118 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11119 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11120 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11121 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11122 	plp->plp_antenna = antenna;
11123 }
11124 
11125 static void
11126 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11127 {
11128 
11129 	bwn_phy_lp_calib(mac);
11130 }
11131 
11132 static void
11133 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11134 {
11135 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11136 	struct bwn_softc *sc = mac->mac_sc;
11137 	struct ifnet *ifp = sc->sc_ifp;
11138 	struct ieee80211com *ic = ifp->if_l2com;
11139 	struct siba_dev_softc *sd = mac->mac_sd;
11140 	struct siba_softc *siba = sd->sd_bus;
11141 	struct siba_sprom *sprom = &siba->siba_sprom;
11142 
11143 	device_printf(sc->sc_dev, "XXX using %dghz\n",
11144 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 2 : 5);
11145 
11146 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11147 		plp->plp_txisoband_m = sprom->tri2g;
11148 		plp->plp_bxarch = sprom->bxa2g;
11149 		plp->plp_rxpwroffset = sprom->rxpo2g;
11150 		plp->plp_rssivf = sprom->rssismf2g;
11151 		plp->plp_rssivc = sprom->rssismc2g;
11152 		plp->plp_rssigs = sprom->rssisav2g;
11153 		return;
11154 	}
11155 
11156 	plp->plp_txisoband_l = sprom->tri5gl;
11157 	plp->plp_txisoband_m = sprom->tri5g;
11158 	plp->plp_txisoband_h = sprom->tri5gh;
11159 	plp->plp_bxarch = sprom->bxa5g;
11160 	plp->plp_rxpwroffset = sprom->rxpo5g;
11161 	plp->plp_rssivf = sprom->rssismf5g;
11162 	plp->plp_rssivc = sprom->rssismc5g;
11163 	plp->plp_rssigs = sprom->rssisav5g;
11164 }
11165 
11166 static void
11167 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11168 {
11169 
11170 	bwn_phy_lp_tblinit(mac);
11171 	if (mac->mac_phy.rev >= 2)
11172 		bwn_phy_lp_bbinit_r2(mac);
11173 	else
11174 		bwn_phy_lp_bbinit_r01(mac);
11175 }
11176 
11177 static void
11178 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11179 {
11180 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11181 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11182 	struct bwn_softc *sc = mac->mac_sc;
11183 	struct ifnet *ifp = sc->sc_ifp;
11184 	struct ieee80211com *ic = ifp->if_l2com;
11185 
11186 	bwn_phy_lp_set_txgain(mac,
11187 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11188 	bwn_phy_lp_set_bbmult(mac, 150);
11189 }
11190 
11191 static void
11192 bwn_phy_lp_calib(struct bwn_mac *mac)
11193 {
11194 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11195 	struct siba_dev_softc *sd = mac->mac_sd;
11196 	struct siba_softc *siba = sd->sd_bus;
11197 	struct bwn_softc *sc = mac->mac_sc;
11198 	struct ifnet *ifp = sc->sc_ifp;
11199 	struct ieee80211com *ic = ifp->if_l2com;
11200 	const struct bwn_rxcompco *rc = NULL;
11201 	struct bwn_txgain ogain;
11202 	int i, omode, oafeovr, orf, obbmult;
11203 	uint8_t mode, fc = 0;
11204 
11205 	if (plp->plp_chanfullcal != plp->plp_chan) {
11206 		plp->plp_chanfullcal = plp->plp_chan;
11207 		fc = 1;
11208 	}
11209 
11210 	bwn_mac_suspend(mac);
11211 
11212 	/* BlueTooth Coexistance Override */
11213 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11214 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11215 
11216 	if (mac->mac_phy.rev >= 2)
11217 		bwn_phy_lp_digflt_save(mac);
11218 	bwn_phy_lp_get_txpctlmode(mac);
11219 	mode = plp->plp_txpctlmode;
11220 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11221 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11222 		bwn_phy_lp_bugfix(mac);
11223 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11224 		bwn_phy_lp_get_txpctlmode(mac);
11225 		omode = plp->plp_txpctlmode;
11226 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11227 		if (oafeovr)
11228 			ogain = bwn_phy_lp_get_txgain(mac);
11229 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11230 		obbmult = bwn_phy_lp_get_bbmult(mac);
11231 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11232 		if (oafeovr)
11233 			bwn_phy_lp_set_txgain(mac, &ogain);
11234 		bwn_phy_lp_set_bbmult(mac, obbmult);
11235 		bwn_phy_lp_set_txpctlmode(mac, omode);
11236 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11237 	}
11238 	bwn_phy_lp_set_txpctlmode(mac, mode);
11239 	if (mac->mac_phy.rev >= 2)
11240 		bwn_phy_lp_digflt_restore(mac);
11241 
11242 	/* do RX IQ Calculation; assumes that noise is true. */
11243 	if (siba->siba_chipid == 0x5354) {
11244 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11245 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11246 				rc = &bwn_rxcompco_5354[i];
11247 		}
11248 	} else if (mac->mac_phy.rev >= 2)
11249 		rc = &bwn_rxcompco_r2;
11250 	else {
11251 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11252 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11253 				rc = &bwn_rxcompco_r12[i];
11254 		}
11255 	}
11256 	if (rc == NULL)
11257 		goto fail;
11258 
11259 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11260 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11261 
11262 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11263 
11264 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11265 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11266 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11267 	} else {
11268 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11269 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11270 	}
11271 
11272 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11273 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11274 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11275 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11276 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11277 	bwn_phy_lp_set_deaf(mac, 0);
11278 	/* XXX no checking return value? */
11279 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11280 	bwn_phy_lp_clear_deaf(mac, 0);
11281 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11282 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11283 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11284 
11285 	/* disable RX GAIN override. */
11286 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11287 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11288 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11289 	if (mac->mac_phy.rev >= 2) {
11290 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11291 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11292 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11293 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11294 		}
11295 	} else {
11296 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11297 	}
11298 
11299 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11300 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11301 fail:
11302 	bwn_mac_enable(mac);
11303 }
11304 
11305 static void
11306 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11307 {
11308 
11309        if (on) {
11310                BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11311 	       return;
11312        }
11313 
11314        BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11315        BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11316 }
11317 
11318 static int
11319 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11320 {
11321 	struct siba_dev_softc *sd = mac->mac_sd;
11322 	struct siba_softc *siba = sd->sd_bus;
11323 	static const struct bwn_b206x_chan *bc = NULL;
11324 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11325 	    tmp[6];
11326 	uint16_t old, scale, tmp16;
11327 	int i, div;
11328 
11329 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11330 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11331 			bc = &bwn_b2063_chantable[i];
11332 			break;
11333 		}
11334 	}
11335 	if (bc == NULL)
11336 		return (EINVAL);
11337 
11338 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11339 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11340 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11341 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11342 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11343 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11344 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11345 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11346 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11347 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11348 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11349 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11350 
11351 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11352 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11353 
11354 	freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11355 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11356 	freqref = freqxtal * 3;
11357 	div = (freqxtal <= 26000000 ? 1 : 2);
11358 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11359 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11360 		999999) / 1000000) + 1;
11361 
11362 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11363 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11364 	    0xfff8, timeout >> 2);
11365 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11366 	    0xff9f,timeout << 5);
11367 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11368 
11369 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11370 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11371 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11372 
11373 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11374 	    (timeoutref + 1)) - 1;
11375 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11376 	    0xf0, count >> 8);
11377 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11378 
11379 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11380 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11381 	while (tmp[1] >= freqref) {
11382 		tmp[0]++;
11383 		tmp[1] -= freqref;
11384 	}
11385 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11386 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11387 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11388 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11389 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11390 
11391 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11392 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11393 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11394 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11395 
11396 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11397 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11398 
11399 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11400 		scale = 1;
11401 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11402 	} else {
11403 		scale = 0;
11404 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11405 	}
11406 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11407 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11408 
11409 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11410 	    (scale + 1);
11411 	if (tmp[5] > 150)
11412 		tmp[5] = 0;
11413 
11414 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11415 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11416 
11417 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11418 	if (freqxtal > 26000000)
11419 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11420 	else
11421 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11422 
11423 	if (val[0] == 45)
11424 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11425 	else
11426 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11427 
11428 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11429 	DELAY(1);
11430 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11431 
11432 	/* VCO Calibration */
11433 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11434 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11435 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11436 	DELAY(1);
11437 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11438 	DELAY(1);
11439 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11440 	DELAY(1);
11441 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11442 	DELAY(300);
11443 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11444 
11445 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11446 	return (0);
11447 }
11448 
11449 static int
11450 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11451 {
11452 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11453 	struct siba_dev_softc *sd = mac->mac_sd;
11454 	struct siba_softc *siba = sd->sd_bus;
11455 	const struct bwn_b206x_chan *bc = NULL;
11456 	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
11457 	uint32_t tmp[9];
11458 	int i;
11459 
11460 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11461 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11462 			bc = &bwn_b2062_chantable[i];
11463 			break;
11464 		}
11465 	}
11466 
11467 	if (bc == NULL)
11468 		return (EINVAL);
11469 
11470 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11471 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11472 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11473 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11474 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11475 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11476 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11477 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11478 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11479 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11480 
11481 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11482 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11483 	bwn_phy_lp_b2062_reset_pllbias(mac);
11484 	tmp[0] = freqxtal / 1000;
11485 	tmp[1] = plp->plp_div * 1000;
11486 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11487 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11488 		tmp[2] *= 2;
11489 	tmp[3] = 48 * tmp[0];
11490 	tmp[5] = tmp[2] / tmp[3];
11491 	tmp[6] = tmp[2] % tmp[3];
11492 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11493 	tmp[4] = tmp[6] * 0x100;
11494 	tmp[5] = tmp[4] / tmp[3];
11495 	tmp[6] = tmp[4] % tmp[3];
11496 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11497 	tmp[4] = tmp[6] * 0x100;
11498 	tmp[5] = tmp[4] / tmp[3];
11499 	tmp[6] = tmp[4] % tmp[3];
11500 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11501 	tmp[4] = tmp[6] * 0x100;
11502 	tmp[5] = tmp[4] / tmp[3];
11503 	tmp[6] = tmp[4] % tmp[3];
11504 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11505 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11506 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11507 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11508 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11509 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11510 
11511 	bwn_phy_lp_b2062_vco_calib(mac);
11512 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11513 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11514 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11515 		bwn_phy_lp_b2062_reset_pllbias(mac);
11516 		bwn_phy_lp_b2062_vco_calib(mac);
11517 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11518 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11519 			return (EIO);
11520 		}
11521 	}
11522 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11523 	return (0);
11524 }
11525 
11526 static void
11527 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11528 {
11529 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11530 	uint16_t tmp = (channel == 14);
11531 
11532 	if (mac->mac_phy.rev < 2) {
11533 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11534 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11535 			bwn_phy_lp_set_rccap(mac);
11536 		return;
11537 	}
11538 
11539 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11540 }
11541 
11542 static void
11543 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11544 {
11545 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11546 	struct bwn_softc *sc = mac->mac_sc;
11547 	struct ifnet *ifp = sc->sc_ifp;
11548 	struct ieee80211com *ic = ifp->if_l2com;
11549 	uint16_t iso, tmp[3];
11550 
11551 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11552 
11553 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11554 		iso = plp->plp_txisoband_m;
11555 	else if (freq <= 5320)
11556 		iso = plp->plp_txisoband_l;
11557 	else if (freq <= 5700)
11558 		iso = plp->plp_txisoband_m;
11559 	else
11560 		iso = plp->plp_txisoband_h;
11561 
11562 	tmp[0] = ((iso - 26) / 12) << 12;
11563 	tmp[1] = tmp[0] + 0x1000;
11564 	tmp[2] = tmp[0] + 0x2000;
11565 
11566 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11567 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11568 }
11569 
11570 static void
11571 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11572 {
11573 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11574 	int i;
11575 	static const uint16_t addr[] = {
11576 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11577 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11578 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11579 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11580 		BWN_PHY_OFDM(0xcf),
11581 	};
11582 	static const uint16_t val[] = {
11583 		0xde5e, 0xe832, 0xe331, 0x4d26,
11584 		0x0026, 0x1420, 0x0020, 0xfe08,
11585 		0x0008,
11586 	};
11587 
11588 	for (i = 0; i < N(addr); i++) {
11589 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11590 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11591 	}
11592 }
11593 
11594 static void
11595 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11596 {
11597 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11598 	struct bwn_softc *sc = mac->mac_sc;
11599 	uint16_t ctl;
11600 
11601 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11602 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11603 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11604 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11605 		break;
11606 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11607 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11608 		break;
11609 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11610 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11611 		break;
11612 	default:
11613 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11614 		device_printf(sc->sc_dev, "unknown command mode\n");
11615 		break;
11616 	}
11617 }
11618 
11619 static void
11620 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11621 {
11622 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11623 	uint16_t ctl;
11624 	uint8_t old;
11625 
11626 	bwn_phy_lp_get_txpctlmode(mac);
11627 	old = plp->plp_txpctlmode;
11628 	if (old == mode)
11629 		return;
11630 	plp->plp_txpctlmode = mode;
11631 
11632 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11633 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11634 		    plp->plp_tssiidx);
11635 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11636 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11637 
11638 		/* disable TX GAIN override */
11639 		if (mac->mac_phy.rev < 2)
11640 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11641 		else {
11642 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11643 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11644 		}
11645 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11646 
11647 		plp->plp_txpwridx = -1;
11648 	}
11649 	if (mac->mac_phy.rev >= 2) {
11650 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11651 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11652 		else
11653 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11654 	}
11655 
11656 	/* writes TX Power Control mode */
11657 	switch (plp->plp_txpctlmode) {
11658 	case BWN_PHYLP_TXPCTL_OFF:
11659 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11660 		break;
11661 	case BWN_PHYLP_TXPCTL_ON_HW:
11662 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11663 		break;
11664 	case BWN_PHYLP_TXPCTL_ON_SW:
11665 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11666 		break;
11667 	default:
11668 		ctl = 0;
11669 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11670 	}
11671 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11672 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11673 }
11674 
11675 static void
11676 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11677 {
11678 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11679 	struct bwn_softc *sc = mac->mac_sc;
11680 	const unsigned int size = 256;
11681 	struct bwn_txgain tg;
11682 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11683 	uint16_t tssinpt, tssiidx, value[2];
11684 	uint8_t mode;
11685 	int8_t txpwridx;
11686 
11687 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11688 	    M_NOWAIT | M_ZERO);
11689 	if (tabs == NULL) {
11690 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11691 		return;
11692 	}
11693 
11694 	bwn_phy_lp_get_txpctlmode(mac);
11695 	mode = plp->plp_txpctlmode;
11696 	txpwridx = plp->plp_txpwridx;
11697 	tssinpt = plp->plp_tssinpt;
11698 	tssiidx = plp->plp_tssiidx;
11699 
11700 	bwn_tab_read_multi(mac,
11701 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11702 	    BWN_TAB_4(7, 0x140), size, tabs);
11703 
11704 	bwn_phy_lp_tblinit(mac);
11705 	bwn_phy_lp_bbinit(mac);
11706 	bwn_phy_lp_txpctl_init(mac);
11707 	bwn_phy_lp_rf_onoff(mac, 1);
11708 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11709 
11710 	bwn_tab_write_multi(mac,
11711 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11712 	    BWN_TAB_4(7, 0x140), size, tabs);
11713 
11714 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11715 	plp->plp_tssinpt = tssinpt;
11716 	plp->plp_tssiidx = tssiidx;
11717 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11718 	if (txpwridx != -1) {
11719 		/* set TX power by index */
11720 		plp->plp_txpwridx = txpwridx;
11721 		bwn_phy_lp_get_txpctlmode(mac);
11722 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11723 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11724 		if (mac->mac_phy.rev >= 2) {
11725 			rxcomp = bwn_tab_read(mac,
11726 			    BWN_TAB_4(7, txpwridx + 320));
11727 			txgain = bwn_tab_read(mac,
11728 			    BWN_TAB_4(7, txpwridx + 192));
11729 			tg.tg_pad = (txgain >> 16) & 0xff;
11730 			tg.tg_gm = txgain & 0xff;
11731 			tg.tg_pga = (txgain >> 8) & 0xff;
11732 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11733 			bwn_phy_lp_set_txgain(mac, &tg);
11734 		} else {
11735 			rxcomp = bwn_tab_read(mac,
11736 			    BWN_TAB_4(10, txpwridx + 320));
11737 			txgain = bwn_tab_read(mac,
11738 			    BWN_TAB_4(10, txpwridx + 192));
11739 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11740 			    0xf800, (txgain >> 4) & 0x7fff);
11741 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11742 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11743 		}
11744 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11745 
11746 		/* set TX IQCC */
11747 		value[0] = (rxcomp >> 10) & 0x3ff;
11748 		value[1] = rxcomp & 0x3ff;
11749 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11750 
11751 		coeff = bwn_tab_read(mac,
11752 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11753 		    BWN_TAB_4(10, txpwridx + 448));
11754 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11755 		if (mac->mac_phy.rev >= 2) {
11756 			rfpwr = bwn_tab_read(mac,
11757 			    BWN_TAB_4(7, txpwridx + 576));
11758 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11759 			    rfpwr & 0xffff);
11760 		}
11761 		bwn_phy_lp_set_txgain_override(mac);
11762 	}
11763 	if (plp->plp_rccap)
11764 		bwn_phy_lp_set_rccap(mac);
11765 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11766 	bwn_phy_lp_set_txpctlmode(mac, mode);
11767 	free(tabs, M_DEVBUF);
11768 }
11769 
11770 static void
11771 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11772 {
11773 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11774 	int i;
11775 	static const uint16_t addr[] = {
11776 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11777 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11778 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11779 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11780 		BWN_PHY_OFDM(0xcf),
11781 	};
11782 
11783 	for (i = 0; i < N(addr); i++)
11784 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11785 }
11786 
11787 static void
11788 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11789 {
11790 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11791 
11792 	if (mac->mac_phy.rev < 2) {
11793 		bwn_phy_lp_tblinit_r01(mac);
11794 		bwn_phy_lp_tblinit_txgain(mac);
11795 		bwn_phy_lp_set_gaintbl(mac, freq);
11796 		return;
11797 	}
11798 
11799 	bwn_phy_lp_tblinit_r2(mac);
11800 	bwn_phy_lp_tblinit_txgain(mac);
11801 }
11802 
11803 struct bwn_wpair {
11804 	uint16_t		reg;
11805 	uint16_t		value;
11806 };
11807 
11808 struct bwn_smpair {
11809 	uint16_t		offset;
11810 	uint16_t		mask;
11811 	uint16_t		set;
11812 };
11813 
11814 static void
11815 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11816 {
11817 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11818 	struct siba_dev_softc *sd = mac->mac_sd;
11819 	struct siba_softc *siba = sd->sd_bus;
11820 	struct bwn_softc *sc = mac->mac_sc;
11821 	struct ifnet *ifp = sc->sc_ifp;
11822 	struct ieee80211com *ic = ifp->if_l2com;
11823 	static const struct bwn_wpair v1[] = {
11824 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11825 		{ BWN_PHY_AFE_CTL, 0x8800 },
11826 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11827 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11828 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11829 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11830 		{ BWN_PHY_OFDM(0xf9), 0 },
11831 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11832 	};
11833 	static const struct bwn_smpair v2[] = {
11834 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11835 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11836 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11837 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11838 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11839 	};
11840 	static const struct bwn_smpair v3[] = {
11841 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11842 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11843 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11844 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11845 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11846 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11847 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11848 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11849 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11850 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11851 
11852 	};
11853 	int i;
11854 
11855 	for (i = 0; i < N(v1); i++)
11856 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11857 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11858 	for (i = 0; i < N(v2); i++)
11859 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11860 
11861 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11862 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11863 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11864 	if (siba->siba_board_rev >= 0x18) {
11865 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11866 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11867 	} else {
11868 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11869 	}
11870 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11871 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11872 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11873 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11874 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11875 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11876 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11877 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11878 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11879 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11880 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11881 	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11882 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11883 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11884 	} else {
11885 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11886 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11887 	}
11888 	for (i = 0; i < N(v3); i++)
11889 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11890 	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11891 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11892 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11893 	}
11894 
11895 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11896 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11897 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11898 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11899 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11900 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11901 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11902 	} else
11903 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11904 
11905 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11906 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11907 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11908 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11909 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11910 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11911 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11912 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11913 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11914 
11915 	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
11916 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11917 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11918 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11919 	}
11920 
11921 	bwn_phy_lp_digflt_save(mac);
11922 }
11923 
11924 static void
11925 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11926 {
11927 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11928 	struct siba_dev_softc *sd = mac->mac_sd;
11929 	struct siba_softc *siba = sd->sd_bus;
11930 	struct bwn_softc *sc = mac->mac_sc;
11931 	struct ifnet *ifp = sc->sc_ifp;
11932 	struct ieee80211com *ic = ifp->if_l2com;
11933 	static const struct bwn_smpair v1[] = {
11934 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11935 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11936 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11937 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11938 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11939 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11940 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11941 	};
11942 	static const struct bwn_smpair v2[] = {
11943 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11944 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11945 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11946 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11947 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11948 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11949 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11950 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11951 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11952 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11953 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11954 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11955 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11956 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11957 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11958 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11959 	};
11960 	static const struct bwn_smpair v3[] = {
11961 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11962 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11963 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11964 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11965 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11966 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11967 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11968 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11969 	};
11970 	static const struct bwn_smpair v4[] = {
11971 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11972 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11973 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11974 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11975 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11976 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11977 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11978 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11979 	};
11980 	static const struct bwn_smpair v5[] = {
11981 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11982 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11983 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11984 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11985 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11986 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11987 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11988 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11989 	};
11990 	int i;
11991 	uint16_t tmp, tmp2;
11992 
11993 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11994 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11995 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11996 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11997 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11998 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11999 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
12000 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
12001 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
12002 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
12003 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
12004 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
12005 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
12006 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
12007 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
12008 	for (i = 0; i < N(v1); i++)
12009 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
12010 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
12011 	    0xff00, plp->plp_rxpwroffset);
12012 	if ((siba->siba_sprom.bf_lo & BWN_BFL_FEM) &&
12013 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
12014 	   (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF))) {
12015 		siba_cc_pmu_set_ldovolt(&siba->siba_cc, SIBA_LDO_PAREF, 0x28);
12016 		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 1);
12017 		if (mac->mac_phy.rev == 0)
12018 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
12019 			    0xffcf, 0x0010);
12020 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
12021 	} else {
12022 		siba_cc_pmu_set_ldoparef(&siba->siba_cc, 0);
12023 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
12024 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
12025 	}
12026 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
12027 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
12028 	if (siba->siba_sprom.bf_hi & BWN_BFH_RSSIINV)
12029 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
12030 	else
12031 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
12032 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
12033 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
12034 	    0xfff9, (plp->plp_bxarch << 1));
12035 	if (mac->mac_phy.rev == 1 &&
12036 	    (siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT)) {
12037 		for (i = 0; i < N(v2); i++)
12038 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
12039 			    v2[i].set);
12040 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
12041 	    (siba->siba_board_type == 0x048a) || ((mac->mac_phy.rev == 0) &&
12042 	    (siba->siba_sprom.bf_lo & BWN_BFL_FEM))) {
12043 		for (i = 0; i < N(v3); i++)
12044 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
12045 			    v3[i].set);
12046 	} else if (mac->mac_phy.rev == 1 ||
12047 		  (siba->siba_sprom.bf_lo & BWN_BFL_FEM)) {
12048 		for (i = 0; i < N(v4); i++)
12049 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
12050 			    v4[i].set);
12051 	} else {
12052 		for (i = 0; i < N(v5); i++)
12053 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
12054 			    v5[i].set);
12055 	}
12056 	if (mac->mac_phy.rev == 1 &&
12057 	    (siba->siba_sprom.bf_hi & BWN_BFH_LDO_PAREF)) {
12058 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
12059 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
12060 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
12061 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
12062 	}
12063 	if ((siba->siba_sprom.bf_hi & BWN_BFH_FEM_BT) &&
12064 	    (siba->siba_chipid == 0x5354) &&
12065 	    (siba->siba_chippkg == SIBA_CHIPPACK_BCM4712S)) {
12066 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
12067 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
12068 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
12069 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
12070 	}
12071 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12072 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
12073 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
12074 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
12075 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
12076 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
12077 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
12078 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
12079 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
12080 	} else {
12081 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
12082 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
12083 	}
12084 	if (mac->mac_phy.rev == 1) {
12085 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
12086 		tmp2 = (tmp & 0x03e0) >> 5;
12087 		tmp2 |= tmp2 << 5;
12088 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12089 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12090 		tmp2 = (tmp & 0x1f00) >> 8;
12091 		tmp2 |= tmp2 << 5;
12092 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12093 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12094 		tmp2 = tmp & 0x00ff;
12095 		tmp2 |= tmp << 8;
12096 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12097 	}
12098 }
12099 
12100 struct bwn_b2062_freq {
12101 	uint16_t		freq;
12102 	uint8_t			value[6];
12103 };
12104 
12105 static void
12106 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12107 {
12108 #define	CALC_CTL7(freq, div)						\
12109 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12110 #define	CALC_CTL18(freq, div)						\
12111 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12112 #define	CALC_CTL19(freq, div)						\
12113 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12114 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12115 	struct siba_dev_softc *sd = mac->mac_sd;
12116 	struct siba_softc *siba = sd->sd_bus;
12117 	struct bwn_softc *sc = mac->mac_sc;
12118 	struct ifnet *ifp = sc->sc_ifp;
12119 	struct ieee80211com *ic = ifp->if_l2com;
12120 	static const struct bwn_b2062_freq freqdata_tab[] = {
12121 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12122 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12123 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12124 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12125 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12126 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12127 	};
12128 	static const struct bwn_wpair v1[] = {
12129 		{ BWN_B2062_N_TXCTL3, 0 },
12130 		{ BWN_B2062_N_TXCTL4, 0 },
12131 		{ BWN_B2062_N_TXCTL5, 0 },
12132 		{ BWN_B2062_N_TXCTL6, 0 },
12133 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12134 		{ BWN_B2062_N_PDNCTL0, 0 },
12135 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12136 		{ BWN_B2062_N_CALIB_TS, 0 }
12137 	};
12138 	const struct bwn_b2062_freq *f = NULL;
12139 	uint32_t xtalfreq, ref;
12140 	unsigned int i;
12141 
12142 	bwn_phy_lp_b2062_tblinit(mac);
12143 
12144 	for (i = 0; i < N(v1); i++)
12145 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12146 	if (mac->mac_phy.rev > 0)
12147 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12148 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12149 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12150 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12151 	else
12152 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12153 
12154 	KASSERT(siba->siba_cc.scc_caps & SIBA_CC_CAPS_PMU,
12155 	    ("%s:%d: fail", __func__, __LINE__));
12156 	xtalfreq = siba->siba_cc.scc_pmu.freq * 1000;
12157 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12158 
12159 	if (xtalfreq <= 30000000) {
12160 		plp->plp_div = 1;
12161 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12162 	} else {
12163 		plp->plp_div = 2;
12164 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12165 	}
12166 
12167 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12168 	    CALC_CTL7(xtalfreq, plp->plp_div));
12169 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12170 	    CALC_CTL18(xtalfreq, plp->plp_div));
12171 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12172 	    CALC_CTL19(xtalfreq, plp->plp_div));
12173 
12174 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12175 	ref &= 0xffff;
12176 	for (i = 0; i < N(freqdata_tab); i++) {
12177 		if (ref < freqdata_tab[i].freq) {
12178 			f = &freqdata_tab[i];
12179 			break;
12180 		}
12181 	}
12182 	if (f == NULL)
12183 		f = &freqdata_tab[N(freqdata_tab) - 1];
12184 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12185 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12186 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12187 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12188 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12189 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12190 #undef CALC_CTL7
12191 #undef CALC_CTL18
12192 #undef CALC_CTL19
12193 }
12194 
12195 static void
12196 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12197 {
12198 
12199 	bwn_phy_lp_b2063_tblinit(mac);
12200 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12201 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12202 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12203 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12204 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12205 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12206 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12207 	if (mac->mac_phy.rev == 2) {
12208 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12209 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12210 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12211 	} else {
12212 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12213 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12214 	}
12215 }
12216 
12217 static void
12218 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12219 {
12220 	struct siba_dev_softc *sd = mac->mac_sd;
12221 	struct siba_softc *siba = sd->sd_bus;
12222 	static const struct bwn_wpair v1[] = {
12223 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12224 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12225 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12226 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12227 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12228 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12229 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12230 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12231 	};
12232 	static const struct bwn_wpair v2[] = {
12233 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12234 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12235 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12236 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12237 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12238 	};
12239 	uint32_t freqxtal = siba->siba_cc.scc_pmu.freq * 1000;
12240 	int i;
12241 	uint8_t tmp;
12242 
12243 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12244 
12245 	for (i = 0; i < 2; i++)
12246 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12247 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12248 	for (i = 2; i < N(v1); i++)
12249 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12250 	for (i = 0; i < 10000; i++) {
12251 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12252 			break;
12253 		DELAY(1000);
12254 	}
12255 
12256 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12257 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12258 
12259 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12260 
12261 	for (i = 0; i < N(v2); i++)
12262 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12263 	if (freqxtal == 24000000) {
12264 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12265 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12266 	} else {
12267 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12268 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12269 	}
12270 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12271 	for (i = 0; i < 10000; i++) {
12272 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12273 			break;
12274 		DELAY(1000);
12275 	}
12276 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12277 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12278 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12279 }
12280 
12281 static void
12282 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12283 {
12284 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12285 	struct bwn_softc *sc = mac->mac_sc;
12286 	struct bwn_phy_lp_iq_est ie;
12287 	struct bwn_txgain tx_gains;
12288 	static const uint32_t pwrtbl[21] = {
12289 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12290 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12291 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12292 		0x0004c, 0x0002c, 0x0001a,
12293 	};
12294 	uint32_t npwr, ipwr, sqpwr, tmp;
12295 	int loopback, i, j, sum, error;
12296 	uint16_t save[7];
12297 	uint8_t txo, bbmult, txpctlmode;
12298 
12299 	error = bwn_phy_lp_switch_channel(mac, 7);
12300 	if (error)
12301 		device_printf(sc->sc_dev,
12302 		    "failed to change channel to 7 (%d)\n", error);
12303 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12304 	bbmult = bwn_phy_lp_get_bbmult(mac);
12305 	if (txo)
12306 		tx_gains = bwn_phy_lp_get_txgain(mac);
12307 
12308 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12309 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12310 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12311 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12312 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12313 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12314 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12315 
12316 	bwn_phy_lp_get_txpctlmode(mac);
12317 	txpctlmode = plp->plp_txpctlmode;
12318 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12319 
12320 	/* disable CRS */
12321 	bwn_phy_lp_set_deaf(mac, 1);
12322 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12323 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12324 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12325 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12326 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12327 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12328 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12329 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12330 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12331 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12332 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12333 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12334 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12335 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12336 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12337 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12338 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12339 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12340 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12341 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12342 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12343 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12344 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12345 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12346 
12347 	loopback = bwn_phy_lp_loopback(mac);
12348 	if (loopback == -1)
12349 		goto done;
12350 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12351 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12352 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12353 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12354 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12355 
12356 	tmp = 0;
12357 	memset(&ie, 0, sizeof(ie));
12358 	for (i = 128; i <= 159; i++) {
12359 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12360 		sum = 0;
12361 		for (j = 5; j <= 25; j++) {
12362 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12363 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12364 				goto done;
12365 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12366 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12367 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12368 			    12);
12369 			sum += ((ipwr - npwr) * (ipwr - npwr));
12370 			if ((i == 128) || (sum < tmp)) {
12371 				plp->plp_rccap = i;
12372 				tmp = sum;
12373 			}
12374 		}
12375 	}
12376 	bwn_phy_lp_ddfs_turnoff(mac);
12377 done:
12378 	/* restore CRS */
12379 	bwn_phy_lp_clear_deaf(mac, 1);
12380 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12381 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12382 
12383 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12384 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12385 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12386 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12387 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12388 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12389 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12390 
12391 	bwn_phy_lp_set_bbmult(mac, bbmult);
12392 	if (txo)
12393 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12394 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12395 	if (plp->plp_rccap)
12396 		bwn_phy_lp_set_rccap(mac);
12397 }
12398 
12399 static void
12400 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12401 {
12402 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12403 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12404 
12405 	if (mac->mac_phy.rev == 1)
12406 		rc_cap = MIN(rc_cap + 5, 15);
12407 
12408 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12409 	    MAX(plp->plp_rccap - 4, 0x80));
12410 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12411 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12412 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12413 }
12414 
12415 static uint32_t
12416 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12417 {
12418 	uint32_t i, q, r;
12419 
12420 	if (div == 0)
12421 		return (0);
12422 
12423 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12424 		q <<= 1;
12425 		if (r << 1 >= div) {
12426 			q++;
12427 			r = (r << 1) - div;
12428 		}
12429 	}
12430 	if (r << 1 >= div)
12431 		q++;
12432 	return (q);
12433 }
12434 
12435 static void
12436 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12437 {
12438 	struct siba_dev_softc *sd = mac->mac_sd;
12439 	struct siba_softc *siba = sd->sd_bus;
12440 
12441 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12442 	DELAY(20);
12443 	if (siba->siba_chipid == 0x5354) {
12444 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12445 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12446 	} else {
12447 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12448 	}
12449 	DELAY(5);
12450 }
12451 
12452 static void
12453 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12454 {
12455 
12456 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12457 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12458 	DELAY(200);
12459 }
12460 
12461 static void
12462 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12463 {
12464 #define	FLAG_A	0x01
12465 #define	FLAG_G	0x02
12466 	struct bwn_softc *sc = mac->mac_sc;
12467 	struct ifnet *ifp = sc->sc_ifp;
12468 	struct ieee80211com *ic = ifp->if_l2com;
12469 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12470 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12471 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12472 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12473 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12474 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12475 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12476 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12477 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12478 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12479 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12480 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12481 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12482 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12483 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12484 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12485 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12486 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12487 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12488 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12489 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12490 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12491 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12492 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12493 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12494 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12495 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12496 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12497 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12498 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12499 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12500 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12501 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12502 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12503 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12504 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12505 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12506 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12507 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12508 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12509 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12510 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12511 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12512 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12513 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12514 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12515 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12516 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12517 	};
12518 	const struct bwn_b206x_rfinit_entry *br;
12519 	unsigned int i;
12520 
12521 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12522 		br = &bwn_b2062_init_tab[i];
12523 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12524 			if (br->br_flags & FLAG_G)
12525 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12526 		} else {
12527 			if (br->br_flags & FLAG_A)
12528 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12529 		}
12530 	}
12531 #undef FLAG_A
12532 #undef FLAG_B
12533 }
12534 
12535 static void
12536 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12537 {
12538 #define	FLAG_A	0x01
12539 #define	FLAG_G	0x02
12540 	struct bwn_softc *sc = mac->mac_sc;
12541 	struct ifnet *ifp = sc->sc_ifp;
12542 	struct ieee80211com *ic = ifp->if_l2com;
12543 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12544 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12545 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12546 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12547 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12548 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12549 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12550 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12551 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12552 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12553 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12554 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12555 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12556 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12557 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12558 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12559 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12560 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12561 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12562 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12563 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12564 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12565 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12566 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12567 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12568 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12569 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12570 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12571 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12572 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12573 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12574 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12575 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12576 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12577 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12578 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12579 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12580 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12581 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12582 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12583 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12584 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12585 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12586 	};
12587 	const struct bwn_b206x_rfinit_entry *br;
12588 	unsigned int i;
12589 
12590 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12591 		br = &bwn_b2063_init_tab[i];
12592 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12593 			if (br->br_flags & FLAG_G)
12594 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12595 		} else {
12596 			if (br->br_flags & FLAG_A)
12597 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12598 		}
12599 	}
12600 #undef FLAG_A
12601 #undef FLAG_B
12602 }
12603 
12604 static void
12605 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12606     int count, void *_data)
12607 {
12608 	unsigned int i;
12609 	uint32_t offset, type;
12610 	uint8_t *data = _data;
12611 
12612 	type = BWN_TAB_GETTYPE(typenoffset);
12613 	offset = BWN_TAB_GETOFFSET(typenoffset);
12614 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12615 
12616 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12617 
12618 	for (i = 0; i < count; i++) {
12619 		switch (type) {
12620 		case BWN_TAB_8BIT:
12621 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12622 			data++;
12623 			break;
12624 		case BWN_TAB_16BIT:
12625 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12626 			    BWN_PHY_TABLEDATALO);
12627 			data += 2;
12628 			break;
12629 		case BWN_TAB_32BIT:
12630 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12631 			    BWN_PHY_TABLEDATAHI);
12632 			*((uint32_t *)data) <<= 16;
12633 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12634 			    BWN_PHY_TABLEDATALO);
12635 			data += 4;
12636 			break;
12637 		default:
12638 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12639 		}
12640 	}
12641 }
12642 
12643 static void
12644 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12645     int count, const void *_data)
12646 {
12647 	uint32_t offset, type, value;
12648 	const uint8_t *data = _data;
12649 	unsigned int i;
12650 
12651 	type = BWN_TAB_GETTYPE(typenoffset);
12652 	offset = BWN_TAB_GETOFFSET(typenoffset);
12653 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12654 
12655 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12656 
12657 	for (i = 0; i < count; i++) {
12658 		switch (type) {
12659 		case BWN_TAB_8BIT:
12660 			value = *data;
12661 			data++;
12662 			KASSERT(!(value & ~0xff),
12663 			    ("%s:%d: fail", __func__, __LINE__));
12664 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12665 			break;
12666 		case BWN_TAB_16BIT:
12667 			value = *((const uint16_t *)data);
12668 			data += 2;
12669 			KASSERT(!(value & ~0xffff),
12670 			    ("%s:%d: fail", __func__, __LINE__));
12671 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12672 			break;
12673 		case BWN_TAB_32BIT:
12674 			value = *((const uint32_t *)data);
12675 			data += 4;
12676 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12677 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12678 			break;
12679 		default:
12680 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12681 		}
12682 	}
12683 }
12684 
12685 static struct bwn_txgain
12686 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12687 {
12688 	struct bwn_txgain tg;
12689 	uint16_t tmp;
12690 
12691 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12692 	if (mac->mac_phy.rev < 2) {
12693 		tmp = BWN_PHY_READ(mac,
12694 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12695 		tg.tg_gm = tmp & 0x0007;
12696 		tg.tg_pga = (tmp & 0x0078) >> 3;
12697 		tg.tg_pad = (tmp & 0x780) >> 7;
12698 		return (tg);
12699 	}
12700 
12701 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12702 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12703 	tg.tg_gm = tmp & 0xff;
12704 	tg.tg_pga = (tmp >> 8) & 0xff;
12705 	return (tg);
12706 }
12707 
12708 static uint8_t
12709 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12710 {
12711 
12712 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12713 }
12714 
12715 static void
12716 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12717 {
12718 	uint16_t pa;
12719 
12720 	if (mac->mac_phy.rev < 2) {
12721 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12722 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12723 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12724 		bwn_phy_lp_set_txgain_override(mac);
12725 		return;
12726 	}
12727 
12728 	pa = bwn_phy_lp_get_pa_gain(mac);
12729 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12730 	    (tg->tg_pga << 8) | tg->tg_gm);
12731 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12732 	    tg->tg_pad | (pa << 6));
12733 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12734 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12735 	    tg->tg_pad | (pa << 8));
12736 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12737 	bwn_phy_lp_set_txgain_override(mac);
12738 }
12739 
12740 static void
12741 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12742 {
12743 
12744 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12745 }
12746 
12747 static void
12748 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12749 {
12750 	uint16_t trsw = (tx << 1) | rx;
12751 
12752 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12753 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12754 }
12755 
12756 static void
12757 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12758 {
12759 	struct bwn_softc *sc = mac->mac_sc;
12760 	struct ifnet *ifp = sc->sc_ifp;
12761 	struct ieee80211com *ic = ifp->if_l2com;
12762 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12763 
12764 	if (mac->mac_phy.rev < 2) {
12765 		trsw = gain & 0x1;
12766 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12767 		ext_lna = (gain & 2) >> 1;
12768 
12769 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12770 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12771 		    0xfbff, ext_lna << 10);
12772 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12773 		    0xf7ff, ext_lna << 11);
12774 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12775 	} else {
12776 		low_gain = gain & 0xffff;
12777 		high_gain = (gain >> 16) & 0xf;
12778 		ext_lna = (gain >> 21) & 0x1;
12779 		trsw = ~(gain >> 20) & 0x1;
12780 
12781 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12782 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12783 		    0xfdff, ext_lna << 9);
12784 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12785 		    0xfbff, ext_lna << 10);
12786 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12787 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12788 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12789 			tmp = (gain >> 2) & 0x3;
12790 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12791 			    0xe7ff, tmp<<11);
12792 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12793 			    tmp << 3);
12794 		}
12795 	}
12796 
12797 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12798 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12799 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12800 	if (mac->mac_phy.rev >= 2) {
12801 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12802 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12803 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12804 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12805 		}
12806 		return;
12807 	}
12808 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12809 }
12810 
12811 static void
12812 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12813 {
12814 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12815 
12816 	if (user)
12817 		plp->plp_crsusr_off = 1;
12818 	else
12819 		plp->plp_crssys_off = 1;
12820 
12821 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12822 }
12823 
12824 static void
12825 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12826 {
12827 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12828 	struct bwn_softc *sc = mac->mac_sc;
12829 	struct ifnet *ifp = sc->sc_ifp;
12830 	struct ieee80211com *ic = ifp->if_l2com;
12831 
12832 	if (user)
12833 		plp->plp_crsusr_off = 0;
12834 	else
12835 		plp->plp_crssys_off = 0;
12836 
12837 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12838 		return;
12839 
12840 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12841 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12842 	else
12843 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12844 }
12845 
12846 static unsigned int
12847 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12848 {
12849 	struct bwn_softc *sc = mac->mac_sc;
12850 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12851 	static uint8_t sqrt_table[256] = {
12852 		10, 14, 17, 20, 22, 24, 26, 28,
12853 		30, 31, 33, 34, 36, 37, 38, 40,
12854 		41, 42, 43, 44, 45, 46, 47, 48,
12855 		50, 50, 51, 52, 53, 54, 55, 56,
12856 		57, 58, 59, 60, 60, 61, 62, 63,
12857 		64, 64, 65, 66, 67, 67, 68, 69,
12858 		70, 70, 71, 72, 72, 73, 74, 74,
12859 		75, 76, 76, 77, 78, 78, 79, 80,
12860 		80, 81, 81, 82, 83, 83, 84, 84,
12861 		85, 86, 86, 87, 87, 88, 88, 89,
12862 		90, 90, 91, 91, 92, 92, 93, 93,
12863 		94, 94, 95, 95, 96, 96, 97, 97,
12864 		98, 98, 99, 100, 100, 100, 101, 101,
12865 		102, 102, 103, 103, 104, 104, 105, 105,
12866 		106, 106, 107, 107, 108, 108, 109, 109,
12867 		110, 110, 110, 111, 111, 112, 112, 113,
12868 		113, 114, 114, 114, 115, 115, 116, 116,
12869 		117, 117, 117, 118, 118, 119, 119, 120,
12870 		120, 120, 121, 121, 122, 122, 122, 123,
12871 		123, 124, 124, 124, 125, 125, 126, 126,
12872 		126, 127, 127, 128, 128, 128, 129, 129,
12873 		130, 130, 130, 131, 131, 131, 132, 132,
12874 		133, 133, 133, 134, 134, 134, 135, 135,
12875 		136, 136, 136, 137, 137, 137, 138, 138,
12876 		138, 139, 139, 140, 140, 140, 141, 141,
12877 		141, 142, 142, 142, 143, 143, 143, 144,
12878 		144, 144, 145, 145, 145, 146, 146, 146,
12879 		147, 147, 147, 148, 148, 148, 149, 149,
12880 		150, 150, 150, 150, 151, 151, 151, 152,
12881 		152, 152, 153, 153, 153, 154, 154, 154,
12882 		155, 155, 155, 156, 156, 156, 157, 157,
12883 		157, 158, 158, 158, 159, 159, 159, 160
12884 	};
12885 
12886 	if (x == 0)
12887 		return (0);
12888 	if (x >= 256) {
12889 		device_printf(sc->sc_dev,
12890 		    "out of bounds of the square-root table (%d)\n", x);
12891 		return (16);
12892 	}
12893 	return (sqrt_table[x - 1] / 10);
12894 }
12895 
12896 static int
12897 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12898 {
12899 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12900 	int _t;								\
12901 	_t = _x - 20;							\
12902 	if (_t >= 0) {							\
12903 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12904 	} else {							\
12905 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12906 	}								\
12907 } while (0)
12908 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12909 	int _t;								\
12910 	_t = _x - 11;							\
12911 	if (_t >= 0)							\
12912 		tmp[3] = (_y << (31 - _x)) / (_z >> _t);		\
12913 	else								\
12914 		tmp[3] = (_y << (31 - _x)) / (_z << -_t);		\
12915 } while (0)
12916 	struct bwn_phy_lp_iq_est ie;
12917 	uint16_t v0, v1;
12918 	int tmp[2], ret;
12919 
12920 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12921 	v0 = v1 >> 8;
12922 	v1 |= 0xff;
12923 
12924 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12925 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12926 
12927 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12928 	if (ret == 0)
12929 		goto done;
12930 
12931 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12932 		ret = 0;
12933 		goto done;
12934 	}
12935 
12936 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12937 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12938 
12939 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12940 	v0 = tmp[0] >> 3;
12941 	v1 = tmp[1] >> 4;
12942 done:
12943 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12944 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12945 	return ret;
12946 #undef CALC_COEFF
12947 #undef CALC_COEFF2
12948 }
12949 
12950 static void
12951 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12952 {
12953 	static const uint16_t noisescale[] = {
12954 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12955 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12956 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12957 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12958 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12959 	};
12960 	static const uint16_t crsgainnft[] = {
12961 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12962 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12963 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12964 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12965 		0x013d,
12966 	};
12967 	static const uint16_t filterctl[] = {
12968 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12969 		0xff53, 0x0127,
12970 	};
12971 	static const uint32_t psctl[] = {
12972 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12973 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12974 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12975 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12976 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12977 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12978 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12979 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12980 	};
12981 	static const uint16_t ofdmcckgain_r0[] = {
12982 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12983 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12984 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12985 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12986 		0x755d,
12987 	};
12988 	static const uint16_t ofdmcckgain_r1[] = {
12989 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12990 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12991 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12992 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12993 		0x755d,
12994 	};
12995 	static const uint16_t gaindelta[] = {
12996 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12997 		0x0000,
12998 	};
12999 	static const uint32_t txpwrctl[] = {
13000 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
13001 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
13002 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
13003 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
13004 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
13005 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
13006 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
13007 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
13008 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
13009 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
13010 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
13011 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
13012 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
13013 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13014 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13015 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13016 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13017 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13018 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13019 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13020 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13021 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13022 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13023 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13024 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13025 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13026 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13027 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13028 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13029 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13030 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13031 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13032 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13033 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13034 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13035 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13036 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13037 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13038 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
13039 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
13040 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
13041 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
13042 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
13043 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
13044 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
13045 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
13046 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
13047 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
13048 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
13049 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
13050 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
13051 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
13052 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
13053 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
13054 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
13055 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
13056 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
13057 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
13058 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
13059 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
13060 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
13061 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
13062 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
13063 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
13064 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13065 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13066 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13067 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13068 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13069 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13070 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13071 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13072 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13073 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13074 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13075 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13076 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13077 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13078 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13079 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13080 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13081 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13082 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13083 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13084 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13085 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13086 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13087 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
13088 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
13089 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13090 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13091 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13092 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13093 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13094 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13095 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13096 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13097 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13098 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13099 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13100 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13101 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13102 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13103 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13104 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13105 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13106 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13107 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13108 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13109 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13110 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13111 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13112 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13113 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13114 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13115 		0x00000702,
13116 	};
13117 
13118 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13119 
13120 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13121 	    bwn_tab_sigsq_tbl);
13122 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13123 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13124 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13125 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13126 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13127 	    bwn_tab_pllfrac_tbl);
13128 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13129 	    bwn_tabl_iqlocal_tbl);
13130 	if (mac->mac_phy.rev == 0) {
13131 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13132 		    ofdmcckgain_r0);
13133 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13134 		    ofdmcckgain_r0);
13135 	} else {
13136 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13137 		    ofdmcckgain_r1);
13138 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13139 		    ofdmcckgain_r1);
13140 	}
13141 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13142 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13143 }
13144 
13145 static void
13146 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13147 {
13148 	struct siba_dev_softc *sd = mac->mac_sd;
13149 	struct siba_softc *siba = sd->sd_bus;
13150 	int i;
13151 	static const uint16_t noisescale[] = {
13152 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13153 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13154 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13155 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13156 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13157 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13158 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13159 	};
13160 	static const uint32_t filterctl[] = {
13161 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13162 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13163 	};
13164 	static const uint32_t psctl[] = {
13165 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13166 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13167 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13168 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13169 	};
13170 	static const uint32_t gainidx[] = {
13171 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13172 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13173 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13174 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13175 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13176 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13177 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13178 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13179 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13180 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13181 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13182 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13183 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13184 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13185 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13186 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13187 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13188 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13189 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13190 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13191 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13192 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13193 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13194 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13195 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13196 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13197 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13198 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13199 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13200 		0x0000001a, 0x64ca55ad, 0x0000001a
13201 	};
13202 	static const uint16_t auxgainidx[] = {
13203 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13204 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13205 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13206 		0x0004, 0x0016
13207 	};
13208 	static const uint16_t swctl[] = {
13209 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13210 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13211 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13212 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13213 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13214 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13215 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13216 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13217 	};
13218 	static const uint8_t hf[] = {
13219 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13220 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13221 	};
13222 	static const uint32_t gainval[] = {
13223 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13224 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13225 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13226 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13227 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13228 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13229 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13230 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13231 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13232 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13233 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13234 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13235 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13236 		0x000000f1, 0x00000000, 0x00000000
13237 	};
13238 	static const uint16_t gain[] = {
13239 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13240 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13241 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13242 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13243 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13244 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13245 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13246 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13247 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13248 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13249 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13250 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13251 	};
13252 	static const uint32_t papdeps[] = {
13253 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13254 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13255 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13256 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13257 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13258 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13259 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13260 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13261 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13262 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13263 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13264 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13265 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13266 	};
13267 	static const uint32_t papdmult[] = {
13268 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13269 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13270 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13271 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13272 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13273 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13274 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13275 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13276 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13277 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13278 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13279 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13280 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13281 	};
13282 	static const uint32_t gainidx_a0[] = {
13283 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13284 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13285 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13286 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13287 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13288 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13289 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13290 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13291 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13292 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13293 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13294 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13295 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13296 	};
13297 	static const uint16_t auxgainidx_a0[] = {
13298 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13299 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13300 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13301 		0x0002, 0x0014
13302 	};
13303 	static const uint32_t gainval_a0[] = {
13304 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13305 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13306 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13307 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13308 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13309 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13310 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13311 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13312 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13313 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13314 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13315 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13316 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13317 		0x000000f7, 0x00000000, 0x00000000
13318 	};
13319 	static const uint16_t gain_a0[] = {
13320 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13321 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13322 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13323 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13324 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13325 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13326 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13327 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13328 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13329 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13330 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13331 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13332 	};
13333 
13334 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13335 
13336 	for (i = 0; i < 704; i++)
13337 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13338 
13339 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13340 	    bwn_tab_sigsq_tbl);
13341 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13342 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13343 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13344 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13345 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13346 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13347 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13348 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13349 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13350 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13351 	    bwn_tab_pllfrac_tbl);
13352 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13353 	    bwn_tabl_iqlocal_tbl);
13354 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13355 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13356 
13357 	if ((siba->siba_chipid == 0x4325) && (siba->siba_chiprev == 0)) {
13358 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13359 		    gainidx_a0);
13360 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13361 		    auxgainidx_a0);
13362 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13363 		    gainval_a0);
13364 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13365 	}
13366 }
13367 
13368 static void
13369 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13370 {
13371 	struct siba_dev_softc *sd = mac->mac_sd;
13372 	struct siba_softc *siba = sd->sd_bus;
13373 	struct bwn_softc *sc = mac->mac_sc;
13374 	struct ifnet *ifp = sc->sc_ifp;
13375 	struct ieee80211com *ic = ifp->if_l2com;
13376 	static struct bwn_txgain_entry txgain_r2[] = {
13377 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13378 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13379 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13380 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13381 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13382 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13383 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13384 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13385 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13386 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13387 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13388 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13389 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13390 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13391 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13392 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13393 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13394 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13395 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13396 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13397 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13398 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13399 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13400 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13401 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13402 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13403 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13404 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13405 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13406 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13407 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13408 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13409 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13410 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13411 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13412 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13413 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13414 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13415 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13416 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13417 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13418 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13419 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13420 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13421 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13422 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13423 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13424 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13425 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13426 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13427 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13428 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13429 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13430 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13431 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13432 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13433 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13434 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13435 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13436 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13437 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13438 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13439 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13440 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13441 	};
13442 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13443 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13444 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13445 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13446 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13447 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13448 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13449 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13450 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13451 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13452 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13453 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13454 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13455 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13456 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13457 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13458 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13459 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13460 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13461 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13462 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13463 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13464 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13465 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13466 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13467 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13468 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13469 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13470 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13471 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13472 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13473 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13474 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13475 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13476 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13477 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13478 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13479 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13480 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13481 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13482 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13483 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13484 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13485 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13486 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13487 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13488 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13489 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13490 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13491 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13492 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13493 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13494 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13495 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13496 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13497 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13498 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13499 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13500 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13501 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13502 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13503 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13504 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13505 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13506 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13507 	};
13508 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13509 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13510 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13511 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13512 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13513 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13514 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13515 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13516 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13517 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13518 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13519 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13520 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13521 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13522 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13523 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13524 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13525 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13526 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13527 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13528 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13529 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13530 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13531 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13532 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13533 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13534 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13535 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13536 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13537 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13538 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13539 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13540 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13541 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13542 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13543 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13544 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13545 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13546 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13547 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13548 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13549 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13550 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13551 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13552 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13553 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13554 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13555 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13556 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13557 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13558 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13559 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13560 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13561 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13562 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13563 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13564 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13565 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13566 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13567 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13568 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13569 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13570 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13571 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13572 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13573 	};
13574 	static struct bwn_txgain_entry txgain_r0[] = {
13575 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13576 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13577 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13578 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13579 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13580 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13581 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13582 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13583 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13584 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13585 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13586 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13587 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13588 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13589 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13590 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13591 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13592 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13593 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13594 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13595 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13596 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13597 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13598 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13599 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13600 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13601 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13602 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13603 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13604 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13605 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13606 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13607 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13608 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13609 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13610 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13611 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13612 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13613 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13614 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13615 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13616 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13617 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13618 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13619 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13620 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13621 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13622 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13623 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13624 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13625 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13626 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13627 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13628 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13629 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13630 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13631 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13632 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13633 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13634 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13635 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13636 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13637 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13638 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13639 	};
13640 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13641 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13642 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13643 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13644 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13645 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13646 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13647 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13648 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13649 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13650 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13651 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13652 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13653 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13654 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13655 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13656 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13657 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13658 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13659 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13660 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13661 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13662 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13663 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13664 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13665 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13666 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13667 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13668 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13669 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13670 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13671 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13672 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13673 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13674 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13675 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13676 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13677 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13678 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13679 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13680 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13681 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13682 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13683 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13684 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13685 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13686 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13687 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13688 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13689 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13690 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13691 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13692 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13693 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13694 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13695 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13696 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13697 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13698 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13699 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13700 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13701 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13702 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13703 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13704 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13705 	};
13706 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13707 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13708 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13709 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13710 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13711 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13712 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13713 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13714 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13715 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13716 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13717 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13718 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13719 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13720 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13721 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13722 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13723 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13724 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13725 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13726 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13727 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13728 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13729 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13730 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13731 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13732 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13733 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13734 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13735 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13736 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13737 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13738 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13739 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13740 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13741 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13742 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13743 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13744 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13745 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13746 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13747 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13748 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13749 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13750 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13751 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13752 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13753 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13754 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13755 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13756 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13757 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13758 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13759 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13760 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13761 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13762 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13763 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13764 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13765 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13766 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13767 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13768 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13769 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13770 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13771 	};
13772 	static struct bwn_txgain_entry txgain_r1[] = {
13773 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13774 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13775 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13776 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13777 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13778 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13779 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13780 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13781 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13782 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13783 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13784 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13785 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13786 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13787 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13788 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13789 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13790 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13791 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13792 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13793 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13794 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13795 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13796 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13797 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13798 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13799 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13800 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13801 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13802 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13803 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13804 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13805 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13806 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13807 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13808 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13809 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13810 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13811 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13812 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13813 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13814 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13815 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13816 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13817 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13818 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13819 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13820 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13821 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13822 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13823 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13824 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13825 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13826 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13827 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13828 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13829 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13830 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13831 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13832 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13833 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13834 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13835 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13836 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13837 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13838 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13839 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13840 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13841 		{ 7, 11, 6, 0, 71 }
13842 	};
13843 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13844 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13845 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13846 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13847 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13848 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13849 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13850 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13851 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13852 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13853 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13854 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13855 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13856 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13857 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13858 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13859 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13860 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13861 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13862 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13863 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13864 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13865 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13866 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13867 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13868 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13869 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13870 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13871 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13872 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13873 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13874 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13875 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13876 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13877 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13878 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13879 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13880 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13881 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13882 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13883 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13884 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13885 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13886 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13887 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13888 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13889 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13890 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13891 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13892 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13893 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13894 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13895 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13896 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13897 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13898 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13899 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13900 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13901 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13902 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13903 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13904 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13905 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13906 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13907 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13908 	};
13909 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13910 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13911 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13912 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13913 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13914 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13915 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13916 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13917 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13918 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13919 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13920 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13921 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13922 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13923 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13924 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13925 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13926 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13927 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13928 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13929 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13930 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13931 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13932 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13933 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13934 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13935 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13936 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13937 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13938 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13939 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13940 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13941 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13942 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13943 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13944 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13945 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13946 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13947 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13948 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13949 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13950 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13951 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13952 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13953 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13954 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13955 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13956 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13957 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13958 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13959 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13960 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13961 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13962 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13963 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13964 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13965 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13966 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13967 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13968 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13969 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13970 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13971 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13972 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13973 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13974 	};
13975 
13976 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13977 		if (siba->siba_sprom.bf_hi & BWN_BFH_NOPA)
13978 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13979 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13980 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13981 			    txgain_2ghz_r2);
13982 		else
13983 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13984 			    txgain_5ghz_r2);
13985 		return;
13986 	}
13987 
13988 	if (mac->mac_phy.rev == 0) {
13989 		if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
13990 		    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
13991 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13992 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13993 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13994 			    txgain_2ghz_r0);
13995 		else
13996 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13997 			    txgain_5ghz_r0);
13998 		return;
13999 	}
14000 
14001 	if ((siba->siba_sprom.bf_hi & BWN_BFH_NOPA) ||
14002 	    (siba->siba_sprom.bf_lo & BWN_BFL_HGPA))
14003 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
14004 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
14005 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
14006 	else
14007 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
14008 }
14009 
14010 static void
14011 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
14012 {
14013 	uint32_t offset, type;
14014 
14015 	type = BWN_TAB_GETTYPE(typeoffset);
14016 	offset = BWN_TAB_GETOFFSET(typeoffset);
14017 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14018 
14019 	switch (type) {
14020 	case BWN_TAB_8BIT:
14021 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
14022 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14023 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14024 		break;
14025 	case BWN_TAB_16BIT:
14026 		KASSERT(!(value & ~0xffff),
14027 		    ("%s:%d: fail", __func__, __LINE__));
14028 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14029 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14030 		break;
14031 	case BWN_TAB_32BIT:
14032 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14033 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
14034 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
14035 		break;
14036 	default:
14037 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14038 	}
14039 }
14040 
14041 static int
14042 bwn_phy_lp_loopback(struct bwn_mac *mac)
14043 {
14044 	struct bwn_phy_lp_iq_est ie;
14045 	int i, index = -1;
14046 	uint32_t tmp;
14047 
14048 	memset(&ie, 0, sizeof(ie));
14049 
14050 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
14051 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
14052 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
14053 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
14054 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
14055 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
14056 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
14057 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
14058 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
14059 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
14060 	for (i = 0; i < 32; i++) {
14061 		bwn_phy_lp_set_rxgain_idx(mac, i);
14062 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
14063 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
14064 			continue;
14065 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
14066 		if ((tmp > 4000) && (tmp < 10000)) {
14067 			index = i;
14068 			break;
14069 		}
14070 	}
14071 	bwn_phy_lp_ddfs_turnoff(mac);
14072 	return (index);
14073 }
14074 
14075 static void
14076 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
14077 {
14078 
14079 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
14080 }
14081 
14082 static void
14083 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
14084     int incr1, int incr2, int scale_idx)
14085 {
14086 
14087 	bwn_phy_lp_ddfs_turnoff(mac);
14088 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
14089 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
14090 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
14091 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14092 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14093 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14094 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14095 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14096 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14097 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14098 }
14099 
14100 static uint8_t
14101 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14102     struct bwn_phy_lp_iq_est *ie)
14103 {
14104 	int i;
14105 
14106 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14107 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14108 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14109 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14110 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14111 
14112 	for (i = 0; i < 500; i++) {
14113 		if (!(BWN_PHY_READ(mac,
14114 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14115 			break;
14116 		DELAY(1000);
14117 	}
14118 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14119 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14120 		return 0;
14121 	}
14122 
14123 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14124 	ie->ie_iqprod <<= 16;
14125 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14126 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14127 	ie->ie_ipwr <<= 16;
14128 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14129 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14130 	ie->ie_qpwr <<= 16;
14131 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14132 
14133 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14134 	return 1;
14135 }
14136 
14137 static uint32_t
14138 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14139 {
14140 	uint32_t offset, type, value;
14141 
14142 	type = BWN_TAB_GETTYPE(typeoffset);
14143 	offset = BWN_TAB_GETOFFSET(typeoffset);
14144 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14145 
14146 	switch (type) {
14147 	case BWN_TAB_8BIT:
14148 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14149 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14150 		break;
14151 	case BWN_TAB_16BIT:
14152 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14153 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14154 		break;
14155 	case BWN_TAB_32BIT:
14156 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14157 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14158 		value <<= 16;
14159 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14160 		break;
14161 	default:
14162 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14163 		value = 0;
14164 	}
14165 
14166 	return (value);
14167 }
14168 
14169 static void
14170 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14171 {
14172 
14173 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14174 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14175 }
14176 
14177 static void
14178 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14179 {
14180 	uint16_t ctl;
14181 
14182 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14183 	ctl |= dac << 7;
14184 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14185 }
14186 
14187 static void
14188 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14189 {
14190 
14191 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14192 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14193 }
14194 
14195 static void
14196 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14197 {
14198 
14199 	if (mac->mac_phy.rev < 2)
14200 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14201 	else {
14202 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14203 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14204 	}
14205 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14206 }
14207 
14208 static uint16_t
14209 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14210 {
14211 
14212 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14213 }
14214 
14215 static uint8_t
14216 bwn_nbits(int32_t val)
14217 {
14218 	uint32_t tmp;
14219 	uint8_t nbits = 0;
14220 
14221 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14222 		nbits++;
14223 	return (nbits);
14224 }
14225 
14226 static void
14227 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14228     struct bwn_txgain_entry *table)
14229 {
14230 	int i;
14231 
14232 	for (i = offset; i < count; i++)
14233 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14234 }
14235 
14236 static void
14237 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14238     struct bwn_txgain_entry data)
14239 {
14240 
14241 	if (mac->mac_phy.rev >= 2)
14242 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14243 	else
14244 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14245 }
14246 
14247 static void
14248 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14249     struct bwn_txgain_entry te)
14250 {
14251 	struct bwn_softc *sc = mac->mac_sc;
14252 	struct ifnet *ifp = sc->sc_ifp;
14253 	struct ieee80211com *ic = ifp->if_l2com;
14254 	uint32_t tmp;
14255 
14256 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14257 
14258 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14259 	if (mac->mac_phy.rev >= 3) {
14260 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14261 		    (0x10 << 24) : (0x70 << 24));
14262 	} else {
14263 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14264 		    (0x14 << 24) : (0x7f << 24));
14265 	}
14266 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14267 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14268 	    te.te_bbmult << 20 | te.te_dac << 28);
14269 }
14270 
14271 static void
14272 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14273     struct bwn_txgain_entry te)
14274 {
14275 
14276 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14277 
14278 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14279 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14280 	    te.te_dac);
14281 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14282 }
14283 
14284 static void
14285 bwn_sysctl_node(struct bwn_softc *sc)
14286 {
14287 	device_t dev = sc->sc_dev;
14288 	struct bwn_mac *mac;
14289 	struct bwn_stats *stats;
14290 
14291 	/* XXX assume that count of MAC is only 1. */
14292 
14293 	if ((mac = sc->sc_curmac) == NULL)
14294 		return;
14295 	stats = &mac->mac_stats;
14296 
14297 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14298 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14299 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14300 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14301 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14302 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14303 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14304 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14305 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14306 
14307 #ifdef BWN_DEBUG
14308 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14309 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14310 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14311 #endif
14312 }
14313 
14314 static void
14315 bwn_identify(driver_t *driver, device_t parent)
14316 {
14317 
14318 	BUS_ADD_CHILD(parent, 0, "bwn", -1);
14319 }
14320 
14321 static device_method_t bwn_methods[] = {
14322 	/* Device interface */
14323 	DEVMETHOD(device_identify,	bwn_identify),
14324 	DEVMETHOD(device_probe,		bwn_probe),
14325 	DEVMETHOD(device_attach,	bwn_attach),
14326 	DEVMETHOD(device_detach,	bwn_detach),
14327 	DEVMETHOD(device_suspend,	bwn_suspend),
14328 	DEVMETHOD(device_resume,	bwn_resume),
14329 	{ 0,0 }
14330 };
14331 static driver_t bwn_driver = {
14332 	"bwn",
14333 	bwn_methods,
14334 	sizeof(struct bwn_softc)
14335 };
14336 static devclass_t bwn_devclass;
14337 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14338 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14339 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14340 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14341 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14342