xref: /dragonfly/sys/dev/netif/bwn/bwn/if_bwn.c (revision db299a73)
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: head/sys/dev/bwn/if_bwn.c 260444 2014-01-08 08:06:56Z kevlo $");
32 
33 /*
34  * The Broadcom Wireless LAN controller driver.
35  */
36 
37 #include <opt_wlan.h>
38 #include <opt_bwn.h>
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/module.h>
43 #include <sys/kernel.h>
44 #include <sys/endian.h>
45 #include <sys/errno.h>
46 #include <sys/firmware.h>
47 #include <sys/bus_resource.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_var.h>
56 #include <net/if_arp.h>
57 #include <net/if_dl.h>
58 #include <net/if_llc.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/ifq_var.h>
62 
63 #include <bus/pci/pcivar.h>
64 #include <bus/pci/pcireg.h>
65 #include <dev/netif/bwn/siba/siba_ids.h>
66 #include <dev/netif/bwn/siba/sibareg.h>
67 #include <dev/netif/bwn/siba/sibavar.h>
68 
69 #include <netproto/802_11/ieee80211_var.h>
70 #include <netproto/802_11/ieee80211_radiotap.h>
71 #include <netproto/802_11/ieee80211_regdomain.h>
72 #include <netproto/802_11/ieee80211_phy.h>
73 #include <netproto/802_11/ieee80211_ratectl.h>
74 
75 #include "if_bwnreg.h"
76 #include "if_bwnvar.h"
77 
78 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
79     "Broadcom driver parameters");
80 
81 /*
82  * Tunable & sysctl variables.
83  */
84 
85 #ifdef BWN_DEBUG
86 static	int bwn_debug = 0;
87 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
88     "Broadcom debugging printfs");
89 TUNABLE_INT("hw.bwn.debug", &bwn_debug);
90 enum {
91 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
92 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
93 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
94 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
95 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
96 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
97 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
98 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
99 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
100 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
101 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
102 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
103 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
104 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
105 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
106 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
107 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
108 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
109 	BWN_DEBUG_ANY		= 0xffffffff
110 };
111 #define	DPRINTF(sc, m, fmt, ...) do {			\
112 	if (sc->sc_debug & (m))				\
113 		kprintf(fmt, __VA_ARGS__);		\
114 } while (0)
115 #else
116 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
117 #endif
118 
119 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
120 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
121     "uses Bad Frames Preemption");
122 static int	bwn_bluetooth = 1;
123 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
124     "turns on Bluetooth Coexistence");
125 static int	bwn_hwpctl = 0;
126 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
127     "uses H/W power control");
128 static int      bwn_msi_enable = 1;
129 TUNABLE_INT("hw.bwn.msi.enable", &bwn_msi_enable);
130 static int	bwn_usedma = 1;
131 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
132     "uses DMA");
133 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
134 static int	bwn_wme = 1;
135 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
136     "uses WME support");
137 
138 static int	bwn_attach_pre(struct bwn_softc *);
139 static int	bwn_attach_post(struct bwn_softc *);
140 static void	bwn_sprom_bugfixes(device_t);
141 static void	bwn_init(void *);
142 static int	bwn_init_locked(struct bwn_softc *);
143 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
144 static void	bwn_start(struct ifnet *, struct ifaltq_subque *);
145 static int	bwn_attach_core(struct bwn_mac *);
146 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
147 static int	bwn_phy_getinfo(struct bwn_mac *, int);
148 static int	bwn_chiptest(struct bwn_mac *);
149 static int	bwn_setup_channels(struct bwn_mac *, int, int);
150 static int	bwn_phy_g_attach(struct bwn_mac *);
151 static void	bwn_phy_g_detach(struct bwn_mac *);
152 static void	bwn_phy_g_init_pre(struct bwn_mac *);
153 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
154 static int	bwn_phy_g_init(struct bwn_mac *);
155 static void	bwn_phy_g_exit(struct bwn_mac *);
156 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
157 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
158 		    uint16_t);
159 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
160 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
161 		    uint16_t);
162 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
163 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
164 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
165 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
166 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
167 static int	bwn_phy_g_im(struct bwn_mac *, int);
168 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
169 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
170 static void	bwn_phy_g_task_15s(struct bwn_mac *);
171 static void	bwn_phy_g_task_60s(struct bwn_mac *);
172 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
173 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
174 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
175 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
176 		    uint16_t);
177 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
178 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
179 		    uint32_t);
180 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
181 		    uint16_t);
182 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
183 		    const struct bwn_channelinfo *, int);
184 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
185 		    const struct ieee80211_bpf_params *);
186 static void	bwn_updateslot(struct ifnet *);
187 static void	bwn_update_promisc(struct ifnet *);
188 static void	bwn_wme_init(struct bwn_mac *);
189 static int	bwn_wme_update(struct ieee80211com *);
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_scan_start(struct ieee80211com *);
195 static void	bwn_scan_end(struct ieee80211com *);
196 static void	bwn_set_channel(struct ieee80211com *);
197 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
198 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
199 		    const uint8_t [IEEE80211_ADDR_LEN],
200 		    const uint8_t [IEEE80211_ADDR_LEN]);
201 static void	bwn_vap_delete(struct ieee80211vap *);
202 static void	bwn_stop(struct bwn_softc *, int);
203 static void	bwn_stop_locked(struct bwn_softc *, int);
204 static int	bwn_core_init(struct bwn_mac *);
205 static void	bwn_core_start(struct bwn_mac *);
206 static void	bwn_core_exit(struct bwn_mac *);
207 static void	bwn_bt_disable(struct bwn_mac *);
208 static int	bwn_chip_init(struct bwn_mac *);
209 static uint64_t	bwn_hf_read(struct bwn_mac *);
210 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
211 static void	bwn_set_txretry(struct bwn_mac *, int, int);
212 static void	bwn_rate_init(struct bwn_mac *);
213 static void	bwn_set_phytxctl(struct bwn_mac *);
214 static void	bwn_spu_setdelay(struct bwn_mac *, int);
215 static void	bwn_bt_enable(struct bwn_mac *);
216 static void	bwn_set_macaddr(struct bwn_mac *);
217 static void	bwn_crypt_init(struct bwn_mac *);
218 static void	bwn_chip_exit(struct bwn_mac *);
219 static int	bwn_fw_fillinfo(struct bwn_mac *);
220 static int	bwn_fw_loaducode(struct bwn_mac *);
221 static int	bwn_gpio_init(struct bwn_mac *);
222 static int	bwn_fw_loadinitvals(struct bwn_mac *);
223 static int	bwn_phy_init(struct bwn_mac *);
224 static void	bwn_set_txantenna(struct bwn_mac *, int);
225 static void	bwn_set_opmode(struct bwn_mac *);
226 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
227 static uint8_t	bwn_plcp_getcck(const uint8_t);
228 static uint8_t	bwn_plcp_getofdm(const uint8_t);
229 static void	bwn_pio_init(struct bwn_mac *);
230 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
231 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
232 		    int);
233 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
234 		    struct bwn_pio_rxqueue *, int);
235 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
236 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
237 		    uint16_t);
238 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
239 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
240 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
241 static void	bwn_pio_handle_txeof(struct bwn_mac *,
242 		    const struct bwn_txstatus *);
243 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
244 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
245 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
246 		    uint16_t);
247 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
248 		    uint32_t);
249 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
250 		    struct mbuf *);
251 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
252 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
253 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
254 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
255 		    uint16_t, uint32_t);
256 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
257 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
258 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
259 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
260 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
261 		    uint16_t, struct bwn_pio_txpkt **);
262 static void	bwn_dma_init(struct bwn_mac *);
263 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
264 static int	bwn_dma_mask2type(uint64_t);
265 static uint64_t	bwn_dma_mask(struct bwn_mac *);
266 static uint16_t	bwn_dma_base(int, int);
267 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
268 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
269 		    int, struct bwn_dmadesc_generic **,
270 		    struct bwn_dmadesc_meta **);
271 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
272 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
273 		    int, int);
274 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
275 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
276 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
277 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
278 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
279 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
280 		    int, struct bwn_dmadesc_generic **,
281 		    struct bwn_dmadesc_meta **);
282 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
283 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
284 		    int, int);
285 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
286 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
287 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
288 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
289 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
290 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
291 static void	bwn_dma_setup(struct bwn_dma_ring *);
292 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
293 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
294 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
295 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
296 static void	bwn_dma_rx_handle_overflow(struct bwn_dma_ring *);
297 static void	bwn_dma_rx(struct bwn_dma_ring *);
298 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
299 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
300 		    struct bwn_dmadesc_meta *);
301 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
302 static int	bwn_dma_gettype(struct bwn_mac *);
303 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
304 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
305 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
306 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
307 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
308 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
309 		    int);
310 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
311 		    bus_size_t, int);
312 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
313 static void	bwn_dma_handle_txeof(struct bwn_mac *,
314 		    const struct bwn_txstatus *);
315 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
316 		    struct mbuf *);
317 static int	bwn_dma_getslot(struct bwn_dma_ring *);
318 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
319 		    uint8_t);
320 static int	bwn_dma_attach(struct bwn_mac *);
321 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
322 		    int, int, int);
323 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
324 		    const struct bwn_txstatus *, uint16_t, int *);
325 static void	bwn_dma_free(struct bwn_mac *);
326 static void	bwn_phy_g_init_sub(struct bwn_mac *);
327 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
328 static void	bwn_phy_init_b5(struct bwn_mac *);
329 static void	bwn_phy_init_b6(struct bwn_mac *);
330 static void	bwn_phy_init_a(struct bwn_mac *);
331 static void	bwn_loopback_calcgain(struct bwn_mac *);
332 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
333 static void	bwn_lo_g_init(struct bwn_mac *);
334 static void	bwn_lo_g_adjust(struct bwn_mac *);
335 static void	bwn_lo_get_powervector(struct bwn_mac *);
336 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
337 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
338 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
339 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
340 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
341 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
342 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
343 		    uint8_t);
344 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
345 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
346 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
347 static void	bwn_wa_init(struct bwn_mac *);
348 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
349 		    uint16_t);
350 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
351 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
352 		    uint32_t);
353 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
354 		    uint16_t);
355 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
356 static void	bwn_mac_suspend(struct bwn_mac *);
357 static void	bwn_mac_enable(struct bwn_mac *);
358 static void	bwn_psctl(struct bwn_mac *, uint32_t);
359 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
360 static void	bwn_nrssi_offset(struct bwn_mac *);
361 static void	bwn_nrssi_threshold(struct bwn_mac *);
362 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
363 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
364 		    int16_t);
365 static void	bwn_set_original_gains(struct bwn_mac *);
366 static void	bwn_hwpctl_early_init(struct bwn_mac *);
367 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
368 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
369 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
370 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
371 		    const char *, struct bwn_fwfile *);
372 static void	bwn_release_firmware(struct bwn_mac *);
373 static void	bwn_do_release_fw(struct bwn_fwfile *);
374 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
375 static int	bwn_fwinitvals_write(struct bwn_mac *,
376 		    const struct bwn_fwinitvals *, size_t, size_t);
377 static int	bwn_switch_channel(struct bwn_mac *, int);
378 static uint16_t	bwn_ant2phy(int);
379 static void	bwn_mac_write_bssid(struct bwn_mac *);
380 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
381 		    const uint8_t *);
382 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
383 		    const uint8_t *, size_t, const uint8_t *);
384 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
385 		    const uint8_t *);
386 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
387 		    const uint8_t *);
388 static void	bwn_phy_exit(struct bwn_mac *);
389 static void	bwn_core_stop(struct bwn_mac *);
390 static int	bwn_switch_band(struct bwn_softc *,
391 		    struct ieee80211_channel *);
392 static void	bwn_phy_reset(struct bwn_mac *);
393 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
394 static void	bwn_set_pretbtt(struct bwn_mac *);
395 static void	bwn_intr(void *);
396 static void	bwn_intrtask(void *, int);
397 static void	bwn_restart(struct bwn_mac *, const char *);
398 static void	bwn_intr_ucode_debug(struct bwn_mac *);
399 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
400 static void	bwn_intr_atim_end(struct bwn_mac *);
401 static void	bwn_intr_beacon(struct bwn_mac *);
402 static void	bwn_intr_pmq(struct bwn_mac *);
403 static void	bwn_intr_noise(struct bwn_mac *);
404 static void	bwn_intr_txeof(struct bwn_mac *);
405 static void	bwn_hwreset(void *, int);
406 static void	bwn_handle_fwpanic(struct bwn_mac *);
407 static void	bwn_load_beacon0(struct bwn_mac *);
408 static void	bwn_load_beacon1(struct bwn_mac *);
409 static uint32_t	bwn_jssi_read(struct bwn_mac *);
410 static void	bwn_noise_gensample(struct bwn_mac *);
411 static void	bwn_handle_txeof(struct bwn_mac *,
412 		    const struct bwn_txstatus *);
413 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
414 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
415 static void	bwn_start_locked(struct ifnet *);
416 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
417 		    struct mbuf *);
418 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
419 static int	bwn_set_txhdr(struct bwn_mac *,
420 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
421 		    uint16_t);
422 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
423 		    const uint8_t);
424 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
425 static uint8_t	bwn_get_fbrate(uint8_t);
426 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
427 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
428 static void	bwn_phy_lock(struct bwn_mac *);
429 static void	bwn_phy_unlock(struct bwn_mac *);
430 static void	bwn_rf_lock(struct bwn_mac *);
431 static void	bwn_rf_unlock(struct bwn_mac *);
432 static void	bwn_txpwr(void *, int);
433 static void	bwn_tasks(void *);
434 static void	bwn_task_15s(struct bwn_mac *);
435 static void	bwn_task_30s(struct bwn_mac *);
436 static void	bwn_task_60s(struct bwn_mac *);
437 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
438 		    uint8_t);
439 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
440 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
441 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
442 		    int, int);
443 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
444 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
445 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
446 static void	bwn_watchdog(void *);
447 static void	bwn_dma_stop(struct bwn_mac *);
448 static void	bwn_pio_stop(struct bwn_mac *);
449 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
450 static void	bwn_led_attach(struct bwn_mac *);
451 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
452 static void	bwn_led_event(struct bwn_mac *, int);
453 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
454 static void	bwn_led_blink_next(void *);
455 static void	bwn_led_blink_end(void *);
456 static void	bwn_rfswitch(void *);
457 static void	bwn_rf_turnon(struct bwn_mac *);
458 static void	bwn_rf_turnoff(struct bwn_mac *);
459 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
460 static int	bwn_phy_lp_init(struct bwn_mac *);
461 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
462 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
463 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
464 		    uint16_t);
465 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
466 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
467 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
468 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
469 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
470 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
471 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
472 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
473 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
474 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
475 static void	bwn_phy_lp_calib(struct bwn_mac *);
476 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
477 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
478 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
479 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
480 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
481 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
482 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
483 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
484 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
485 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
486 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
487 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
488 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
489 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
490 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
491 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
492 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
493 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
494 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
495 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
496 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
497 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
498 		    const void *);
499 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
500 static struct bwn_txgain
501 		bwn_phy_lp_get_txgain(struct bwn_mac *);
502 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
503 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
504 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
505 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
506 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
507 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
508 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
509 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
510 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
511 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
512 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
513 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
514 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
515 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
516 static int	bwn_phy_lp_loopback(struct bwn_mac *);
517 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
518 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
519 		    int);
520 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
521 		    struct bwn_phy_lp_iq_est *);
522 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
523 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
524 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
525 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
526 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
527 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
528 static uint8_t	bwn_nbits(int32_t);
529 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
530 		    struct bwn_txgain_entry *);
531 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
532 		    struct bwn_txgain_entry);
533 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
534 		    struct bwn_txgain_entry);
535 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
536 		    struct bwn_txgain_entry);
537 static void	bwn_sysctl_node(struct bwn_softc *);
538 
539 static const struct bwn_channelinfo bwn_chantable_bg = {
540 	.channels = {
541 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
542 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
543 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
544 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
545 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
546 	.nchannels = 14
547 };
548 
549 static const struct bwn_channelinfo bwn_chantable_a = {
550 	.channels = {
551 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
552 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
553 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
554 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
555 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
556 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
557 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
558 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
559 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
560 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
561 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
562 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
563 		{ 6080, 216, 30 } },
564 	.nchannels = 37
565 };
566 
567 static const struct bwn_channelinfo bwn_chantable_n = {
568 	.channels = {
569 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
570 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
571 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
572 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
573 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
574 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
575 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
576 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
577 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
578 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
579 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
580 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
581 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
582 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
583 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
584 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
585 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
586 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
587 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
588 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
589 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
590 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
591 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
592 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
593 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
594 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
595 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
596 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
597 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
598 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
599 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
600 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
601 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
602 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
603 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
604 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
605 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
606 	.nchannels = 110
607 };
608 
609 static const uint8_t bwn_b2063_chantable_data[33][12] = {
610 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
611 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
612 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
613 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
614 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
615 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
616 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
617 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
618 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
619 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
620 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
621 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
622 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
623 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
624 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
625 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
626 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
627 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
628 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
629 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
630 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
631 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
632 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
633 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
634 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
635 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
636 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
637 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
638 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
639 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
640 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
641 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
642 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
643 };
644 
645 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
646 	{ 1, 2412, bwn_b2063_chantable_data[0] },
647 	{ 2, 2417, bwn_b2063_chantable_data[0] },
648 	{ 3, 2422, bwn_b2063_chantable_data[0] },
649 	{ 4, 2427, bwn_b2063_chantable_data[1] },
650 	{ 5, 2432, bwn_b2063_chantable_data[1] },
651 	{ 6, 2437, bwn_b2063_chantable_data[1] },
652 	{ 7, 2442, bwn_b2063_chantable_data[1] },
653 	{ 8, 2447, bwn_b2063_chantable_data[1] },
654 	{ 9, 2452, bwn_b2063_chantable_data[2] },
655 	{ 10, 2457, bwn_b2063_chantable_data[2] },
656 	{ 11, 2462, bwn_b2063_chantable_data[3] },
657 	{ 12, 2467, bwn_b2063_chantable_data[3] },
658 	{ 13, 2472, bwn_b2063_chantable_data[3] },
659 	{ 14, 2484, bwn_b2063_chantable_data[4] },
660 	{ 34, 5170, bwn_b2063_chantable_data[5] },
661 	{ 36, 5180, bwn_b2063_chantable_data[6] },
662 	{ 38, 5190, bwn_b2063_chantable_data[7] },
663 	{ 40, 5200, bwn_b2063_chantable_data[8] },
664 	{ 42, 5210, bwn_b2063_chantable_data[9] },
665 	{ 44, 5220, bwn_b2063_chantable_data[10] },
666 	{ 46, 5230, bwn_b2063_chantable_data[11] },
667 	{ 48, 5240, bwn_b2063_chantable_data[12] },
668 	{ 52, 5260, bwn_b2063_chantable_data[13] },
669 	{ 56, 5280, bwn_b2063_chantable_data[14] },
670 	{ 60, 5300, bwn_b2063_chantable_data[14] },
671 	{ 64, 5320, bwn_b2063_chantable_data[15] },
672 	{ 100, 5500, bwn_b2063_chantable_data[16] },
673 	{ 104, 5520, bwn_b2063_chantable_data[17] },
674 	{ 108, 5540, bwn_b2063_chantable_data[18] },
675 	{ 112, 5560, bwn_b2063_chantable_data[19] },
676 	{ 116, 5580, bwn_b2063_chantable_data[20] },
677 	{ 120, 5600, bwn_b2063_chantable_data[21] },
678 	{ 124, 5620, bwn_b2063_chantable_data[21] },
679 	{ 128, 5640, bwn_b2063_chantable_data[22] },
680 	{ 132, 5660, bwn_b2063_chantable_data[22] },
681 	{ 136, 5680, bwn_b2063_chantable_data[22] },
682 	{ 140, 5700, bwn_b2063_chantable_data[23] },
683 	{ 149, 5745, bwn_b2063_chantable_data[23] },
684 	{ 153, 5765, bwn_b2063_chantable_data[23] },
685 	{ 157, 5785, bwn_b2063_chantable_data[23] },
686 	{ 161, 5805, bwn_b2063_chantable_data[23] },
687 	{ 165, 5825, bwn_b2063_chantable_data[23] },
688 	{ 184, 4920, bwn_b2063_chantable_data[24] },
689 	{ 188, 4940, bwn_b2063_chantable_data[25] },
690 	{ 192, 4960, bwn_b2063_chantable_data[26] },
691 	{ 196, 4980, bwn_b2063_chantable_data[27] },
692 	{ 200, 5000, bwn_b2063_chantable_data[28] },
693 	{ 204, 5020, bwn_b2063_chantable_data[29] },
694 	{ 208, 5040, bwn_b2063_chantable_data[30] },
695 	{ 212, 5060, bwn_b2063_chantable_data[31] },
696 	{ 216, 5080, bwn_b2063_chantable_data[32] }
697 };
698 
699 static const uint8_t bwn_b2062_chantable_data[22][12] = {
700 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
701 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
702 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
703 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
704 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
705 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
706 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
707 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
710 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
711 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
712 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
713 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
714 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
715 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
716 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
717 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
718 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
719 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
721 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
722 };
723 
724 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
725 	{ 1, 2412, bwn_b2062_chantable_data[0] },
726 	{ 2, 2417, bwn_b2062_chantable_data[0] },
727 	{ 3, 2422, bwn_b2062_chantable_data[0] },
728 	{ 4, 2427, bwn_b2062_chantable_data[0] },
729 	{ 5, 2432, bwn_b2062_chantable_data[0] },
730 	{ 6, 2437, bwn_b2062_chantable_data[0] },
731 	{ 7, 2442, bwn_b2062_chantable_data[0] },
732 	{ 8, 2447, bwn_b2062_chantable_data[0] },
733 	{ 9, 2452, bwn_b2062_chantable_data[0] },
734 	{ 10, 2457, bwn_b2062_chantable_data[0] },
735 	{ 11, 2462, bwn_b2062_chantable_data[0] },
736 	{ 12, 2467, bwn_b2062_chantable_data[0] },
737 	{ 13, 2472, bwn_b2062_chantable_data[0] },
738 	{ 14, 2484, bwn_b2062_chantable_data[0] },
739 	{ 34, 5170, bwn_b2062_chantable_data[1] },
740 	{ 38, 5190, bwn_b2062_chantable_data[2] },
741 	{ 42, 5210, bwn_b2062_chantable_data[2] },
742 	{ 46, 5230, bwn_b2062_chantable_data[3] },
743 	{ 36, 5180, bwn_b2062_chantable_data[4] },
744 	{ 40, 5200, bwn_b2062_chantable_data[5] },
745 	{ 44, 5220, bwn_b2062_chantable_data[6] },
746 	{ 48, 5240, bwn_b2062_chantable_data[3] },
747 	{ 52, 5260, bwn_b2062_chantable_data[3] },
748 	{ 56, 5280, bwn_b2062_chantable_data[3] },
749 	{ 60, 5300, bwn_b2062_chantable_data[7] },
750 	{ 64, 5320, bwn_b2062_chantable_data[8] },
751 	{ 100, 5500, bwn_b2062_chantable_data[9] },
752 	{ 104, 5520, bwn_b2062_chantable_data[10] },
753 	{ 108, 5540, bwn_b2062_chantable_data[10] },
754 	{ 112, 5560, bwn_b2062_chantable_data[10] },
755 	{ 116, 5580, bwn_b2062_chantable_data[11] },
756 	{ 120, 5600, bwn_b2062_chantable_data[12] },
757 	{ 124, 5620, bwn_b2062_chantable_data[12] },
758 	{ 128, 5640, bwn_b2062_chantable_data[12] },
759 	{ 132, 5660, bwn_b2062_chantable_data[12] },
760 	{ 136, 5680, bwn_b2062_chantable_data[12] },
761 	{ 140, 5700, bwn_b2062_chantable_data[12] },
762 	{ 149, 5745, bwn_b2062_chantable_data[12] },
763 	{ 153, 5765, bwn_b2062_chantable_data[12] },
764 	{ 157, 5785, bwn_b2062_chantable_data[12] },
765 	{ 161, 5805, bwn_b2062_chantable_data[12] },
766 	{ 165, 5825, bwn_b2062_chantable_data[12] },
767 	{ 184, 4920, bwn_b2062_chantable_data[13] },
768 	{ 188, 4940, bwn_b2062_chantable_data[14] },
769 	{ 192, 4960, bwn_b2062_chantable_data[15] },
770 	{ 196, 4980, bwn_b2062_chantable_data[16] },
771 	{ 200, 5000, bwn_b2062_chantable_data[17] },
772 	{ 204, 5020, bwn_b2062_chantable_data[18] },
773 	{ 208, 5040, bwn_b2062_chantable_data[19] },
774 	{ 212, 5060, bwn_b2062_chantable_data[20] },
775 	{ 216, 5080, bwn_b2062_chantable_data[21] }
776 };
777 
778 /* for LP PHY */
779 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
780 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
781 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
782 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
783 	{ 13, -66, 13 }, { 14, -66, 13 },
784 };
785 
786 /* for LP PHY */
787 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
788 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
789 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
790 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
791 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
792 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
793 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
794 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
795 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
796 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
797 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
798 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
799 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
800 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
801 };
802 
803 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
804 
805 static const uint8_t bwn_tab_sigsq_tbl[] = {
806 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
807 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
808 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
809 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
810 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
811 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
812 };
813 
814 static const uint8_t bwn_tab_pllfrac_tbl[] = {
815 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
816 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
817 };
818 
819 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
820 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
821 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
822 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
823 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
824 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
825 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
826 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
827 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
828 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
829 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
830 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
831 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
832 };
833 
834 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
835 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
836 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
837 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
838 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
839 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
840 
841 #define	VENDOR_LED_ACT(vendor)				\
842 {							\
843 	.vid = PCI_VENDOR_##vendor,			\
844 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
845 }
846 
847 static const struct {
848 	uint16_t	vid;
849 	uint8_t		led_act[BWN_LED_MAX];
850 } bwn_vendor_led_act[] = {
851 	VENDOR_LED_ACT(COMPAQ),
852 	VENDOR_LED_ACT(ASUSTEK)
853 };
854 
855 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
856 	{ BWN_VENDOR_LED_ACT_DEFAULT };
857 
858 #undef VENDOR_LED_ACT
859 
860 static const struct {
861 	int		on_dur;
862 	int		off_dur;
863 } bwn_led_duration[109] = {
864 	[0]	= { 400, 100 },
865 	[2]	= { 150, 75 },
866 	[4]	= { 90, 45 },
867 	[11]	= { 66, 34 },
868 	[12]	= { 53, 26 },
869 	[18]	= { 42, 21 },
870 	[22]	= { 35, 17 },
871 	[24]	= { 32, 16 },
872 	[36]	= { 21, 10 },
873 	[48]	= { 16, 8 },
874 	[72]	= { 11, 5 },
875 	[96]	= { 9, 4 },
876 	[108]	= { 7, 3 }
877 };
878 
879 static const uint16_t bwn_wme_shm_offsets[] = {
880 	[0] = BWN_WME_BESTEFFORT,
881 	[1] = BWN_WME_BACKGROUND,
882 	[2] = BWN_WME_VOICE,
883 	[3] = BWN_WME_VIDEO,
884 };
885 
886 static const struct siba_devid bwn_devs[] = {
887 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
888 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
889 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
890 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
891 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
892 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
893 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
894 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
895 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
896 };
897 
898 static int
899 bwn_probe(device_t dev)
900 {
901 	int i;
902 
903 	wlan_serialize_enter();
904 
905 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
906 		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
907 		    siba_get_device(dev) == bwn_devs[i].sd_device &&
908 		    siba_get_revid(dev) == bwn_devs[i].sd_rev) {
909 			wlan_serialize_exit();
910 			return (BUS_PROBE_DEFAULT);
911 		}
912 	}
913 	wlan_serialize_exit();
914 	return (ENXIO);
915 }
916 
917 static int
918 bwn_attach(device_t dev)
919 {
920 	struct bwn_mac *mac;
921 	struct bwn_softc *sc = device_get_softc(dev);
922 	int error;
923 	u_int irq_flags;
924 
925 	wlan_serialize_enter();
926 
927 	sc->sc_dev = dev;
928 #ifdef BWN_DEBUG
929 	sc->sc_debug = bwn_debug;
930 #endif
931 
932 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933 		error = bwn_attach_pre(sc);
934 		if (error != 0) {
935 			wlan_serialize_exit();
936 			return (error);
937 		}
938 		bwn_sprom_bugfixes(dev);
939 		sc->sc_flags |= BWN_FLAG_ATTACHED;
940 	}
941 
942 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
943 		if (siba_get_pci_device(dev) != 0x4313 &&
944 		    siba_get_pci_device(dev) != 0x431a &&
945 		    siba_get_pci_device(dev) != 0x4321) {
946 			device_printf(sc->sc_dev,
947 			    "skip 802.11 cores\n");
948 			wlan_serialize_exit();
949 			return (ENODEV);
950 		}
951 	}
952 
953 	mac = (struct bwn_mac *)kmalloc(sizeof(*mac), M_DEVBUF,
954 	    M_INTWAIT | M_ZERO);
955 	mac->mac_sc = sc;
956 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
957 	if (bwn_bfp != 0)
958 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
959 
960 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
961 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
962 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
963 
964 	error = bwn_attach_core(mac);
965 	if (error)
966 		goto fail0;
967 	bwn_led_attach(mac);
968 
969 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
970 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
971 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
972 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
973 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
974 	    mac->mac_phy.rf_rev);
975 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
976 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
977 		    mac->mac_method.dma.dmatype);
978 	else
979 		device_printf(sc->sc_dev, "PIO\n");
980 
981 	/* Allocate IRQ resource. */
982 	sc->bwn_irq_rid = 0;
983 	sc->bwn_irq_type = pci_alloc_1intr(sc->sc_dev, bwn_msi_enable,
984 	    &sc->bwn_irq_rid, &irq_flags);
985 	if ((sc->bwn_irq = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
986 	    &sc->bwn_irq_rid, irq_flags)) == NULL) {
987 		device_printf(sc->sc_dev, "Cannot allocate interrupt\n");
988 		goto fail1;
989 	}
990 	if (bus_setup_intr(sc->sc_dev, sc->bwn_irq, INTR_MPSAFE,
991 		bwn_intr, mac, &sc->bwn_intr, &wlan_global_serializer)) {
992 		device_printf(sc->sc_dev, "Cannot set up interrupt\n");
993 		return (EINVAL);
994 	}
995 
996 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
997 
998 	/*
999 	 * calls attach-post routine
1000 	 */
1001 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1002 		bwn_attach_post(sc);
1003 
1004 	wlan_serialize_exit();
1005 	return (0);
1006 fail1:
1007 	if (sc->bwn_irq_type == PCI_INTR_TYPE_MSI)
1008 		pci_release_msi(dev);
1009 fail0:
1010 	kfree(mac, M_DEVBUF);
1011 	wlan_serialize_exit();
1012 	return (error);
1013 }
1014 
1015 static int
1016 bwn_is_valid_ether_addr(uint8_t *addr)
1017 {
1018 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1019 
1020 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1021 		return (FALSE);
1022 
1023 	return (TRUE);
1024 }
1025 
1026 static int
1027 bwn_attach_post(struct bwn_softc *sc)
1028 {
1029 	struct ieee80211com *ic;
1030 	struct ifnet *ifp = sc->sc_ifp;
1031 
1032 	ic = ifp->if_l2com;
1033 	ic->ic_ifp = ifp;
1034 	/* XXX not right but it's not used anywhere important */
1035 	ic->ic_phytype = IEEE80211_T_OFDM;
1036 	ic->ic_opmode = IEEE80211_M_STA;
1037 	ic->ic_caps =
1038 		  IEEE80211_C_STA		/* station mode supported */
1039 		| IEEE80211_C_MONITOR		/* monitor mode */
1040 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1041 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1042 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1043 		| IEEE80211_C_WME		/* WME/WMM supported */
1044 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1045 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1046 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1047 		;
1048 
1049 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1050 
1051 	/* call MI attach routine. */
1052 	ieee80211_ifattach(ic,
1053 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1054 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1055 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1056 
1057 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1058 
1059 	/* override default methods */
1060 	ic->ic_raw_xmit = bwn_raw_xmit;
1061 	ic->ic_updateslot = bwn_updateslot;
1062 	ic->ic_update_promisc = bwn_update_promisc;
1063 	ic->ic_wme.wme_update = bwn_wme_update;
1064 
1065 	ic->ic_scan_start = bwn_scan_start;
1066 	ic->ic_scan_end = bwn_scan_end;
1067 	ic->ic_set_channel = bwn_set_channel;
1068 
1069 	ic->ic_vap_create = bwn_vap_create;
1070 	ic->ic_vap_delete = bwn_vap_delete;
1071 
1072 	ieee80211_radiotap_attach(ic,
1073 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1074 	    BWN_TX_RADIOTAP_PRESENT,
1075 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1076 	    BWN_RX_RADIOTAP_PRESENT);
1077 
1078 	bwn_sysctl_node(sc);
1079 
1080 	if (bootverbose)
1081 		ieee80211_announce(ic);
1082 	return (0);
1083 }
1084 
1085 static void
1086 bwn_phy_detach(struct bwn_mac *mac)
1087 {
1088 
1089 	if (mac->mac_phy.detach != NULL)
1090 		mac->mac_phy.detach(mac);
1091 }
1092 
1093 static int
1094 bwn_detach(device_t dev)
1095 {
1096 	struct bwn_softc *sc = device_get_softc(dev);
1097 	struct bwn_mac *mac = sc->sc_curmac;
1098 	struct ifnet *ifp = sc->sc_ifp;
1099 	struct ieee80211com *ic = ifp->if_l2com;
1100 
1101 	wlan_serialize_enter();
1102 
1103 	sc->sc_flags |= BWN_FLAG_INVALID;
1104 
1105 	if (device_is_attached(sc->sc_dev)) {
1106 		bwn_stop(sc, 1);
1107 		bwn_dma_free(mac);
1108 		callout_stop_sync(&sc->sc_led_blink_ch);
1109 		callout_stop_sync(&sc->sc_rfswitch_ch);
1110 		callout_stop_sync(&sc->sc_task_ch);
1111 		callout_stop_sync(&sc->sc_watchdog_ch);
1112 		bwn_phy_detach(mac);
1113 		if (ifp != NULL) {
1114 			wlan_serialize_exit();
1115 			ieee80211_draintask(ic, &mac->mac_hwreset);
1116 			ieee80211_draintask(ic, &mac->mac_txpower);
1117 			wlan_serialize_enter();
1118 			ieee80211_ifdetach(ic);
1119 			if_free(ifp);
1120 		}
1121 	}
1122 	wlan_serialize_exit();
1123 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1124 	taskqueue_free(sc->sc_tq);
1125 	wlan_serialize_enter();
1126 
1127 	if (sc->bwn_intr)
1128 		bus_teardown_intr(dev, sc->bwn_irq, sc->bwn_intr);
1129 	if (sc->bwn_irq != NULL)
1130 		bus_release_resource(dev, SYS_RES_IRQ, sc->bwn_irq_rid,
1131 		    sc->bwn_irq);
1132 
1133 	if (sc->bwn_irq_type == PCI_INTR_TYPE_MSI)
1134 		pci_release_msi(dev);
1135 
1136 	if (sc->sc_sysctl_tree) {
1137 		sysctl_ctx_free(&sc->sc_sysctl_ctx);
1138 		sc->sc_sysctl_tree = NULL;
1139 	}
1140 
1141 	wlan_serialize_exit();
1142 	return (0);
1143 }
1144 
1145 static int
1146 bwn_attach_pre(struct bwn_softc *sc)
1147 {
1148 	struct ifnet *ifp;
1149 	int error = 0;
1150 
1151 	TAILQ_INIT(&sc->sc_maclist);
1152 	callout_init(&sc->sc_rfswitch_ch);
1153 	callout_init(&sc->sc_task_ch);
1154 	callout_init(&sc->sc_watchdog_ch);
1155 
1156 	sc->sc_tq = taskqueue_create("bwn_taskq", M_WAITOK,
1157 		taskqueue_thread_enqueue, &sc->sc_tq);
1158 	taskqueue_start_threads(&sc->sc_tq, 1, TDPRI_KERN_DAEMON, -1,
1159 		"%s taskq", device_get_nameunit(sc->sc_dev));
1160 
1161 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1162 	if (ifp == NULL) {
1163 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1164 		error = ENOSPC;
1165 		goto fail;
1166 	}
1167 
1168 	/* set these up early for if_printf use */
1169 	if_initname(ifp, device_get_name(sc->sc_dev),
1170 	    device_get_unit(sc->sc_dev));
1171 
1172 	/* prepare sysctl tree for use in sub modules */
1173 	sysctl_ctx_init(&sc->sc_sysctl_ctx);
1174 	sc->sc_sysctl_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx,
1175 		SYSCTL_STATIC_CHILDREN(_hw),
1176 		OID_AUTO,
1177 		device_get_nameunit(sc->sc_dev),
1178 		CTLFLAG_RD, 0, "");
1179 
1180 	ifp->if_softc = sc;
1181 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1182 	ifp->if_init = bwn_init;
1183 	ifp->if_ioctl = bwn_ioctl;
1184 	ifp->if_start = bwn_start;
1185 	ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
1186 
1187 	return (0);
1188 
1189 fail:
1190 	return (error);
1191 }
1192 
1193 static void
1194 bwn_sprom_bugfixes(device_t dev)
1195 {
1196 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1197 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1198 	 (siba_get_pci_device(dev) == _device) &&			\
1199 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1200 	 (siba_get_pci_subdevice(dev) == _subdevice))
1201 
1202 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1203 	    siba_get_pci_subdevice(dev) == 0x4e &&
1204 	    siba_get_pci_revid(dev) > 0x40)
1205 		siba_sprom_set_bf_lo(dev,
1206 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1207 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1208 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1209 		siba_sprom_set_bf_lo(dev,
1210 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1211 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1212 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1213 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1214 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1215 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1216 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1217 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1218 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1219 			siba_sprom_set_bf_lo(dev,
1220 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1221 	}
1222 #undef	BWN_ISDEV
1223 }
1224 
1225 static int
1226 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
1227 	  struct ucred *cr __unused)
1228 {
1229 #define IS_RUNNING(ifp) \
1230         ((ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
1231 	struct bwn_softc *sc = ifp->if_softc;
1232 	struct ieee80211com *ic = ifp->if_l2com;
1233 	struct ifreq *ifr = (struct ifreq *)data;
1234 	int error = 0;
1235 
1236 	switch (cmd) {
1237 	case SIOCSIFFLAGS:
1238 		if (IS_RUNNING(ifp)) {
1239 			bwn_update_promisc(ifp);
1240 		} else if (ifp->if_flags & IFF_UP) {
1241 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1242 				bwn_init(sc);
1243 			}
1244 		} else
1245 			bwn_stop(sc, 1);
1246 		break;
1247 	case SIOCGIFMEDIA:
1248 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1249 		break;
1250 	case SIOCGIFADDR:
1251 		error = ether_ioctl(ifp, cmd, data);
1252 		break;
1253 	default:
1254 		error = EINVAL;
1255 		break;
1256 	}
1257 	return (error);
1258 }
1259 
1260 static void
1261 bwn_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
1262 {
1263 	wlan_assert_serialized();
1264 	bwn_start_locked(ifp);
1265 }
1266 
1267 static void
1268 bwn_start_locked(struct ifnet *ifp)
1269 {
1270 	struct bwn_softc *sc = ifp->if_softc;
1271 	struct bwn_mac *mac = sc->sc_curmac;
1272 	struct ieee80211_frame *wh;
1273 	struct ieee80211_node *ni;
1274 	struct ieee80211_key *k;
1275 	struct mbuf *m;
1276 
1277 	wlan_assert_serialized();
1278 
1279 	if ((ifp->if_flags & IFF_RUNNING) == 0 || mac == NULL ||
1280 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1281 		return;
1282 
1283 	for (;;) {
1284 		m = ifq_dequeue(&ifp->if_snd);	/* XXX: LOCK */
1285 		if (m == NULL)
1286 			break;
1287 
1288 		if (bwn_tx_isfull(sc, m))
1289 			break;
1290 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1291 		if (ni == NULL) {
1292 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1293 			m_freem(m);
1294 			ifp->if_oerrors++;
1295 			continue;
1296 		}
1297 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1298 		wh = mtod(m, struct ieee80211_frame *);
1299 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1300 			k = ieee80211_crypto_encap(ni, m);
1301 			if (k == NULL) {
1302 				ieee80211_free_node(ni);
1303 				m_freem(m);
1304 				ifp->if_oerrors++;
1305 				continue;
1306 			}
1307 		}
1308 		wh = NULL;	/* Catch any invalid use */
1309 
1310 		if (bwn_tx_start(sc, ni, m) != 0) {
1311 			if (ni != NULL)
1312 				ieee80211_free_node(ni);
1313 			ifp->if_oerrors++;
1314 			continue;
1315 		}
1316 
1317 		sc->sc_watchdog_timer = 5;
1318 	}
1319 }
1320 
1321 static int
1322 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1323 {
1324 	struct bwn_dma_ring *dr;
1325 	struct bwn_mac *mac = sc->sc_curmac;
1326 	struct bwn_pio_txqueue *tq;
1327 	struct ifnet *ifp = sc->sc_ifp;
1328 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1329 
1330 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1331 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1332 		if (dr->dr_stop == 1 ||
1333 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1334 			dr->dr_stop = 1;
1335 			goto full;
1336 		}
1337 	} else {
1338 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1339 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1340 		    pktlen > (tq->tq_size - tq->tq_used)) {
1341 			tq->tq_stop = 1;
1342 			goto full;
1343 		}
1344 	}
1345 	return (0);
1346 full:
1347 	ifq_prepend(&ifp->if_snd, m);
1348 	ifq_set_oactive(&ifp->if_snd);
1349 	return (1);
1350 }
1351 
1352 static int
1353 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1354 {
1355 	struct bwn_mac *mac = sc->sc_curmac;
1356 	int error;
1357 
1358 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1359 		m_freem(m);
1360 		return (ENXIO);
1361 	}
1362 
1363 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1364 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1365 	if (error) {
1366 		m_freem(m);
1367 		return (error);
1368 	}
1369 	return (0);
1370 }
1371 
1372 static int
1373 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1374 {
1375 	struct bwn_pio_txpkt *tp;
1376 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1377 	struct bwn_softc *sc = mac->mac_sc;
1378 	struct bwn_txhdr txhdr;
1379 	struct mbuf *m_new;
1380 	uint32_t ctl32;
1381 	int error;
1382 	uint16_t ctl16;
1383 
1384 	/* XXX TODO send packets after DTIM */
1385 
1386 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1387 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1388 	tp->tp_ni = ni;
1389 	tp->tp_m = m;
1390 
1391 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1392 	if (error) {
1393 		device_printf(sc->sc_dev, "tx fail\n");
1394 		return (error);
1395 	}
1396 
1397 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1398 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1399 	tq->tq_free--;
1400 
1401 	if (siba_get_revid(sc->sc_dev) >= 8) {
1402 		/*
1403 		 * XXX please removes m_defrag(9)
1404 		 */
1405 		m_new = m_defrag(m, M_INTWAIT);
1406 		if (m_new == NULL) {
1407 			device_printf(sc->sc_dev,
1408 			    "%s: can't defrag TX buffer\n",
1409 			    __func__);
1410 			return (ENOBUFS);
1411 		}
1412 		if (m_new->m_next != NULL)
1413 			device_printf(sc->sc_dev,
1414 			    "TODO: fragmented packets for PIO\n");
1415 		tp->tp_m = m_new;
1416 
1417 		/* send HEADER */
1418 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1419 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1420 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1421 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1422 		/* send BODY */
1423 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1424 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1425 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1426 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1427 	} else {
1428 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1429 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1430 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1431 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1432 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1433 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1434 		    ctl16 | BWN_PIO_TXCTL_EOF);
1435 	}
1436 
1437 	return (0);
1438 }
1439 
1440 static struct bwn_pio_txqueue *
1441 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1442 {
1443 
1444 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1445 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1446 
1447 	switch (prio) {
1448 	case 0:
1449 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1450 	case 1:
1451 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1452 	case 2:
1453 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1454 	case 3:
1455 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1456 	}
1457 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1458 	return (NULL);
1459 }
1460 
1461 static int
1462 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1463 {
1464 #define	BWN_GET_TXHDRCACHE(slot)					\
1465 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_MAX_HDRSIZE(mac)])
1466 	struct bwn_dma *dma = &mac->mac_method.dma;
1467 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1468 	struct bwn_dmadesc_generic *desc;
1469 	struct bwn_dmadesc_meta *mt;
1470 	struct bwn_softc *sc = mac->mac_sc;
1471 	struct ifnet *ifp = sc->sc_ifp;
1472 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1473 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1474 
1475 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1476 
1477 	/* XXX send after DTIM */
1478 
1479 	slot = bwn_dma_getslot(dr);
1480 	dr->getdesc(dr, slot, &desc, &mt);
1481 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1482 	    ("%s:%d: fail", __func__, __LINE__));
1483 
1484 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1485 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1486 	    BWN_DMA_COOKIE(dr, slot));
1487 	if (error)
1488 		goto fail;
1489 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1490 	    BUS_DMASYNC_PREWRITE);
1491 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1492 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1493 	    BUS_DMASYNC_PREWRITE);
1494 
1495 	slot = bwn_dma_getslot(dr);
1496 	dr->getdesc(dr, slot, &desc, &mt);
1497 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1498 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1499 	mt->mt_m = m;
1500 	mt->mt_ni = ni;
1501 
1502 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1503 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1504 	if (error && error != EFBIG) {
1505 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1506 		    __func__, error);
1507 		goto fail;
1508 	}
1509 	if (error) {    /* error == EFBIG */
1510 		struct mbuf *m_new;
1511 
1512 		m_new = m_defrag(m, M_INTWAIT);
1513 		if (m_new == NULL) {
1514 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1515 			    __func__);
1516 			error = ENOBUFS;
1517 			goto fail;
1518 		} else {
1519 			m = m_new;
1520 		}
1521 
1522 		mt->mt_m = m;
1523 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1524 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1525 		if (error) {
1526 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1527 			    __func__, error);
1528 			goto fail;
1529 		}
1530 	}
1531 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1532 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1533 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1534 	    BUS_DMASYNC_PREWRITE);
1535 
1536 	/* XXX send after DTIM */
1537 
1538 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1539 	return (0);
1540 fail:
1541 	dr->dr_curslot = backup[0];
1542 	dr->dr_usedslot = backup[1];
1543 	return (error);
1544 #undef BWN_GET_TXHDRCACHE
1545 }
1546 
1547 static void
1548 bwn_watchdog(void *arg)
1549 {
1550 	struct bwn_softc *sc = arg;
1551 	struct ifnet *ifp = sc->sc_ifp;
1552 
1553 	wlan_serialize_enter();
1554 
1555 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1556 		if_printf(ifp, "device timeout\n");
1557 		ifp->if_oerrors++;
1558 	}
1559 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
1560 	wlan_serialize_exit();
1561 }
1562 
1563 static int
1564 bwn_attach_core(struct bwn_mac *mac)
1565 {
1566 	struct bwn_softc *sc = mac->mac_sc;
1567 	int error, have_bg = 0, have_a = 0;
1568 	uint32_t high;
1569 
1570 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1571 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1572 
1573 	siba_powerup(sc->sc_dev, 0);
1574 
1575 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1576 	bwn_reset_core(mac,
1577 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1578 	error = bwn_phy_getinfo(mac, high);
1579 	if (error)
1580 		goto fail;
1581 
1582 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1583 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1584 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1585 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1586 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1587 		have_a = have_bg = 0;
1588 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1589 			have_a = 1;
1590 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1591 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1592 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1593 			have_bg = 1;
1594 		else
1595 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1596 			    mac->mac_phy.type));
1597 	}
1598 	/* XXX turns off PHY A because it's not supported */
1599 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1600 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1601 		have_a = 0;
1602 		have_bg = 1;
1603 	}
1604 
1605 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1606 		mac->mac_phy.attach = bwn_phy_g_attach;
1607 		mac->mac_phy.detach = bwn_phy_g_detach;
1608 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1609 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1610 		mac->mac_phy.init = bwn_phy_g_init;
1611 		mac->mac_phy.exit = bwn_phy_g_exit;
1612 		mac->mac_phy.phy_read = bwn_phy_g_read;
1613 		mac->mac_phy.phy_write = bwn_phy_g_write;
1614 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1615 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1616 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1617 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1618 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1619 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1620 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1621 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1622 		mac->mac_phy.set_im = bwn_phy_g_im;
1623 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1624 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1625 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1626 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1627 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1628 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1629 		mac->mac_phy.init = bwn_phy_lp_init;
1630 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1631 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1632 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1633 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1634 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1635 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1636 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1637 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1638 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1639 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1640 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1641 	} else {
1642 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1643 		    mac->mac_phy.type);
1644 		error = ENXIO;
1645 		goto fail;
1646 	}
1647 
1648 	mac->mac_phy.gmode = have_bg;
1649 	if (mac->mac_phy.attach != NULL) {
1650 		error = mac->mac_phy.attach(mac);
1651 		if (error) {
1652 			device_printf(sc->sc_dev, "failed\n");
1653 			goto fail;
1654 		}
1655 	}
1656 
1657 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1658 
1659 	error = bwn_chiptest(mac);
1660 	if (error)
1661 		goto fail;
1662 	error = bwn_setup_channels(mac, have_bg, have_a);
1663 	if (error) {
1664 		device_printf(sc->sc_dev, "failed to setup channels\n");
1665 		goto fail;
1666 	}
1667 
1668 	if (sc->sc_curmac == NULL)
1669 		sc->sc_curmac = mac;
1670 
1671 	wlan_assert_serialized();
1672 	wlan_serialize_exit();
1673 	error = bwn_dma_attach(mac);
1674 	wlan_serialize_enter();
1675 	if (error != 0) {
1676 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1677 		goto fail;
1678 	}
1679 
1680 	mac->mac_phy.switch_analog(mac, 0);
1681 
1682 	siba_dev_down(sc->sc_dev, 0);
1683 fail:
1684 	siba_powerdown(sc->sc_dev);
1685 	return (error);
1686 }
1687 
1688 static void
1689 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1690 {
1691 	struct bwn_softc *sc = mac->mac_sc;
1692 	uint32_t low, ctl;
1693 
1694 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1695 
1696 	siba_dev_up(sc->sc_dev, flags);
1697 	DELAY(2000);
1698 
1699 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1700 	    ~BWN_TGSLOW_PHYRESET;
1701 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1702 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1703 	DELAY(1000);
1704 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1705 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1706 	DELAY(1000);
1707 
1708 	if (mac->mac_phy.switch_analog != NULL)
1709 		mac->mac_phy.switch_analog(mac, 1);
1710 
1711 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1712 	if (flags & BWN_TGSLOW_SUPPORT_G)
1713 		ctl |= BWN_MACCTL_GMODE;
1714 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1715 }
1716 
1717 static int
1718 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1719 {
1720 	struct bwn_phy *phy = &mac->mac_phy;
1721 	struct bwn_softc *sc = mac->mac_sc;
1722 	uint32_t tmp;
1723 
1724 	/* PHY */
1725 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1726 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1727 	phy->rf_on = 1;
1728 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1729 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1730 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1731 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1732 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1733 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1734 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1735 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1736 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1737 		goto unsupphy;
1738 
1739 	/* RADIO */
1740 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1741 		if (siba_get_chiprev(sc->sc_dev) == 0)
1742 			tmp = 0x3205017f;
1743 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1744 			tmp = 0x4205017f;
1745 		else
1746 			tmp = 0x5205017f;
1747 	} else {
1748 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1749 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1750 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1751 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1752 	}
1753 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1754 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1755 	phy->rf_manuf = (tmp & 0x00000fff);
1756 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1757 		goto unsupradio;
1758 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1759 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1760 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1761 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1762 	    (phy->type == BWN_PHYTYPE_N &&
1763 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1764 	    (phy->type == BWN_PHYTYPE_LP &&
1765 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1766 		goto unsupradio;
1767 
1768 	return (0);
1769 unsupphy:
1770 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1771 	    "analog %#x)\n",
1772 	    phy->type, phy->rev, phy->analog);
1773 	return (ENXIO);
1774 unsupradio:
1775 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1776 	    "rev %#x)\n",
1777 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1778 	return (ENXIO);
1779 }
1780 
1781 static int
1782 bwn_chiptest(struct bwn_mac *mac)
1783 {
1784 #define	TESTVAL0	0x55aaaa55
1785 #define	TESTVAL1	0xaa5555aa
1786 	struct bwn_softc *sc = mac->mac_sc;
1787 	uint32_t v, backup;
1788 
1789 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1790 
1791 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1792 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1793 		goto error;
1794 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1795 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1796 		goto error;
1797 
1798 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1799 
1800 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1801 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1802 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1803 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1804 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1805 			goto error;
1806 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1807 			goto error;
1808 	}
1809 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1810 
1811 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1812 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1813 		goto error;
1814 
1815 	return (0);
1816 error:
1817 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1818 	return (ENODEV);
1819 }
1820 
1821 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1822 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1823 
1824 static int
1825 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1826 {
1827 	struct bwn_softc *sc = mac->mac_sc;
1828 	struct ifnet *ifp = sc->sc_ifp;
1829 	struct ieee80211com *ic = ifp->if_l2com;
1830 
1831 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1832 	ic->ic_nchans = 0;
1833 
1834 	if (have_bg)
1835 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1836 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1837 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1838 		if (have_a)
1839 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1840 			    &ic->ic_nchans, &bwn_chantable_n,
1841 			    IEEE80211_CHAN_HTA);
1842 	} else {
1843 		if (have_a)
1844 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1845 			    &ic->ic_nchans, &bwn_chantable_a,
1846 			    IEEE80211_CHAN_A);
1847 	}
1848 
1849 	mac->mac_phy.supports_2ghz = have_bg;
1850 	mac->mac_phy.supports_5ghz = have_a;
1851 
1852 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1853 }
1854 
1855 static uint32_t
1856 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1857 {
1858 	uint32_t ret;
1859 
1860 	if (way == BWN_SHARED) {
1861 		KASSERT((offset & 0x0001) == 0,
1862 		    ("%s:%d warn", __func__, __LINE__));
1863 		if (offset & 0x0003) {
1864 			bwn_shm_ctlword(mac, way, offset >> 2);
1865 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1866 			ret <<= 16;
1867 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1868 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1869 			goto out;
1870 		}
1871 		offset >>= 2;
1872 	}
1873 	bwn_shm_ctlword(mac, way, offset);
1874 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1875 out:
1876 	return (ret);
1877 }
1878 
1879 static uint16_t
1880 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1881 {
1882 	uint16_t ret;
1883 
1884 	if (way == BWN_SHARED) {
1885 		KASSERT((offset & 0x0001) == 0,
1886 		    ("%s:%d warn", __func__, __LINE__));
1887 		if (offset & 0x0003) {
1888 			bwn_shm_ctlword(mac, way, offset >> 2);
1889 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1890 			goto out;
1891 		}
1892 		offset >>= 2;
1893 	}
1894 	bwn_shm_ctlword(mac, way, offset);
1895 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1896 out:
1897 
1898 	return (ret);
1899 }
1900 
1901 static void
1902 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1903     uint16_t offset)
1904 {
1905 	uint32_t control;
1906 
1907 	control = way;
1908 	control <<= 16;
1909 	control |= offset;
1910 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1911 }
1912 
1913 static void
1914 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1915     uint32_t value)
1916 {
1917 	if (way == BWN_SHARED) {
1918 		KASSERT((offset & 0x0001) == 0,
1919 		    ("%s:%d warn", __func__, __LINE__));
1920 		if (offset & 0x0003) {
1921 			bwn_shm_ctlword(mac, way, offset >> 2);
1922 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1923 				    (value >> 16) & 0xffff);
1924 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1925 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1926 			return;
1927 		}
1928 		offset >>= 2;
1929 	}
1930 	bwn_shm_ctlword(mac, way, offset);
1931 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1932 }
1933 
1934 static void
1935 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1936     uint16_t value)
1937 {
1938 	if (way == BWN_SHARED) {
1939 		KASSERT((offset & 0x0001) == 0,
1940 		    ("%s:%d warn", __func__, __LINE__));
1941 		if (offset & 0x0003) {
1942 			bwn_shm_ctlword(mac, way, offset >> 2);
1943 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1944 			return;
1945 		}
1946 		offset >>= 2;
1947 	}
1948 	bwn_shm_ctlword(mac, way, offset);
1949 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1950 }
1951 
1952 static void
1953 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1954     int txpow)
1955 {
1956 
1957 	c->ic_freq = freq;
1958 	c->ic_flags = flags;
1959 	c->ic_ieee = ieee;
1960 	c->ic_minpower = 0;
1961 	c->ic_maxpower = 2 * txpow;
1962 	c->ic_maxregpower = txpow;
1963 }
1964 
1965 static void
1966 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1967     const struct bwn_channelinfo *ci, int flags)
1968 {
1969 	struct ieee80211_channel *c;
1970 	int i;
1971 
1972 	c = &chans[*nchans];
1973 
1974 	for (i = 0; i < ci->nchannels; i++) {
1975 		const struct bwn_channel *hc;
1976 
1977 		hc = &ci->channels[i];
1978 		if (*nchans >= maxchans)
1979 			break;
1980 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
1981 		c++, (*nchans)++;
1982 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
1983 			/* g channel have a separate b-only entry */
1984 			if (*nchans >= maxchans)
1985 				break;
1986 			c[0] = c[-1];
1987 			c[-1].ic_flags = IEEE80211_CHAN_B;
1988 			c++, (*nchans)++;
1989 		}
1990 		if (flags == IEEE80211_CHAN_HTG) {
1991 			/* HT g channel have a separate g-only entry */
1992 			if (*nchans >= maxchans)
1993 				break;
1994 			c[-1].ic_flags = IEEE80211_CHAN_G;
1995 			c[0] = c[-1];
1996 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1997 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1998 			c++, (*nchans)++;
1999 		}
2000 		if (flags == IEEE80211_CHAN_HTA) {
2001 			/* HT a channel have a separate a-only entry */
2002 			if (*nchans >= maxchans)
2003 				break;
2004 			c[-1].ic_flags = IEEE80211_CHAN_A;
2005 			c[0] = c[-1];
2006 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2007 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2008 			c++, (*nchans)++;
2009 		}
2010 	}
2011 }
2012 
2013 static int
2014 bwn_phy_g_attach(struct bwn_mac *mac)
2015 {
2016 	struct bwn_softc *sc = mac->mac_sc;
2017 	struct bwn_phy *phy = &mac->mac_phy;
2018 	struct bwn_phy_g *pg = &phy->phy_g;
2019 	unsigned int i;
2020 	int16_t pab0, pab1, pab2;
2021 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2022 	int8_t bg;
2023 
2024 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2025 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2026 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2027 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2028 
2029 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2030 		device_printf(sc->sc_dev, "not supported anymore\n");
2031 
2032 	pg->pg_flags = 0;
2033 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2034 	    pab2 == -1) {
2035 		pg->pg_idletssi = 52;
2036 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2037 		return (0);
2038 	}
2039 
2040 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2041 	pg->pg_tssi2dbm = (uint8_t *)kmalloc(64, M_DEVBUF, M_INTWAIT | M_ZERO);
2042 	for (i = 0; i < 64; i++) {
2043 		int32_t m1, m2, f, q, delta;
2044 		int8_t j = 0;
2045 
2046 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2047 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2048 		f = 256;
2049 
2050 		do {
2051 			if (j > 15) {
2052 				device_printf(sc->sc_dev,
2053 				    "failed to generate tssi2dBm\n");
2054 				kfree(pg->pg_tssi2dbm, M_DEVBUF);
2055 				return (ENOMEM);
2056 			}
2057 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2058 			    f, 2048);
2059 			delta = abs(q - f);
2060 			f = q;
2061 			j++;
2062 		} while (delta >= 2);
2063 
2064 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2065 		    128);
2066 	}
2067 
2068 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2069 	return (0);
2070 }
2071 
2072 static void
2073 bwn_phy_g_detach(struct bwn_mac *mac)
2074 {
2075 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2076 
2077 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2078 		kfree(pg->pg_tssi2dbm, M_DEVBUF);
2079 		pg->pg_tssi2dbm = NULL;
2080 	}
2081 	pg->pg_flags = 0;
2082 }
2083 
2084 static void
2085 bwn_phy_g_init_pre(struct bwn_mac *mac)
2086 {
2087 	struct bwn_phy *phy = &mac->mac_phy;
2088 	struct bwn_phy_g *pg = &phy->phy_g;
2089 	void *tssi2dbm;
2090 	int idletssi;
2091 	unsigned int i;
2092 
2093 	tssi2dbm = pg->pg_tssi2dbm;
2094 	idletssi = pg->pg_idletssi;
2095 
2096 	memset(pg, 0, sizeof(*pg));
2097 
2098 	pg->pg_tssi2dbm = tssi2dbm;
2099 	pg->pg_idletssi = idletssi;
2100 
2101 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2102 
2103 	for (i = 0; i < N(pg->pg_nrssi); i++)
2104 		pg->pg_nrssi[i] = -1000;
2105 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2106 		pg->pg_nrssi_lt[i] = i;
2107 	pg->pg_lofcal = 0xffff;
2108 	pg->pg_initval = 0xffff;
2109 	pg->pg_immode = BWN_IMMODE_NONE;
2110 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2111 	pg->pg_avgtssi = 0xff;
2112 
2113 	pg->pg_loctl.tx_bias = 0xff;
2114 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2115 }
2116 
2117 static int
2118 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2119 {
2120 	struct bwn_phy *phy = &mac->mac_phy;
2121 	struct bwn_phy_g *pg = &phy->phy_g;
2122 	struct bwn_softc *sc = mac->mac_sc;
2123 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2124 	static const struct bwn_rfatt rfatt0[] = {
2125 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2126 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2127 		{ 3, 1 }, { 4, 1 }
2128 	};
2129 	static const struct bwn_rfatt rfatt1[] = {
2130 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2131 		{ 14, 1 }
2132 	};
2133 	static const struct bwn_rfatt rfatt2[] = {
2134 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2135 		{ 9, 1 }
2136 	};
2137 	static const struct bwn_bbatt bbatt_0[] = {
2138 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2139 	};
2140 
2141 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2142 
2143 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2144 		pg->pg_bbatt.att = 0;
2145 	else
2146 		pg->pg_bbatt.att = 2;
2147 
2148 	/* prepare Radio Attenuation */
2149 	pg->pg_rfatt.padmix = 0;
2150 
2151 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2152 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2153 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2154 			pg->pg_rfatt.att = 2;
2155 			goto done;
2156 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2157 			pg->pg_rfatt.att = 3;
2158 			goto done;
2159 		}
2160 	}
2161 
2162 	if (phy->type == BWN_PHYTYPE_A) {
2163 		pg->pg_rfatt.att = 0x60;
2164 		goto done;
2165 	}
2166 
2167 	switch (phy->rf_ver) {
2168 	case 0x2050:
2169 		switch (phy->rf_rev) {
2170 		case 0:
2171 			pg->pg_rfatt.att = 5;
2172 			goto done;
2173 		case 1:
2174 			if (phy->type == BWN_PHYTYPE_G) {
2175 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2176 				    SIBA_BOARDVENDOR_BCM &&
2177 				    siba_get_pci_subdevice(sc->sc_dev) ==
2178 				    SIBA_BOARD_BCM4309G &&
2179 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2180 					pg->pg_rfatt.att = 3;
2181 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2182 				    SIBA_BOARDVENDOR_BCM &&
2183 				    siba_get_pci_subdevice(sc->sc_dev) ==
2184 				    SIBA_BOARD_BU4306)
2185 					pg->pg_rfatt.att = 3;
2186 				else
2187 					pg->pg_rfatt.att = 1;
2188 			} else {
2189 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2190 				    SIBA_BOARDVENDOR_BCM &&
2191 				    siba_get_pci_subdevice(sc->sc_dev) ==
2192 				    SIBA_BOARD_BCM4309G &&
2193 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2194 					pg->pg_rfatt.att = 7;
2195 				else
2196 					pg->pg_rfatt.att = 6;
2197 			}
2198 			goto done;
2199 		case 2:
2200 			if (phy->type == BWN_PHYTYPE_G) {
2201 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2202 				    SIBA_BOARDVENDOR_BCM &&
2203 				    siba_get_pci_subdevice(sc->sc_dev) ==
2204 				    SIBA_BOARD_BCM4309G &&
2205 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2206 					pg->pg_rfatt.att = 3;
2207 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2208 				    SIBA_BOARDVENDOR_BCM &&
2209 				    siba_get_pci_subdevice(sc->sc_dev) ==
2210 				    SIBA_BOARD_BU4306)
2211 					pg->pg_rfatt.att = 5;
2212 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2213 					pg->pg_rfatt.att = 4;
2214 				else
2215 					pg->pg_rfatt.att = 3;
2216 			} else
2217 				pg->pg_rfatt.att = 6;
2218 			goto done;
2219 		case 3:
2220 			pg->pg_rfatt.att = 5;
2221 			goto done;
2222 		case 4:
2223 		case 5:
2224 			pg->pg_rfatt.att = 1;
2225 			goto done;
2226 		case 6:
2227 		case 7:
2228 			pg->pg_rfatt.att = 5;
2229 			goto done;
2230 		case 8:
2231 			pg->pg_rfatt.att = 0xa;
2232 			pg->pg_rfatt.padmix = 1;
2233 			goto done;
2234 		case 9:
2235 		default:
2236 			pg->pg_rfatt.att = 5;
2237 			goto done;
2238 		}
2239 		break;
2240 	case 0x2053:
2241 		switch (phy->rf_rev) {
2242 		case 1:
2243 			pg->pg_rfatt.att = 6;
2244 			goto done;
2245 		}
2246 		break;
2247 	}
2248 	pg->pg_rfatt.att = 5;
2249 done:
2250 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2251 
2252 	if (!bwn_has_hwpctl(mac)) {
2253 		lo->rfatt.array = rfatt0;
2254 		lo->rfatt.len = N(rfatt0);
2255 		lo->rfatt.min = 0;
2256 		lo->rfatt.max = 9;
2257 		goto genbbatt;
2258 	}
2259 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2260 		lo->rfatt.array = rfatt1;
2261 		lo->rfatt.len = N(rfatt1);
2262 		lo->rfatt.min = 0;
2263 		lo->rfatt.max = 14;
2264 		goto genbbatt;
2265 	}
2266 	lo->rfatt.array = rfatt2;
2267 	lo->rfatt.len = N(rfatt2);
2268 	lo->rfatt.min = 0;
2269 	lo->rfatt.max = 9;
2270 genbbatt:
2271 	lo->bbatt.array = bbatt_0;
2272 	lo->bbatt.len = N(bbatt_0);
2273 	lo->bbatt.min = 0;
2274 	lo->bbatt.max = 8;
2275 
2276 	BWN_READ_4(mac, BWN_MACCTL);
2277 	if (phy->rev == 1) {
2278 		phy->gmode = 0;
2279 		bwn_reset_core(mac, 0);
2280 		bwn_phy_g_init_sub(mac);
2281 		phy->gmode = 1;
2282 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2283 	}
2284 	return (0);
2285 }
2286 
2287 static uint16_t
2288 bwn_phy_g_txctl(struct bwn_mac *mac)
2289 {
2290 	struct bwn_phy *phy = &mac->mac_phy;
2291 
2292 	if (phy->rf_ver != 0x2050)
2293 		return (0);
2294 	if (phy->rf_rev == 1)
2295 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2296 	if (phy->rf_rev < 6)
2297 		return (BWN_TXCTL_PA2DB);
2298 	if (phy->rf_rev == 8)
2299 		return (BWN_TXCTL_TXMIX);
2300 	return (0);
2301 }
2302 
2303 static int
2304 bwn_phy_g_init(struct bwn_mac *mac)
2305 {
2306 
2307 	bwn_phy_g_init_sub(mac);
2308 	return (0);
2309 }
2310 
2311 static void
2312 bwn_phy_g_exit(struct bwn_mac *mac)
2313 {
2314 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2315 	struct bwn_lo_calib *cal, *tmp;
2316 
2317 	if (lo == NULL)
2318 		return;
2319 	TAILQ_FOREACH_MUTABLE(cal, &lo->calib_list, list, tmp) {
2320 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2321 		kfree(cal, M_DEVBUF);
2322 	}
2323 }
2324 
2325 static uint16_t
2326 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2327 {
2328 
2329 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2330 	return (BWN_READ_2(mac, BWN_PHYDATA));
2331 }
2332 
2333 static void
2334 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2335 {
2336 
2337 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2338 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2339 }
2340 
2341 static uint16_t
2342 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2343 {
2344 
2345 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2346 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2347 	return (BWN_READ_2(mac, BWN_RFDATALO));
2348 }
2349 
2350 static void
2351 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2352 {
2353 
2354 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2355 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2356 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2357 }
2358 
2359 static int
2360 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2361 {
2362 
2363 	return (mac->mac_phy.rev >= 6);
2364 }
2365 
2366 static void
2367 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2368 {
2369 	struct bwn_phy *phy = &mac->mac_phy;
2370 	struct bwn_phy_g *pg = &phy->phy_g;
2371 	unsigned int channel;
2372 	uint16_t rfover, rfoverval;
2373 
2374 	if (on) {
2375 		if (phy->rf_on)
2376 			return;
2377 
2378 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2379 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2380 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2381 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2382 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2383 			    pg->pg_radioctx_over);
2384 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2385 			    pg->pg_radioctx_overval);
2386 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2387 		}
2388 		channel = phy->chan;
2389 		bwn_phy_g_switch_chan(mac, 6, 1);
2390 		bwn_phy_g_switch_chan(mac, channel, 0);
2391 		return;
2392 	}
2393 
2394 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2395 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2396 	pg->pg_radioctx_over = rfover;
2397 	pg->pg_radioctx_overval = rfoverval;
2398 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2399 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2400 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2401 }
2402 
2403 static int
2404 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2405 {
2406 
2407 	if ((newchan < 1) || (newchan > 14))
2408 		return (EINVAL);
2409 	bwn_phy_g_switch_chan(mac, newchan, 0);
2410 
2411 	return (0);
2412 }
2413 
2414 static uint32_t
2415 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2416 {
2417 
2418 	return (1);
2419 }
2420 
2421 static void
2422 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2423 {
2424 	struct bwn_phy *phy = &mac->mac_phy;
2425 	uint64_t hf;
2426 	int autodiv = 0;
2427 	uint16_t tmp;
2428 
2429 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2430 		autodiv = 1;
2431 
2432 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2433 	bwn_hf_write(mac, hf);
2434 
2435 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2436 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2437 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2438 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2439 
2440 	if (autodiv) {
2441 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2442 		if (antenna == BWN_ANTAUTO1)
2443 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2444 		else
2445 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2446 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2447 	}
2448 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2449 	if (autodiv)
2450 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2451 	else
2452 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2453 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2454 	if (phy->rev >= 2) {
2455 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2456 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2457 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2458 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2459 		    0x15);
2460 		if (phy->rev == 2)
2461 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2462 		else
2463 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2464 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2465 			    8);
2466 	}
2467 	if (phy->rev >= 6)
2468 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2469 
2470 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2471 	bwn_hf_write(mac, hf);
2472 }
2473 
2474 static int
2475 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2476 {
2477 	struct bwn_phy *phy = &mac->mac_phy;
2478 	struct bwn_phy_g *pg = &phy->phy_g;
2479 
2480 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2481 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2482 
2483 	if (phy->rev == 0 || !phy->gmode)
2484 		return (ENODEV);
2485 
2486 	pg->pg_aci_wlan_automatic = 0;
2487 	return (0);
2488 }
2489 
2490 static int
2491 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2492 {
2493 	struct bwn_phy *phy = &mac->mac_phy;
2494 	struct bwn_phy_g *pg = &phy->phy_g;
2495 	struct bwn_softc *sc = mac->mac_sc;
2496 	unsigned int tssi;
2497 	int cck, ofdm;
2498 	int power;
2499 	int rfatt, bbatt;
2500 	unsigned int max;
2501 
2502 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2503 
2504 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2505 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2506 	if (cck < 0 && ofdm < 0) {
2507 		if (ignore_tssi == 0)
2508 			return (BWN_TXPWR_RES_DONE);
2509 		cck = 0;
2510 		ofdm = 0;
2511 	}
2512 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2513 	if (pg->pg_avgtssi != 0xff)
2514 		tssi = (tssi + pg->pg_avgtssi) / 2;
2515 	pg->pg_avgtssi = tssi;
2516 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2517 
2518 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2519 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2520 		max -= 3;
2521 	if (max >= 120) {
2522 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2523 		max = 80;
2524 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2525 	}
2526 
2527 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2528 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2529 	     tssi, 0x00), 0x3f)]);
2530 	if (power == 0)
2531 		return (BWN_TXPWR_RES_DONE);
2532 
2533 	rfatt = -((power + 7) / 8);
2534 	bbatt = (-(power / 2)) - (4 * rfatt);
2535 	if ((rfatt == 0) && (bbatt == 0))
2536 		return (BWN_TXPWR_RES_DONE);
2537 	pg->pg_bbatt_delta = bbatt;
2538 	pg->pg_rfatt_delta = rfatt;
2539 	return (BWN_TXPWR_RES_NEED_ADJUST);
2540 }
2541 
2542 static void
2543 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2544 {
2545 	struct bwn_phy *phy = &mac->mac_phy;
2546 	struct bwn_phy_g *pg = &phy->phy_g;
2547 	struct bwn_softc *sc = mac->mac_sc;
2548 	int rfatt, bbatt;
2549 	uint8_t txctl;
2550 
2551 	bwn_mac_suspend(mac);
2552 
2553 	bbatt = pg->pg_bbatt.att;
2554 	bbatt += pg->pg_bbatt_delta;
2555 	rfatt = pg->pg_rfatt.att;
2556 	rfatt += pg->pg_rfatt_delta;
2557 
2558 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2559 	txctl = pg->pg_txctl;
2560 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2561 		if (rfatt <= 1) {
2562 			if (txctl == 0) {
2563 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2564 				rfatt += 2;
2565 				bbatt += 2;
2566 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2567 			    BWN_BFL_PACTRL) {
2568 				bbatt += 4 * (rfatt - 2);
2569 				rfatt = 2;
2570 			}
2571 		} else if (rfatt > 4 && txctl) {
2572 			txctl = 0;
2573 			if (bbatt < 3) {
2574 				rfatt -= 3;
2575 				bbatt += 2;
2576 			} else {
2577 				rfatt -= 2;
2578 				bbatt -= 2;
2579 			}
2580 		}
2581 	}
2582 	pg->pg_txctl = txctl;
2583 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2584 	pg->pg_rfatt.att = rfatt;
2585 	pg->pg_bbatt.att = bbatt;
2586 
2587 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2588 
2589 	bwn_phy_lock(mac);
2590 	bwn_rf_lock(mac);
2591 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2592 	    pg->pg_txctl);
2593 	bwn_rf_unlock(mac);
2594 	bwn_phy_unlock(mac);
2595 
2596 	bwn_mac_enable(mac);
2597 }
2598 
2599 static void
2600 bwn_phy_g_task_15s(struct bwn_mac *mac)
2601 {
2602 	struct bwn_phy *phy = &mac->mac_phy;
2603 	struct bwn_phy_g *pg = &phy->phy_g;
2604 	struct bwn_softc *sc = mac->mac_sc;
2605 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2606 	unsigned long expire, now;
2607 	struct bwn_lo_calib *cal, *tmp;
2608 	uint8_t expired = 0;
2609 
2610 	bwn_mac_suspend(mac);
2611 
2612 	if (lo == NULL)
2613 		goto fail;
2614 
2615 	BWN_GETTIME(now);
2616 	if (bwn_has_hwpctl(mac)) {
2617 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2618 		if (time_before(lo->pwr_vec_read_time, expire)) {
2619 			bwn_lo_get_powervector(mac);
2620 			bwn_phy_g_dc_lookup_init(mac, 0);
2621 		}
2622 		goto fail;
2623 	}
2624 
2625 	expire = now - BWN_LO_CALIB_EXPIRE;
2626 	TAILQ_FOREACH_MUTABLE(cal, &lo->calib_list, list, tmp) {
2627 		if (!time_before(cal->calib_time, expire))
2628 			continue;
2629 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2630 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2631 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2632 			expired = 1;
2633 		}
2634 
2635 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2636 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2637 		    cal->ctl.i, cal->ctl.q);
2638 
2639 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2640 		kfree(cal, M_DEVBUF);
2641 	}
2642 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2643 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2644 		    &pg->pg_rfatt);
2645 		if (cal == NULL) {	/* XXX ivadasz: can't happen */
2646 			device_printf(sc->sc_dev,
2647 			    "failed to recalibrate LO\n");
2648 			goto fail;
2649 		}
2650 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2651 		bwn_lo_write(mac, &cal->ctl);
2652 	}
2653 
2654 fail:
2655 	bwn_mac_enable(mac);
2656 }
2657 
2658 static void
2659 bwn_phy_g_task_60s(struct bwn_mac *mac)
2660 {
2661 	struct bwn_phy *phy = &mac->mac_phy;
2662 	struct bwn_softc *sc = mac->mac_sc;
2663 	uint8_t old = phy->chan;
2664 
2665 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2666 		return;
2667 
2668 	bwn_mac_suspend(mac);
2669 	bwn_nrssi_slope_11g(mac);
2670 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2671 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2672 		bwn_switch_channel(mac, old);
2673 	}
2674 	bwn_mac_enable(mac);
2675 }
2676 
2677 static void
2678 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2679 {
2680 
2681 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2682 }
2683 
2684 static int
2685 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2686 	const struct ieee80211_bpf_params *params)
2687 {
2688 	struct ieee80211com *ic = ni->ni_ic;
2689 	struct ifnet *ifp = ic->ic_ifp;
2690 	struct bwn_softc *sc = ifp->if_softc;
2691 	struct bwn_mac *mac = sc->sc_curmac;
2692 
2693 	if ((ifp->if_flags & IFF_RUNNING) == 0 ||
2694 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2695 		ieee80211_free_node(ni);
2696 		m_freem(m);
2697 		return (ENETDOWN);
2698 	}
2699 
2700 	if (bwn_tx_isfull(sc, m)) {
2701 		ieee80211_free_node(ni);
2702 		m_freem(m);
2703 		ifp->if_oerrors++;
2704 		return (ENOBUFS);
2705 	}
2706 
2707 	if (bwn_tx_start(sc, ni, m) != 0) {
2708 		if (ni != NULL)
2709 			ieee80211_free_node(ni);
2710 		ifp->if_oerrors++;
2711 	}
2712 	sc->sc_watchdog_timer = 5;
2713 	return (0);
2714 }
2715 
2716 /*
2717  * Callback from the 802.11 layer to update the slot time
2718  * based on the current setting.  We use it to notify the
2719  * firmware of ERP changes and the f/w takes care of things
2720  * like slot time and preamble.
2721  */
2722 static void
2723 bwn_updateslot(struct ifnet *ifp)
2724 {
2725 	struct bwn_softc *sc = ifp->if_softc;
2726 	struct ieee80211com *ic = ifp->if_l2com;
2727 	struct bwn_mac *mac;
2728 
2729 	if (ifp->if_flags & IFF_RUNNING) {
2730 		mac = (struct bwn_mac *)sc->sc_curmac;
2731 		bwn_set_slot_time(mac,
2732 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2733 	}
2734 }
2735 
2736 /*
2737  * Callback from the 802.11 layer after a promiscuous mode change.
2738  * Note this interface does not check the operating mode as this
2739  * is an internal callback and we are expected to honor the current
2740  * state (e.g. this is used for setting the interface in promiscuous
2741  * mode when operating in hostap mode to do ACS).
2742  */
2743 static void
2744 bwn_update_promisc(struct ifnet *ifp)
2745 {
2746 	struct bwn_softc *sc = ifp->if_softc;
2747 	struct bwn_mac *mac = sc->sc_curmac;
2748 
2749 	mac = sc->sc_curmac;
2750 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2751 		if (ifp->if_flags & IFF_PROMISC)
2752 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2753 		else
2754 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2755 		bwn_set_opmode(mac);
2756 	}
2757 }
2758 
2759 /*
2760  * Callback from the 802.11 layer to update WME parameters.
2761  */
2762 static int
2763 bwn_wme_update(struct ieee80211com *ic)
2764 {
2765 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2766 	struct bwn_mac *mac = sc->sc_curmac;
2767 	struct wmeParams *wmep;
2768 	int i;
2769 
2770 	mac = sc->sc_curmac;
2771 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2772 		bwn_mac_suspend(mac);
2773 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2774 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2775 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2776 		}
2777 		bwn_mac_enable(mac);
2778 	}
2779 	return (0);
2780 }
2781 
2782 static void
2783 bwn_scan_start(struct ieee80211com *ic)
2784 {
2785 	struct ifnet *ifp = ic->ic_ifp;
2786 	struct bwn_softc *sc = ifp->if_softc;
2787 	struct bwn_mac *mac;
2788 
2789 	mac = sc->sc_curmac;
2790 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2791 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2792 		bwn_set_opmode(mac);
2793 		/* disable CFP update during scan */
2794 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2795 	}
2796 }
2797 
2798 static void
2799 bwn_scan_end(struct ieee80211com *ic)
2800 {
2801 	struct ifnet *ifp = ic->ic_ifp;
2802 	struct bwn_softc *sc = ifp->if_softc;
2803 	struct bwn_mac *mac;
2804 
2805 	mac = sc->sc_curmac;
2806 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2807 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2808 		bwn_set_opmode(mac);
2809 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2810 	}
2811 }
2812 
2813 static void
2814 bwn_set_channel(struct ieee80211com *ic)
2815 {
2816 	struct ifnet *ifp = ic->ic_ifp;
2817 	struct bwn_softc *sc = ifp->if_softc;
2818 	struct bwn_mac *mac = sc->sc_curmac;
2819 	struct bwn_phy *phy = &mac->mac_phy;
2820 	int chan, error;
2821 
2822 	error = bwn_switch_band(sc, ic->ic_curchan);
2823 	if (error)
2824 		goto fail;
2825 	bwn_mac_suspend(mac);
2826 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2827 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2828 	if (chan != phy->chan)
2829 		bwn_switch_channel(mac, chan);
2830 
2831 	/* TX power level */
2832 	if (ic->ic_curchan->ic_maxpower != 0 &&
2833 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2834 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2835 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2836 		    BWN_TXPWR_IGNORE_TSSI);
2837 	}
2838 
2839 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2840 	if (phy->set_antenna)
2841 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2842 
2843 	if (sc->sc_rf_enabled != phy->rf_on) {
2844 		if (sc->sc_rf_enabled) {
2845 			bwn_rf_turnon(mac);
2846 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2847 				device_printf(sc->sc_dev,
2848 				    "please turn on the RF switch\n");
2849 		} else
2850 			bwn_rf_turnoff(mac);
2851 	}
2852 
2853 	bwn_mac_enable(mac);
2854 
2855 fail:
2856 	/*
2857 	 * Setup radio tap channel freq and flags
2858 	 */
2859 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2860 		htole16(ic->ic_curchan->ic_freq);
2861 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2862 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2863 }
2864 
2865 static struct ieee80211vap *
2866 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2867     enum ieee80211_opmode opmode, int flags,
2868     const uint8_t bssid[IEEE80211_ADDR_LEN],
2869     const uint8_t mac0[IEEE80211_ADDR_LEN])
2870 {
2871 	struct ifnet *ifp = ic->ic_ifp;
2872 	struct bwn_softc *sc = ifp->if_softc;
2873 	struct ieee80211vap *vap;
2874 	struct bwn_vap *bvp;
2875 	uint8_t mac[IEEE80211_ADDR_LEN];
2876 
2877 	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
2878 		return NULL;
2879 
2880 	IEEE80211_ADDR_COPY(mac, mac0);
2881 	switch (opmode) {
2882 	case IEEE80211_M_HOSTAP:
2883 	case IEEE80211_M_MBSS:
2884 	case IEEE80211_M_STA:
2885 	case IEEE80211_M_WDS:
2886 	case IEEE80211_M_MONITOR:
2887 	case IEEE80211_M_IBSS:
2888 	case IEEE80211_M_AHDEMO:
2889 		break;
2890 	default:
2891 		return (NULL);
2892 	}
2893 
2894 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2895 
2896 	bvp = (struct bwn_vap *) kmalloc(sizeof(struct bwn_vap),
2897 	    M_80211_VAP, M_INTWAIT | M_ZERO);
2898 	vap = &bvp->bv_vap;
2899 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2900 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2901 	/* override with driver methods */
2902 	bvp->bv_newstate = vap->iv_newstate;
2903 	vap->iv_newstate = bwn_newstate;
2904 
2905 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2906 	vap->iv_max_aid = BWN_STAID_MAX;
2907 
2908 	ieee80211_ratectl_init(vap);
2909 
2910 	/* complete setup */
2911 	ieee80211_vap_attach(vap, ieee80211_media_change,
2912 	    ieee80211_media_status);
2913 	ic->ic_opmode = opmode;
2914 	return (vap);
2915 }
2916 
2917 static void
2918 bwn_vap_delete(struct ieee80211vap *vap)
2919 {
2920 	struct bwn_vap *bvp = BWN_VAP(vap);
2921 
2922 	ieee80211_ratectl_deinit(vap);
2923 	ieee80211_vap_detach(vap);
2924 	kfree(bvp, M_80211_VAP);
2925 }
2926 
2927 static void
2928 bwn_init(void *arg)
2929 {
2930 	struct bwn_softc *sc = arg;
2931 	struct ifnet *ifp = sc->sc_ifp;
2932 	struct ieee80211com *ic = ifp->if_l2com;
2933 	int error = 0;
2934 
2935 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2936 		__func__, ifp->if_flags);
2937 
2938 	wlan_assert_serialized();
2939 	error = bwn_init_locked(sc);
2940 
2941 	if (error == 0)
2942 		ieee80211_start_all(ic);	/* start all vap's */
2943 }
2944 
2945 static int
2946 bwn_init_locked(struct bwn_softc *sc)
2947 {
2948 	struct bwn_mac *mac;
2949 	struct ifnet *ifp = sc->sc_ifp;
2950 	int error;
2951 
2952 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2953 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2954 	sc->sc_filters = 0;
2955 	bwn_wme_clear(sc);
2956 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2957 	sc->sc_rf_enabled = 1;
2958 
2959 	mac = sc->sc_curmac;
2960 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2961 		error = bwn_core_init(mac);
2962 		if (error != 0)
2963 			return (error);
2964 	}
2965 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2966 		bwn_core_start(mac);
2967 
2968 	bwn_set_opmode(mac);
2969 	bwn_set_pretbtt(mac);
2970 	bwn_spu_setdelay(mac, 0);
2971 	bwn_set_macaddr(mac);
2972 
2973 	ifp->if_flags |= IFF_RUNNING;
2974 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2975 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2976 
2977 	return (0);
2978 }
2979 
2980 static void
2981 bwn_stop(struct bwn_softc *sc, int statechg)
2982 {
2983 
2984 	wlan_assert_serialized();
2985 	bwn_stop_locked(sc, statechg);
2986 }
2987 
2988 static void
2989 bwn_stop_locked(struct bwn_softc *sc, int statechg)
2990 {
2991 	struct bwn_mac *mac = sc->sc_curmac;
2992 	struct ifnet *ifp = sc->sc_ifp;
2993 
2994 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2995 		/* XXX FIXME opmode not based on VAP */
2996 		bwn_set_opmode(mac);
2997 		bwn_set_macaddr(mac);
2998 	}
2999 
3000 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3001 		bwn_core_stop(mac);
3002 
3003 	callout_stop(&sc->sc_led_blink_ch);
3004 	sc->sc_led_blinking = 0;
3005 
3006 	bwn_core_exit(mac);
3007 	sc->sc_rf_enabled = 0;
3008 
3009 	ifp->if_flags &= ~IFF_RUNNING;
3010 	ifq_clr_oactive(&ifp->if_snd);
3011 }
3012 
3013 static void
3014 bwn_wme_clear(struct bwn_softc *sc)
3015 {
3016 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3017 	struct wmeParams *p;
3018 	unsigned int i;
3019 
3020 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3021 	    ("%s:%d: fail", __func__, __LINE__));
3022 
3023 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3024 		p = &(sc->sc_wmeParams[i]);
3025 
3026 		switch (bwn_wme_shm_offsets[i]) {
3027 		case BWN_WME_VOICE:
3028 			p->wmep_txopLimit = 0;
3029 			p->wmep_aifsn = 2;
3030 			/* XXX FIXME: log2(cwmin) */
3031 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3032 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3033 			break;
3034 		case BWN_WME_VIDEO:
3035 			p->wmep_txopLimit = 0;
3036 			p->wmep_aifsn = 2;
3037 			/* XXX FIXME: log2(cwmin) */
3038 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3039 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3040 			break;
3041 		case BWN_WME_BESTEFFORT:
3042 			p->wmep_txopLimit = 0;
3043 			p->wmep_aifsn = 3;
3044 			/* XXX FIXME: log2(cwmin) */
3045 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3046 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3047 			break;
3048 		case BWN_WME_BACKGROUND:
3049 			p->wmep_txopLimit = 0;
3050 			p->wmep_aifsn = 7;
3051 			/* XXX FIXME: log2(cwmin) */
3052 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3053 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3054 			break;
3055 		default:
3056 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3057 		}
3058 	}
3059 }
3060 
3061 static int
3062 bwn_core_init(struct bwn_mac *mac)
3063 {
3064 	struct bwn_softc *sc = mac->mac_sc;
3065 	uint64_t hf;
3066 	int error;
3067 
3068 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3069 	    ("%s:%d: fail", __func__, __LINE__));
3070 
3071 	siba_powerup(sc->sc_dev, 0);
3072 	if (!siba_dev_isup(sc->sc_dev))
3073 		bwn_reset_core(mac,
3074 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3075 
3076 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3077 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3078 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3079 	BWN_GETTIME(mac->mac_phy.nexttime);
3080 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3081 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3082 	mac->mac_stats.link_noise = -95;
3083 	mac->mac_reason_intr = 0;
3084 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3085 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3086 #ifdef BWN_DEBUG
3087 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3088 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3089 #endif
3090 	mac->mac_suspended = 1;
3091 	mac->mac_task_state = 0;
3092 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3093 
3094 	mac->mac_phy.init_pre(mac);
3095 
3096 	siba_pcicore_intr(sc->sc_dev);
3097 
3098 	siba_fix_imcfglobug(sc->sc_dev);
3099 	bwn_bt_disable(mac);
3100 	if (mac->mac_phy.prepare_hw) {
3101 		error = mac->mac_phy.prepare_hw(mac);
3102 		if (error)
3103 			goto fail0;
3104 	}
3105 	error = bwn_chip_init(mac);
3106 	if (error)
3107 		goto fail0;
3108 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3109 	    siba_get_revid(sc->sc_dev));
3110 	hf = bwn_hf_read(mac);
3111 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3112 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3113 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3114 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3115 		if (mac->mac_phy.rev == 1)
3116 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3117 	}
3118 	if (mac->mac_phy.rf_ver == 0x2050) {
3119 		if (mac->mac_phy.rf_rev < 6)
3120 			hf |= BWN_HF_FORCE_VCO_RECALC;
3121 		if (mac->mac_phy.rf_rev == 6)
3122 			hf |= BWN_HF_4318_TSSI;
3123 	}
3124 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3125 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3126 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3127 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3128 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3129 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3130 	bwn_hf_write(mac, hf);
3131 
3132 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3133 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3134 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3135 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3136 
3137 	bwn_rate_init(mac);
3138 	bwn_set_phytxctl(mac);
3139 
3140 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3141 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3142 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3143 
3144 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3145 		bwn_pio_init(mac);
3146 	else
3147 		bwn_dma_init(mac);
3148 	bwn_wme_init(mac);
3149 	bwn_spu_setdelay(mac, 1);
3150 	bwn_bt_enable(mac);
3151 
3152 	siba_powerup(sc->sc_dev,
3153 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3154 	bwn_set_macaddr(mac);
3155 	bwn_crypt_init(mac);
3156 
3157 	/* XXX LED initializatin */
3158 
3159 	mac->mac_status = BWN_MAC_STATUS_INITED;
3160 
3161 	return (error);
3162 
3163 fail0:
3164 	siba_powerdown(sc->sc_dev);
3165 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3166 	    ("%s:%d: fail", __func__, __LINE__));
3167 	return (error);
3168 }
3169 
3170 static void
3171 bwn_core_start(struct bwn_mac *mac)
3172 {
3173 	struct bwn_softc *sc = mac->mac_sc;
3174 	uint32_t tmp;
3175 
3176 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3177 	    ("%s:%d: fail", __func__, __LINE__));
3178 
3179 	if (siba_get_revid(sc->sc_dev) < 5)
3180 		return;
3181 
3182 	while (1) {
3183 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3184 		if (!(tmp & 0x00000001))
3185 			break;
3186 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3187 	}
3188 
3189 	bwn_mac_enable(mac);
3190 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3191 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3192 
3193 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3194 }
3195 
3196 static void
3197 bwn_core_exit(struct bwn_mac *mac)
3198 {
3199 	struct bwn_softc *sc = mac->mac_sc;
3200 	uint32_t macctl;
3201 
3202 	wlan_assert_serialized();
3203 
3204 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3205 	    ("%s:%d: fail", __func__, __LINE__));
3206 
3207 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3208 		return;
3209 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3210 
3211 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3212 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3213 	macctl |= BWN_MACCTL_MCODE_JMP0;
3214 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3215 
3216 	bwn_dma_stop(mac);
3217 	bwn_pio_stop(mac);
3218 	bwn_chip_exit(mac);
3219 	mac->mac_phy.switch_analog(mac, 0);
3220 	siba_dev_down(sc->sc_dev, 0);
3221 	siba_powerdown(sc->sc_dev);
3222 }
3223 
3224 static void
3225 bwn_bt_disable(struct bwn_mac *mac)
3226 {
3227 	struct bwn_softc *sc = mac->mac_sc;
3228 
3229 	(void)sc;
3230 	/* XXX do nothing yet */
3231 }
3232 
3233 static int
3234 bwn_chip_init(struct bwn_mac *mac)
3235 {
3236 	struct bwn_softc *sc = mac->mac_sc;
3237 	struct bwn_phy *phy = &mac->mac_phy;
3238 	uint32_t macctl;
3239 	int error;
3240 
3241 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3242 	if (phy->gmode)
3243 		macctl |= BWN_MACCTL_GMODE;
3244 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3245 
3246 	error = bwn_fw_fillinfo(mac);
3247 	if (error)
3248 		return (error);
3249 	error = bwn_fw_loaducode(mac);
3250 	if (error)
3251 		return (error);
3252 
3253 	error = bwn_gpio_init(mac);
3254 	if (error)
3255 		return (error);
3256 
3257 	error = bwn_fw_loadinitvals(mac);
3258 	if (error) {
3259 		siba_gpio_set(sc->sc_dev, 0);
3260 		return (error);
3261 	}
3262 	phy->switch_analog(mac, 1);
3263 	error = bwn_phy_init(mac);
3264 	if (error) {
3265 		siba_gpio_set(sc->sc_dev, 0);
3266 		return (error);
3267 	}
3268 	if (phy->set_im)
3269 		phy->set_im(mac, BWN_IMMODE_NONE);
3270 	if (phy->set_antenna)
3271 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3272 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3273 
3274 	if (phy->type == BWN_PHYTYPE_B)
3275 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3276 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3277 	if (siba_get_revid(sc->sc_dev) < 5)
3278 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3279 
3280 	BWN_WRITE_4(mac, BWN_MACCTL,
3281 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3282 	BWN_WRITE_4(mac, BWN_MACCTL,
3283 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3284 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3285 
3286 	bwn_set_opmode(mac);
3287 	if (siba_get_revid(sc->sc_dev) < 3) {
3288 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3289 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3290 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3291 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3292 	} else {
3293 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3294 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3295 	}
3296 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3297 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001fc00);
3298 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3299 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3300 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3301 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3302 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3303 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3304 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3305 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3306 	return (error);
3307 }
3308 
3309 /* read hostflags */
3310 static uint64_t
3311 bwn_hf_read(struct bwn_mac *mac)
3312 {
3313 	uint64_t ret;
3314 
3315 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3316 	ret <<= 16;
3317 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3318 	ret <<= 16;
3319 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3320 	return (ret);
3321 }
3322 
3323 static void
3324 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3325 {
3326 
3327 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3328 	    (value & 0x00000000ffffull));
3329 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3330 	    (value & 0x0000ffff0000ull) >> 16);
3331 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3332 	    (value & 0xffff00000000ULL) >> 32);
3333 }
3334 
3335 static void
3336 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3337 {
3338 
3339 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3340 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3341 }
3342 
3343 static void
3344 bwn_rate_init(struct bwn_mac *mac)
3345 {
3346 
3347 	switch (mac->mac_phy.type) {
3348 	case BWN_PHYTYPE_A:
3349 	case BWN_PHYTYPE_G:
3350 	case BWN_PHYTYPE_LP:
3351 	case BWN_PHYTYPE_N:
3352 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3353 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3354 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3355 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3356 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3357 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3358 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3359 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3360 			break;
3361 		/* FALLTHROUGH */
3362 	case BWN_PHYTYPE_B:
3363 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3364 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3365 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3366 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3367 		break;
3368 	default:
3369 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3370 	}
3371 }
3372 
3373 static void
3374 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3375 {
3376 	uint16_t offset;
3377 
3378 	if (ofdm) {
3379 		offset = 0x480;
3380 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3381 	} else {
3382 		offset = 0x4c0;
3383 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3384 	}
3385 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3386 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3387 }
3388 
3389 static uint8_t
3390 bwn_plcp_getcck(const uint8_t bitrate)
3391 {
3392 
3393 	switch (bitrate) {
3394 	case BWN_CCK_RATE_1MB:
3395 		return (0x0a);
3396 	case BWN_CCK_RATE_2MB:
3397 		return (0x14);
3398 	case BWN_CCK_RATE_5MB:
3399 		return (0x37);
3400 	case BWN_CCK_RATE_11MB:
3401 		return (0x6e);
3402 	}
3403 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3404 	return (0);
3405 }
3406 
3407 static uint8_t
3408 bwn_plcp_getofdm(const uint8_t bitrate)
3409 {
3410 
3411 	switch (bitrate) {
3412 	case BWN_OFDM_RATE_6MB:
3413 		return (0xb);
3414 	case BWN_OFDM_RATE_9MB:
3415 		return (0xf);
3416 	case BWN_OFDM_RATE_12MB:
3417 		return (0xa);
3418 	case BWN_OFDM_RATE_18MB:
3419 		return (0xe);
3420 	case BWN_OFDM_RATE_24MB:
3421 		return (0x9);
3422 	case BWN_OFDM_RATE_36MB:
3423 		return (0xd);
3424 	case BWN_OFDM_RATE_48MB:
3425 		return (0x8);
3426 	case BWN_OFDM_RATE_54MB:
3427 		return (0xc);
3428 	}
3429 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3430 	return (0);
3431 }
3432 
3433 static void
3434 bwn_set_phytxctl(struct bwn_mac *mac)
3435 {
3436 	uint16_t ctl;
3437 
3438 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3439 	    BWN_TX_PHY_TXPWR);
3440 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3441 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3442 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3443 }
3444 
3445 static void
3446 bwn_pio_init(struct bwn_mac *mac)
3447 {
3448 	struct bwn_pio *pio = &mac->mac_method.pio;
3449 
3450 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3451 	    & ~BWN_MACCTL_BIGENDIAN);
3452 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3453 
3454 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3455 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3456 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3457 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3458 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3459 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3460 }
3461 
3462 static void
3463 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3464     int index)
3465 {
3466 	struct bwn_pio_txpkt *tp;
3467 	struct bwn_softc *sc = mac->mac_sc;
3468 	unsigned int i;
3469 
3470 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3471 	tq->tq_index = index;
3472 
3473 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3474 	if (siba_get_revid(sc->sc_dev) >= 8)
3475 		tq->tq_size = 1920;
3476 	else {
3477 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3478 		tq->tq_size -= 80;
3479 	}
3480 
3481 	TAILQ_INIT(&tq->tq_pktlist);
3482 	for (i = 0; i < N(tq->tq_pkts); i++) {
3483 		tp = &(tq->tq_pkts[i]);
3484 		tp->tp_index = i;
3485 		tp->tp_queue = tq;
3486 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3487 	}
3488 }
3489 
3490 static uint16_t
3491 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3492 {
3493 	struct bwn_softc *sc = mac->mac_sc;
3494 	static const uint16_t bases[] = {
3495 		BWN_PIO_BASE0,
3496 		BWN_PIO_BASE1,
3497 		BWN_PIO_BASE2,
3498 		BWN_PIO_BASE3,
3499 		BWN_PIO_BASE4,
3500 		BWN_PIO_BASE5,
3501 		BWN_PIO_BASE6,
3502 		BWN_PIO_BASE7,
3503 	};
3504 	static const uint16_t bases_rev11[] = {
3505 		BWN_PIO11_BASE0,
3506 		BWN_PIO11_BASE1,
3507 		BWN_PIO11_BASE2,
3508 		BWN_PIO11_BASE3,
3509 		BWN_PIO11_BASE4,
3510 		BWN_PIO11_BASE5,
3511 	};
3512 
3513 	if (siba_get_revid(sc->sc_dev) >= 11) {
3514 		if (index >= N(bases_rev11))
3515 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3516 		return (bases_rev11[index]);
3517 	}
3518 	if (index >= N(bases))
3519 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3520 	return (bases[index]);
3521 }
3522 
3523 static void
3524 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3525     int index)
3526 {
3527 	struct bwn_softc *sc = mac->mac_sc;
3528 
3529 	prq->prq_mac = mac;
3530 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3531 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3532 	bwn_dma_rxdirectfifo(mac, index, 1);
3533 }
3534 
3535 static void
3536 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3537 {
3538 	if (tq == NULL)
3539 		return;
3540 	bwn_pio_cancel_tx_packets(tq);
3541 }
3542 
3543 static void
3544 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3545 {
3546 
3547 	bwn_destroy_pioqueue_tx(pio);
3548 }
3549 
3550 static uint16_t
3551 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3552     uint16_t offset)
3553 {
3554 
3555 	return (BWN_READ_2(mac, tq->tq_base + offset));
3556 }
3557 
3558 static void
3559 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3560 {
3561 	uint32_t ctl;
3562 	int type;
3563 	uint16_t base;
3564 
3565 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3566 	base = bwn_dma_base(type, idx);
3567 	if (type == BWN_DMA_64BIT) {
3568 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3569 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3570 		if (enable)
3571 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3572 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3573 	} else {
3574 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3575 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3576 		if (enable)
3577 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3578 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3579 	}
3580 }
3581 
3582 static uint64_t
3583 bwn_dma_mask(struct bwn_mac *mac)
3584 {
3585 	uint32_t tmp;
3586 	uint16_t base;
3587 
3588 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3589 	if (tmp & SIBA_TGSHIGH_DMA64)
3590 		return (BWN_DMA_BIT_MASK(64));
3591 	base = bwn_dma_base(0, 0);
3592 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3593 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3594 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3595 		return (BWN_DMA_BIT_MASK(32));
3596 
3597 	return (BWN_DMA_BIT_MASK(30));
3598 }
3599 
3600 static int
3601 bwn_dma_mask2type(uint64_t dmamask)
3602 {
3603 
3604 	if (dmamask == BWN_DMA_BIT_MASK(30))
3605 		return (BWN_DMA_30BIT);
3606 	if (dmamask == BWN_DMA_BIT_MASK(32))
3607 		return (BWN_DMA_32BIT);
3608 	if (dmamask == BWN_DMA_BIT_MASK(64))
3609 		return (BWN_DMA_64BIT);
3610 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3611 	return (BWN_DMA_30BIT);
3612 }
3613 
3614 static void
3615 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3616 {
3617 	struct bwn_pio_txpkt *tp;
3618 	unsigned int i;
3619 
3620 	for (i = 0; i < N(tq->tq_pkts); i++) {
3621 		tp = &(tq->tq_pkts[i]);
3622 		if (tp->tp_m) {
3623 			m_freem(tp->tp_m);
3624 			tp->tp_m = NULL;
3625 		}
3626 	}
3627 }
3628 
3629 static uint16_t
3630 bwn_dma_base(int type, int controller_idx)
3631 {
3632 	static const uint16_t map64[] = {
3633 		BWN_DMA64_BASE0,
3634 		BWN_DMA64_BASE1,
3635 		BWN_DMA64_BASE2,
3636 		BWN_DMA64_BASE3,
3637 		BWN_DMA64_BASE4,
3638 		BWN_DMA64_BASE5,
3639 	};
3640 	static const uint16_t map32[] = {
3641 		BWN_DMA32_BASE0,
3642 		BWN_DMA32_BASE1,
3643 		BWN_DMA32_BASE2,
3644 		BWN_DMA32_BASE3,
3645 		BWN_DMA32_BASE4,
3646 		BWN_DMA32_BASE5,
3647 	};
3648 
3649 	if (type == BWN_DMA_64BIT) {
3650 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3651 		    ("%s:%d: fail", __func__, __LINE__));
3652 		return (map64[controller_idx]);
3653 	}
3654 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3655 	    ("%s:%d: fail", __func__, __LINE__));
3656 	return (map32[controller_idx]);
3657 }
3658 
3659 static void
3660 bwn_dma_init(struct bwn_mac *mac)
3661 {
3662 	struct bwn_dma *dma = &mac->mac_method.dma;
3663 
3664 	/* setup TX DMA channels. */
3665 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3666 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3667 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3668 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3669 	bwn_dma_setup(dma->mcast);
3670 	/* setup RX DMA channel. */
3671 	bwn_dma_setup(dma->rx);
3672 }
3673 
3674 static struct bwn_dma_ring *
3675 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3676     int for_tx, int type)
3677 {
3678 	struct bwn_dma *dma = &mac->mac_method.dma;
3679 	struct bwn_dma_ring *dr;
3680 	struct bwn_dmadesc_generic *desc;
3681 	struct bwn_dmadesc_meta *mt;
3682 	struct bwn_softc *sc = mac->mac_sc;
3683 	int error, i;
3684 
3685 	dr = kmalloc(sizeof(*dr), M_DEVBUF, M_INTWAIT | M_ZERO);
3686 	dr->dr_numslots = BWN_RXRING_SLOTS;
3687 	if (for_tx)
3688 		dr->dr_numslots = BWN_TXRING_SLOTS;
3689 
3690 	dr->dr_meta = kmalloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3691 	    M_DEVBUF, M_INTWAIT | M_ZERO);
3692 
3693 	dr->dr_type = type;
3694 	dr->dr_mac = mac;
3695 	dr->dr_base = bwn_dma_base(type, controller_index);
3696 	dr->dr_index = controller_index;
3697 	if (type == BWN_DMA_64BIT) {
3698 		dr->getdesc = bwn_dma_64_getdesc;
3699 		dr->setdesc = bwn_dma_64_setdesc;
3700 		dr->start_transfer = bwn_dma_64_start_transfer;
3701 		dr->suspend = bwn_dma_64_suspend;
3702 		dr->resume = bwn_dma_64_resume;
3703 		dr->get_curslot = bwn_dma_64_get_curslot;
3704 		dr->set_curslot = bwn_dma_64_set_curslot;
3705 	} else {
3706 		dr->getdesc = bwn_dma_32_getdesc;
3707 		dr->setdesc = bwn_dma_32_setdesc;
3708 		dr->start_transfer = bwn_dma_32_start_transfer;
3709 		dr->suspend = bwn_dma_32_suspend;
3710 		dr->resume = bwn_dma_32_resume;
3711 		dr->get_curslot = bwn_dma_32_get_curslot;
3712 		dr->set_curslot = bwn_dma_32_set_curslot;
3713 	}
3714 	if (for_tx) {
3715 		dr->dr_tx = 1;
3716 		dr->dr_curslot = -1;
3717 	} else {
3718 		if (dr->dr_index == 0) {
3719 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3720 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3721 		} else
3722 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3723 	}
3724 
3725 	error = bwn_dma_allocringmemory(dr);
3726 	if (error)
3727 		goto fail1;
3728 
3729 	if (for_tx) {
3730 		/*
3731 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3732 		 * BWN_TX_SLOTS_PER_FRAME
3733 		 */
3734 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3735 		    ("%s:%d: fail", __func__, __LINE__));
3736 
3737 		/*
3738 		 * Create TX ring DMA stuffs
3739 		 */
3740 		dr->dr_txhdr_cache = bus_dmamem_coherent_any(dma->parent_dtag,
3741 		    4, (dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3742 		    BWN_MAX_HDRSIZE(mac),
3743 		    BUS_DMA_WAITOK | BUS_DMA_ZERO,
3744 		    &dr->dr_txring_dtag, &dr->dr_txring_dmap,
3745 		    &dr->dr_txring_paddr);
3746 		if (dr->dr_txhdr_cache == NULL) {
3747 			device_printf(sc->sc_dev,
3748 			    "can't create TX ring DMA memory\n");
3749 			goto fail1;
3750 		}
3751 
3752 		for (i = 0; i < dr->dr_numslots; i += 2) {
3753 			dr->getdesc(dr, i, &desc, &mt);
3754 
3755 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3756 			mt->mt_m = NULL;
3757 			mt->mt_ni = NULL;
3758 			mt->mt_islast = 0;
3759 			mt->mt_dmap = dr->dr_txring_dmap;
3760 			mt->mt_paddr = dr->dr_txring_paddr +
3761 			    (i / BWN_TX_SLOTS_PER_FRAME) *
3762 			    BWN_MAX_HDRSIZE(mac);
3763 
3764 			dr->getdesc(dr, i + 1, &desc, &mt);
3765 
3766 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3767 			mt->mt_m = NULL;
3768 			mt->mt_ni = NULL;
3769 			mt->mt_islast = 1;
3770 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3771 			    &mt->mt_dmap);
3772 			if (error) {
3773 				device_printf(sc->sc_dev,
3774 				     "can't create RX buf DMA map\n");
3775 				goto fail2;
3776 			}
3777 		}
3778 	} else {
3779 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3780 		    &dr->dr_spare_dmap);
3781 		if (error) {
3782 			device_printf(sc->sc_dev,
3783 			    "can't create RX buf DMA map\n");
3784 			goto out;		/* XXX wrong! */
3785 		}
3786 
3787 		for (i = 0; i < dr->dr_numslots; i++) {
3788 			dr->getdesc(dr, i, &desc, &mt);
3789 
3790 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3791 			    &mt->mt_dmap);
3792 			if (error) {
3793 				device_printf(sc->sc_dev,
3794 				    "can't create RX buf DMA map\n");
3795 				goto out;	/* XXX wrong! */
3796 			}
3797 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3798 			if (error) {
3799 				device_printf(sc->sc_dev,
3800 				    "failed to allocate RX buf\n");
3801 				goto out;	/* XXX wrong! */
3802 			}
3803 		}
3804 
3805 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3806 		    BUS_DMASYNC_PREWRITE);
3807 
3808 		dr->dr_usedslot = dr->dr_numslots;
3809 	}
3810 
3811       out:
3812 	return (dr);
3813 
3814 fail2:
3815 	/* XXX free up dma allocations */
3816 fail1:
3817 	kfree(dr->dr_meta, M_DEVBUF);
3818 	kfree(dr, M_DEVBUF);
3819 	return (NULL);
3820 }
3821 
3822 static void
3823 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3824 {
3825 
3826 	if (dr == NULL)
3827 		return;
3828 
3829 	bwn_dma_free_descbufs(*dr);
3830 	bwn_dma_free_ringmemory(*dr);
3831 
3832 	if ((*dr)->dr_meta != NULL)
3833 		kfree((*dr)->dr_meta, M_DEVBUF);
3834 	kfree(*dr, M_DEVBUF);
3835 
3836 	*dr = NULL;
3837 }
3838 
3839 static void
3840 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3841     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3842 {
3843 	struct bwn_dmadesc32 *desc;
3844 
3845 	*meta = &(dr->dr_meta[slot]);
3846 	desc = dr->dr_ring_descbase;
3847 	desc = &(desc[slot]);
3848 
3849 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3850 }
3851 
3852 static void
3853 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3854     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3855     int start, int end, int irq)
3856 {
3857 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3858 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3859 	uint32_t addr, addrext, ctl;
3860 	int slot;
3861 
3862 	slot = (int)(&(desc->dma.dma32) - descbase);
3863 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3864 	    ("%s:%d: fail", __func__, __LINE__));
3865 
3866 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3867 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3868 	addr |= siba_dma_translation(sc->sc_dev);
3869 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3870 	if (slot == dr->dr_numslots - 1)
3871 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3872 	if (start)
3873 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3874 	if (end)
3875 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3876 	if (irq)
3877 		ctl |= BWN_DMA32_DCTL_IRQ;
3878 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3879 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3880 
3881 	desc->dma.dma32.control = htole32(ctl);
3882 	desc->dma.dma32.address = htole32(addr);
3883 }
3884 
3885 static void
3886 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3887 {
3888 
3889 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3890 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3891 }
3892 
3893 static void
3894 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3895 {
3896 
3897 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3898 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3899 }
3900 
3901 static void
3902 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3903 {
3904 
3905 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3906 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3907 }
3908 
3909 static int
3910 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3911 {
3912 	uint32_t val;
3913 
3914 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3915 	val &= BWN_DMA32_RXDPTR;
3916 
3917 	return (val / sizeof(struct bwn_dmadesc32));
3918 }
3919 
3920 static void
3921 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3922 {
3923 
3924 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3925 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3926 }
3927 
3928 static void
3929 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3930     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3931 {
3932 	struct bwn_dmadesc64 *desc;
3933 
3934 	*meta = &(dr->dr_meta[slot]);
3935 	desc = dr->dr_ring_descbase;
3936 	desc = &(desc[slot]);
3937 
3938 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3939 }
3940 
3941 static void
3942 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3943     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3944     int start, int end, int irq)
3945 {
3946 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3947 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3948 	int slot;
3949 	uint32_t ctl0 = 0, ctl1 = 0;
3950 	uint32_t addrlo, addrhi;
3951 	uint32_t addrext;
3952 
3953 	slot = (int)(&(desc->dma.dma64) - descbase);
3954 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3955 	    ("%s:%d: fail", __func__, __LINE__));
3956 
3957 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3958 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3959 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3960 	    30;
3961 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3962 	if (slot == dr->dr_numslots - 1)
3963 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3964 	if (start)
3965 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3966 	if (end)
3967 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3968 	if (irq)
3969 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3970 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3971 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3972 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3973 
3974 	desc->dma.dma64.control0 = htole32(ctl0);
3975 	desc->dma.dma64.control1 = htole32(ctl1);
3976 	desc->dma.dma64.address_low = htole32(addrlo);
3977 	desc->dma.dma64.address_high = htole32(addrhi);
3978 }
3979 
3980 static void
3981 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3982 {
3983 
3984 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3985 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3986 }
3987 
3988 static void
3989 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3990 {
3991 
3992 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3993 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3994 }
3995 
3996 static void
3997 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3998 {
3999 
4000 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4001 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4002 }
4003 
4004 static int
4005 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4006 {
4007 	uint32_t val;
4008 
4009 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4010 	val &= BWN_DMA64_RXSTATDPTR;
4011 
4012 	return (val / sizeof(struct bwn_dmadesc64));
4013 }
4014 
4015 static void
4016 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4017 {
4018 
4019 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4020 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4021 }
4022 
4023 static int
4024 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4025 {
4026 	struct bwn_mac *mac = dr->dr_mac;
4027 	struct bwn_dma *dma = &mac->mac_method.dma;
4028 	struct bwn_softc *sc = mac->mac_sc;
4029 	int error;
4030 
4031 	error = bus_dma_tag_create(dma->parent_dtag,
4032 			    BWN_ALIGN, 0,
4033 			    BUS_SPACE_MAXADDR,
4034 			    BUS_SPACE_MAXADDR,
4035 			    NULL, NULL,
4036 			    BWN_DMA_RINGMEMSIZE,
4037 			    1,
4038 			    BUS_SPACE_MAXSIZE_32BIT,
4039 			    0,
4040 			    &dr->dr_ring_dtag);
4041 	if (error) {
4042 		device_printf(sc->sc_dev,
4043 		    "can't create TX ring DMA tag: TODO frees\n");
4044 		return (-1);
4045 	}
4046 
4047 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4048 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4049 	    &dr->dr_ring_dmap);
4050 	if (error) {
4051 		device_printf(sc->sc_dev,
4052 		    "can't allocate DMA mem: TODO frees\n");
4053 		return (-1);
4054 	}
4055 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4056 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4057 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, 0);
4058 	if (error) {
4059 		device_printf(sc->sc_dev,
4060 		    "can't load DMA mem: TODO free\n");
4061 		return (-1);
4062 	}
4063 
4064 	return (0);
4065 }
4066 
4067 static void
4068 bwn_dma_setup(struct bwn_dma_ring *dr)
4069 {
4070 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4071 	uint64_t ring64;
4072 	uint32_t addrext, ring32, value;
4073 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4074 
4075 	if (dr->dr_tx) {
4076 		dr->dr_curslot = -1;
4077 
4078 		if (dr->dr_type == BWN_DMA_64BIT) {
4079 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4080 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4081 			    >> 30;
4082 			value = BWN_DMA64_TXENABLE;
4083 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4084 			    & BWN_DMA64_TXADDREXT_MASK;
4085 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4086 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4087 			    (ring64 & 0xffffffff));
4088 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4089 			    ((ring64 >> 32) &
4090 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4091 		} else {
4092 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4093 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4094 			value = BWN_DMA32_TXENABLE;
4095 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4096 			    & BWN_DMA32_TXADDREXT_MASK;
4097 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4098 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4099 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4100 		}
4101 		return;
4102 	}
4103 
4104 	/*
4105 	 * set for RX
4106 	 */
4107 	dr->dr_usedslot = dr->dr_numslots;
4108 
4109 	if (dr->dr_type == BWN_DMA_64BIT) {
4110 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4111 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4112 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4113 		value |= BWN_DMA64_RXENABLE;
4114 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4115 		    & BWN_DMA64_RXADDREXT_MASK;
4116 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4117 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4118 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4119 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4120 		    | (trans << 1));
4121 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4122 		    sizeof(struct bwn_dmadesc64));
4123 	} else {
4124 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4125 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4126 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4127 		value |= BWN_DMA32_RXENABLE;
4128 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4129 		    & BWN_DMA32_RXADDREXT_MASK;
4130 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4131 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4132 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4133 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4134 		    sizeof(struct bwn_dmadesc32));
4135 	}
4136 }
4137 
4138 static void
4139 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4140 {
4141 
4142 	if (dr->dr_tx) {
4143 		bus_dmamap_unload(dr->dr_txring_dtag, dr->dr_txring_dmap);
4144 		if (dr->dr_txhdr_cache != NULL)
4145 			bus_dmamem_free(dr->dr_txring_dtag, dr->dr_txhdr_cache,
4146 			    dr->dr_txring_dmap);
4147 		bus_dma_tag_destroy(dr->dr_txring_dtag);
4148 	}
4149 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4150 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4151 	    dr->dr_ring_dmap);
4152 	bus_dma_tag_destroy(dr->dr_ring_dtag);
4153 }
4154 
4155 static void
4156 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4157 {
4158 
4159 	if (dr->dr_tx) {
4160 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4161 		if (dr->dr_type == BWN_DMA_64BIT) {
4162 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4163 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4164 		} else
4165 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4166 	} else {
4167 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4168 		if (dr->dr_type == BWN_DMA_64BIT) {
4169 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4170 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4171 		} else
4172 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4173 	}
4174 }
4175 
4176 static void
4177 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4178 {
4179 	struct bwn_dmadesc_generic *desc;
4180 	struct bwn_dmadesc_meta *meta;
4181 	struct bwn_mac *mac = dr->dr_mac;
4182 	struct bwn_dma *dma = &mac->mac_method.dma;
4183 	struct bwn_softc *sc = mac->mac_sc;
4184 	int i;
4185 
4186 	if (!dr->dr_usedslot)
4187 		return;
4188 	for (i = 0; i < dr->dr_numslots; i++) {
4189 		dr->getdesc(dr, i, &desc, &meta);
4190 
4191 		if (meta->mt_m == NULL) {
4192 			if (!dr->dr_tx)
4193 				device_printf(sc->sc_dev, "%s: not TX?\n",
4194 				    __func__);
4195 			continue;
4196 		}
4197 		if (dr->dr_tx) {
4198 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) {
4199 				/* Nothing */
4200 			} else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) {
4201 				bus_dmamap_unload(dma->txbuf_dtag,
4202 				    meta->mt_dmap);
4203 			}
4204 		} else
4205 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4206 		bwn_dma_free_descbuf(dr, meta);
4207 	}
4208 }
4209 
4210 static int
4211 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4212     int type)
4213 {
4214 	struct bwn_softc *sc = mac->mac_sc;
4215 	uint32_t value;
4216 	int i;
4217 	uint16_t offset;
4218 
4219 	for (i = 0; i < 10; i++) {
4220 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4221 		    BWN_DMA32_TXSTATUS;
4222 		value = BWN_READ_4(mac, base + offset);
4223 		if (type == BWN_DMA_64BIT) {
4224 			value &= BWN_DMA64_TXSTAT;
4225 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4226 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4227 			    value == BWN_DMA64_TXSTAT_STOPPED)
4228 				break;
4229 		} else {
4230 			value &= BWN_DMA32_TXSTATE;
4231 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4232 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4233 			    value == BWN_DMA32_TXSTAT_STOPPED)
4234 				break;
4235 		}
4236 		DELAY(1000);
4237 	}
4238 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4239 	BWN_WRITE_4(mac, base + offset, 0);
4240 	for (i = 0; i < 10; i++) {
4241 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4242 						   BWN_DMA32_TXSTATUS;
4243 		value = BWN_READ_4(mac, base + offset);
4244 		if (type == BWN_DMA_64BIT) {
4245 			value &= BWN_DMA64_TXSTAT;
4246 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4247 				i = -1;
4248 				break;
4249 			}
4250 		} else {
4251 			value &= BWN_DMA32_TXSTATE;
4252 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4253 				i = -1;
4254 				break;
4255 			}
4256 		}
4257 		DELAY(1000);
4258 	}
4259 	if (i != -1) {
4260 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4261 		return (ENODEV);
4262 	}
4263 	DELAY(1000);
4264 
4265 	return (0);
4266 }
4267 
4268 static int
4269 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4270     int type)
4271 {
4272 	struct bwn_softc *sc = mac->mac_sc;
4273 	uint32_t value;
4274 	int i;
4275 	uint16_t offset;
4276 
4277 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4278 	BWN_WRITE_4(mac, base + offset, 0);
4279 	for (i = 0; i < 10; i++) {
4280 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4281 		    BWN_DMA32_RXSTATUS;
4282 		value = BWN_READ_4(mac, base + offset);
4283 		if (type == BWN_DMA_64BIT) {
4284 			value &= BWN_DMA64_RXSTAT;
4285 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4286 				i = -1;
4287 				break;
4288 			}
4289 		} else {
4290 			value &= BWN_DMA32_RXSTATE;
4291 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4292 				i = -1;
4293 				break;
4294 			}
4295 		}
4296 		DELAY(1000);
4297 	}
4298 	if (i != -1) {
4299 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4300 		return (ENODEV);
4301 	}
4302 
4303 	return (0);
4304 }
4305 
4306 static void
4307 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4308     struct bwn_dmadesc_meta *meta)
4309 {
4310 
4311 	if (meta->mt_m != NULL) {
4312 		m_freem(meta->mt_m);
4313 		meta->mt_m = NULL;
4314 	}
4315 	if (meta->mt_ni != NULL) {
4316 		ieee80211_free_node(meta->mt_ni);
4317 		meta->mt_ni = NULL;
4318 	}
4319 }
4320 
4321 static void
4322 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4323 {
4324 	struct bwn_rxhdr4 *rxhdr;
4325 	unsigned char *frame;
4326 
4327 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4328 	rxhdr->frame_len = 0;
4329 
4330 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4331 	    sizeof(struct bwn_plcp6) + 2,
4332 	    ("%s:%d: fail", __func__, __LINE__));
4333 	frame = mtod(m, char *) + dr->dr_frameoffset;
4334 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4335 }
4336 
4337 static uint8_t
4338 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4339 {
4340 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4341 
4342 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4343 	    == 0xff);
4344 }
4345 
4346 static void
4347 bwn_wme_init(struct bwn_mac *mac)
4348 {
4349 
4350 	bwn_wme_load(mac);
4351 
4352 	/* enable WME support. */
4353 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4354 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4355 	    BWN_IFSCTL_USE_EDCF);
4356 }
4357 
4358 static void
4359 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4360 {
4361 	struct bwn_softc *sc = mac->mac_sc;
4362 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4363 	uint16_t delay;	/* microsec */
4364 
4365 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4366 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4367 		delay = 500;
4368 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4369 		delay = max(delay, (uint16_t)2400);
4370 
4371 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4372 }
4373 
4374 static void
4375 bwn_bt_enable(struct bwn_mac *mac)
4376 {
4377 	struct bwn_softc *sc = mac->mac_sc;
4378 	uint64_t hf;
4379 
4380 	if (bwn_bluetooth == 0)
4381 		return;
4382 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4383 		return;
4384 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4385 		return;
4386 
4387 	hf = bwn_hf_read(mac);
4388 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4389 		hf |= BWN_HF_BT_COEXISTALT;
4390 	else
4391 		hf |= BWN_HF_BT_COEXIST;
4392 	bwn_hf_write(mac, hf);
4393 }
4394 
4395 static void
4396 bwn_set_macaddr(struct bwn_mac *mac)
4397 {
4398 
4399 	bwn_mac_write_bssid(mac);
4400 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4401 }
4402 
4403 static void
4404 bwn_clear_keys(struct bwn_mac *mac)
4405 {
4406 	int i;
4407 
4408 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4409 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4410 		    ("%s:%d: fail", __func__, __LINE__));
4411 
4412 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4413 		    NULL, BWN_SEC_KEYSIZE, NULL);
4414 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4415 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4416 			    NULL, BWN_SEC_KEYSIZE, NULL);
4417 		}
4418 		mac->mac_key[i].keyconf = NULL;
4419 	}
4420 }
4421 
4422 static void
4423 bwn_crypt_init(struct bwn_mac *mac)
4424 {
4425 	struct bwn_softc *sc = mac->mac_sc;
4426 
4427 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4428 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4429 	    ("%s:%d: fail", __func__, __LINE__));
4430 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4431 	mac->mac_ktp *= 2;
4432 	if (siba_get_revid(sc->sc_dev) >= 5)
4433 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4434 	bwn_clear_keys(mac);
4435 }
4436 
4437 static void
4438 bwn_chip_exit(struct bwn_mac *mac)
4439 {
4440 	struct bwn_softc *sc = mac->mac_sc;
4441 
4442 	bwn_phy_exit(mac);
4443 	siba_gpio_set(sc->sc_dev, 0);
4444 }
4445 
4446 static int
4447 bwn_fw_fillinfo(struct bwn_mac *mac)
4448 {
4449 	int error;
4450 
4451 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4452 	if (error == 0)
4453 		return (0);
4454 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4455 	if (error == 0)
4456 		return (0);
4457 	return (error);
4458 }
4459 
4460 static int
4461 bwn_gpio_init(struct bwn_mac *mac)
4462 {
4463 	struct bwn_softc *sc = mac->mac_sc;
4464 	uint32_t mask = 0x1f, set = 0xf, value;
4465 
4466 	BWN_WRITE_4(mac, BWN_MACCTL,
4467 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4468 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4469 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4470 
4471 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4472 		mask |= 0x0060;
4473 		set |= 0x0060;
4474 	}
4475 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4476 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4477 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4478 		mask |= 0x0200;
4479 		set |= 0x0200;
4480 	}
4481 	if (siba_get_revid(sc->sc_dev) >= 2)
4482 		mask |= 0x0010;
4483 
4484 	value = siba_gpio_get(sc->sc_dev);
4485 	if (value == -1)
4486 		return (0);
4487 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4488 
4489 	return (0);
4490 }
4491 
4492 static int
4493 bwn_fw_loadinitvals(struct bwn_mac *mac)
4494 {
4495 #define	GETFWOFFSET(fwp, offset)				\
4496 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4497 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4498 	const struct bwn_fwhdr *hdr;
4499 	struct bwn_fw *fw = &mac->mac_fw;
4500 	int error;
4501 
4502 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4503 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4504 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4505 	if (error)
4506 		return (error);
4507 	if (fw->initvals_band.fw) {
4508 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4509 		error = bwn_fwinitvals_write(mac,
4510 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4511 		    be32toh(hdr->size),
4512 		    fw->initvals_band.fw->datasize - hdr_len);
4513 	}
4514 	return (error);
4515 #undef GETFWOFFSET
4516 }
4517 
4518 static int
4519 bwn_phy_init(struct bwn_mac *mac)
4520 {
4521 	struct bwn_softc *sc = mac->mac_sc;
4522 	int error;
4523 
4524 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4525 	mac->mac_phy.rf_onoff(mac, 1);
4526 	error = mac->mac_phy.init(mac);
4527 	if (error) {
4528 		device_printf(sc->sc_dev, "PHY init failed\n");
4529 		goto fail0;
4530 	}
4531 	error = bwn_switch_channel(mac,
4532 	    mac->mac_phy.get_default_chan(mac));
4533 	if (error) {
4534 		device_printf(sc->sc_dev,
4535 		    "failed to switch default channel\n");
4536 		goto fail1;
4537 	}
4538 	return (0);
4539 fail1:
4540 	if (mac->mac_phy.exit)
4541 		mac->mac_phy.exit(mac);
4542 fail0:
4543 	mac->mac_phy.rf_onoff(mac, 0);
4544 
4545 	return (error);
4546 }
4547 
4548 static void
4549 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4550 {
4551 	uint16_t ant;
4552 	uint16_t tmp;
4553 
4554 	ant = bwn_ant2phy(antenna);
4555 
4556 	/* For ACK/CTS */
4557 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4558 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4559 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4560 	/* For Probe Resposes */
4561 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4562 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4563 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4564 }
4565 
4566 static void
4567 bwn_set_opmode(struct bwn_mac *mac)
4568 {
4569 	struct bwn_softc *sc = mac->mac_sc;
4570 	struct ifnet *ifp = sc->sc_ifp;
4571 	struct ieee80211com *ic = ifp->if_l2com;
4572 	uint32_t ctl;
4573 	uint16_t cfp_pretbtt;
4574 
4575 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4576 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4577 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4578 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4579 	ctl |= BWN_MACCTL_STA;
4580 
4581 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4582 	    ic->ic_opmode == IEEE80211_M_MBSS)
4583 		ctl |= BWN_MACCTL_HOSTAP;
4584 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4585 		ctl &= ~BWN_MACCTL_STA;
4586 	ctl |= sc->sc_filters;
4587 
4588 	if (siba_get_revid(sc->sc_dev) <= 4)
4589 		ctl |= BWN_MACCTL_PROMISC;
4590 
4591 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4592 
4593 	cfp_pretbtt = 2;
4594 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4595 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4596 		    siba_get_chiprev(sc->sc_dev) == 3)
4597 			cfp_pretbtt = 100;
4598 		else
4599 			cfp_pretbtt = 50;
4600 	}
4601 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4602 }
4603 
4604 static int
4605 bwn_dma_gettype(struct bwn_mac *mac)
4606 {
4607 	uint32_t tmp;
4608 	uint16_t base;
4609 
4610 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4611 	if (tmp & SIBA_TGSHIGH_DMA64)
4612 		return (BWN_DMA_64BIT);
4613 	base = bwn_dma_base(0, 0);
4614 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4615 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4616 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4617 		return (BWN_DMA_32BIT);
4618 
4619 	return (BWN_DMA_30BIT);
4620 }
4621 
4622 static void
4623 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4624 {
4625 	if (!error) {
4626 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4627 		*((bus_addr_t *)arg) = seg->ds_addr;
4628 	}
4629 }
4630 
4631 static void
4632 bwn_phy_g_init_sub(struct bwn_mac *mac)
4633 {
4634 	struct bwn_phy *phy = &mac->mac_phy;
4635 	struct bwn_phy_g *pg = &phy->phy_g;
4636 	struct bwn_softc *sc = mac->mac_sc;
4637 	uint16_t i, tmp;
4638 
4639 	if (phy->rev == 1)
4640 		bwn_phy_init_b5(mac);
4641 	else
4642 		bwn_phy_init_b6(mac);
4643 
4644 	if (phy->rev >= 2 || phy->gmode)
4645 		bwn_phy_init_a(mac);
4646 
4647 	if (phy->rev >= 2) {
4648 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4649 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4650 	}
4651 	if (phy->rev == 2) {
4652 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4653 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4654 	}
4655 	if (phy->rev > 5) {
4656 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4657 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4658 	}
4659 	if (phy->gmode || phy->rev >= 2) {
4660 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4661 		tmp &= BWN_PHYVER_VERSION;
4662 		if (tmp == 3 || tmp == 5) {
4663 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4664 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4665 		}
4666 		if (tmp == 5) {
4667 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4668 			    0x1f00);
4669 		}
4670 	}
4671 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4672 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4673 	if (phy->rf_rev == 8) {
4674 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4675 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4676 	}
4677 	if (BWN_HAS_LOOPBACK(phy))
4678 		bwn_loopback_calcgain(mac);
4679 
4680 	if (phy->rf_rev != 8) {
4681 		if (pg->pg_initval == 0xffff)
4682 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4683 		else
4684 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4685 	}
4686 	bwn_lo_g_init(mac);
4687 	if (BWN_HAS_TXMAG(phy)) {
4688 		BWN_RF_WRITE(mac, 0x52,
4689 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4690 		    | pg->pg_loctl.tx_bias |
4691 		    pg->pg_loctl.tx_magn);
4692 	} else {
4693 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4694 	}
4695 	if (phy->rev >= 6) {
4696 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4697 		    (pg->pg_loctl.tx_bias << 12));
4698 	}
4699 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4700 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4701 	else
4702 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4703 	if (phy->rev < 2)
4704 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4705 	else
4706 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4707 	if (phy->gmode || phy->rev >= 2) {
4708 		bwn_lo_g_adjust(mac);
4709 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4710 	}
4711 
4712 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4713 		for (i = 0; i < 64; i++) {
4714 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4715 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4716 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4717 			    -32), 31));
4718 		}
4719 		bwn_nrssi_threshold(mac);
4720 	} else if (phy->gmode || phy->rev >= 2) {
4721 		if (pg->pg_nrssi[0] == -1000) {
4722 			KASSERT(pg->pg_nrssi[1] == -1000,
4723 			    ("%s:%d: fail", __func__, __LINE__));
4724 			bwn_nrssi_slope_11g(mac);
4725 		} else
4726 			bwn_nrssi_threshold(mac);
4727 	}
4728 	if (phy->rf_rev == 8)
4729 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4730 	bwn_phy_hwpctl_init(mac);
4731 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4732 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4733 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4734 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4735 	}
4736 }
4737 
4738 static uint8_t
4739 bwn_has_hwpctl(struct bwn_mac *mac)
4740 {
4741 
4742 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4743 		return (0);
4744 	return (mac->mac_phy.use_hwpctl(mac));
4745 }
4746 
4747 static void
4748 bwn_phy_init_b5(struct bwn_mac *mac)
4749 {
4750 	struct bwn_phy *phy = &mac->mac_phy;
4751 	struct bwn_phy_g *pg = &phy->phy_g;
4752 	struct bwn_softc *sc = mac->mac_sc;
4753 	uint16_t offset, value;
4754 	uint8_t old_channel;
4755 
4756 	if (phy->analog == 1)
4757 		BWN_RF_SET(mac, 0x007a, 0x0050);
4758 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4759 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4760 		value = 0x2120;
4761 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4762 			BWN_PHY_WRITE(mac, offset, value);
4763 			value += 0x202;
4764 		}
4765 	}
4766 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4767 	if (phy->rf_ver == 0x2050)
4768 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4769 
4770 	if (phy->gmode || phy->rev >= 2) {
4771 		if (phy->rf_ver == 0x2050) {
4772 			BWN_RF_SET(mac, 0x007a, 0x0020);
4773 			BWN_RF_SET(mac, 0x0051, 0x0004);
4774 		}
4775 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4776 
4777 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4778 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4779 
4780 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4781 
4782 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4783 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4784 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4785 	}
4786 
4787 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4788 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4789 
4790 	if (phy->analog == 1) {
4791 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4792 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4793 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4794 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4795 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4796 	} else
4797 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4798 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4799 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4800 
4801 	if (phy->analog == 1)
4802 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4803 	else
4804 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4805 
4806 	if (phy->analog == 0)
4807 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4808 
4809 	old_channel = phy->chan;
4810 	bwn_phy_g_switch_chan(mac, 7, 0);
4811 
4812 	if (phy->rf_ver != 0x2050) {
4813 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4814 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4815 	}
4816 
4817 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4818 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4819 
4820 	if (phy->rf_ver == 0x2050) {
4821 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4822 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4823 	}
4824 
4825 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4826 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4827 	BWN_RF_SET(mac, 0x007a, 0x0007);
4828 
4829 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4830 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4831 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4832 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4833 
4834 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4835 	    pg->pg_txctl);
4836 
4837 	if (phy->rf_ver == 0x2050)
4838 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4839 
4840 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4841 }
4842 
4843 static void
4844 bwn_loopback_calcgain(struct bwn_mac *mac)
4845 {
4846 	struct bwn_phy *phy = &mac->mac_phy;
4847 	struct bwn_phy_g *pg = &phy->phy_g;
4848 	struct bwn_softc *sc = mac->mac_sc;
4849 	uint16_t backup_phy[16] = { 0 };
4850 	uint16_t backup_radio[3];
4851 	uint16_t backup_bband;
4852 	uint16_t i, j, loop_i_max;
4853 	uint16_t trsw_rx;
4854 	uint16_t loop1_outer_done, loop1_inner_done;
4855 
4856 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4857 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4858 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4859 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4860 	if (phy->rev != 1) {
4861 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4862 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4863 	}
4864 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4865 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4866 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4867 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4868 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4869 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4870 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4871 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4872 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4873 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4874 	backup_bband = pg->pg_bbatt.att;
4875 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4876 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4877 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4878 
4879 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4880 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4881 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4882 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4883 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4884 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4885 	if (phy->rev != 1) {
4886 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4887 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4888 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4889 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4890 	}
4891 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4892 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4893 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4894 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4895 
4896 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4897 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4898 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4899 
4900 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4901 	if (phy->rev != 1) {
4902 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4903 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4904 	}
4905 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4906 
4907 	if (phy->rf_rev == 8)
4908 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4909 	else {
4910 		BWN_RF_WRITE(mac, 0x52, 0);
4911 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4912 	}
4913 	bwn_phy_g_set_bbatt(mac, 11);
4914 
4915 	if (phy->rev >= 3)
4916 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4917 	else
4918 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4919 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4920 
4921 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4922 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4923 
4924 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4925 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4926 
4927 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4928 		if (phy->rev >= 7) {
4929 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4930 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4931 		}
4932 	}
4933 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4934 
4935 	j = 0;
4936 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4937 	for (i = 0; i < loop_i_max; i++) {
4938 		for (j = 0; j < 16; j++) {
4939 			BWN_RF_WRITE(mac, 0x43, i);
4940 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4941 			    (j << 8));
4942 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4943 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4944 			DELAY(20);
4945 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4946 				goto done0;
4947 		}
4948 	}
4949 done0:
4950 	loop1_outer_done = i;
4951 	loop1_inner_done = j;
4952 	if (j >= 8) {
4953 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4954 		trsw_rx = 0x1b;
4955 		for (j = j - 8; j < 16; j++) {
4956 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4957 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4958 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4959 			DELAY(20);
4960 			trsw_rx -= 3;
4961 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4962 				goto done1;
4963 		}
4964 	} else
4965 		trsw_rx = 0x18;
4966 done1:
4967 
4968 	if (phy->rev != 1) {
4969 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4970 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4971 	}
4972 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4973 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4974 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4975 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4976 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4977 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4978 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4979 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4980 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4981 
4982 	bwn_phy_g_set_bbatt(mac, backup_bband);
4983 
4984 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4985 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4986 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4987 
4988 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4989 	DELAY(10);
4990 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4991 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4992 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4993 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4994 
4995 	pg->pg_max_lb_gain =
4996 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4997 	pg->pg_trsw_rx_gain = trsw_rx * 2;
4998 }
4999 
5000 static uint16_t
5001 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5002 {
5003 	struct bwn_phy *phy = &mac->mac_phy;
5004 	uint32_t tmp1 = 0, tmp2 = 0;
5005 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5006 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5007 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5008 	static const uint8_t rcc_table[] = {
5009 		0x02, 0x03, 0x01, 0x0f,
5010 		0x06, 0x07, 0x05, 0x0f,
5011 		0x0a, 0x0b, 0x09, 0x0f,
5012 		0x0e, 0x0f, 0x0d, 0x0f,
5013 	};
5014 
5015 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5016 	    rfoverval = rfover = cck3 = 0;
5017 	radio0 = BWN_RF_READ(mac, 0x43);
5018 	radio1 = BWN_RF_READ(mac, 0x51);
5019 	radio2 = BWN_RF_READ(mac, 0x52);
5020 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5021 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5022 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5023 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5024 
5025 	if (phy->type == BWN_PHYTYPE_B) {
5026 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5027 		reg0 = BWN_READ_2(mac, 0x3ec);
5028 
5029 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5030 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5031 	} else if (phy->gmode || phy->rev >= 2) {
5032 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5033 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5034 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5035 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5036 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5037 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5038 
5039 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5040 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5041 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5042 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5043 		if (BWN_HAS_LOOPBACK(phy)) {
5044 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5045 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5046 			if (phy->rev >= 3)
5047 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5048 			else
5049 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5050 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5051 		}
5052 
5053 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5054 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5055 			BWN_LPD(0, 1, 1)));
5056 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5057 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5058 	}
5059 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5060 
5061 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5062 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5063 	reg1 = BWN_READ_2(mac, 0x3e6);
5064 	reg2 = BWN_READ_2(mac, 0x3f4);
5065 
5066 	if (phy->analog == 0)
5067 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5068 	else {
5069 		if (phy->analog >= 2)
5070 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5071 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5072 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5073 	}
5074 
5075 	reg = BWN_RF_READ(mac, 0x60);
5076 	index = (reg & 0x001e) >> 1;
5077 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5078 
5079 	if (phy->type == BWN_PHYTYPE_B)
5080 		BWN_RF_WRITE(mac, 0x78, 0x26);
5081 	if (phy->gmode || phy->rev >= 2) {
5082 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5083 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5084 			BWN_LPD(0, 1, 1)));
5085 	}
5086 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5087 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5088 	if (phy->gmode || phy->rev >= 2) {
5089 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5090 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5091 			BWN_LPD(0, 0, 1)));
5092 	}
5093 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5094 	BWN_RF_SET(mac, 0x51, 0x0004);
5095 	if (phy->rf_rev == 8)
5096 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5097 	else {
5098 		BWN_RF_WRITE(mac, 0x52, 0);
5099 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5100 	}
5101 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5102 
5103 	for (i = 0; i < 16; i++) {
5104 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5105 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5106 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5107 		if (phy->gmode || phy->rev >= 2) {
5108 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5109 			    bwn_rf_2050_rfoverval(mac,
5110 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5111 		}
5112 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5113 		DELAY(10);
5114 		if (phy->gmode || phy->rev >= 2) {
5115 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5116 			    bwn_rf_2050_rfoverval(mac,
5117 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5118 		}
5119 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5120 		DELAY(10);
5121 		if (phy->gmode || phy->rev >= 2) {
5122 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5123 			    bwn_rf_2050_rfoverval(mac,
5124 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5125 		}
5126 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5127 		DELAY(20);
5128 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5129 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5130 		if (phy->gmode || phy->rev >= 2) {
5131 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5132 			    bwn_rf_2050_rfoverval(mac,
5133 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5134 		}
5135 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5136 	}
5137 	DELAY(10);
5138 
5139 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5140 	tmp1++;
5141 	tmp1 >>= 9;
5142 
5143 	for (i = 0; i < 16; i++) {
5144 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5145 		BWN_RF_WRITE(mac, 0x78, radio78);
5146 		DELAY(10);
5147 		for (j = 0; j < 16; j++) {
5148 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5149 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5150 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5151 			if (phy->gmode || phy->rev >= 2) {
5152 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5153 				    bwn_rf_2050_rfoverval(mac,
5154 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5155 			}
5156 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5157 			DELAY(10);
5158 			if (phy->gmode || phy->rev >= 2) {
5159 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5160 				    bwn_rf_2050_rfoverval(mac,
5161 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5162 			}
5163 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5164 			DELAY(10);
5165 			if (phy->gmode || phy->rev >= 2) {
5166 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5167 				    bwn_rf_2050_rfoverval(mac,
5168 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5169 			}
5170 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5171 			DELAY(10);
5172 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5173 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5174 			if (phy->gmode || phy->rev >= 2) {
5175 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5176 				    bwn_rf_2050_rfoverval(mac,
5177 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5178 			}
5179 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5180 		}
5181 		tmp2++;
5182 		tmp2 >>= 8;
5183 		if (tmp1 < tmp2)
5184 			break;
5185 	}
5186 
5187 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5188 	BWN_RF_WRITE(mac, 0x51, radio1);
5189 	BWN_RF_WRITE(mac, 0x52, radio2);
5190 	BWN_RF_WRITE(mac, 0x43, radio0);
5191 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5192 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5193 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5194 	BWN_WRITE_2(mac, 0x3e6, reg1);
5195 	if (phy->analog != 0)
5196 		BWN_WRITE_2(mac, 0x3f4, reg2);
5197 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5198 	bwn_spu_workaround(mac, phy->chan);
5199 	if (phy->type == BWN_PHYTYPE_B) {
5200 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5201 		BWN_WRITE_2(mac, 0x3ec, reg0);
5202 	} else if (phy->gmode) {
5203 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5204 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5205 			    & 0x7fff);
5206 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5207 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5208 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5209 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5210 			      analogoverval);
5211 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5212 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5213 		if (BWN_HAS_LOOPBACK(phy)) {
5214 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5215 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5216 		}
5217 	}
5218 
5219 	return ((i > 15) ? radio78 : rcc);
5220 }
5221 
5222 static void
5223 bwn_phy_init_b6(struct bwn_mac *mac)
5224 {
5225 	struct bwn_phy *phy = &mac->mac_phy;
5226 	struct bwn_phy_g *pg = &phy->phy_g;
5227 	struct bwn_softc *sc = mac->mac_sc;
5228 	uint16_t offset, val;
5229 	uint8_t old_channel;
5230 
5231 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5232 	    ("%s:%d: fail", __func__, __LINE__));
5233 
5234 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5235 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5236 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5237 		BWN_RF_WRITE(mac, 0x51, 0x37);
5238 		BWN_RF_WRITE(mac, 0x52, 0x70);
5239 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5240 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5241 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5242 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5243 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5244 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5245 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5246 		bwn_hf_write(mac,
5247 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5248 	}
5249 	if (phy->rf_rev == 8) {
5250 		BWN_RF_WRITE(mac, 0x51, 0);
5251 		BWN_RF_WRITE(mac, 0x52, 0x40);
5252 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5253 		BWN_RF_WRITE(mac, 0x54, 0x98);
5254 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5255 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5256 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5257 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5258 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5259 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5260 		} else {
5261 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5262 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5263 		}
5264 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5265 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5266 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5267 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5268 	}
5269 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5270 		BWN_PHY_WRITE(mac, offset, val);
5271 		val -= 0x0202;
5272 	}
5273 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5274 		BWN_PHY_WRITE(mac, offset, val);
5275 		val -= 0x0202;
5276 	}
5277 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5278 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5279 		val += 0x0202;
5280 	}
5281 	if (phy->type == BWN_PHYTYPE_G) {
5282 		BWN_RF_SET(mac, 0x007a, 0x0020);
5283 		BWN_RF_SET(mac, 0x0051, 0x0004);
5284 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5285 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5286 		BWN_PHY_WRITE(mac, 0x5b, 0);
5287 		BWN_PHY_WRITE(mac, 0x5c, 0);
5288 	}
5289 
5290 	old_channel = phy->chan;
5291 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5292 
5293 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5294 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5295 	DELAY(40);
5296 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5297 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5298 		BWN_RF_WRITE(mac, 0x50, 0x20);
5299 	}
5300 	if (phy->rf_rev <= 2) {
5301 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5302 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5303 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5304 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5305 	}
5306 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5307 
5308 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5309 
5310 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5311 	if (phy->rf_rev >= 6)
5312 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5313 	else
5314 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5315 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5316 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5317 	    pg->pg_txctl);
5318 	if (phy->rf_rev <= 5)
5319 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5320 	if (phy->rf_rev <= 2)
5321 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5322 
5323 	if (phy->analog == 4) {
5324 		BWN_WRITE_2(mac, 0x3e4, 9);
5325 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5326 	} else
5327 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5328 	if (phy->type == BWN_PHYTYPE_B)
5329 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5330 	else if (phy->type == BWN_PHYTYPE_G)
5331 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5332 }
5333 
5334 static void
5335 bwn_phy_init_a(struct bwn_mac *mac)
5336 {
5337 	struct bwn_phy *phy = &mac->mac_phy;
5338 	struct bwn_softc *sc = mac->mac_sc;
5339 
5340 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5341 	    ("%s:%d: fail", __func__, __LINE__));
5342 
5343 	if (phy->rev >= 6) {
5344 		if (phy->type == BWN_PHYTYPE_A)
5345 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5346 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5347 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5348 		else
5349 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5350 	}
5351 
5352 	bwn_wa_init(mac);
5353 
5354 	if (phy->type == BWN_PHYTYPE_G &&
5355 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5356 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5357 }
5358 
5359 static void
5360 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5361 {
5362 	int i;
5363 
5364 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5365 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5366 }
5367 
5368 static void
5369 bwn_wa_agc(struct bwn_mac *mac)
5370 {
5371 	struct bwn_phy *phy = &mac->mac_phy;
5372 
5373 	if (phy->rev == 1) {
5374 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5375 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5376 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5377 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5378 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5379 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5380 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5381 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5382 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5383 	} else {
5384 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5385 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5386 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5387 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5388 	}
5389 
5390 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5391 	    0x5700);
5392 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5393 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5394 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5395 	BWN_RF_SET(mac, 0x7a, 0x0008);
5396 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5397 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5398 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5399 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5400 	if (phy->rev == 1)
5401 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5402 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5403 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5404 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5405 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5406 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5407 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5408 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5409 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5410 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5411 	if (phy->rev == 1) {
5412 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5413 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5414 	} else {
5415 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5416 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5417 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5418 		if (phy->rev >= 6) {
5419 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5420 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5421 			    (uint16_t)~0xf000, 0x3000);
5422 		}
5423 	}
5424 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5425 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5426 	if (phy->rev == 1) {
5427 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5428 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5429 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5430 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5431 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5432 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5433 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5434 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5435 	} else {
5436 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5437 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5438 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5439 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5440 	}
5441 	if (phy->rev >= 6) {
5442 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5443 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5444 	}
5445 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5446 }
5447 
5448 static void
5449 bwn_wa_grev1(struct bwn_mac *mac)
5450 {
5451 	struct bwn_phy *phy = &mac->mac_phy;
5452 	int i;
5453 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5454 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5455 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5456 
5457 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5458 
5459 	/* init CRSTHRES and ANTDWELL */
5460 	if (phy->rev == 1) {
5461 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5462 	} else if (phy->rev == 2) {
5463 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5464 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5465 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5466 	} else {
5467 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5468 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5469 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5470 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5471 	}
5472 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5473 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5474 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5475 
5476 	/* XXX support PHY-A??? */
5477 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5478 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5479 		    bwn_tab_finefreqg[i]);
5480 
5481 	/* XXX support PHY-A??? */
5482 	if (phy->rev == 1)
5483 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5484 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5485 			    bwn_tab_noise_g1[i]);
5486 	else
5487 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5488 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5489 			    bwn_tab_noise_g2[i]);
5490 
5491 
5492 	for (i = 0; i < N(bwn_tab_rotor); i++)
5493 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5494 		    bwn_tab_rotor[i]);
5495 
5496 	/* XXX support PHY-A??? */
5497 	if (phy->rev >= 6) {
5498 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5499 		    BWN_PHY_ENCORE_EN)
5500 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5501 		else
5502 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5503 	} else
5504 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5505 
5506 	for (i = 0; i < N(bwn_tab_retard); i++)
5507 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5508 		    bwn_tab_retard[i]);
5509 
5510 	if (phy->rev == 1) {
5511 		for (i = 0; i < 16; i++)
5512 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5513 			    i, 0x0020);
5514 	} else {
5515 		for (i = 0; i < 32; i++)
5516 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5517 	}
5518 
5519 	bwn_wa_agc(mac);
5520 }
5521 
5522 static void
5523 bwn_wa_grev26789(struct bwn_mac *mac)
5524 {
5525 	struct bwn_phy *phy = &mac->mac_phy;
5526 	int i;
5527 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5528 	uint16_t ofdmrev;
5529 
5530 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5531 
5532 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5533 
5534 	/* init CRSTHRES and ANTDWELL */
5535 	if (phy->rev == 1)
5536 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5537 	else if (phy->rev == 2) {
5538 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5539 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5540 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5541 	} else {
5542 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5543 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5544 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5545 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5546 	}
5547 
5548 	for (i = 0; i < 64; i++)
5549 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5550 
5551 	/* XXX support PHY-A??? */
5552 	if (phy->rev == 1)
5553 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5554 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5555 			    bwn_tab_noise_g1[i]);
5556 	else
5557 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5558 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5559 			    bwn_tab_noise_g2[i]);
5560 
5561 	/* XXX support PHY-A??? */
5562 	if (phy->rev >= 6) {
5563 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5564 		    BWN_PHY_ENCORE_EN)
5565 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5566 		else
5567 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5568 	} else
5569 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5570 
5571 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5572 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5573 		    bwn_tab_sigmasqr2[i]);
5574 
5575 	if (phy->rev == 1) {
5576 		for (i = 0; i < 16; i++)
5577 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5578 			    0x0020);
5579 	} else {
5580 		for (i = 0; i < 32; i++)
5581 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5582 	}
5583 
5584 	bwn_wa_agc(mac);
5585 
5586 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5587 	if (ofdmrev > 2) {
5588 		if (phy->type == BWN_PHYTYPE_A)
5589 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5590 		else
5591 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5592 	} else {
5593 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5594 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5595 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5596 	}
5597 
5598 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5599 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5600 }
5601 
5602 static void
5603 bwn_wa_init(struct bwn_mac *mac)
5604 {
5605 	struct bwn_phy *phy = &mac->mac_phy;
5606 	struct bwn_softc *sc = mac->mac_sc;
5607 
5608 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5609 
5610 	switch (phy->rev) {
5611 	case 1:
5612 		bwn_wa_grev1(mac);
5613 		break;
5614 	case 2:
5615 	case 6:
5616 	case 7:
5617 	case 8:
5618 	case 9:
5619 		bwn_wa_grev26789(mac);
5620 		break;
5621 	default:
5622 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5623 	}
5624 
5625 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5626 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5627 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5628 		if (phy->rev < 2) {
5629 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5630 			    0x0002);
5631 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5632 			    0x0001);
5633 		} else {
5634 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5635 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5636 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5637 			     BWN_BFL_EXTLNA) &&
5638 			    (phy->rev >= 7)) {
5639 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5640 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5641 				    0x0020, 0x0001);
5642 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5643 				    0x0021, 0x0001);
5644 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5645 				    0x0022, 0x0001);
5646 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5647 				    0x0023, 0x0000);
5648 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5649 				    0x0000, 0x0000);
5650 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5651 				    0x0003, 0x0002);
5652 			}
5653 		}
5654 	}
5655 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5656 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5657 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5658 	}
5659 
5660 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5661 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5662 }
5663 
5664 static void
5665 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5666     uint16_t value)
5667 {
5668 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5669 	uint16_t addr;
5670 
5671 	addr = table + offset;
5672 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5673 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5674 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5675 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5676 	}
5677 	pg->pg_ofdmtab_addr = addr;
5678 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5679 }
5680 
5681 static void
5682 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5683     uint32_t value)
5684 {
5685 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5686 	uint16_t addr;
5687 
5688 	addr = table + offset;
5689 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5690 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5691 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5692 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5693 	}
5694 	pg->pg_ofdmtab_addr = addr;
5695 
5696 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5697 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5698 }
5699 
5700 static void
5701 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5702     uint16_t value)
5703 {
5704 
5705 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5706 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5707 }
5708 
5709 static void
5710 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5711 {
5712 	struct bwn_phy *phy = &mac->mac_phy;
5713 	struct bwn_softc *sc = mac->mac_sc;
5714 	unsigned int i, max_loop;
5715 	uint16_t value;
5716 	uint32_t buffer[5] = {
5717 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5718 	};
5719 
5720 	if (ofdm) {
5721 		max_loop = 0x1e;
5722 		buffer[0] = 0x000201cc;
5723 	} else {
5724 		max_loop = 0xfa;
5725 		buffer[0] = 0x000b846e;
5726 	}
5727 
5728 	for (i = 0; i < 5; i++)
5729 		bwn_ram_write(mac, i * 4, buffer[i]);
5730 
5731 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5732 	BWN_WRITE_2(mac, 0x07c0,
5733 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5734 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5735 	BWN_WRITE_2(mac, 0x050c, value);
5736 	if (phy->type == BWN_PHYTYPE_LP)
5737 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5738 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5739 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5740 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5741 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5742 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5743 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5744 	if (phy->type == BWN_PHYTYPE_LP)
5745 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5746 	else
5747 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5748 
5749 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5750 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5751 	for (i = 0x00; i < max_loop; i++) {
5752 		value = BWN_READ_2(mac, 0x050e);
5753 		if (value & 0x0080)
5754 			break;
5755 		DELAY(10);
5756 	}
5757 	for (i = 0x00; i < 0x0a; i++) {
5758 		value = BWN_READ_2(mac, 0x050e);
5759 		if (value & 0x0400)
5760 			break;
5761 		DELAY(10);
5762 	}
5763 	for (i = 0x00; i < 0x19; i++) {
5764 		value = BWN_READ_2(mac, 0x0690);
5765 		if (!(value & 0x0100))
5766 			break;
5767 		DELAY(10);
5768 	}
5769 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5770 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5771 }
5772 
5773 static void
5774 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5775 {
5776 	uint32_t macctl;
5777 
5778 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5779 
5780 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5781 	if (macctl & BWN_MACCTL_BIGENDIAN)
5782 		kprintf("TODO: need swap\n");
5783 
5784 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5785 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5786 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5787 }
5788 
5789 static void
5790 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5791 {
5792 	uint16_t value;
5793 
5794 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5795 	    ("%s:%d: fail", __func__, __LINE__));
5796 
5797 	value = (uint8_t) (ctl->q);
5798 	value |= ((uint8_t) (ctl->i)) << 8;
5799 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5800 }
5801 
5802 static uint16_t
5803 bwn_lo_calcfeed(struct bwn_mac *mac,
5804     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5805 {
5806 	struct bwn_phy *phy = &mac->mac_phy;
5807 	struct bwn_softc *sc = mac->mac_sc;
5808 	uint16_t rfover;
5809 	uint16_t feedthrough;
5810 
5811 	if (phy->gmode) {
5812 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5813 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5814 
5815 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5816 		    ("%s:%d: fail", __func__, __LINE__));
5817 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5818 		    ("%s:%d: fail", __func__, __LINE__));
5819 
5820 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5821 
5822 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5823 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5824 		    phy->rev > 6)
5825 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5826 
5827 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5828 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5829 		DELAY(10);
5830 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5831 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5832 		DELAY(10);
5833 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5834 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5835 		DELAY(10);
5836 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5837 	} else {
5838 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5839 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5840 		DELAY(10);
5841 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5842 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5843 		DELAY(10);
5844 		pga |= BWN_PHY_PGACTL_LPF;
5845 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5846 	}
5847 	DELAY(21);
5848 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5849 
5850 	return (feedthrough);
5851 }
5852 
5853 static uint16_t
5854 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5855     uint16_t *value, uint16_t *pad_mix_gain)
5856 {
5857 	struct bwn_phy *phy = &mac->mac_phy;
5858 	uint16_t reg, v, padmix;
5859 
5860 	if (phy->type == BWN_PHYTYPE_B) {
5861 		v = 0x30;
5862 		if (phy->rf_rev <= 5) {
5863 			reg = 0x43;
5864 			padmix = 0;
5865 		} else {
5866 			reg = 0x52;
5867 			padmix = 5;
5868 		}
5869 	} else {
5870 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5871 			reg = 0x43;
5872 			v = 0x10;
5873 			padmix = 2;
5874 		} else {
5875 			reg = 0x52;
5876 			v = 0x30;
5877 			padmix = 5;
5878 		}
5879 	}
5880 	if (value)
5881 		*value = v;
5882 	if (pad_mix_gain)
5883 		*pad_mix_gain = padmix;
5884 
5885 	return (reg);
5886 }
5887 
5888 static void
5889 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5890 {
5891 	struct bwn_phy *phy = &mac->mac_phy;
5892 	struct bwn_phy_g *pg = &phy->phy_g;
5893 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5894 	uint16_t reg, mask;
5895 	uint16_t trsw_rx, pga;
5896 	uint16_t rf_pctl_reg;
5897 
5898 	static const uint8_t tx_bias_values[] = {
5899 		0x09, 0x08, 0x0a, 0x01, 0x00,
5900 		0x02, 0x05, 0x04, 0x06,
5901 	};
5902 	static const uint8_t tx_magn_values[] = {
5903 		0x70, 0x40,
5904 	};
5905 
5906 	if (!BWN_HAS_LOOPBACK(phy)) {
5907 		rf_pctl_reg = 6;
5908 		trsw_rx = 2;
5909 		pga = 0;
5910 	} else {
5911 		int lb_gain;
5912 
5913 		trsw_rx = 0;
5914 		lb_gain = pg->pg_max_lb_gain / 2;
5915 		if (lb_gain > 10) {
5916 			rf_pctl_reg = 0;
5917 			pga = abs(10 - lb_gain) / 6;
5918 			pga = MIN(MAX(pga, 0), 15);
5919 		} else {
5920 			int cmp_val;
5921 			int tmp;
5922 
5923 			pga = 0;
5924 			cmp_val = 0x24;
5925 			if ((phy->rev >= 2) &&
5926 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5927 				cmp_val = 0x3c;
5928 			tmp = lb_gain;
5929 			if ((10 - lb_gain) < cmp_val)
5930 				tmp = (10 - lb_gain);
5931 			if (tmp < 0)
5932 				tmp += 6;
5933 			else
5934 				tmp += 3;
5935 			cmp_val /= 4;
5936 			tmp /= 4;
5937 			if (tmp >= cmp_val)
5938 				rf_pctl_reg = cmp_val;
5939 			else
5940 				rf_pctl_reg = tmp;
5941 		}
5942 	}
5943 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5944 	bwn_phy_g_set_bbatt(mac, 2);
5945 
5946 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5947 	mask = ~mask;
5948 	BWN_RF_MASK(mac, reg, mask);
5949 
5950 	if (BWN_HAS_TXMAG(phy)) {
5951 		int i, j;
5952 		int feedthrough;
5953 		int min_feedth = 0xffff;
5954 		uint8_t tx_magn, tx_bias;
5955 
5956 		for (i = 0; i < N(tx_magn_values); i++) {
5957 			tx_magn = tx_magn_values[i];
5958 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5959 			for (j = 0; j < N(tx_bias_values); j++) {
5960 				tx_bias = tx_bias_values[j];
5961 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5962 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5963 				    trsw_rx);
5964 				if (feedthrough < min_feedth) {
5965 					lo->tx_bias = tx_bias;
5966 					lo->tx_magn = tx_magn;
5967 					min_feedth = feedthrough;
5968 				}
5969 				if (lo->tx_bias == 0)
5970 					break;
5971 			}
5972 			BWN_RF_WRITE(mac, 0x52,
5973 					  (BWN_RF_READ(mac, 0x52)
5974 					   & 0xff00) | lo->tx_bias | lo->
5975 					  tx_magn);
5976 		}
5977 	} else {
5978 		lo->tx_magn = 0;
5979 		lo->tx_bias = 0;
5980 		BWN_RF_MASK(mac, 0x52, 0xfff0);
5981 	}
5982 
5983 	BWN_GETTIME(lo->txctl_measured_time);
5984 }
5985 
5986 static void
5987 bwn_lo_get_powervector(struct bwn_mac *mac)
5988 {
5989 	struct bwn_phy *phy = &mac->mac_phy;
5990 	struct bwn_phy_g *pg = &phy->phy_g;
5991 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5992 	int i;
5993 	uint64_t tmp;
5994 	uint64_t power_vector = 0;
5995 
5996 	for (i = 0; i < 8; i += 2) {
5997 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5998 		power_vector |= (tmp << (i * 8));
5999 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6000 	}
6001 	if (power_vector)
6002 		lo->power_vector = power_vector;
6003 
6004 	BWN_GETTIME(lo->pwr_vec_read_time);
6005 }
6006 
6007 static void
6008 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6009     int use_trsw_rx)
6010 {
6011 	struct bwn_phy *phy = &mac->mac_phy;
6012 	struct bwn_phy_g *pg = &phy->phy_g;
6013 	uint16_t tmp;
6014 
6015 	if (max_rx_gain < 0)
6016 		max_rx_gain = 0;
6017 
6018 	if (BWN_HAS_LOOPBACK(phy)) {
6019 		int trsw_rx = 0;
6020 		int trsw_rx_gain;
6021 
6022 		if (use_trsw_rx) {
6023 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6024 			if (max_rx_gain >= trsw_rx_gain) {
6025 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6026 				trsw_rx = 0x20;
6027 			}
6028 		} else
6029 			trsw_rx_gain = max_rx_gain;
6030 		if (trsw_rx_gain < 9) {
6031 			pg->pg_lna_lod_gain = 0;
6032 		} else {
6033 			pg->pg_lna_lod_gain = 1;
6034 			trsw_rx_gain -= 8;
6035 		}
6036 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6037 		pg->pg_pga_gain = trsw_rx_gain / 3;
6038 		if (pg->pg_pga_gain >= 5) {
6039 			pg->pg_pga_gain -= 5;
6040 			pg->pg_lna_gain = 2;
6041 		} else
6042 			pg->pg_lna_gain = 0;
6043 	} else {
6044 		pg->pg_lna_gain = 0;
6045 		pg->pg_trsw_rx_gain = 0x20;
6046 		if (max_rx_gain >= 0x14) {
6047 			pg->pg_lna_lod_gain = 1;
6048 			pg->pg_pga_gain = 2;
6049 		} else if (max_rx_gain >= 0x12) {
6050 			pg->pg_lna_lod_gain = 1;
6051 			pg->pg_pga_gain = 1;
6052 		} else if (max_rx_gain >= 0xf) {
6053 			pg->pg_lna_lod_gain = 1;
6054 			pg->pg_pga_gain = 0;
6055 		} else {
6056 			pg->pg_lna_lod_gain = 0;
6057 			pg->pg_pga_gain = 0;
6058 		}
6059 	}
6060 
6061 	tmp = BWN_RF_READ(mac, 0x7a);
6062 	if (pg->pg_lna_lod_gain == 0)
6063 		tmp &= ~0x0008;
6064 	else
6065 		tmp |= 0x0008;
6066 	BWN_RF_WRITE(mac, 0x7a, tmp);
6067 }
6068 
6069 static void
6070 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6071 {
6072 	struct bwn_phy *phy = &mac->mac_phy;
6073 	struct bwn_phy_g *pg = &phy->phy_g;
6074 	struct bwn_softc *sc = mac->mac_sc;
6075 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6076 	struct timespec ts;
6077 	uint16_t tmp;
6078 
6079 	if (bwn_has_hwpctl(mac)) {
6080 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6081 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6082 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6083 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6084 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6085 
6086 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6087 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6088 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6089 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6090 	}
6091 	if (phy->type == BWN_PHYTYPE_B &&
6092 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6093 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6094 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6095 	}
6096 	if (phy->rev >= 2) {
6097 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6098 		sav->phy_analogoverval =
6099 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6100 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6101 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6102 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6103 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6104 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6105 
6106 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6107 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6108 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6109 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6110 		if (phy->type == BWN_PHYTYPE_G) {
6111 			if ((phy->rev >= 7) &&
6112 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6113 			     BWN_BFL_EXTLNA)) {
6114 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6115 			} else {
6116 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6117 			}
6118 		} else {
6119 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6120 		}
6121 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6122 	}
6123 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6124 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6125 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6126 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6127 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6128 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6129 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6130 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6131 
6132 	if (!BWN_HAS_TXMAG(phy)) {
6133 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6134 		sav->rf2 &= 0x00f0;
6135 	}
6136 	if (phy->type == BWN_PHYTYPE_B) {
6137 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6138 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6139 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6140 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6141 	} else {
6142 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6143 			    | 0x8000);
6144 	}
6145 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6146 		    & 0xf000);
6147 
6148 	tmp =
6149 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6150 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6151 
6152 	tmp = sav->phy_syncctl;
6153 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6154 	tmp = sav->rf1;
6155 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6156 
6157 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6158 	if (phy->type == BWN_PHYTYPE_G ||
6159 	    (phy->type == BWN_PHYTYPE_B &&
6160 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6161 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6162 	} else
6163 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6164 	if (phy->rev >= 2)
6165 		bwn_dummy_transmission(mac, 0, 1);
6166 	bwn_phy_g_switch_chan(mac, 6, 0);
6167 	BWN_RF_READ(mac, 0x51);
6168 	if (phy->type == BWN_PHYTYPE_G)
6169 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6170 
6171 	nanouptime(&ts);
6172 	if (time_before(lo->txctl_measured_time,
6173 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6174 		bwn_lo_measure_txctl_values(mac);
6175 
6176 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6177 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6178 	else {
6179 		if (phy->type == BWN_PHYTYPE_B)
6180 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6181 		else
6182 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6183 	}
6184 }
6185 
6186 static void
6187 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6188 {
6189 	struct bwn_phy *phy = &mac->mac_phy;
6190 	struct bwn_phy_g *pg = &phy->phy_g;
6191 	uint16_t tmp;
6192 
6193 	if (phy->rev >= 2) {
6194 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6195 		tmp = (pg->pg_pga_gain << 8);
6196 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6197 		DELAY(5);
6198 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6199 		DELAY(2);
6200 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6201 	} else {
6202 		tmp = (pg->pg_pga_gain | 0xefa0);
6203 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6204 	}
6205 	if (phy->type == BWN_PHYTYPE_G) {
6206 		if (phy->rev >= 3)
6207 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6208 		else
6209 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6210 		if (phy->rev >= 2)
6211 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6212 		else
6213 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6214 	}
6215 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6216 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6217 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6218 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6219 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6220 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6221 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6222 	if (!BWN_HAS_TXMAG(phy)) {
6223 		tmp = sav->rf2;
6224 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6225 	}
6226 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6227 	if (phy->type == BWN_PHYTYPE_B &&
6228 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6229 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6230 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6231 	}
6232 	if (phy->rev >= 2) {
6233 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6234 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6235 			      sav->phy_analogoverval);
6236 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6237 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6238 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6239 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6240 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6241 	}
6242 	if (bwn_has_hwpctl(mac)) {
6243 		tmp = (sav->phy_lomask & 0xbfff);
6244 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6245 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6246 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6247 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6248 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6249 	}
6250 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6251 }
6252 
6253 static int
6254 bwn_lo_probe_loctl(struct bwn_mac *mac,
6255     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6256 {
6257 	struct bwn_phy *phy = &mac->mac_phy;
6258 	struct bwn_phy_g *pg = &phy->phy_g;
6259 	struct bwn_loctl orig, test;
6260 	struct bwn_loctl prev = { -100, -100 };
6261 	static const struct bwn_loctl modifiers[] = {
6262 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6263 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6264 	};
6265 	int begin, end, lower = 0, i;
6266 	uint16_t feedth;
6267 
6268 	if (d->curstate == 0) {
6269 		begin = 1;
6270 		end = 8;
6271 	} else if (d->curstate % 2 == 0) {
6272 		begin = d->curstate - 1;
6273 		end = d->curstate + 1;
6274 	} else {
6275 		begin = d->curstate - 2;
6276 		end = d->curstate + 2;
6277 	}
6278 	if (begin < 1)
6279 		begin += 8;
6280 	if (end > 8)
6281 		end -= 8;
6282 
6283 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6284 	i = begin;
6285 	d->curstate = i;
6286 	while (1) {
6287 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6288 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6289 		test.i += modifiers[i - 1].i * d->multipler;
6290 		test.q += modifiers[i - 1].q * d->multipler;
6291 		if ((test.i != prev.i || test.q != prev.q) &&
6292 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6293 			bwn_lo_write(mac, &test);
6294 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6295 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6296 			if (feedth < d->feedth) {
6297 				memcpy(probe, &test,
6298 				    sizeof(struct bwn_loctl));
6299 				lower = 1;
6300 				d->feedth = feedth;
6301 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6302 					break;
6303 			}
6304 		}
6305 		memcpy(&prev, &test, sizeof(prev));
6306 		if (i == end)
6307 			break;
6308 		if (i == 8)
6309 			i = 1;
6310 		else
6311 			i++;
6312 		d->curstate = i;
6313 	}
6314 
6315 	return (lower);
6316 }
6317 
6318 static void
6319 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6320 {
6321 	struct bwn_phy *phy = &mac->mac_phy;
6322 	struct bwn_phy_g *pg = &phy->phy_g;
6323 	struct bwn_lo_g_sm d;
6324 	struct bwn_loctl probe;
6325 	int lower, repeat, cnt = 0;
6326 	uint16_t feedth;
6327 
6328 	d.nmeasure = 0;
6329 	d.multipler = 1;
6330 	if (BWN_HAS_LOOPBACK(phy))
6331 		d.multipler = 3;
6332 
6333 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6334 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6335 
6336 	do {
6337 		bwn_lo_write(mac, &d.loctl);
6338 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6339 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6340 		if (feedth < 0x258) {
6341 			if (feedth >= 0x12c)
6342 				*rxgain += 6;
6343 			else
6344 				*rxgain += 3;
6345 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6346 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6347 		}
6348 		d.feedth = feedth;
6349 		d.curstate = 0;
6350 		do {
6351 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6352 			    ("%s:%d: fail", __func__, __LINE__));
6353 			memcpy(&probe, &d.loctl,
6354 			       sizeof(struct bwn_loctl));
6355 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6356 			if (!lower)
6357 				break;
6358 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6359 				break;
6360 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6361 			d.nmeasure++;
6362 		} while (d.nmeasure < 24);
6363 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6364 
6365 		if (BWN_HAS_LOOPBACK(phy)) {
6366 			if (d.feedth > 0x1194)
6367 				*rxgain -= 6;
6368 			else if (d.feedth < 0x5dc)
6369 				*rxgain += 3;
6370 			if (cnt == 0) {
6371 				if (d.feedth <= 0x5dc) {
6372 					d.multipler = 1;
6373 					cnt++;
6374 				} else
6375 					d.multipler = 2;
6376 			} else if (cnt == 2)
6377 				d.multipler = 1;
6378 		}
6379 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6380 	} while (++cnt < repeat);
6381 }
6382 
6383 static struct bwn_lo_calib *
6384 bwn_lo_calibset(struct bwn_mac *mac,
6385     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6386 {
6387 	struct bwn_phy *phy = &mac->mac_phy;
6388 	struct bwn_phy_g *pg = &phy->phy_g;
6389 	struct bwn_loctl loctl = { 0, 0 };
6390 	struct bwn_lo_calib *cal;
6391 	struct bwn_lo_g_value sval = { 0 };
6392 	int rxgain;
6393 	uint16_t pad, reg, value;
6394 
6395 	sval.old_channel = phy->chan;
6396 	bwn_mac_suspend(mac);
6397 	bwn_lo_save(mac, &sval);
6398 
6399 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6400 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6401 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6402 
6403 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6404 	if (rfatt->padmix)
6405 		rxgain -= pad;
6406 	if (BWN_HAS_LOOPBACK(phy))
6407 		rxgain += pg->pg_max_lb_gain;
6408 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6409 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6410 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6411 
6412 	bwn_lo_restore(mac, &sval);
6413 	bwn_mac_enable(mac);
6414 
6415 	cal = kmalloc(sizeof(*cal), M_DEVBUF, M_INTWAIT | M_ZERO);
6416 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6417 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6418 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6419 
6420 	BWN_GETTIME(cal->calib_time);
6421 
6422 	return (cal);
6423 }
6424 
6425 static struct bwn_lo_calib *
6426 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6427     const struct bwn_rfatt *rfatt)
6428 {
6429 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6430 	struct bwn_lo_calib *c;
6431 
6432 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6433 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6434 			continue;
6435 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6436 			continue;
6437 		return (c);
6438 	}
6439 
6440 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6441 	if (c == NULL)	/* XXX ivadasz: can't happen */
6442 		return (NULL);
6443 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6444 
6445 	return (c);
6446 }
6447 
6448 static void
6449 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6450 {
6451 	struct bwn_phy *phy = &mac->mac_phy;
6452 	struct bwn_phy_g *pg = &phy->phy_g;
6453 	struct bwn_softc *sc = mac->mac_sc;
6454 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6455 	const struct bwn_rfatt *rfatt;
6456 	const struct bwn_bbatt *bbatt;
6457 	uint64_t pvector;
6458 	int i;
6459 	int rf_offset, bb_offset;
6460 	uint8_t changed = 0;
6461 
6462 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6463 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6464 	    ("%s:%d: fail", __func__, __LINE__));
6465 
6466 	pvector = lo->power_vector;
6467 	if (!update && !pvector)
6468 		return;
6469 
6470 	bwn_mac_suspend(mac);
6471 
6472 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6473 		struct bwn_lo_calib *cal;
6474 		int idx;
6475 		uint16_t val;
6476 
6477 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6478 			continue;
6479 		bb_offset = i / lo->rfatt.len;
6480 		rf_offset = i % lo->rfatt.len;
6481 		bbatt = &(lo->bbatt.array[bb_offset]);
6482 		rfatt = &(lo->rfatt.array[rf_offset]);
6483 
6484 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6485 		if (cal == NULL) {	/* XXX ivadasz: can't happen */
6486 			device_printf(sc->sc_dev, "LO: Could not "
6487 			    "calibrate DC table entry\n");
6488 			continue;
6489 		}
6490 		val = (uint8_t)(cal->ctl.q);
6491 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6492 		kfree(cal, M_DEVBUF);
6493 
6494 		idx = i / 2;
6495 		if (i % 2)
6496 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6497 			    | ((val & 0x00ff) << 8);
6498 		else
6499 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6500 			    | (val & 0x00ff);
6501 		changed = 1;
6502 	}
6503 	if (changed) {
6504 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6505 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6506 	}
6507 	bwn_mac_enable(mac);
6508 }
6509 
6510 static void
6511 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6512 {
6513 
6514 	if (!rf->padmix)
6515 		return;
6516 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6517 		rf->att = 4;
6518 }
6519 
6520 static void
6521 bwn_lo_g_adjust(struct bwn_mac *mac)
6522 {
6523 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6524 	struct bwn_lo_calib *cal;
6525 	struct bwn_rfatt rf;
6526 
6527 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6528 	bwn_lo_fixup_rfatt(&rf);
6529 
6530 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6531 	if (cal == NULL)	/* XXX ivadasz: can't happen */
6532 		return;
6533 	bwn_lo_write(mac, &cal->ctl);
6534 }
6535 
6536 static void
6537 bwn_lo_g_init(struct bwn_mac *mac)
6538 {
6539 
6540 	if (!bwn_has_hwpctl(mac))
6541 		return;
6542 
6543 	bwn_lo_get_powervector(mac);
6544 	bwn_phy_g_dc_lookup_init(mac, 1);
6545 }
6546 
6547 static void
6548 bwn_mac_suspend(struct bwn_mac *mac)
6549 {
6550 	struct bwn_softc *sc = mac->mac_sc;
6551 	int i;
6552 	uint32_t tmp;
6553 
6554 	KASSERT(mac->mac_suspended >= 0,
6555 	    ("%s:%d: fail", __func__, __LINE__));
6556 
6557 	if (mac->mac_suspended == 0) {
6558 		bwn_psctl(mac, BWN_PS_AWAKE);
6559 		BWN_WRITE_4(mac, BWN_MACCTL,
6560 			    BWN_READ_4(mac, BWN_MACCTL)
6561 			    & ~BWN_MACCTL_ON);
6562 		BWN_READ_4(mac, BWN_MACCTL);
6563 		for (i = 35; i; i--) {
6564 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6565 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6566 				goto out;
6567 			DELAY(10);
6568 		}
6569 		for (i = 40; i; i--) {
6570 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6571 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6572 				goto out;
6573 			DELAY(1000);
6574 		}
6575 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6576 	}
6577 out:
6578 	mac->mac_suspended++;
6579 }
6580 
6581 static void
6582 bwn_mac_enable(struct bwn_mac *mac)
6583 {
6584 	struct bwn_softc *sc = mac->mac_sc;
6585 	uint16_t state;
6586 
6587 	state = bwn_shm_read_2(mac, BWN_SHARED,
6588 	    BWN_SHARED_UCODESTAT);
6589 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6590 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6591 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6592 
6593 	mac->mac_suspended--;
6594 	KASSERT(mac->mac_suspended >= 0,
6595 	    ("%s:%d: fail", __func__, __LINE__));
6596 	if (mac->mac_suspended == 0) {
6597 		BWN_WRITE_4(mac, BWN_MACCTL,
6598 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6599 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6600 		BWN_READ_4(mac, BWN_MACCTL);
6601 		BWN_READ_4(mac, BWN_INTR_REASON);
6602 		bwn_psctl(mac, 0);
6603 	}
6604 }
6605 
6606 static void
6607 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6608 {
6609 	struct bwn_softc *sc = mac->mac_sc;
6610 	int i;
6611 	uint16_t ucstat;
6612 
6613 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6614 	    ("%s:%d: fail", __func__, __LINE__));
6615 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6616 	    ("%s:%d: fail", __func__, __LINE__));
6617 
6618 	/* XXX forcibly awake and hwps-off */
6619 
6620 	BWN_WRITE_4(mac, BWN_MACCTL,
6621 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6622 	    ~BWN_MACCTL_HWPS);
6623 	BWN_READ_4(mac, BWN_MACCTL);
6624 	if (siba_get_revid(sc->sc_dev) >= 5) {
6625 		for (i = 0; i < 100; i++) {
6626 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6627 			    BWN_SHARED_UCODESTAT);
6628 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6629 				break;
6630 			DELAY(10);
6631 		}
6632 	}
6633 }
6634 
6635 static int16_t
6636 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6637 {
6638 
6639 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6640 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6641 }
6642 
6643 static void
6644 bwn_nrssi_threshold(struct bwn_mac *mac)
6645 {
6646 	struct bwn_phy *phy = &mac->mac_phy;
6647 	struct bwn_phy_g *pg = &phy->phy_g;
6648 	struct bwn_softc *sc = mac->mac_sc;
6649 	int32_t a, b;
6650 	int16_t tmp16;
6651 	uint16_t tmpu16;
6652 
6653 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6654 
6655 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6656 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6657 			a = 0x13;
6658 			b = 0x12;
6659 		} else {
6660 			a = 0xe;
6661 			b = 0x11;
6662 		}
6663 
6664 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6665 		a += (pg->pg_nrssi[0] << 6);
6666 		a += (a < 32) ? 31 : 32;
6667 		a = a >> 6;
6668 		a = MIN(MAX(a, -31), 31);
6669 
6670 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6671 		b += (pg->pg_nrssi[0] << 6);
6672 		if (b < 32)
6673 			b += 31;
6674 		else
6675 			b += 32;
6676 		b = b >> 6;
6677 		b = MIN(MAX(b, -31), 31);
6678 
6679 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6680 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6681 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6682 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6683 		return;
6684 	}
6685 
6686 	tmp16 = bwn_nrssi_read(mac, 0x20);
6687 	if (tmp16 >= 0x20)
6688 		tmp16 -= 0x40;
6689 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6690 }
6691 
6692 static void
6693 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6694 {
6695 #define	SAVE_RF_MAX		3
6696 #define	SAVE_PHY_COMM_MAX	4
6697 #define	SAVE_PHY3_MAX		8
6698 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6699 		{ 0x7a, 0x52, 0x43 };
6700 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6701 		{ 0x15, 0x5a, 0x59, 0x58 };
6702 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6703 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6704 		0x0801, 0x0060, 0x0014, 0x0478
6705 	};
6706 	struct bwn_phy *phy = &mac->mac_phy;
6707 	struct bwn_phy_g *pg = &phy->phy_g;
6708 	int32_t i, tmp32, phy3_idx = 0;
6709 	uint16_t delta, tmp;
6710 	uint16_t save_rf[SAVE_RF_MAX];
6711 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6712 	uint16_t save_phy3[SAVE_PHY3_MAX];
6713 	uint16_t ant_div, phy0, chan_ex;
6714 	int16_t nrssi0, nrssi1;
6715 
6716 	KASSERT(phy->type == BWN_PHYTYPE_G,
6717 	    ("%s:%d: fail", __func__, __LINE__));
6718 
6719 	if (phy->rf_rev >= 9)
6720 		return;
6721 	if (phy->rf_rev == 8)
6722 		bwn_nrssi_offset(mac);
6723 
6724 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6725 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6726 
6727 	/*
6728 	 * Save RF/PHY registers for later restoration
6729 	 */
6730 	ant_div = BWN_READ_2(mac, 0x03e2);
6731 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6732 	for (i = 0; i < SAVE_RF_MAX; ++i)
6733 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6734 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6735 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6736 
6737 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6738 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6739 	if (phy->rev >= 3) {
6740 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6741 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6742 		BWN_PHY_WRITE(mac, 0x002e, 0);
6743 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6744 		switch (phy->rev) {
6745 		case 4:
6746 		case 6:
6747 		case 7:
6748 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6749 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6750 			break;
6751 		case 3:
6752 		case 5:
6753 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6754 			break;
6755 		}
6756 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6757 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6758 	}
6759 	/*
6760 	 * Calculate nrssi0
6761 	 */
6762 	BWN_RF_SET(mac, 0x007a, 0x0070);
6763 	bwn_set_all_gains(mac, 0, 8, 0);
6764 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6765 	if (phy->rev >= 2) {
6766 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6767 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6768 	}
6769 	BWN_RF_SET(mac, 0x007a, 0x0080);
6770 	DELAY(20);
6771 
6772 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6773 	if (nrssi0 >= 0x0020)
6774 		nrssi0 -= 0x0040;
6775 
6776 	/*
6777 	 * Calculate nrssi1
6778 	 */
6779 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6780 	if (phy->rev >= 2)
6781 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6782 
6783 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6784 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6785 	BWN_RF_SET(mac, 0x007a, 0x000f);
6786 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6787 	if (phy->rev >= 2) {
6788 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6789 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6790 	}
6791 
6792 	bwn_set_all_gains(mac, 3, 0, 1);
6793 	if (phy->rf_rev == 8) {
6794 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6795 	} else {
6796 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6797 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6798 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6799 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6800 	}
6801 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6802 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6803 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6804 	DELAY(20);
6805 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6806 
6807 	/*
6808 	 * Install calculated narrow RSSI values
6809 	 */
6810 	if (nrssi1 >= 0x0020)
6811 		nrssi1 -= 0x0040;
6812 	if (nrssi0 == nrssi1)
6813 		pg->pg_nrssi_slope = 0x00010000;
6814 	else
6815 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6816 	if (nrssi0 >= -4) {
6817 		pg->pg_nrssi[0] = nrssi1;
6818 		pg->pg_nrssi[1] = nrssi0;
6819 	}
6820 
6821 	/*
6822 	 * Restore saved RF/PHY registers
6823 	 */
6824 	if (phy->rev >= 3) {
6825 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6826 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6827 			    save_phy3[phy3_idx]);
6828 		}
6829 	}
6830 	if (phy->rev >= 2) {
6831 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6832 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6833 	}
6834 
6835 	for (i = 0; i < SAVE_RF_MAX; ++i)
6836 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6837 
6838 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6839 	BWN_WRITE_2(mac, 0x03e6, phy0);
6840 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6841 
6842 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6843 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6844 
6845 	bwn_spu_workaround(mac, phy->chan);
6846 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6847 	bwn_set_original_gains(mac);
6848 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6849 	if (phy->rev >= 3) {
6850 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6851 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6852 			    save_phy3[phy3_idx]);
6853 		}
6854 	}
6855 
6856 	delta = 0x1f - pg->pg_nrssi[0];
6857 	for (i = 0; i < 64; i++) {
6858 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6859 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6860 		pg->pg_nrssi_lt[i] = tmp32;
6861 	}
6862 
6863 	bwn_nrssi_threshold(mac);
6864 #undef SAVE_RF_MAX
6865 #undef SAVE_PHY_COMM_MAX
6866 #undef SAVE_PHY3_MAX
6867 }
6868 
6869 static void
6870 bwn_nrssi_offset(struct bwn_mac *mac)
6871 {
6872 #define	SAVE_RF_MAX		2
6873 #define	SAVE_PHY_COMM_MAX	10
6874 #define	SAVE_PHY6_MAX		8
6875 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6876 		{ 0x7a, 0x43 };
6877 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6878 		0x0001, 0x0811, 0x0812, 0x0814,
6879 		0x0815, 0x005a, 0x0059, 0x0058,
6880 		0x000a, 0x0003
6881 	};
6882 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6883 		0x002e, 0x002f, 0x080f, 0x0810,
6884 		0x0801, 0x0060, 0x0014, 0x0478
6885 	};
6886 	struct bwn_phy *phy = &mac->mac_phy;
6887 	int i, phy6_idx = 0;
6888 	uint16_t save_rf[SAVE_RF_MAX];
6889 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6890 	uint16_t save_phy6[SAVE_PHY6_MAX];
6891 	int16_t nrssi;
6892 	uint16_t saved = 0xffff;
6893 
6894 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6895 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6896 	for (i = 0; i < SAVE_RF_MAX; ++i)
6897 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6898 
6899 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6900 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6901 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6902 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6903 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6904 	if (phy->rev >= 6) {
6905 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6906 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6907 
6908 		BWN_PHY_WRITE(mac, 0x002e, 0);
6909 		BWN_PHY_WRITE(mac, 0x002f, 0);
6910 		BWN_PHY_WRITE(mac, 0x080f, 0);
6911 		BWN_PHY_WRITE(mac, 0x0810, 0);
6912 		BWN_PHY_SET(mac, 0x0478, 0x0100);
6913 		BWN_PHY_SET(mac, 0x0801, 0x0040);
6914 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6915 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6916 	}
6917 	BWN_RF_SET(mac, 0x007a, 0x0070);
6918 	BWN_RF_SET(mac, 0x007a, 0x0080);
6919 	DELAY(30);
6920 
6921 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6922 	if (nrssi >= 0x20)
6923 		nrssi -= 0x40;
6924 	if (nrssi == 31) {
6925 		for (i = 7; i >= 4; i--) {
6926 			BWN_RF_WRITE(mac, 0x007b, i);
6927 			DELAY(20);
6928 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6929 			    0x003f);
6930 			if (nrssi >= 0x20)
6931 				nrssi -= 0x40;
6932 			if (nrssi < 31 && saved == 0xffff)
6933 				saved = i;
6934 		}
6935 		if (saved == 0xffff)
6936 			saved = 4;
6937 	} else {
6938 		BWN_RF_MASK(mac, 0x007a, 0x007f);
6939 		if (phy->rev != 1) {
6940 			BWN_PHY_SET(mac, 0x0814, 0x0001);
6941 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6942 		}
6943 		BWN_PHY_SET(mac, 0x0811, 0x000c);
6944 		BWN_PHY_SET(mac, 0x0812, 0x000c);
6945 		BWN_PHY_SET(mac, 0x0811, 0x0030);
6946 		BWN_PHY_SET(mac, 0x0812, 0x0030);
6947 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6948 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6949 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6950 		if (phy->rev == 0)
6951 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6952 		else
6953 			BWN_PHY_SET(mac, 0x000a, 0x2000);
6954 		if (phy->rev != 1) {
6955 			BWN_PHY_SET(mac, 0x0814, 0x0004);
6956 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6957 		}
6958 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6959 		BWN_RF_SET(mac, 0x007a, 0x000f);
6960 		bwn_set_all_gains(mac, 3, 0, 1);
6961 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6962 		DELAY(30);
6963 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6964 		if (nrssi >= 0x20)
6965 			nrssi -= 0x40;
6966 		if (nrssi == -32) {
6967 			for (i = 0; i < 4; i++) {
6968 				BWN_RF_WRITE(mac, 0x007b, i);
6969 				DELAY(20);
6970 				nrssi = (int16_t)((BWN_PHY_READ(mac,
6971 				    0x047f) >> 8) & 0x003f);
6972 				if (nrssi >= 0x20)
6973 					nrssi -= 0x40;
6974 				if (nrssi > -31 && saved == 0xffff)
6975 					saved = i;
6976 			}
6977 			if (saved == 0xffff)
6978 				saved = 3;
6979 		} else
6980 			saved = 0;
6981 	}
6982 	BWN_RF_WRITE(mac, 0x007b, saved);
6983 
6984 	/*
6985 	 * Restore saved RF/PHY registers
6986 	 */
6987 	if (phy->rev >= 6) {
6988 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6989 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6990 			    save_phy6[phy6_idx]);
6991 		}
6992 	}
6993 	if (phy->rev != 1) {
6994 		for (i = 3; i < 5; i++)
6995 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6996 			    save_phy_comm[i]);
6997 	}
6998 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6999 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7000 
7001 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7002 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7003 
7004 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7005 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7006 	bwn_set_original_gains(mac);
7007 	if (phy->rev >= 6) {
7008 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7009 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7010 			    save_phy6[phy6_idx]);
7011 		}
7012 	}
7013 
7014 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7015 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7016 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7017 }
7018 
7019 static void
7020 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7021     int16_t third)
7022 {
7023 	struct bwn_phy *phy = &mac->mac_phy;
7024 	uint16_t i;
7025 	uint16_t start = 0x08, end = 0x18;
7026 	uint16_t tmp;
7027 	uint16_t table;
7028 
7029 	if (phy->rev <= 1) {
7030 		start = 0x10;
7031 		end = 0x20;
7032 	}
7033 
7034 	table = BWN_OFDMTAB_GAINX;
7035 	if (phy->rev <= 1)
7036 		table = BWN_OFDMTAB_GAINX_R1;
7037 	for (i = 0; i < 4; i++)
7038 		bwn_ofdmtab_write_2(mac, table, i, first);
7039 
7040 	for (i = start; i < end; i++)
7041 		bwn_ofdmtab_write_2(mac, table, i, second);
7042 
7043 	if (third != -1) {
7044 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7045 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7046 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7047 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7048 	}
7049 	bwn_dummy_transmission(mac, 0, 1);
7050 }
7051 
7052 static void
7053 bwn_set_original_gains(struct bwn_mac *mac)
7054 {
7055 	struct bwn_phy *phy = &mac->mac_phy;
7056 	uint16_t i, tmp;
7057 	uint16_t table;
7058 	uint16_t start = 0x0008, end = 0x0018;
7059 
7060 	if (phy->rev <= 1) {
7061 		start = 0x0010;
7062 		end = 0x0020;
7063 	}
7064 
7065 	table = BWN_OFDMTAB_GAINX;
7066 	if (phy->rev <= 1)
7067 		table = BWN_OFDMTAB_GAINX_R1;
7068 	for (i = 0; i < 4; i++) {
7069 		tmp = (i & 0xfffc);
7070 		tmp |= (i & 0x0001) << 1;
7071 		tmp |= (i & 0x0002) >> 1;
7072 
7073 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7074 	}
7075 
7076 	for (i = start; i < end; i++)
7077 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7078 
7079 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7080 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7081 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7082 	bwn_dummy_transmission(mac, 0, 1);
7083 }
7084 
7085 static void
7086 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7087 {
7088 	struct bwn_phy *phy = &mac->mac_phy;
7089 	struct bwn_phy_g *pg = &phy->phy_g;
7090 	struct bwn_rfatt old_rfatt, rfatt;
7091 	struct bwn_bbatt old_bbatt, bbatt;
7092 	struct bwn_softc *sc = mac->mac_sc;
7093 	uint8_t old_txctl = 0;
7094 
7095 	KASSERT(phy->type == BWN_PHYTYPE_G,
7096 	    ("%s:%d: fail", __func__, __LINE__));
7097 
7098 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7099 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7100 		return;
7101 
7102 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7103 
7104 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7105 
7106 	if (!phy->gmode)
7107 		return;
7108 	bwn_hwpctl_early_init(mac);
7109 	if (pg->pg_curtssi == 0) {
7110 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7111 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7112 		} else {
7113 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7114 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7115 			old_txctl = pg->pg_txctl;
7116 
7117 			bbatt.att = 11;
7118 			if (phy->rf_rev == 8) {
7119 				rfatt.att = 15;
7120 				rfatt.padmix = 1;
7121 			} else {
7122 				rfatt.att = 9;
7123 				rfatt.padmix = 0;
7124 			}
7125 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7126 		}
7127 		bwn_dummy_transmission(mac, 0, 1);
7128 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7129 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7130 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7131 		else
7132 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7133 			    &old_rfatt, old_txctl);
7134 	}
7135 	bwn_hwpctl_init_gphy(mac);
7136 
7137 	/* clear TSSI */
7138 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7139 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7140 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7141 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7142 }
7143 
7144 static void
7145 bwn_hwpctl_early_init(struct bwn_mac *mac)
7146 {
7147 	struct bwn_phy *phy = &mac->mac_phy;
7148 
7149 	if (!bwn_has_hwpctl(mac)) {
7150 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7151 		return;
7152 	}
7153 
7154 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7155 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7156 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7157 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7158 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7159 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7160 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7161 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7162 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7163 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7164 	} else {
7165 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7166 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7167 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7168 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7169 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7170 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7171 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7172 	}
7173 }
7174 
7175 static void
7176 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7177 {
7178 	struct bwn_phy *phy = &mac->mac_phy;
7179 	struct bwn_phy_g *pg = &phy->phy_g;
7180 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7181 	int i;
7182 	uint16_t nr_written = 0, tmp, value;
7183 	uint8_t rf, bb;
7184 
7185 	if (!bwn_has_hwpctl(mac)) {
7186 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7187 		return;
7188 	}
7189 
7190 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7191 	    (pg->pg_idletssi - pg->pg_curtssi));
7192 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7193 	    (pg->pg_idletssi - pg->pg_curtssi));
7194 
7195 	for (i = 0; i < 32; i++)
7196 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7197 	for (i = 32; i < 64; i++)
7198 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7199 	for (i = 0; i < 64; i += 2) {
7200 		value = (uint16_t) pg->pg_tssi2dbm[i];
7201 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7202 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7203 	}
7204 
7205 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7206 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7207 			if (nr_written >= 0x40)
7208 				return;
7209 			tmp = lo->bbatt.array[bb].att;
7210 			tmp <<= 8;
7211 			if (phy->rf_rev == 8)
7212 				tmp |= 0x50;
7213 			else
7214 				tmp |= 0x40;
7215 			tmp |= lo->rfatt.array[rf].att;
7216 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7217 			nr_written++;
7218 		}
7219 	}
7220 
7221 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7222 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7223 
7224 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7225 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7226 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7227 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7228 
7229 	bwn_phy_g_dc_lookup_init(mac, 1);
7230 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7231 }
7232 
7233 static void
7234 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7235 {
7236 	struct bwn_softc *sc = mac->mac_sc;
7237 
7238 	if (spu != 0)
7239 		bwn_spu_workaround(mac, channel);
7240 
7241 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7242 
7243 	if (channel == 14) {
7244 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7245 			bwn_hf_write(mac,
7246 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7247 		else
7248 			bwn_hf_write(mac,
7249 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7250 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7251 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7252 		return;
7253 	}
7254 
7255 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7256 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7257 }
7258 
7259 static uint16_t
7260 bwn_phy_g_chan2freq(uint8_t channel)
7261 {
7262 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7263 
7264 	KASSERT(channel >= 1 && channel <= 14,
7265 	    ("%s:%d: fail", __func__, __LINE__));
7266 
7267 	return (bwn_phy_g_rf_channels[channel - 1]);
7268 }
7269 
7270 static void
7271 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7272     const struct bwn_rfatt *rfatt, uint8_t txctl)
7273 {
7274 	struct bwn_phy *phy = &mac->mac_phy;
7275 	struct bwn_phy_g *pg = &phy->phy_g;
7276 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7277 	uint16_t bb, rf;
7278 	uint16_t tx_bias, tx_magn;
7279 
7280 	bb = bbatt->att;
7281 	rf = rfatt->att;
7282 	tx_bias = lo->tx_bias;
7283 	tx_magn = lo->tx_magn;
7284 	if (tx_bias == 0xff)
7285 		tx_bias = 0;
7286 
7287 	pg->pg_txctl = txctl;
7288 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7289 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7290 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7291 	bwn_phy_g_set_bbatt(mac, bb);
7292 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7293 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7294 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7295 	else {
7296 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7297 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7298 	}
7299 	if (BWN_HAS_TXMAG(phy))
7300 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7301 	else
7302 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7303 	bwn_lo_g_adjust(mac);
7304 }
7305 
7306 static void
7307 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7308     uint16_t bbatt)
7309 {
7310 	struct bwn_phy *phy = &mac->mac_phy;
7311 
7312 	if (phy->analog == 0) {
7313 		BWN_WRITE_2(mac, BWN_PHY0,
7314 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7315 		return;
7316 	}
7317 	if (phy->analog > 1) {
7318 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7319 		return;
7320 	}
7321 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7322 }
7323 
7324 static uint16_t
7325 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7326 {
7327 	struct bwn_phy *phy = &mac->mac_phy;
7328 	struct bwn_phy_g *pg = &phy->phy_g;
7329 	struct bwn_softc *sc = mac->mac_sc;
7330 	int max_lb_gain;
7331 	uint16_t extlna;
7332 	uint16_t i;
7333 
7334 	if (phy->gmode == 0)
7335 		return (0);
7336 
7337 	if (BWN_HAS_LOOPBACK(phy)) {
7338 		max_lb_gain = pg->pg_max_lb_gain;
7339 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7340 		if (max_lb_gain >= 0x46) {
7341 			extlna = 0x3000;
7342 			max_lb_gain -= 0x46;
7343 		} else if (max_lb_gain >= 0x3a) {
7344 			extlna = 0x1000;
7345 			max_lb_gain -= 0x3a;
7346 		} else if (max_lb_gain >= 0x2e) {
7347 			extlna = 0x2000;
7348 			max_lb_gain -= 0x2e;
7349 		} else {
7350 			extlna = 0;
7351 			max_lb_gain -= 0x10;
7352 		}
7353 
7354 		for (i = 0; i < 16; i++) {
7355 			max_lb_gain -= (i * 6);
7356 			if (max_lb_gain < 6)
7357 				break;
7358 		}
7359 
7360 		if ((phy->rev < 7) ||
7361 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7362 			if (reg == BWN_PHY_RFOVER) {
7363 				return (0x1b3);
7364 			} else if (reg == BWN_PHY_RFOVERVAL) {
7365 				extlna |= (i << 8);
7366 				switch (lpd) {
7367 				case BWN_LPD(0, 1, 1):
7368 					return (0x0f92);
7369 				case BWN_LPD(0, 0, 1):
7370 				case BWN_LPD(1, 0, 1):
7371 					return (0x0092 | extlna);
7372 				case BWN_LPD(1, 0, 0):
7373 					return (0x0093 | extlna);
7374 				}
7375 				KASSERT(0 == 1,
7376 				    ("%s:%d: fail", __func__, __LINE__));
7377 			}
7378 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7379 		} else {
7380 			if (reg == BWN_PHY_RFOVER)
7381 				return (0x9b3);
7382 			if (reg == BWN_PHY_RFOVERVAL) {
7383 				if (extlna)
7384 					extlna |= 0x8000;
7385 				extlna |= (i << 8);
7386 				switch (lpd) {
7387 				case BWN_LPD(0, 1, 1):
7388 					return (0x8f92);
7389 				case BWN_LPD(0, 0, 1):
7390 					return (0x8092 | extlna);
7391 				case BWN_LPD(1, 0, 1):
7392 					return (0x2092 | extlna);
7393 				case BWN_LPD(1, 0, 0):
7394 					return (0x2093 | extlna);
7395 				}
7396 				KASSERT(0 == 1,
7397 				    ("%s:%d: fail", __func__, __LINE__));
7398 			}
7399 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7400 		}
7401 		return (0);
7402 	}
7403 
7404 	if ((phy->rev < 7) ||
7405 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7406 		if (reg == BWN_PHY_RFOVER) {
7407 			return (0x1b3);
7408 		} else if (reg == BWN_PHY_RFOVERVAL) {
7409 			switch (lpd) {
7410 			case BWN_LPD(0, 1, 1):
7411 				return (0x0fb2);
7412 			case BWN_LPD(0, 0, 1):
7413 				return (0x00b2);
7414 			case BWN_LPD(1, 0, 1):
7415 				return (0x30b2);
7416 			case BWN_LPD(1, 0, 0):
7417 				return (0x30b3);
7418 			}
7419 			KASSERT(0 == 1,
7420 			    ("%s:%d: fail", __func__, __LINE__));
7421 		}
7422 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7423 	} else {
7424 		if (reg == BWN_PHY_RFOVER) {
7425 			return (0x9b3);
7426 		} else if (reg == BWN_PHY_RFOVERVAL) {
7427 			switch (lpd) {
7428 			case BWN_LPD(0, 1, 1):
7429 				return (0x8fb2);
7430 			case BWN_LPD(0, 0, 1):
7431 				return (0x80b2);
7432 			case BWN_LPD(1, 0, 1):
7433 				return (0x20b2);
7434 			case BWN_LPD(1, 0, 0):
7435 				return (0x20b3);
7436 			}
7437 			KASSERT(0 == 1,
7438 			    ("%s:%d: fail", __func__, __LINE__));
7439 		}
7440 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7441 	}
7442 	return (0);
7443 }
7444 
7445 static void
7446 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7447 {
7448 
7449 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7450 		return;
7451 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7452 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7453 	DELAY(1000);
7454 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7455 }
7456 
7457 static int
7458 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7459 {
7460 	struct bwn_softc *sc = mac->mac_sc;
7461 	struct bwn_fw *fw = &mac->mac_fw;
7462 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7463 	const char *filename;
7464 	uint32_t high;
7465 	int error;
7466 
7467 	/* microcode */
7468 	if (rev >= 5 && rev <= 10)
7469 		filename = "ucode5";
7470 	else if (rev >= 11 && rev <= 12)
7471 		filename = "ucode11";
7472 	else if (rev == 13)
7473 		filename = "ucode13";
7474 	else if (rev == 14)
7475 		filename = "ucode14";
7476 	else if (rev >= 15)
7477 		filename = "ucode15";
7478 	else {
7479 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7480 		bwn_release_firmware(mac);
7481 		return (EOPNOTSUPP);
7482 	}
7483 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7484 	if (error) {
7485 		bwn_release_firmware(mac);
7486 		return (error);
7487 	}
7488 
7489 	/* PCM */
7490 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7491 	if (rev >= 5 && rev <= 10) {
7492 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7493 		if (error == ENOENT)
7494 			fw->no_pcmfile = 1;
7495 		else if (error) {
7496 			bwn_release_firmware(mac);
7497 			return (error);
7498 		}
7499 	} else if (rev < 11) {
7500 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7501 		return (EOPNOTSUPP);
7502 	}
7503 
7504 	/* initvals */
7505 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7506 	switch (mac->mac_phy.type) {
7507 	case BWN_PHYTYPE_A:
7508 		if (rev < 5 || rev > 10)
7509 			goto fail1;
7510 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7511 			filename = "a0g1initvals5";
7512 		else
7513 			filename = "a0g0initvals5";
7514 		break;
7515 	case BWN_PHYTYPE_G:
7516 		if (rev >= 5 && rev <= 10)
7517 			filename = "b0g0initvals5";
7518 		else if (rev >= 13)
7519 			filename = "b0g0initvals13";
7520 		else
7521 			goto fail1;
7522 		break;
7523 	case BWN_PHYTYPE_LP:
7524 		if (rev == 13)
7525 			filename = "lp0initvals13";
7526 		else if (rev == 14)
7527 			filename = "lp0initvals14";
7528 		else if (rev >= 15)
7529 			filename = "lp0initvals15";
7530 		else
7531 			goto fail1;
7532 		break;
7533 	case BWN_PHYTYPE_N:
7534 		if (rev >= 11 && rev <= 12)
7535 			filename = "n0initvals11";
7536 		else
7537 			goto fail1;
7538 		break;
7539 	default:
7540 		goto fail1;
7541 	}
7542 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7543 	if (error) {
7544 		bwn_release_firmware(mac);
7545 		return (error);
7546 	}
7547 
7548 	/* bandswitch initvals */
7549 	switch (mac->mac_phy.type) {
7550 	case BWN_PHYTYPE_A:
7551 		if (rev >= 5 && rev <= 10) {
7552 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7553 				filename = "a0g1bsinitvals5";
7554 			else
7555 				filename = "a0g0bsinitvals5";
7556 		} else if (rev >= 11)
7557 			filename = NULL;
7558 		else
7559 			goto fail1;
7560 		break;
7561 	case BWN_PHYTYPE_G:
7562 		if (rev >= 5 && rev <= 10)
7563 			filename = "b0g0bsinitvals5";
7564 		else if (rev >= 11)
7565 			filename = NULL;
7566 		else
7567 			goto fail1;
7568 		break;
7569 	case BWN_PHYTYPE_LP:
7570 		if (rev == 13)
7571 			filename = "lp0bsinitvals13";
7572 		else if (rev == 14)
7573 			filename = "lp0bsinitvals14";
7574 		else if (rev >= 15)
7575 			filename = "lp0bsinitvals15";
7576 		else
7577 			goto fail1;
7578 		break;
7579 	case BWN_PHYTYPE_N:
7580 		if (rev >= 11 && rev <= 12)
7581 			filename = "n0bsinitvals11";
7582 		else
7583 			goto fail1;
7584 		break;
7585 	default:
7586 		goto fail1;
7587 	}
7588 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7589 	if (error) {
7590 		bwn_release_firmware(mac);
7591 		return (error);
7592 	}
7593 	return (0);
7594 fail1:
7595 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7596 	bwn_release_firmware(mac);
7597 	return (EOPNOTSUPP);
7598 }
7599 
7600 static int
7601 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7602     const char *name, struct bwn_fwfile *bfw)
7603 {
7604 	const struct bwn_fwhdr *hdr;
7605 	struct bwn_softc *sc = mac->mac_sc;
7606 	const struct firmware *fw;
7607 	char namebuf[64];
7608 
7609 	if (name == NULL) {
7610 		bwn_do_release_fw(bfw);
7611 		return (0);
7612 	}
7613 	if (bfw->filename != NULL) {
7614 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7615 			return (0);
7616 		bwn_do_release_fw(bfw);
7617 	}
7618 
7619 	ksnprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7620 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7621 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7622 	wlan_assert_serialized();
7623 	wlan_serialize_exit();
7624 	fw = firmware_get(namebuf);
7625 	wlan_serialize_enter();
7626 	if (fw == NULL) {
7627 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7628 		    namebuf);
7629 		return (ENOENT);
7630 	}
7631 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7632 		goto fail;
7633 	hdr = (const struct bwn_fwhdr *)(fw->data);
7634 	switch (hdr->type) {
7635 	case BWN_FWTYPE_UCODE:
7636 	case BWN_FWTYPE_PCM:
7637 		if (be32toh(hdr->size) !=
7638 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7639 			goto fail;
7640 		/* FALLTHROUGH */
7641 	case BWN_FWTYPE_IV:
7642 		if (hdr->ver != 1)
7643 			goto fail;
7644 		break;
7645 	default:
7646 		goto fail;
7647 	}
7648 	bfw->filename = name;
7649 	bfw->fw = fw;
7650 	bfw->type = type;
7651 	return (0);
7652 fail:
7653 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7654 	if (fw != NULL)
7655 		firmware_put(fw, FIRMWARE_UNLOAD);
7656 	return (EPROTO);
7657 }
7658 
7659 static void
7660 bwn_release_firmware(struct bwn_mac *mac)
7661 {
7662 
7663 	bwn_do_release_fw(&mac->mac_fw.ucode);
7664 	bwn_do_release_fw(&mac->mac_fw.pcm);
7665 	bwn_do_release_fw(&mac->mac_fw.initvals);
7666 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7667 }
7668 
7669 static void
7670 bwn_do_release_fw(struct bwn_fwfile *bfw)
7671 {
7672 
7673 	if (bfw->fw != NULL)
7674 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7675 	bfw->fw = NULL;
7676 	bfw->filename = NULL;
7677 }
7678 
7679 static int
7680 bwn_fw_loaducode(struct bwn_mac *mac)
7681 {
7682 #define	GETFWOFFSET(fwp, offset)	\
7683 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7684 #define	GETFWSIZE(fwp, offset)	\
7685 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7686 	struct bwn_softc *sc = mac->mac_sc;
7687 	const uint32_t *data;
7688 	unsigned int i;
7689 	uint32_t ctl;
7690 	uint16_t date, fwcaps, time;
7691 	int error = 0;
7692 
7693 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7694 	ctl |= BWN_MACCTL_MCODE_JMP0;
7695 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7696 	    __LINE__));
7697 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7698 	for (i = 0; i < 64; i++)
7699 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7700 	for (i = 0; i < 4096; i += 2)
7701 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7702 
7703 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7704 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7705 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7706 	     i++) {
7707 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7708 		DELAY(10);
7709 	}
7710 
7711 	if (mac->mac_fw.pcm.fw) {
7712 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7713 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7714 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7715 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7716 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7717 		    sizeof(struct bwn_fwhdr)); i++) {
7718 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7719 			DELAY(10);
7720 		}
7721 	}
7722 
7723 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7724 	BWN_WRITE_4(mac, BWN_MACCTL,
7725 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7726 	    BWN_MACCTL_MCODE_RUN);
7727 
7728 	for (i = 0; i < 21; i++) {
7729 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7730 			break;
7731 		if (i >= 20) {
7732 			device_printf(sc->sc_dev, "ucode timeout\n");
7733 			error = ENXIO;
7734 			goto error;
7735 		}
7736 		DELAY(50000);
7737 	}
7738 	BWN_READ_4(mac, BWN_INTR_REASON);
7739 
7740 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7741 	if (mac->mac_fw.rev <= 0x128) {
7742 		device_printf(sc->sc_dev, "the firmware is too old\n");
7743 		error = EOPNOTSUPP;
7744 		goto error;
7745 	}
7746 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7747 	    BWN_SHARED_UCODE_PATCH);
7748 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7749 	mac->mac_fw.opensource = (date == 0xffff);
7750 	if (bwn_wme != 0)
7751 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7752 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7753 
7754 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7755 	if (mac->mac_fw.opensource == 0) {
7756 		device_printf(sc->sc_dev,
7757 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7758 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7759 		if (mac->mac_fw.no_pcmfile)
7760 			device_printf(sc->sc_dev,
7761 			    "no HW crypto acceleration due to pcm5\n");
7762 	} else {
7763 		mac->mac_fw.patch = time;
7764 		fwcaps = bwn_fwcaps_read(mac);
7765 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7766 			device_printf(sc->sc_dev,
7767 			    "disabling HW crypto acceleration\n");
7768 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7769 		}
7770 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7771 			device_printf(sc->sc_dev, "disabling WME support\n");
7772 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7773 		}
7774 	}
7775 
7776 	if (BWN_ISOLDFMT(mac))
7777 		device_printf(sc->sc_dev, "using old firmware image\n");
7778 
7779 	return (0);
7780 
7781 error:
7782 	BWN_WRITE_4(mac, BWN_MACCTL,
7783 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7784 	    BWN_MACCTL_MCODE_JMP0);
7785 
7786 	return (error);
7787 #undef GETFWSIZE
7788 #undef GETFWOFFSET
7789 }
7790 
7791 /* OpenFirmware only */
7792 static uint16_t
7793 bwn_fwcaps_read(struct bwn_mac *mac)
7794 {
7795 
7796 	KASSERT(mac->mac_fw.opensource == 1,
7797 	    ("%s:%d: fail", __func__, __LINE__));
7798 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7799 }
7800 
7801 static int
7802 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7803     size_t count, size_t array_size)
7804 {
7805 #define	GET_NEXTIV16(iv)						\
7806 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7807 	    sizeof(uint16_t) + sizeof(uint16_t)))
7808 #define	GET_NEXTIV32(iv)						\
7809 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7810 	    sizeof(uint16_t) + sizeof(uint32_t)))
7811 	struct bwn_softc *sc = mac->mac_sc;
7812 	const struct bwn_fwinitvals *iv;
7813 	uint16_t offset;
7814 	size_t i;
7815 	uint8_t bit32;
7816 
7817 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7818 	    ("%s:%d: fail", __func__, __LINE__));
7819 	iv = ivals;
7820 	for (i = 0; i < count; i++) {
7821 		if (array_size < sizeof(iv->offset_size))
7822 			goto fail;
7823 		array_size -= sizeof(iv->offset_size);
7824 		offset = be16toh(iv->offset_size);
7825 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7826 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7827 		if (offset >= 0x1000)
7828 			goto fail;
7829 		if (bit32) {
7830 			if (array_size < sizeof(iv->data.d32))
7831 				goto fail;
7832 			array_size -= sizeof(iv->data.d32);
7833 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7834 			iv = GET_NEXTIV32(iv);
7835 		} else {
7836 
7837 			if (array_size < sizeof(iv->data.d16))
7838 				goto fail;
7839 			array_size -= sizeof(iv->data.d16);
7840 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7841 
7842 			iv = GET_NEXTIV16(iv);
7843 		}
7844 	}
7845 	if (array_size != 0)
7846 		goto fail;
7847 	return (0);
7848 fail:
7849 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7850 	return (EPROTO);
7851 #undef GET_NEXTIV16
7852 #undef GET_NEXTIV32
7853 }
7854 
7855 static int
7856 bwn_switch_channel(struct bwn_mac *mac, int chan)
7857 {
7858 	struct bwn_phy *phy = &(mac->mac_phy);
7859 	struct bwn_softc *sc = mac->mac_sc;
7860 	struct ifnet *ifp = sc->sc_ifp;
7861 	struct ieee80211com *ic = ifp->if_l2com;
7862 	uint16_t channelcookie, savedcookie;
7863 	int error;
7864 
7865 	if (chan == 0xffff)
7866 		chan = phy->get_default_chan(mac);
7867 
7868 	channelcookie = chan;
7869 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7870 		channelcookie |= 0x100;
7871 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7872 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7873 	error = phy->switch_channel(mac, chan);
7874 	if (error)
7875 		goto fail;
7876 
7877 	mac->mac_phy.chan = chan;
7878 	DELAY(8000);
7879 	return (0);
7880 fail:
7881 	device_printf(sc->sc_dev, "failed to switch channel\n");
7882 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7883 	return (error);
7884 }
7885 
7886 static uint16_t
7887 bwn_ant2phy(int antenna)
7888 {
7889 
7890 	switch (antenna) {
7891 	case BWN_ANT0:
7892 		return (BWN_TX_PHY_ANT0);
7893 	case BWN_ANT1:
7894 		return (BWN_TX_PHY_ANT1);
7895 	case BWN_ANT2:
7896 		return (BWN_TX_PHY_ANT2);
7897 	case BWN_ANT3:
7898 		return (BWN_TX_PHY_ANT3);
7899 	case BWN_ANTAUTO:
7900 		return (BWN_TX_PHY_ANT01AUTO);
7901 	}
7902 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7903 	return (0);
7904 }
7905 
7906 static void
7907 bwn_wme_load(struct bwn_mac *mac)
7908 {
7909 	struct bwn_softc *sc = mac->mac_sc;
7910 	int i;
7911 
7912 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7913 	    ("%s:%d: fail", __func__, __LINE__));
7914 
7915 	bwn_mac_suspend(mac);
7916 	for (i = 0; i < N(sc->sc_wmeParams); i++)
7917 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7918 		    bwn_wme_shm_offsets[i]);
7919 	bwn_mac_enable(mac);
7920 }
7921 
7922 static void
7923 bwn_wme_loadparams(struct bwn_mac *mac,
7924     const struct wmeParams *p, uint16_t shm_offset)
7925 {
7926 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7927 	struct bwn_softc *sc = mac->mac_sc;
7928 	uint16_t params[BWN_NR_WMEPARAMS];
7929 	int slot, tmp;
7930 	unsigned int i;
7931 
7932 	slot = BWN_READ_2(mac, BWN_RNG) &
7933 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7934 
7935 	memset(&params, 0, sizeof(params));
7936 
7937 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7938 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7939 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7940 
7941 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7942 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7943 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7944 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7945 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7946 	params[BWN_WMEPARAM_BSLOTS] = slot;
7947 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7948 
7949 	for (i = 0; i < N(params); i++) {
7950 		if (i == BWN_WMEPARAM_STATUS) {
7951 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7952 			    shm_offset + (i * 2));
7953 			tmp |= 0x100;
7954 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7955 			    tmp);
7956 		} else {
7957 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7958 			    params[i]);
7959 		}
7960 	}
7961 }
7962 
7963 static void
7964 bwn_mac_write_bssid(struct bwn_mac *mac)
7965 {
7966 	struct bwn_softc *sc = mac->mac_sc;
7967 	uint32_t tmp;
7968 	int i;
7969 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7970 
7971 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7972 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
7973 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7974 	    IEEE80211_ADDR_LEN);
7975 
7976 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7977 		tmp = (uint32_t) (mac_bssid[i + 0]);
7978 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7979 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7980 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7981 		bwn_ram_write(mac, 0x20 + i, tmp);
7982 	}
7983 }
7984 
7985 static void
7986 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7987     const uint8_t *macaddr)
7988 {
7989 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7990 	uint16_t data;
7991 
7992 	if (mac == NULL)
7993 		macaddr = zero;
7994 
7995 	offset |= 0x0020;
7996 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7997 
7998 	data = macaddr[0];
7999 	data |= macaddr[1] << 8;
8000 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8001 	data = macaddr[2];
8002 	data |= macaddr[3] << 8;
8003 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8004 	data = macaddr[4];
8005 	data |= macaddr[5] << 8;
8006 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8007 }
8008 
8009 static void
8010 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8011     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8012 {
8013 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8014 	uint8_t per_sta_keys_start = 8;
8015 
8016 	if (BWN_SEC_NEWAPI(mac))
8017 		per_sta_keys_start = 4;
8018 
8019 	KASSERT(index < mac->mac_max_nr_keys,
8020 	    ("%s:%d: fail", __func__, __LINE__));
8021 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8022 	    ("%s:%d: fail", __func__, __LINE__));
8023 
8024 	if (index >= per_sta_keys_start)
8025 		bwn_key_macwrite(mac, index, NULL);
8026 	if (key)
8027 		memcpy(buf, key, key_len);
8028 	bwn_key_write(mac, index, algorithm, buf);
8029 	if (index >= per_sta_keys_start)
8030 		bwn_key_macwrite(mac, index, mac_addr);
8031 
8032 	mac->mac_key[index].algorithm = algorithm;
8033 }
8034 
8035 static void
8036 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8037 {
8038 	struct bwn_softc *sc = mac->mac_sc;
8039 	uint32_t addrtmp[2] = { 0, 0 };
8040 	uint8_t start = 8;
8041 
8042 	if (BWN_SEC_NEWAPI(mac))
8043 		start = 4;
8044 
8045 	KASSERT(index >= start,
8046 	    ("%s:%d: fail", __func__, __LINE__));
8047 	index -= start;
8048 
8049 	if (addr) {
8050 		addrtmp[0] = addr[0];
8051 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8052 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8053 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8054 		addrtmp[1] = addr[4];
8055 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8056 	}
8057 
8058 	if (siba_get_revid(sc->sc_dev) >= 5) {
8059 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8060 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8061 	} else {
8062 		if (index >= 8) {
8063 			bwn_shm_write_4(mac, BWN_SHARED,
8064 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8065 			bwn_shm_write_2(mac, BWN_SHARED,
8066 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8067 		}
8068 	}
8069 }
8070 
8071 static void
8072 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8073     const uint8_t *key)
8074 {
8075 	unsigned int i;
8076 	uint32_t offset;
8077 	uint16_t kidx, value;
8078 
8079 	kidx = BWN_SEC_KEY2FW(mac, index);
8080 	bwn_shm_write_2(mac, BWN_SHARED,
8081 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8082 
8083 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8084 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8085 		value = key[i];
8086 		value |= (uint16_t)(key[i + 1]) << 8;
8087 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8088 	}
8089 }
8090 
8091 static void
8092 bwn_phy_exit(struct bwn_mac *mac)
8093 {
8094 
8095 	mac->mac_phy.rf_onoff(mac, 0);
8096 	if (mac->mac_phy.exit != NULL)
8097 		mac->mac_phy.exit(mac);
8098 }
8099 
8100 static void
8101 bwn_dma_free(struct bwn_mac *mac)
8102 {
8103 	struct bwn_dma *dma;
8104 
8105 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8106 		return;
8107 	dma = &mac->mac_method.dma;
8108 
8109 	bwn_dma_ringfree(&dma->rx);
8110 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8111 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8112 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8113 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8114 	bwn_dma_ringfree(&dma->mcast);
8115 }
8116 
8117 static void
8118 bwn_core_stop(struct bwn_mac *mac)
8119 {
8120 	struct bwn_softc *sc = mac->mac_sc;
8121 
8122 	wlan_assert_serialized();
8123 
8124 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8125 		return;
8126 
8127 	callout_stop(&sc->sc_rfswitch_ch);
8128 	callout_stop(&sc->sc_task_ch);
8129 	callout_stop(&sc->sc_watchdog_ch);
8130 	sc->sc_watchdog_timer = 0;
8131 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8132 	BWN_READ_4(mac, BWN_INTR_MASK);
8133 	bwn_mac_suspend(mac);
8134 
8135 	mac->mac_status = BWN_MAC_STATUS_INITED;
8136 }
8137 
8138 static int
8139 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8140 {
8141 	struct bwn_mac *up_dev = NULL;
8142 	struct bwn_mac *down_dev;
8143 	struct bwn_mac *mac;
8144 	int err, status;
8145 	uint8_t gmode;
8146 
8147 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8148 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8149 		    mac->mac_phy.supports_2ghz) {
8150 			up_dev = mac;
8151 			gmode = 1;
8152 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8153 		    mac->mac_phy.supports_5ghz) {
8154 			up_dev = mac;
8155 			gmode = 0;
8156 		} else {
8157 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8158 			return (EINVAL);
8159 		}
8160 		if (up_dev != NULL)
8161 			break;
8162 	}
8163 	if (up_dev == NULL) {
8164 		device_printf(sc->sc_dev, "Could not find a device\n");
8165 		return (ENODEV);
8166 	}
8167 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8168 		return (0);
8169 
8170 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8171 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8172 
8173 	down_dev = sc->sc_curmac;
8174 	status = down_dev->mac_status;
8175 	if (status >= BWN_MAC_STATUS_STARTED)
8176 		bwn_core_stop(down_dev);
8177 	if (status >= BWN_MAC_STATUS_INITED)
8178 		bwn_core_exit(down_dev);
8179 
8180 	if (down_dev != up_dev)
8181 		bwn_phy_reset(down_dev);
8182 
8183 	up_dev->mac_phy.gmode = gmode;
8184 	if (status >= BWN_MAC_STATUS_INITED) {
8185 		err = bwn_core_init(up_dev);
8186 		if (err) {
8187 			device_printf(sc->sc_dev,
8188 			    "fatal: failed to initialize for %s-GHz\n",
8189 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8190 			goto fail;
8191 		}
8192 	}
8193 	if (status >= BWN_MAC_STATUS_STARTED)
8194 		bwn_core_start(up_dev);
8195 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8196 	sc->sc_curmac = up_dev;
8197 
8198 	return (0);
8199 fail:
8200 	sc->sc_curmac = NULL;
8201 	return (err);
8202 }
8203 
8204 static void
8205 bwn_rf_turnon(struct bwn_mac *mac)
8206 {
8207 
8208 	bwn_mac_suspend(mac);
8209 	mac->mac_phy.rf_onoff(mac, 1);
8210 	mac->mac_phy.rf_on = 1;
8211 	bwn_mac_enable(mac);
8212 }
8213 
8214 static void
8215 bwn_rf_turnoff(struct bwn_mac *mac)
8216 {
8217 
8218 	bwn_mac_suspend(mac);
8219 	mac->mac_phy.rf_onoff(mac, 0);
8220 	mac->mac_phy.rf_on = 0;
8221 	bwn_mac_enable(mac);
8222 }
8223 
8224 static void
8225 bwn_phy_reset(struct bwn_mac *mac)
8226 {
8227 	struct bwn_softc *sc = mac->mac_sc;
8228 
8229 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8230 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8231 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8232 	DELAY(1000);
8233 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8234 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8235 	    BWN_TGSLOW_PHYRESET);
8236 	DELAY(1000);
8237 }
8238 
8239 static int
8240 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8241 {
8242 	struct bwn_vap *bvp = BWN_VAP(vap);
8243 	struct ieee80211com *ic= vap->iv_ic;
8244 	struct ifnet *ifp = ic->ic_ifp;
8245 	enum ieee80211_state ostate = vap->iv_state;
8246 	struct bwn_softc *sc = ifp->if_softc;
8247 	struct bwn_mac *mac = sc->sc_curmac;
8248 	int error;
8249 
8250 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8251 	    ieee80211_state_name[vap->iv_state],
8252 	    ieee80211_state_name[nstate]);
8253 
8254 	error = bvp->bv_newstate(vap, nstate, arg);
8255 	if (error != 0)
8256 		return (error);
8257 
8258 	bwn_led_newstate(mac, nstate);
8259 
8260 	/*
8261 	 * Clear the BSSID when we stop a STA
8262 	 */
8263 	if (vap->iv_opmode == IEEE80211_M_STA) {
8264 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8265 			/*
8266 			 * Clear out the BSSID.  If we reassociate to
8267 			 * the same AP, this will reinialize things
8268 			 * correctly...
8269 			 */
8270 			if (ic->ic_opmode == IEEE80211_M_STA &&
8271 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8272 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8273 				bwn_set_macaddr(mac);
8274 			}
8275 		}
8276 	}
8277 
8278 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8279 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8280 		/* XXX nothing to do? */
8281 	} else if (nstate == IEEE80211_S_RUN) {
8282 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8283 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8284 		bwn_set_opmode(mac);
8285 		bwn_set_pretbtt(mac);
8286 		bwn_spu_setdelay(mac, 0);
8287 		bwn_set_macaddr(mac);
8288 	}
8289 
8290 	return (error);
8291 }
8292 
8293 static void
8294 bwn_set_pretbtt(struct bwn_mac *mac)
8295 {
8296 	struct bwn_softc *sc = mac->mac_sc;
8297 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8298 	uint16_t pretbtt;
8299 
8300 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8301 		pretbtt = 2;
8302 	else
8303 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8304 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8305 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8306 }
8307 
8308 static void
8309 bwn_intr(void *arg)
8310 {
8311 	struct bwn_mac *mac = arg;
8312 	struct bwn_softc *sc = mac->mac_sc;
8313 	uint32_t reason;
8314 
8315 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8316 	    (sc->sc_flags & BWN_FLAG_INVALID))
8317 		return;
8318 
8319 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8320 	if (reason == 0xffffffff)	/* shared IRQ */
8321 		return;
8322 	reason &= mac->mac_intr_mask;
8323 	if (reason == 0)
8324 		return;
8325 
8326 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001fc00;
8327 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8328 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8329 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8330 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8331 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8332 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8333 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8334 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8335 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8336 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8337 
8338 	/* Disable interrupts. */
8339 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8340 
8341 	mac->mac_reason_intr = reason;
8342 
8343 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8344 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8345 
8346 	taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask);
8347 	return;
8348 }
8349 
8350 static void
8351 bwn_intrtask(void *arg, int npending)
8352 {
8353 	struct bwn_mac *mac = arg;
8354 	struct bwn_softc *sc = mac->mac_sc;
8355 	struct ifnet *ifp = sc->sc_ifp;
8356 	uint32_t merged = 0;
8357 	int i, tx = 0, rx = 0;
8358 
8359 	wlan_serialize_enter();
8360 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8361 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8362 		wlan_serialize_exit();
8363 		return;
8364 	}
8365 
8366 	for (i = 0; i < N(mac->mac_reason); i++)
8367 		merged |= mac->mac_reason[i];
8368 
8369 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8370 		device_printf(sc->sc_dev, "MAC trans error\n");
8371 
8372 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8373 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8374 		mac->mac_phy.txerrors--;
8375 		if (mac->mac_phy.txerrors == 0) {
8376 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8377 			bwn_restart(mac, "PHY TX errors");
8378 		}
8379 	}
8380 
8381 	if (merged & BWN_DMAINTR_FATALMASK) {
8382 		device_printf(sc->sc_dev,
8383 		    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8384 		    mac->mac_reason[0], mac->mac_reason[1],
8385 		    mac->mac_reason[2], mac->mac_reason[3],
8386 		    mac->mac_reason[4], mac->mac_reason[5]);
8387 		bwn_restart(mac, "DMA error");
8388 		wlan_serialize_exit();
8389 		return;
8390 	}
8391 
8392 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8393 		bwn_intr_ucode_debug(mac);
8394 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8395 		bwn_intr_tbtt_indication(mac);
8396 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8397 		bwn_intr_atim_end(mac);
8398 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8399 		bwn_intr_beacon(mac);
8400 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8401 		bwn_intr_pmq(mac);
8402 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8403 		bwn_intr_noise(mac);
8404 
8405 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8406 		if (mac->mac_reason[0] & BWN_DMAINTR_RDESC_UFLOW) {
8407 			device_printf(sc->sc_dev, "RX descriptor overflow\n");
8408 			bwn_dma_rx_handle_overflow(mac->mac_method.dma.rx);
8409 		}
8410 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8411 			bwn_dma_rx(mac->mac_method.dma.rx);
8412 			rx = 1;
8413 		}
8414 	} else
8415 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8416 
8417 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8418 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8419 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8420 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8421 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8422 
8423 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8424 		bwn_intr_txeof(mac);
8425 		tx = 1;
8426 	}
8427 
8428 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8429 
8430 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8431 		int evt = BWN_LED_EVENT_NONE;
8432 
8433 		if (tx && rx) {
8434 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8435 				evt = BWN_LED_EVENT_RX;
8436 			else
8437 				evt = BWN_LED_EVENT_TX;
8438 		} else if (tx) {
8439 			evt = BWN_LED_EVENT_TX;
8440 		} else if (rx) {
8441 			evt = BWN_LED_EVENT_RX;
8442 		} else if (rx == 0) {
8443 			evt = BWN_LED_EVENT_POLL;
8444 		}
8445 
8446 		if (evt != BWN_LED_EVENT_NONE)
8447 			bwn_led_event(mac, evt);
8448        }
8449 
8450 	if (!ifq_is_oactive(&ifp->if_snd)) {
8451 		if (!ifq_is_empty(&ifp->if_snd))
8452 			bwn_start_locked(ifp);
8453 	}
8454 
8455 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8456 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8457 
8458 	wlan_serialize_exit();
8459 }
8460 
8461 static void
8462 bwn_restart(struct bwn_mac *mac, const char *msg)
8463 {
8464 	struct bwn_softc *sc = mac->mac_sc;
8465 	struct ifnet *ifp = sc->sc_ifp;
8466 	struct ieee80211com *ic = ifp->if_l2com;
8467 
8468 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8469 		return;
8470 
8471 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8472 	ieee80211_runtask(ic, &mac->mac_hwreset);
8473 }
8474 
8475 static void
8476 bwn_intr_ucode_debug(struct bwn_mac *mac)
8477 {
8478 	struct bwn_softc *sc = mac->mac_sc;
8479 	uint16_t reason;
8480 
8481 	if (mac->mac_fw.opensource == 0)
8482 		return;
8483 
8484 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8485 	switch (reason) {
8486 	case BWN_DEBUGINTR_PANIC:
8487 		bwn_handle_fwpanic(mac);
8488 		break;
8489 	case BWN_DEBUGINTR_DUMP_SHM:
8490 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8491 		break;
8492 	case BWN_DEBUGINTR_DUMP_REGS:
8493 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8494 		break;
8495 	case BWN_DEBUGINTR_MARKER:
8496 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8497 		break;
8498 	default:
8499 		device_printf(sc->sc_dev,
8500 		    "ucode debug unknown reason: %#x\n", reason);
8501 	}
8502 
8503 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8504 	    BWN_DEBUGINTR_ACK);
8505 }
8506 
8507 static void
8508 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8509 {
8510 	struct bwn_softc *sc = mac->mac_sc;
8511 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8512 
8513 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8514 		bwn_psctl(mac, 0);
8515 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8516 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8517 }
8518 
8519 static void
8520 bwn_intr_atim_end(struct bwn_mac *mac)
8521 {
8522 
8523 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8524 		BWN_WRITE_4(mac, BWN_MACCMD,
8525 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8526 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8527 	}
8528 }
8529 
8530 static void
8531 bwn_intr_beacon(struct bwn_mac *mac)
8532 {
8533 	struct bwn_softc *sc = mac->mac_sc;
8534 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8535 	uint32_t cmd, beacon0, beacon1;
8536 
8537 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8538 	    ic->ic_opmode == IEEE80211_M_MBSS)
8539 		return;
8540 
8541 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8542 
8543 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8544 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8545 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8546 
8547 	if (beacon0 && beacon1) {
8548 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8549 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8550 		return;
8551 	}
8552 
8553 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8554 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8555 		bwn_load_beacon0(mac);
8556 		bwn_load_beacon1(mac);
8557 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8558 		cmd |= BWN_MACCMD_BEACON0_VALID;
8559 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8560 	} else {
8561 		if (!beacon0) {
8562 			bwn_load_beacon0(mac);
8563 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8564 			cmd |= BWN_MACCMD_BEACON0_VALID;
8565 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8566 		} else if (!beacon1) {
8567 			bwn_load_beacon1(mac);
8568 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8569 			cmd |= BWN_MACCMD_BEACON1_VALID;
8570 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8571 		}
8572 	}
8573 }
8574 
8575 static void
8576 bwn_intr_pmq(struct bwn_mac *mac)
8577 {
8578 	uint32_t tmp;
8579 
8580 	while (1) {
8581 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8582 		if (!(tmp & 0x00000008))
8583 			break;
8584 	}
8585 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8586 }
8587 
8588 static void
8589 bwn_intr_noise(struct bwn_mac *mac)
8590 {
8591 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8592 	uint16_t tmp;
8593 	uint8_t noise[4];
8594 	uint8_t i, j;
8595 	int32_t average;
8596 
8597 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8598 		return;
8599 
8600 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8601 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8602 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8603 	    noise[3] == 0x7f)
8604 		goto new;
8605 
8606 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8607 	    ("%s:%d: fail", __func__, __LINE__));
8608 	i = mac->mac_noise.noi_nsamples;
8609 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8610 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8611 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8612 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8613 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8614 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8615 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8616 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8617 	mac->mac_noise.noi_nsamples++;
8618 	if (mac->mac_noise.noi_nsamples == 8) {
8619 		average = 0;
8620 		for (i = 0; i < 8; i++) {
8621 			for (j = 0; j < 4; j++)
8622 				average += mac->mac_noise.noi_samples[i][j];
8623 		}
8624 		average = (((average / 32) * 125) + 64) / 128;
8625 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8626 		if (tmp >= 8)
8627 			average += 2;
8628 		else
8629 			average -= 25;
8630 		average -= (tmp == 8) ? 72 : 48;
8631 
8632 		mac->mac_stats.link_noise = average;
8633 		mac->mac_noise.noi_running = 0;
8634 		return;
8635 	}
8636 new:
8637 	bwn_noise_gensample(mac);
8638 }
8639 
8640 static int
8641 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8642 {
8643 	struct bwn_mac *mac = prq->prq_mac;
8644 	struct bwn_softc *sc = mac->mac_sc;
8645 	unsigned int i;
8646 
8647 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8648 		return (0);
8649 
8650 	for (i = 0; i < 5000; i++) {
8651 		if (bwn_pio_rxeof(prq) == 0)
8652 			break;
8653 	}
8654 	if (i >= 5000)
8655 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8656 	return ((i > 0) ? 1 : 0);
8657 }
8658 
8659 static void
8660 bwn_dma_rx_handle_overflow(struct bwn_dma_ring *dr)
8661 {
8662 	int curslot, prevslot;
8663 
8664 	curslot = dr->get_curslot(dr);
8665 	if (curslot == 0)
8666 		prevslot = dr->dr_numslots - 1;
8667 	else
8668 		prevslot = curslot - 1;
8669 	dr->set_curslot(dr, prevslot);
8670 }
8671 
8672 static void
8673 bwn_dma_rx(struct bwn_dma_ring *dr)
8674 {
8675 	int slot, curslot;
8676 
8677 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8678 	curslot = dr->get_curslot(dr);
8679 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8680 	    ("%s:%d: fail", __func__, __LINE__));
8681 
8682 	slot = dr->dr_curslot;
8683 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8684 		bwn_dma_rxeof(dr, &slot);
8685 
8686 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8687 	    BUS_DMASYNC_PREWRITE);
8688 
8689 	dr->set_curslot(dr, slot);
8690 	dr->dr_curslot = slot;
8691 }
8692 
8693 static void
8694 bwn_intr_txeof(struct bwn_mac *mac)
8695 {
8696 	struct bwn_txstatus stat;
8697 	uint32_t stat0, stat1;
8698 	uint16_t tmp;
8699 
8700 	while (1) {
8701 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8702 		if (!(stat0 & 0x00000001))
8703 			break;
8704 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8705 
8706 		stat.cookie = (stat0 >> 16);
8707 		stat.seq = (stat1 & 0x0000ffff);
8708 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8709 		tmp = (stat0 & 0x0000ffff);
8710 		stat.framecnt = ((tmp & 0xf000) >> 12);
8711 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8712 		stat.sreason = ((tmp & 0x001c) >> 2);
8713 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8714 		stat.im = (tmp & 0x0040) ? 1 : 0;
8715 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8716 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8717 
8718 		bwn_handle_txeof(mac, &stat);
8719 	}
8720 }
8721 
8722 static void
8723 bwn_hwreset(void *arg, int npending)
8724 {
8725 	struct bwn_mac *mac = arg;
8726 	struct bwn_softc *sc = mac->mac_sc;
8727 	int error = 0;
8728 	int prev_status;
8729 
8730 	wlan_serialize_enter();
8731 
8732 	prev_status = mac->mac_status;
8733 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8734 		bwn_core_stop(mac);
8735 	if (prev_status >= BWN_MAC_STATUS_INITED)
8736 		bwn_core_exit(mac);
8737 
8738 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8739 		error = bwn_core_init(mac);
8740 		if (error)
8741 			goto out;
8742 	}
8743 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8744 		bwn_core_start(mac);
8745 out:
8746 	if (error) {
8747 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8748 		sc->sc_curmac = NULL;
8749 	}
8750 	wlan_serialize_exit();
8751 }
8752 
8753 static void
8754 bwn_handle_fwpanic(struct bwn_mac *mac)
8755 {
8756 	struct bwn_softc *sc = mac->mac_sc;
8757 	uint16_t reason;
8758 
8759 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8760 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8761 
8762 	if (reason == BWN_FWPANIC_RESTART)
8763 		bwn_restart(mac, "ucode panic");
8764 }
8765 
8766 static void
8767 bwn_load_beacon0(struct bwn_mac *mac)
8768 {
8769 
8770 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8771 }
8772 
8773 static void
8774 bwn_load_beacon1(struct bwn_mac *mac)
8775 {
8776 
8777 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8778 }
8779 
8780 static uint32_t
8781 bwn_jssi_read(struct bwn_mac *mac)
8782 {
8783 	uint32_t val = 0;
8784 
8785 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8786 	val <<= 16;
8787 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8788 
8789 	return (val);
8790 }
8791 
8792 static void
8793 bwn_noise_gensample(struct bwn_mac *mac)
8794 {
8795 	uint32_t jssi = 0x7f7f7f7f;
8796 
8797 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8798 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8799 	BWN_WRITE_4(mac, BWN_MACCMD,
8800 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8801 }
8802 
8803 static int
8804 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8805 {
8806 	return (dr->dr_numslots - dr->dr_usedslot);
8807 }
8808 
8809 static int
8810 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8811 {
8812 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8813 	    ("%s:%d: fail", __func__, __LINE__));
8814 	if (slot == dr->dr_numslots - 1)
8815 		return (0);
8816 	return (slot + 1);
8817 }
8818 
8819 static void
8820 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8821 {
8822 	struct bwn_mac *mac = dr->dr_mac;
8823 	struct bwn_softc *sc = mac->mac_sc;
8824 	struct bwn_dma *dma = &mac->mac_method.dma;
8825 	struct bwn_dmadesc_generic *desc;
8826 	struct bwn_dmadesc_meta *meta;
8827 	struct bwn_rxhdr4 *rxhdr;
8828 	struct ifnet *ifp = sc->sc_ifp;
8829 	struct mbuf *m;
8830 	uint32_t macstat;
8831 	int32_t tmp;
8832 	int cnt = 0;
8833 	uint16_t len;
8834 
8835 	dr->getdesc(dr, *slot, &desc, &meta);
8836 
8837 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8838 	m = meta->mt_m;
8839 
8840 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8841 		ifp->if_ierrors++;
8842 		return;
8843 	}
8844 
8845 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8846 	len = le16toh(rxhdr->frame_len);
8847 	if (len <= 0) {
8848 		ifp->if_ierrors++;
8849 		return;
8850 	}
8851 	if (bwn_dma_check_redzone(dr, m)) {
8852 		device_printf(sc->sc_dev, "redzone error.\n");
8853 		bwn_dma_set_redzone(dr, m);
8854 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8855 		    BUS_DMASYNC_PREWRITE);
8856 		return;
8857 	}
8858 	if (len > dr->dr_rx_bufsize) {
8859 		tmp = len;
8860 		while (1) {
8861 			dr->getdesc(dr, *slot, &desc, &meta);
8862 			bwn_dma_set_redzone(dr, meta->mt_m);
8863 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8864 			    BUS_DMASYNC_PREWRITE);
8865 			*slot = bwn_dma_nextslot(dr, *slot);
8866 			cnt++;
8867 			tmp -= dr->dr_rx_bufsize;
8868 			if (tmp <= 0)
8869 				break;
8870 		}
8871 		device_printf(sc->sc_dev, "too small buffer "
8872 		       "(len %u buffer %u dropped %d)\n",
8873 		       len, dr->dr_rx_bufsize, cnt);
8874 		return;
8875 	}
8876 	macstat = le32toh(rxhdr->mac_status);
8877 	if (macstat & BWN_RX_MAC_FCSERR) {
8878 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8879 			device_printf(sc->sc_dev, "RX drop\n");
8880 			return;
8881 		}
8882 	}
8883 
8884 	m->m_pkthdr.rcvif = ifp;
8885 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8886 	m_adj(m, dr->dr_frameoffset);
8887 
8888 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8889 }
8890 
8891 static void
8892 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8893 {
8894 	struct bwn_dma_ring *dr;
8895 	struct bwn_dmadesc_generic *desc;
8896 	struct bwn_dmadesc_meta *meta;
8897 	struct bwn_pio_txqueue *tq;
8898 	struct bwn_pio_txpkt *tp = NULL;
8899 	struct bwn_softc *sc = mac->mac_sc;
8900 	struct bwn_stats *stats = &mac->mac_stats;
8901 	struct ieee80211_node *ni;
8902 	struct ieee80211vap *vap;
8903 	int retrycnt = 0, slot;
8904 
8905 	if (status->im)
8906 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8907 	if (status->ampdu)
8908 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8909 	if (status->rtscnt) {
8910 		if (status->rtscnt == 0xf)
8911 			stats->rtsfail++;
8912 		else
8913 			stats->rts++;
8914 	}
8915 
8916 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8917 		if (status->ack) {
8918 			dr = bwn_dma_parse_cookie(mac, status,
8919 			    status->cookie, &slot);
8920 			if (dr == NULL) {
8921 				device_printf(sc->sc_dev,
8922 				    "failed to parse cookie\n");
8923 				return;
8924 			}
8925 			while (1) {
8926 				dr->getdesc(dr, slot, &desc, &meta);
8927 				if (meta->mt_islast) {
8928 					ni = meta->mt_ni;
8929 					vap = ni->ni_vap;
8930 					ieee80211_ratectl_tx_complete(vap, ni,
8931 					    status->ack ?
8932 					      IEEE80211_RATECTL_TX_SUCCESS :
8933 					      IEEE80211_RATECTL_TX_FAILURE,
8934 					    &retrycnt, 0);
8935 					break;
8936 				}
8937 				slot = bwn_dma_nextslot(dr, slot);
8938 			}
8939 		}
8940 		bwn_dma_handle_txeof(mac, status);
8941 	} else {
8942 		if (status->ack) {
8943 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8944 			if (tq == NULL) {
8945 				device_printf(sc->sc_dev,
8946 				    "failed to parse cookie\n");
8947 				return;
8948 			}
8949 			ni = tp->tp_ni;
8950 			vap = ni->ni_vap;
8951 			ieee80211_ratectl_tx_complete(vap, ni,
8952 			    status->ack ?
8953 			      IEEE80211_RATECTL_TX_SUCCESS :
8954 			      IEEE80211_RATECTL_TX_FAILURE,
8955 			    &retrycnt, 0);
8956 		}
8957 		bwn_pio_handle_txeof(mac, status);
8958 	}
8959 
8960 	bwn_phy_txpower_check(mac, 0);
8961 }
8962 
8963 static uint8_t
8964 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8965 {
8966 	struct bwn_mac *mac = prq->prq_mac;
8967 	struct bwn_softc *sc = mac->mac_sc;
8968 	struct bwn_rxhdr4 rxhdr;
8969 	struct ifnet *ifp = sc->sc_ifp;
8970 	struct mbuf *m;
8971 	uint32_t ctl32, macstat, v32;
8972 	unsigned int i, padding;
8973 	uint16_t ctl16, len, totlen, v16;
8974 	unsigned char *mp;
8975 	char *data;
8976 
8977 	memset(&rxhdr, 0, sizeof(rxhdr));
8978 
8979 	if (prq->prq_rev >= 8) {
8980 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8981 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8982 			return (0);
8983 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8984 		    BWN_PIO8_RXCTL_FRAMEREADY);
8985 		for (i = 0; i < 10; i++) {
8986 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8987 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8988 				goto ready;
8989 			DELAY(10);
8990 		}
8991 	} else {
8992 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8993 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8994 			return (0);
8995 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8996 		    BWN_PIO_RXCTL_FRAMEREADY);
8997 		for (i = 0; i < 10; i++) {
8998 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8999 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9000 				goto ready;
9001 			DELAY(10);
9002 		}
9003 	}
9004 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9005 	return (1);
9006 ready:
9007 	if (prq->prq_rev >= 8)
9008 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9009 		    prq->prq_base + BWN_PIO8_RXDATA);
9010 	else
9011 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9012 		    prq->prq_base + BWN_PIO_RXDATA);
9013 	len = le16toh(rxhdr.frame_len);
9014 	if (len > 0x700) {
9015 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9016 		goto error;
9017 	}
9018 	if (len == 0) {
9019 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9020 		goto error;
9021 	}
9022 
9023 	macstat = le32toh(rxhdr.mac_status);
9024 	if (macstat & BWN_RX_MAC_FCSERR) {
9025 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9026 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9027 			goto error;
9028 		}
9029 	}
9030 
9031 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9032 	totlen = len + padding;
9033 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9034 	m = m_getcl(M_INTWAIT, MT_DATA, M_PKTHDR);
9035 	if (m == NULL) {
9036 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9037 		goto error;
9038 	}
9039 	mp = mtod(m, unsigned char *);
9040 	if (prq->prq_rev >= 8) {
9041 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9042 		    prq->prq_base + BWN_PIO8_RXDATA);
9043 		if (totlen & 3) {
9044 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9045 			data = &(mp[totlen - 1]);
9046 			switch (totlen & 3) {
9047 			case 3:
9048 				*data = (v32 >> 16);
9049 				data--;
9050 			case 2:
9051 				*data = (v32 >> 8);
9052 				data--;
9053 			case 1:
9054 				*data = v32;
9055 			}
9056 		}
9057 	} else {
9058 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9059 		    prq->prq_base + BWN_PIO_RXDATA);
9060 		if (totlen & 1) {
9061 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9062 			mp[totlen - 1] = v16;
9063 		}
9064 	}
9065 
9066 	m->m_pkthdr.rcvif = ifp;
9067 	m->m_len = m->m_pkthdr.len = totlen;
9068 
9069 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9070 
9071 	return (1);
9072 error:
9073 	if (prq->prq_rev >= 8)
9074 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9075 		    BWN_PIO8_RXCTL_DATAREADY);
9076 	else
9077 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9078 	return (1);
9079 }
9080 
9081 static int
9082 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9083     struct bwn_dmadesc_meta *meta, int init)
9084 {
9085 	struct bwn_mac *mac = dr->dr_mac;
9086 	struct bwn_dma *dma = &mac->mac_method.dma;
9087 	struct bwn_rxhdr4 *hdr;
9088 	bus_dmamap_t map;
9089 	bus_addr_t paddr;
9090 	struct mbuf *m;
9091 	int error;
9092 
9093 	m = m_getcl(M_INTWAIT, MT_DATA, M_PKTHDR);
9094 	if (m == NULL) {
9095 		error = ENOBUFS;
9096 
9097 		/*
9098 		 * If the NIC is up and running, we need to:
9099 		 * - Clear RX buffer's header.
9100 		 * - Restore RX descriptor settings.
9101 		 */
9102 		if (init)
9103 			return (error);
9104 		else
9105 			goto back;
9106 	}
9107 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9108 
9109 	bwn_dma_set_redzone(dr, m);
9110 
9111 	/*
9112 	 * Try to load RX buf into temporary DMA map
9113 	 */
9114 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9115 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9116 	if (error) {
9117 		m_freem(m);
9118 
9119 		/*
9120 		 * See the comment above
9121 		 */
9122 		if (init)
9123 			return (error);
9124 		else
9125 			goto back;
9126 	}
9127 
9128 	if (!init)
9129 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9130 	meta->mt_m = m;
9131 	meta->mt_paddr = paddr;
9132 
9133 	/*
9134 	 * Swap RX buf's DMA map with the loaded temporary one
9135 	 */
9136 	map = meta->mt_dmap;
9137 	meta->mt_dmap = dr->dr_spare_dmap;
9138 	dr->dr_spare_dmap = map;
9139 
9140 back:
9141 	/*
9142 	 * Clear RX buf header
9143 	 */
9144 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9145 	bzero(hdr, sizeof(*hdr));
9146 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9147 	    BUS_DMASYNC_PREWRITE);
9148 
9149 	/*
9150 	 * Setup RX buf descriptor
9151 	 */
9152 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9153 	    sizeof(*hdr), 0, 0, 0);
9154 	return (error);
9155 }
9156 
9157 static void
9158 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9159 		 bus_size_t mapsz __unused, int error)
9160 {
9161 
9162 	if (!error) {
9163 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9164 		*((bus_addr_t *)arg) = seg->ds_addr;
9165 	}
9166 }
9167 
9168 static int
9169 bwn_hwrate2ieeerate(int rate)
9170 {
9171 
9172 	switch (rate) {
9173 	case BWN_CCK_RATE_1MB:
9174 		return (2);
9175 	case BWN_CCK_RATE_2MB:
9176 		return (4);
9177 	case BWN_CCK_RATE_5MB:
9178 		return (11);
9179 	case BWN_CCK_RATE_11MB:
9180 		return (22);
9181 	case BWN_OFDM_RATE_6MB:
9182 		return (12);
9183 	case BWN_OFDM_RATE_9MB:
9184 		return (18);
9185 	case BWN_OFDM_RATE_12MB:
9186 		return (24);
9187 	case BWN_OFDM_RATE_18MB:
9188 		return (36);
9189 	case BWN_OFDM_RATE_24MB:
9190 		return (48);
9191 	case BWN_OFDM_RATE_36MB:
9192 		return (72);
9193 	case BWN_OFDM_RATE_48MB:
9194 		return (96);
9195 	case BWN_OFDM_RATE_54MB:
9196 		return (108);
9197 	default:
9198 		kprintf("Ooops\n");
9199 		return (0);
9200 	}
9201 }
9202 
9203 static void
9204 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9205 {
9206 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9207 	struct bwn_plcp6 *plcp;
9208 	struct bwn_softc *sc = mac->mac_sc;
9209 	struct ieee80211_frame_min *wh;
9210 	struct ieee80211_node *ni;
9211 	struct ifnet *ifp = sc->sc_ifp;
9212 	struct ieee80211com *ic = ifp->if_l2com;
9213 	uint32_t macstat;
9214 	int padding, rate, rssi = 0, noise = 0, type;
9215 	uint16_t phytype, phystat0, phystat3, chanstat;
9216 	unsigned char *mp = mtod(m, unsigned char *);
9217 	static int rx_mac_dec_rpt = 0;
9218 
9219 	phystat0 = le16toh(rxhdr->phy_status0);
9220 	phystat3 = le16toh(rxhdr->phy_status3);
9221 	macstat = le32toh(rxhdr->mac_status);
9222 	chanstat = le16toh(rxhdr->channel);
9223 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9224 
9225 	if (macstat & BWN_RX_MAC_FCSERR)
9226 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9227 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9228 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9229 	if (macstat & BWN_RX_MAC_DECERR)
9230 		goto drop;
9231 
9232 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9233 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9234 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9235 		    m->m_pkthdr.len);
9236 		goto drop;
9237 	}
9238 	plcp = (struct bwn_plcp6 *)(mp + padding);
9239 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9240 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9241 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9242 		    m->m_pkthdr.len);
9243 		goto drop;
9244 	}
9245 	wh = mtod(m, struct ieee80211_frame_min *);
9246 
9247 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9248 		device_printf(sc->sc_dev,
9249 		    "RX decryption attempted (old %d keyidx %#x)\n",
9250 		    BWN_ISOLDFMT(mac),
9251 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9252 
9253 	/* XXX calculating RSSI & noise & antenna */
9254 
9255 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9256 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9257 		    phytype == BWN_PHYTYPE_A);
9258 	else
9259 		rate = bwn_plcp_get_cckrate(mac, plcp);
9260 	if (rate == -1) {
9261 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9262 			goto drop;
9263 	}
9264 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9265 
9266 	/* RX radio tap */
9267 	if (ieee80211_radiotap_active(ic))
9268 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9269 	m_adj(m, -IEEE80211_CRC_LEN);
9270 
9271 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9272 	noise = mac->mac_stats.link_noise;
9273 
9274 	ifp->if_ipackets++;
9275 
9276 	ni = ieee80211_find_rxnode(ic, wh);
9277 	if (ni != NULL) {
9278 		type = ieee80211_input(ni, m, rssi, noise);
9279 		ieee80211_free_node(ni);
9280 	} else
9281 		type = ieee80211_input_all(ic, m, rssi, noise);
9282 
9283 	return;
9284 drop:
9285 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9286 }
9287 
9288 static void
9289 bwn_dma_handle_txeof(struct bwn_mac *mac,
9290     const struct bwn_txstatus *status)
9291 {
9292 	struct bwn_dma *dma = &mac->mac_method.dma;
9293 	struct bwn_dma_ring *dr;
9294 	struct bwn_dmadesc_generic *desc;
9295 	struct bwn_dmadesc_meta *meta;
9296 	struct bwn_softc *sc = mac->mac_sc;
9297 	struct ieee80211_node *ni;
9298 	struct ifnet *ifp = sc->sc_ifp;
9299 	struct mbuf *m;
9300 	int slot;
9301 
9302 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9303 	if (dr == NULL) {
9304 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9305 		return;
9306 	}
9307 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9308 
9309 	while (1) {
9310 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9311 		    ("%s:%d: fail", __func__, __LINE__));
9312 		dr->getdesc(dr, slot, &desc, &meta);
9313 
9314 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) {
9315 			bus_dmamap_sync(dr->dr_txring_dtag, meta->mt_dmap,
9316 			    BUS_DMASYNC_POSTWRITE);
9317 		} else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) {
9318 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9319 		}
9320 
9321 		if (meta->mt_islast) {
9322 			KASSERT(meta->mt_m != NULL,
9323 			    ("%s:%d: fail", __func__, __LINE__));
9324 
9325 			ni = meta->mt_ni;
9326 			m = meta->mt_m;
9327 			if (ni != NULL) {
9328 				/*
9329 				 * Do any tx complete callback. Note this must
9330 				 * be done before releasing the node reference.
9331 				 */
9332 				if (m->m_flags & M_TXCB)
9333 					ieee80211_process_callback(ni, m, 0);
9334 				ieee80211_free_node(ni);
9335 				meta->mt_ni = NULL;
9336 			}
9337 			m_freem(m);
9338 			meta->mt_m = NULL;
9339 		} else {
9340 			KASSERT(meta->mt_m == NULL,
9341 			    ("%s:%d: fail", __func__, __LINE__));
9342 		}
9343 
9344 		dr->dr_usedslot--;
9345 		if (meta->mt_islast) {
9346 			ifp->if_opackets++;
9347 			break;
9348 		}
9349 		slot = bwn_dma_nextslot(dr, slot);
9350 	}
9351 	sc->sc_watchdog_timer = 0;
9352 	if (dr->dr_stop) {
9353 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9354 		    ("%s:%d: fail", __func__, __LINE__));
9355 		ifq_clr_oactive(&ifp->if_snd);
9356 		dr->dr_stop = 0;
9357 	}
9358 }
9359 
9360 static void
9361 bwn_pio_handle_txeof(struct bwn_mac *mac,
9362     const struct bwn_txstatus *status)
9363 {
9364 	struct bwn_pio_txqueue *tq;
9365 	struct bwn_pio_txpkt *tp = NULL;
9366 	struct bwn_softc *sc = mac->mac_sc;
9367 	struct ifnet *ifp = sc->sc_ifp;
9368 
9369 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9370 	if (tq == NULL)
9371 		return;
9372 
9373 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9374 	tq->tq_free++;
9375 
9376 	if (tp->tp_ni != NULL) {
9377 		/*
9378 		 * Do any tx complete callback.  Note this must
9379 		 * be done before releasing the node reference.
9380 		 */
9381 		if (tp->tp_m->m_flags & M_TXCB)
9382 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9383 		ieee80211_free_node(tp->tp_ni);
9384 		tp->tp_ni = NULL;
9385 	}
9386 	m_freem(tp->tp_m);
9387 	tp->tp_m = NULL;
9388 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9389 
9390 	ifp->if_opackets++;
9391 
9392 	sc->sc_watchdog_timer = 0;
9393 	if (tq->tq_stop) {
9394 		ifq_clr_oactive(&ifp->if_snd);
9395 		tq->tq_stop = 0;
9396 	}
9397 }
9398 
9399 static void
9400 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9401 {
9402 	struct bwn_softc *sc = mac->mac_sc;
9403 	struct bwn_phy *phy = &mac->mac_phy;
9404 	struct ifnet *ifp = sc->sc_ifp;
9405 	struct ieee80211com *ic = ifp->if_l2com;
9406 	unsigned long now;
9407 	int result;
9408 
9409 	BWN_GETTIME(now);
9410 
9411 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9412 		return;
9413 	phy->nexttime = now + 2 * 1000;
9414 
9415 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9416 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9417 		return;
9418 
9419 	if (phy->recalc_txpwr != NULL) {
9420 		result = phy->recalc_txpwr(mac,
9421 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9422 		if (result == BWN_TXPWR_RES_DONE)
9423 			return;
9424 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9425 		    ("%s: fail", __func__));
9426 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9427 
9428 		ieee80211_runtask(ic, &mac->mac_txpower);
9429 	}
9430 }
9431 
9432 static uint16_t
9433 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9434 {
9435 
9436 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9437 }
9438 
9439 static uint32_t
9440 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9441 {
9442 
9443 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9444 }
9445 
9446 static void
9447 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9448 {
9449 
9450 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9451 }
9452 
9453 static void
9454 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9455 {
9456 
9457 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9458 }
9459 
9460 static int
9461 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9462 {
9463 
9464 	switch (rate) {
9465 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9466 	case 12:
9467 		return (BWN_OFDM_RATE_6MB);
9468 	case 18:
9469 		return (BWN_OFDM_RATE_9MB);
9470 	case 24:
9471 		return (BWN_OFDM_RATE_12MB);
9472 	case 36:
9473 		return (BWN_OFDM_RATE_18MB);
9474 	case 48:
9475 		return (BWN_OFDM_RATE_24MB);
9476 	case 72:
9477 		return (BWN_OFDM_RATE_36MB);
9478 	case 96:
9479 		return (BWN_OFDM_RATE_48MB);
9480 	case 108:
9481 		return (BWN_OFDM_RATE_54MB);
9482 	/* CCK rates (NB: not IEEE std, device-specific) */
9483 	case 2:
9484 		return (BWN_CCK_RATE_1MB);
9485 	case 4:
9486 		return (BWN_CCK_RATE_2MB);
9487 	case 11:
9488 		return (BWN_CCK_RATE_5MB);
9489 	case 22:
9490 		return (BWN_CCK_RATE_11MB);
9491 	}
9492 
9493 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9494 	return (BWN_CCK_RATE_1MB);
9495 }
9496 
9497 static int
9498 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9499     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9500 {
9501 	const struct bwn_phy *phy = &mac->mac_phy;
9502 	struct bwn_softc *sc = mac->mac_sc;
9503 	struct ieee80211_frame *wh;
9504 	struct ieee80211_frame *protwh;
9505 	struct ieee80211_frame_cts *cts;
9506 	struct ieee80211_frame_rts *rts;
9507 	const struct ieee80211_txparam *tp;
9508 	struct ieee80211vap *vap = ni->ni_vap;
9509 	struct ifnet *ifp = sc->sc_ifp;
9510 	struct ieee80211com *ic = ifp->if_l2com;
9511 	struct mbuf *mprot;
9512 	unsigned int len;
9513 	uint32_t macctl = 0;
9514 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9515 	uint16_t phyctl = 0;
9516 	uint8_t rate, rate_fb;
9517 
9518 	wh = mtod(m, struct ieee80211_frame *);
9519 	memset(txhdr, 0, sizeof(*txhdr));
9520 
9521 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9522 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9523 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9524 
9525 	/*
9526 	 * Find TX rate
9527 	 */
9528 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9529 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9530 		rate = rate_fb = tp->mgmtrate;
9531 	else if (ismcast)
9532 		rate = rate_fb = tp->mcastrate;
9533 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9534 		rate = rate_fb = tp->ucastrate;
9535 	else {
9536 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9537 		rate = ni->ni_txrate;
9538 
9539 		if (rix > 0)
9540 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9541 			    IEEE80211_RATE_VAL;
9542 		else
9543 			rate_fb = rate;
9544 	}
9545 
9546 	sc->sc_tx_rate = rate;
9547 
9548 	rate = bwn_ieeerate2hwrate(sc, rate);
9549 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9550 
9551 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9552 	    bwn_plcp_getcck(rate);
9553 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9554 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9555 
9556 	if ((rate_fb == rate) ||
9557 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9558 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9559 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9560 	else
9561 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9562 		    m->m_pkthdr.len, rate, isshort);
9563 
9564 	/* XXX TX encryption */
9565 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9566 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9567 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9568 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9569 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9570 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9571 
9572 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9573 	    BWN_TX_EFT_FB_CCK;
9574 	txhdr->chan = phy->chan;
9575 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9576 	    BWN_TX_PHY_ENC_CCK;
9577 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9578 	     rate == BWN_CCK_RATE_11MB))
9579 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9580 
9581 	/* XXX TX antenna selection */
9582 
9583 	switch (bwn_antenna_sanitize(mac, 0)) {
9584 	case 0:
9585 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9586 		break;
9587 	case 1:
9588 		phyctl |= BWN_TX_PHY_ANT0;
9589 		break;
9590 	case 2:
9591 		phyctl |= BWN_TX_PHY_ANT1;
9592 		break;
9593 	case 3:
9594 		phyctl |= BWN_TX_PHY_ANT2;
9595 		break;
9596 	case 4:
9597 		phyctl |= BWN_TX_PHY_ANT3;
9598 		break;
9599 	default:
9600 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9601 	}
9602 
9603 	if (!ismcast)
9604 		macctl |= BWN_TX_MAC_ACK;
9605 
9606 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9607 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9608 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9609 		macctl |= BWN_TX_MAC_LONGFRAME;
9610 
9611 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9612 		/* XXX RTS rate is always 1MB??? */
9613 		rts_rate = BWN_CCK_RATE_1MB;
9614 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9615 
9616 		protdur = ieee80211_compute_duration(ic->ic_rt,
9617 		    m->m_pkthdr.len, rate, isshort) +
9618 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9619 
9620 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9621 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9622 			    (txhdr->body.old.rts_frame) :
9623 			    (txhdr->body.new.rts_frame));
9624 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9625 			    protdur);
9626 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9627 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9628 			    mprot->m_pkthdr.len);
9629 			m_freem(mprot);
9630 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9631 			len = sizeof(struct ieee80211_frame_cts);
9632 		} else {
9633 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9634 			    (txhdr->body.old.rts_frame) :
9635 			    (txhdr->body.new.rts_frame));
9636 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9637 			    isshort);
9638 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9639 			    wh->i_addr2, protdur);
9640 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9641 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9642 			    mprot->m_pkthdr.len);
9643 			m_freem(mprot);
9644 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9645 			len = sizeof(struct ieee80211_frame_rts);
9646 		}
9647 		len += IEEE80211_CRC_LEN;
9648 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9649 		    &txhdr->body.old.rts_plcp :
9650 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9651 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9652 		    rts_rate_fb);
9653 
9654 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9655 		    (&txhdr->body.old.rts_frame) :
9656 		    (&txhdr->body.new.rts_frame));
9657 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9658 
9659 		if (BWN_ISOFDMRATE(rts_rate)) {
9660 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9661 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9662 		} else {
9663 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9664 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9665 		}
9666 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9667 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9668 	}
9669 
9670 	if (BWN_ISOLDFMT(mac))
9671 		txhdr->body.old.cookie = htole16(cookie);
9672 	else
9673 		txhdr->body.new.cookie = htole16(cookie);
9674 
9675 	txhdr->macctl = htole32(macctl);
9676 	txhdr->phyctl = htole16(phyctl);
9677 
9678 	/*
9679 	 * TX radio tap
9680 	 */
9681 	if (ieee80211_radiotap_active_vap(vap)) {
9682 		sc->sc_tx_th.wt_flags = 0;
9683 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9684 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9685 		if (isshort &&
9686 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9687 		     rate == BWN_CCK_RATE_11MB))
9688 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9689 		sc->sc_tx_th.wt_rate = rate;
9690 
9691 		ieee80211_radiotap_tx(vap, m);
9692 	}
9693 
9694 	return (0);
9695 }
9696 
9697 static void
9698 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9699     const uint8_t rate)
9700 {
9701 	uint32_t d, plen;
9702 	uint8_t *raw = plcp->o.raw;
9703 
9704 	if (BWN_ISOFDMRATE(rate)) {
9705 		d = bwn_plcp_getofdm(rate);
9706 		KASSERT(!(octets & 0xf000),
9707 		    ("%s:%d: fail", __func__, __LINE__));
9708 		d |= (octets << 5);
9709 		plcp->o.data = htole32(d);
9710 	} else {
9711 		plen = octets * 16 / rate;
9712 		if ((octets * 16 % rate) > 0) {
9713 			plen++;
9714 			if ((rate == BWN_CCK_RATE_11MB)
9715 			    && ((octets * 8 % 11) < 4)) {
9716 				raw[1] = 0x84;
9717 			} else
9718 				raw[1] = 0x04;
9719 		} else
9720 			raw[1] = 0x04;
9721 		plcp->o.data |= htole32(plen << 16);
9722 		raw[0] = bwn_plcp_getcck(rate);
9723 	}
9724 }
9725 
9726 static uint8_t
9727 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9728 {
9729 	struct bwn_softc *sc = mac->mac_sc;
9730 	uint8_t mask;
9731 
9732 	if (n == 0)
9733 		return (0);
9734 	if (mac->mac_phy.gmode)
9735 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9736 	else
9737 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9738 	if (!(mask & (1 << (n - 1))))
9739 		return (0);
9740 	return (n);
9741 }
9742 
9743 static uint8_t
9744 bwn_get_fbrate(uint8_t bitrate)
9745 {
9746 	switch (bitrate) {
9747 	case BWN_CCK_RATE_1MB:
9748 		return (BWN_CCK_RATE_1MB);
9749 	case BWN_CCK_RATE_2MB:
9750 		return (BWN_CCK_RATE_1MB);
9751 	case BWN_CCK_RATE_5MB:
9752 		return (BWN_CCK_RATE_2MB);
9753 	case BWN_CCK_RATE_11MB:
9754 		return (BWN_CCK_RATE_5MB);
9755 	case BWN_OFDM_RATE_6MB:
9756 		return (BWN_CCK_RATE_5MB);
9757 	case BWN_OFDM_RATE_9MB:
9758 		return (BWN_OFDM_RATE_6MB);
9759 	case BWN_OFDM_RATE_12MB:
9760 		return (BWN_OFDM_RATE_9MB);
9761 	case BWN_OFDM_RATE_18MB:
9762 		return (BWN_OFDM_RATE_12MB);
9763 	case BWN_OFDM_RATE_24MB:
9764 		return (BWN_OFDM_RATE_18MB);
9765 	case BWN_OFDM_RATE_36MB:
9766 		return (BWN_OFDM_RATE_24MB);
9767 	case BWN_OFDM_RATE_48MB:
9768 		return (BWN_OFDM_RATE_36MB);
9769 	case BWN_OFDM_RATE_54MB:
9770 		return (BWN_OFDM_RATE_48MB);
9771 	}
9772 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9773 	return (0);
9774 }
9775 
9776 static uint32_t
9777 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9778     uint32_t ctl, const void *_data, int len)
9779 {
9780 	struct bwn_softc *sc = mac->mac_sc;
9781 	uint32_t value = 0;
9782 	const uint8_t *data = _data;
9783 
9784 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9785 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9786 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9787 
9788 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9789 	    tq->tq_base + BWN_PIO8_TXDATA);
9790 	if (len & 3) {
9791 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9792 		    BWN_PIO8_TXCTL_24_31);
9793 		data = &(data[len - 1]);
9794 		switch (len & 3) {
9795 		case 3:
9796 			ctl |= BWN_PIO8_TXCTL_16_23;
9797 			value |= (uint32_t)(*data) << 16;
9798 			data--;
9799 		case 2:
9800 			ctl |= BWN_PIO8_TXCTL_8_15;
9801 			value |= (uint32_t)(*data) << 8;
9802 			data--;
9803 		case 1:
9804 			value |= (uint32_t)(*data);
9805 		}
9806 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9807 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9808 	}
9809 
9810 	return (ctl);
9811 }
9812 
9813 static void
9814 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9815     uint16_t offset, uint32_t value)
9816 {
9817 
9818 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9819 }
9820 
9821 static uint16_t
9822 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9823     uint16_t ctl, const void *_data, int len)
9824 {
9825 	struct bwn_softc *sc = mac->mac_sc;
9826 	const uint8_t *data = _data;
9827 
9828 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9829 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9830 
9831 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9832 	    tq->tq_base + BWN_PIO_TXDATA);
9833 	if (len & 1) {
9834 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9835 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9836 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9837 	}
9838 
9839 	return (ctl);
9840 }
9841 
9842 static uint16_t
9843 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9844     uint16_t ctl, struct mbuf *m0)
9845 {
9846 	int i, j = 0;
9847 	uint16_t data = 0;
9848 	const uint8_t *buf;
9849 	struct mbuf *m = m0;
9850 
9851 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9852 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9853 
9854 	for (; m != NULL; m = m->m_next) {
9855 		buf = mtod(m, const uint8_t *);
9856 		for (i = 0; i < m->m_len; i++) {
9857 			if (!((j++) % 2))
9858 				data |= buf[i];
9859 			else {
9860 				data |= (buf[i] << 8);
9861 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9862 				data = 0;
9863 			}
9864 		}
9865 	}
9866 	if (m0->m_pkthdr.len % 2) {
9867 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9868 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9869 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9870 	}
9871 
9872 	return (ctl);
9873 }
9874 
9875 static void
9876 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9877 {
9878 
9879 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9880 		return;
9881 	BWN_WRITE_2(mac, 0x684, 510 + time);
9882 
9883 	/*
9884 	 * XXX ivadasz: Linux's b43 comments this. Enabling this causes a
9885 	 *              a severe performance penalty (especially when sending).
9886 	 */
9887 #if 0
9888 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9889 #endif
9890 }
9891 
9892 static struct bwn_dma_ring *
9893 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9894 {
9895 
9896 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9897 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9898 
9899 	switch (prio) {
9900 	case 3:
9901 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9902 	case 2:
9903 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9904 	case 0:
9905 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9906 	case 1:
9907 		return (mac->mac_method.dma.wme[WME_AC_BK]);
9908 	}
9909 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9910 	return (NULL);
9911 }
9912 
9913 static int
9914 bwn_dma_getslot(struct bwn_dma_ring *dr)
9915 {
9916 	int slot;
9917 
9918 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9919 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9920 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9921 
9922 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9923 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9924 	dr->dr_curslot = slot;
9925 	dr->dr_usedslot++;
9926 
9927 	return (slot);
9928 }
9929 
9930 static int
9931 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9932 {
9933 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9934 	unsigned int a, b, c, d;
9935 	unsigned int avg;
9936 	uint32_t tmp;
9937 
9938 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9939 	a = tmp & 0xff;
9940 	b = (tmp >> 8) & 0xff;
9941 	c = (tmp >> 16) & 0xff;
9942 	d = (tmp >> 24) & 0xff;
9943 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9944 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9945 		return (ENOENT);
9946 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9947 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9948 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9949 
9950 	if (ofdm) {
9951 		a = (a + 32) & 0x3f;
9952 		b = (b + 32) & 0x3f;
9953 		c = (c + 32) & 0x3f;
9954 		d = (d + 32) & 0x3f;
9955 	}
9956 
9957 	avg = (a + b + c + d + 2) / 4;
9958 	if (ofdm) {
9959 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9960 		    & BWN_HF_4DB_CCK_POWERBOOST)
9961 			avg = (avg >= 13) ? (avg - 13) : 0;
9962 	}
9963 	return (avg);
9964 }
9965 
9966 static void
9967 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9968 {
9969 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9970 	int rfatt = *rfattp;
9971 	int bbatt = *bbattp;
9972 
9973 	while (1) {
9974 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9975 			break;
9976 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9977 			break;
9978 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9979 			break;
9980 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9981 			break;
9982 		if (bbatt > lo->bbatt.max) {
9983 			bbatt -= 4;
9984 			rfatt += 1;
9985 			continue;
9986 		}
9987 		if (bbatt < lo->bbatt.min) {
9988 			bbatt += 4;
9989 			rfatt -= 1;
9990 			continue;
9991 		}
9992 		if (rfatt > lo->rfatt.max) {
9993 			rfatt -= 1;
9994 			bbatt += 4;
9995 			continue;
9996 		}
9997 		if (rfatt < lo->rfatt.min) {
9998 			rfatt += 1;
9999 			bbatt -= 4;
10000 			continue;
10001 		}
10002 		break;
10003 	}
10004 
10005 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10006 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10007 }
10008 
10009 static void
10010 bwn_phy_lock(struct bwn_mac *mac)
10011 {
10012 	struct bwn_softc *sc = mac->mac_sc;
10013 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10014 
10015 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10016 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10017 
10018 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10019 		bwn_psctl(mac, BWN_PS_AWAKE);
10020 }
10021 
10022 static void
10023 bwn_phy_unlock(struct bwn_mac *mac)
10024 {
10025 	struct bwn_softc *sc = mac->mac_sc;
10026 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10027 
10028 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10029 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10030 
10031 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10032 		bwn_psctl(mac, 0);
10033 }
10034 
10035 static void
10036 bwn_rf_lock(struct bwn_mac *mac)
10037 {
10038 
10039 	BWN_WRITE_4(mac, BWN_MACCTL,
10040 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10041 	BWN_READ_4(mac, BWN_MACCTL);
10042 	DELAY(10);
10043 }
10044 
10045 static void
10046 bwn_rf_unlock(struct bwn_mac *mac)
10047 {
10048 
10049 	BWN_READ_2(mac, BWN_PHYVER);
10050 	BWN_WRITE_4(mac, BWN_MACCTL,
10051 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10052 }
10053 
10054 static struct bwn_pio_txqueue *
10055 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10056     struct bwn_pio_txpkt **pack)
10057 {
10058 	struct bwn_pio *pio = &mac->mac_method.pio;
10059 	struct bwn_pio_txqueue *tq = NULL;
10060 	unsigned int index;
10061 
10062 	switch (cookie & 0xf000) {
10063 	case 0x1000:
10064 		tq = &pio->wme[WME_AC_BK];
10065 		break;
10066 	case 0x2000:
10067 		tq = &pio->wme[WME_AC_BE];
10068 		break;
10069 	case 0x3000:
10070 		tq = &pio->wme[WME_AC_VI];
10071 		break;
10072 	case 0x4000:
10073 		tq = &pio->wme[WME_AC_VO];
10074 		break;
10075 	case 0x5000:
10076 		tq = &pio->mcast;
10077 		break;
10078 	}
10079 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10080 	if (tq == NULL)
10081 		return (NULL);
10082 	index = (cookie & 0x0fff);
10083 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10084 	if (index >= N(tq->tq_pkts))
10085 		return (NULL);
10086 	*pack = &tq->tq_pkts[index];
10087 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10088 	return (tq);
10089 }
10090 
10091 static void
10092 bwn_txpwr(void *arg, int npending)
10093 {
10094 	struct bwn_mac *mac = arg;
10095 
10096 	wlan_serialize_enter();
10097 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10098 	    mac->mac_phy.set_txpwr != NULL)
10099 		mac->mac_phy.set_txpwr(mac);
10100 	wlan_serialize_exit();
10101 }
10102 
10103 static void
10104 bwn_task_15s(struct bwn_mac *mac)
10105 {
10106 	uint16_t reg;
10107 
10108 	if (mac->mac_fw.opensource) {
10109 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10110 		if (reg) {
10111 			bwn_restart(mac, "fw watchdog");
10112 			return;
10113 		}
10114 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10115 	}
10116 	if (mac->mac_phy.task_15s)
10117 		mac->mac_phy.task_15s(mac);
10118 
10119 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10120 }
10121 
10122 static void
10123 bwn_task_30s(struct bwn_mac *mac)
10124 {
10125 
10126 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10127 		return;
10128 	mac->mac_noise.noi_running = 1;
10129 	mac->mac_noise.noi_nsamples = 0;
10130 
10131 	bwn_noise_gensample(mac);
10132 }
10133 
10134 static void
10135 bwn_task_60s(struct bwn_mac *mac)
10136 {
10137 
10138 	if (mac->mac_phy.task_60s)
10139 		mac->mac_phy.task_60s(mac);
10140 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10141 }
10142 
10143 static void
10144 bwn_tasks(void *arg)
10145 {
10146 	struct bwn_mac *mac = arg;
10147 	struct bwn_softc *sc = mac->mac_sc;
10148 
10149 	wlan_serialize_enter();
10150 
10151 	if (mac->mac_status != BWN_MAC_STATUS_STARTED) {
10152 		wlan_serialize_exit();
10153 		return;
10154 	}
10155 
10156 	if (mac->mac_task_state % 4 == 0)
10157 		bwn_task_60s(mac);
10158 	if (mac->mac_task_state % 2 == 0)
10159 		bwn_task_30s(mac);
10160 	bwn_task_15s(mac);
10161 
10162 	mac->mac_task_state++;
10163 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10164 	wlan_serialize_exit();
10165 }
10166 
10167 static int
10168 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10169 {
10170 	struct bwn_softc *sc = mac->mac_sc;
10171 
10172 	KASSERT(a == 0, ("not support APHY\n"));
10173 
10174 	switch (plcp->o.raw[0] & 0xf) {
10175 	case 0xb:
10176 		return (BWN_OFDM_RATE_6MB);
10177 	case 0xf:
10178 		return (BWN_OFDM_RATE_9MB);
10179 	case 0xa:
10180 		return (BWN_OFDM_RATE_12MB);
10181 	case 0xe:
10182 		return (BWN_OFDM_RATE_18MB);
10183 	case 0x9:
10184 		return (BWN_OFDM_RATE_24MB);
10185 	case 0xd:
10186 		return (BWN_OFDM_RATE_36MB);
10187 	case 0x8:
10188 		return (BWN_OFDM_RATE_48MB);
10189 	case 0xc:
10190 		return (BWN_OFDM_RATE_54MB);
10191 	}
10192 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10193 	    plcp->o.raw[0] & 0xf);
10194 	return (-1);
10195 }
10196 
10197 static int
10198 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10199 {
10200 	struct bwn_softc *sc = mac->mac_sc;
10201 
10202 	switch (plcp->o.raw[0]) {
10203 	case 0x0a:
10204 		return (BWN_CCK_RATE_1MB);
10205 	case 0x14:
10206 		return (BWN_CCK_RATE_2MB);
10207 	case 0x37:
10208 		return (BWN_CCK_RATE_5MB);
10209 	case 0x6e:
10210 		return (BWN_CCK_RATE_11MB);
10211 	}
10212 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10213 	return (-1);
10214 }
10215 
10216 static void
10217 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10218     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10219     int rssi, int noise)
10220 {
10221 	struct bwn_softc *sc = mac->mac_sc;
10222 	const struct ieee80211_frame_min *wh;
10223 	uint64_t tsf;
10224 	uint16_t low_mactime_now;
10225 
10226 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10227 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10228 
10229 	wh = mtod(m, const struct ieee80211_frame_min *);
10230 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10231 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10232 
10233 	bwn_tsf_read(mac, &tsf);
10234 	low_mactime_now = tsf;
10235 	tsf = tsf & ~0xffffULL;
10236 	tsf += le16toh(rxhdr->mac_time);
10237 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10238 		tsf -= 0x10000;
10239 
10240 	sc->sc_rx_th.wr_tsf = tsf;
10241 	sc->sc_rx_th.wr_rate = rate;
10242 	sc->sc_rx_th.wr_antsignal = rssi;
10243 	sc->sc_rx_th.wr_antnoise = noise;
10244 }
10245 
10246 static void
10247 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10248 {
10249 	uint32_t low, high;
10250 
10251 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10252 	    ("%s:%d: fail", __func__, __LINE__));
10253 
10254 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10255 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10256 	*tsf = high;
10257 	*tsf <<= 32;
10258 	*tsf |= low;
10259 }
10260 
10261 static int
10262 bwn_dma_attach(struct bwn_mac *mac)
10263 {
10264 	struct bwn_dma *dma = &mac->mac_method.dma;
10265 	struct bwn_softc *sc = mac->mac_sc;
10266 	bus_addr_t lowaddr = 0;
10267 	int error;
10268 
10269 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10270 		return (0);
10271 
10272 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10273 
10274 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10275 
10276 	dma->dmatype = bwn_dma_gettype(mac);
10277 	if (dma->dmatype == BWN_DMA_30BIT)
10278 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10279 	else if (dma->dmatype == BWN_DMA_32BIT)
10280 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10281 	else
10282 		lowaddr = BUS_SPACE_MAXADDR;
10283 
10284 	/*
10285 	 * Create top level DMA tag
10286 	 */
10287 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10288 			       BWN_ALIGN, 0,		/* alignment, bounds */
10289 			       lowaddr,			/* lowaddr */
10290 			       BUS_SPACE_MAXADDR,	/* highaddr */
10291 			       NULL, NULL,		/* filter, filterarg */
10292 			       MAXBSIZE,		/* maxsize */
10293 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10294 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10295 			       0,			/* flags */
10296 			       &dma->parent_dtag);
10297 	if (error) {
10298 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10299 		return (error);
10300 	}
10301 
10302 	/*
10303 	 * Create TX/RX mbuf DMA tag
10304 	 */
10305 	error = bus_dma_tag_create(dma->parent_dtag,
10306 				4,
10307 				0,
10308 				BUS_SPACE_MAXADDR,
10309 				BUS_SPACE_MAXADDR,
10310 				NULL, NULL,
10311 				MCLBYTES,
10312 				1,
10313 				BUS_SPACE_MAXSIZE_32BIT,
10314 				0,
10315 				&dma->rxbuf_dtag);
10316 	if (error) {
10317 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10318 		goto fail0;
10319 	}
10320 	error = bus_dma_tag_create(dma->parent_dtag,
10321 				4,
10322 				0,
10323 				BUS_SPACE_MAXADDR,
10324 				BUS_SPACE_MAXADDR,
10325 				NULL, NULL,
10326 				MCLBYTES,
10327 				1,
10328 				BUS_SPACE_MAXSIZE_32BIT,
10329 				0,
10330 				&dma->txbuf_dtag);
10331 	if (error) {
10332 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10333 		goto fail1;
10334 	}
10335 
10336 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10337 	if (dma->wme[WME_AC_BK] == NULL)
10338 		goto fail2;
10339 
10340 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10341 	if (dma->wme[WME_AC_BE] == NULL)
10342 		goto fail3;
10343 
10344 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10345 	if (dma->wme[WME_AC_VI] == NULL)
10346 		goto fail4;
10347 
10348 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10349 	if (dma->wme[WME_AC_VO] == NULL)
10350 		goto fail5;
10351 
10352 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10353 	if (dma->mcast == NULL)
10354 		goto fail6;
10355 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10356 	if (dma->rx == NULL)
10357 		goto fail7;
10358 
10359 	return (error);
10360 
10361 fail7:	bwn_dma_ringfree(&dma->mcast);
10362 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10363 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10364 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10365 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10366 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10367 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10368 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10369 	return (error);
10370 }
10371 
10372 static struct bwn_dma_ring *
10373 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10374     uint16_t cookie, int *slot)
10375 {
10376 	struct bwn_dma *dma = &mac->mac_method.dma;
10377 	struct bwn_dma_ring *dr;
10378 	struct bwn_softc *sc = mac->mac_sc;
10379 
10380 	switch (cookie & 0xf000) {
10381 	case 0x1000:
10382 		dr = dma->wme[WME_AC_BK];
10383 		break;
10384 	case 0x2000:
10385 		dr = dma->wme[WME_AC_BE];
10386 		break;
10387 	case 0x3000:
10388 		dr = dma->wme[WME_AC_VI];
10389 		break;
10390 	case 0x4000:
10391 		dr = dma->wme[WME_AC_VO];
10392 		break;
10393 	case 0x5000:
10394 		dr = dma->mcast;
10395 		break;
10396 	default:
10397 		dr = NULL;
10398 		KASSERT(0 == 1,
10399 		    ("invalid cookie value %d", cookie & 0xf000));
10400 	}
10401 	*slot = (cookie & 0x0fff);
10402 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10403 		/*
10404 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10405 		 * that it occurs events which have same H/W sequence numbers.
10406 		 * When it's occurred just prints a WARNING msgs and ignores.
10407 		 */
10408 		KASSERT(status->seq == dma->lastseq,
10409 		    ("%s:%d: fail", __func__, __LINE__));
10410 		device_printf(sc->sc_dev,
10411 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10412 		    dr->dr_numslots);
10413 		return (NULL);
10414 	}
10415 	dma->lastseq = status->seq;
10416 	return (dr);
10417 }
10418 
10419 static void
10420 bwn_dma_stop(struct bwn_mac *mac)
10421 {
10422 	struct bwn_dma *dma;
10423 
10424 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10425 		return;
10426 	dma = &mac->mac_method.dma;
10427 
10428 	bwn_dma_ringstop(&dma->rx);
10429 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10430 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10431 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10432 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10433 	bwn_dma_ringstop(&dma->mcast);
10434 }
10435 
10436 static void
10437 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10438 {
10439 
10440 	if (dr == NULL)
10441 		return;
10442 
10443 	bwn_dma_cleanup(*dr);
10444 }
10445 
10446 static void
10447 bwn_pio_stop(struct bwn_mac *mac)
10448 {
10449 	struct bwn_pio *pio;
10450 
10451 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10452 		return;
10453 	pio = &mac->mac_method.pio;
10454 
10455 	bwn_destroy_queue_tx(&pio->mcast);
10456 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10457 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10458 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10459 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10460 }
10461 
10462 static void
10463 bwn_led_attach(struct bwn_mac *mac)
10464 {
10465 	struct bwn_softc *sc = mac->mac_sc;
10466 	const uint8_t *led_act = NULL;
10467 	uint16_t val[BWN_LED_MAX];
10468 	int i;
10469 
10470 	sc->sc_led_idle = (2350 * hz) / 1000;
10471 	sc->sc_led_blink = 1;
10472 
10473 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10474 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10475 		    bwn_vendor_led_act[i].vid) {
10476 			led_act = bwn_vendor_led_act[i].led_act;
10477 			break;
10478 		}
10479 	}
10480 	if (led_act == NULL)
10481 		led_act = bwn_default_led_act;
10482 
10483 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10484 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10485 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10486 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10487 
10488 	for (i = 0; i < BWN_LED_MAX; ++i) {
10489 		struct bwn_led *led = &sc->sc_leds[i];
10490 
10491 		if (val[i] == 0xff) {
10492 			led->led_act = led_act[i];
10493 		} else {
10494 			if (val[i] & BWN_LED_ACT_LOW)
10495 				led->led_flags |= BWN_LED_F_ACTLOW;
10496 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10497 		}
10498 		led->led_mask = (1 << i);
10499 
10500 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10501 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10502 		    led->led_act == BWN_LED_ACT_BLINK) {
10503 			led->led_flags |= BWN_LED_F_BLINK;
10504 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10505 				led->led_flags |= BWN_LED_F_POLLABLE;
10506 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10507 				led->led_flags |= BWN_LED_F_SLOW;
10508 
10509 			if (sc->sc_blink_led == NULL) {
10510 				sc->sc_blink_led = led;
10511 				if (led->led_flags & BWN_LED_F_SLOW)
10512 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10513 			}
10514 		}
10515 
10516 		DPRINTF(sc, BWN_DEBUG_LED,
10517 		    "%dth led, act %d, lowact %d\n", i,
10518 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10519 	}
10520 	callout_init(&sc->sc_led_blink_ch);
10521 }
10522 
10523 static __inline uint16_t
10524 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10525 {
10526 
10527 	if (led->led_flags & BWN_LED_F_ACTLOW)
10528 		on = !on;
10529 	if (on)
10530 		val |= led->led_mask;
10531 	else
10532 		val &= ~led->led_mask;
10533 	return val;
10534 }
10535 
10536 static void
10537 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10538 {
10539 	struct bwn_softc *sc = mac->mac_sc;
10540 	struct ifnet *ifp = sc->sc_ifp;
10541 	struct ieee80211com *ic = ifp->if_l2com;
10542 	uint16_t val;
10543 	int i;
10544 
10545 	if (nstate == IEEE80211_S_INIT) {
10546 		callout_stop(&sc->sc_led_blink_ch);
10547 		sc->sc_led_blinking = 0;
10548 	}
10549 
10550 	if ((ic->ic_ifp->if_flags & IFF_RUNNING) == 0)
10551 		return;
10552 
10553 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10554 	for (i = 0; i < BWN_LED_MAX; ++i) {
10555 		struct bwn_led *led = &sc->sc_leds[i];
10556 		int on;
10557 
10558 		if (led->led_act == BWN_LED_ACT_UNKN ||
10559 		    led->led_act == BWN_LED_ACT_NULL)
10560 			continue;
10561 
10562 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10563 		    nstate != IEEE80211_S_INIT)
10564 			continue;
10565 
10566 		switch (led->led_act) {
10567 		case BWN_LED_ACT_ON:    /* Always on */
10568 			on = 1;
10569 			break;
10570 		case BWN_LED_ACT_OFF:   /* Always off */
10571 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10572 			on = 0;
10573 			break;
10574 		default:
10575 			on = 1;
10576 			switch (nstate) {
10577 			case IEEE80211_S_INIT:
10578 				on = 0;
10579 				break;
10580 			case IEEE80211_S_RUN:
10581 				if (led->led_act == BWN_LED_ACT_11G &&
10582 				    ic->ic_curmode != IEEE80211_MODE_11G)
10583 					on = 0;
10584 				break;
10585 			default:
10586 				if (led->led_act == BWN_LED_ACT_ASSOC)
10587 					on = 0;
10588 				break;
10589 			}
10590 			break;
10591 		}
10592 
10593 		val = bwn_led_onoff(led, val, on);
10594 	}
10595 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10596 }
10597 
10598 static void
10599 bwn_led_event(struct bwn_mac *mac, int event)
10600 {
10601 	struct bwn_softc *sc = mac->mac_sc;
10602 	struct bwn_led *led = sc->sc_blink_led;
10603 	int rate;
10604 
10605 	if (event == BWN_LED_EVENT_POLL) {
10606 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10607 			return;
10608 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10609 			return;
10610 	}
10611 
10612 	sc->sc_led_ticks = ticks;
10613 	if (sc->sc_led_blinking)
10614 		return;
10615 
10616 	switch (event) {
10617 	case BWN_LED_EVENT_RX:
10618 		rate = sc->sc_rx_rate;
10619 		break;
10620 	case BWN_LED_EVENT_TX:
10621 		rate = sc->sc_tx_rate;
10622 		break;
10623 	case BWN_LED_EVENT_POLL:
10624 		rate = 0;
10625 		break;
10626 	default:
10627 		panic("unknown LED event %d\n", event);
10628 		break;
10629 	}
10630 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10631 	    bwn_led_duration[rate].off_dur);
10632 }
10633 
10634 static void
10635 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10636 {
10637 	struct bwn_softc *sc = mac->mac_sc;
10638 	struct bwn_led *led = sc->sc_blink_led;
10639 	uint16_t val;
10640 
10641 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10642 	val = bwn_led_onoff(led, val, 1);
10643 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10644 
10645 	if (led->led_flags & BWN_LED_F_SLOW) {
10646 		BWN_LED_SLOWDOWN(on_dur);
10647 		BWN_LED_SLOWDOWN(off_dur);
10648 	}
10649 
10650 	sc->sc_led_blinking = 1;
10651 	sc->sc_led_blink_offdur = off_dur;
10652 
10653 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10654 }
10655 
10656 static void
10657 bwn_led_blink_next(void *arg)
10658 {
10659 	struct bwn_mac *mac = arg;
10660 	struct bwn_softc *sc = mac->mac_sc;
10661 	uint16_t val;
10662 
10663 	wlan_serialize_enter();
10664 
10665 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10666 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10667 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10668 
10669 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10670 	    bwn_led_blink_end, mac);
10671 	wlan_serialize_exit();
10672 }
10673 
10674 static void
10675 bwn_led_blink_end(void *arg)
10676 {
10677 	struct bwn_mac *mac = arg;
10678 	struct bwn_softc *sc = mac->mac_sc;
10679 
10680 	sc->sc_led_blinking = 0;
10681 }
10682 
10683 static int
10684 bwn_suspend(device_t dev)
10685 {
10686 	struct bwn_softc *sc = device_get_softc(dev);
10687 
10688 	wlan_serialize_enter();
10689 	bwn_stop(sc, 1);
10690 	wlan_serialize_exit();
10691 
10692 	return (0);
10693 }
10694 
10695 static int
10696 bwn_resume(device_t dev)
10697 {
10698 	struct bwn_softc *sc = device_get_softc(dev);
10699 	struct ifnet *ifp = sc->sc_ifp;
10700 
10701 	wlan_serialize_enter();
10702 	if (ifp->if_flags & IFF_UP)
10703 		bwn_init(sc);
10704 	wlan_serialize_exit();
10705 	return (0);
10706 }
10707 
10708 static void
10709 bwn_rfswitch(void *arg)
10710 {
10711 	struct bwn_softc *sc = arg;
10712 	struct bwn_mac *mac = sc->sc_curmac;
10713 	int cur = 0, prev = 0;
10714 
10715 	wlan_serialize_enter();
10716 
10717 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10718 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10719 
10720 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10721 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10722 			& BWN_RF_HWENABLED_HI_MASK))
10723 			cur = 1;
10724 	} else {
10725 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10726 		    & BWN_RF_HWENABLED_LO_MASK)
10727 			cur = 1;
10728 	}
10729 
10730 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10731 		prev = 1;
10732 
10733 	if (cur != prev) {
10734 		if (cur)
10735 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10736 		else
10737 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10738 
10739 		device_printf(sc->sc_dev,
10740 		    "status of RF switch is changed to %s\n",
10741 		    cur ? "ON" : "OFF");
10742 		if (cur != mac->mac_phy.rf_on) {
10743 			if (cur)
10744 				bwn_rf_turnon(mac);
10745 			else
10746 				bwn_rf_turnoff(mac);
10747 		}
10748 	}
10749 
10750 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
10751 	wlan_serialize_exit();
10752 }
10753 
10754 static void
10755 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10756 {
10757 	struct bwn_phy *phy = &mac->mac_phy;
10758 	struct bwn_phy_lp *plp = &phy->phy_lp;
10759 
10760 	plp->plp_antenna = BWN_ANT_DEFAULT;
10761 }
10762 
10763 static int
10764 bwn_phy_lp_init(struct bwn_mac *mac)
10765 {
10766 	static const struct bwn_stxtable tables[] = {
10767 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10768 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10769 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10770 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10771 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10772 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10773 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10774 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10775 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10776 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10777 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10778 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10779 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10780 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10781 		{ 2, 11, 0x40, 0, 0x0f }
10782 	};
10783 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10784 	struct bwn_softc *sc = mac->mac_sc;
10785 	const struct bwn_stxtable *st;
10786 	struct ifnet *ifp = sc->sc_ifp;
10787 	struct ieee80211com *ic = ifp->if_l2com;
10788 	int i, error;
10789 	uint16_t tmp;
10790 
10791 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10792 	bwn_phy_lp_bbinit(mac);
10793 
10794 	/* initialize RF */
10795 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10796 	DELAY(1);
10797 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10798 	DELAY(1);
10799 
10800 	if (mac->mac_phy.rf_ver == 0x2062)
10801 		bwn_phy_lp_b2062_init(mac);
10802 	else {
10803 		bwn_phy_lp_b2063_init(mac);
10804 
10805 		/* synchronize stx table. */
10806 		for (i = 0; i < N(tables); i++) {
10807 			st = &tables[i];
10808 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10809 			tmp >>= st->st_rfshift;
10810 			tmp <<= st->st_physhift;
10811 			BWN_PHY_SETMASK(mac,
10812 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10813 			    ~(st->st_mask << st->st_physhift), tmp);
10814 		}
10815 
10816 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10817 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10818 	}
10819 
10820 	/* calibrate RC */
10821 	if (mac->mac_phy.rev >= 2)
10822 		bwn_phy_lp_rxcal_r2(mac);
10823 	else if (!plp->plp_rccap) {
10824 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10825 			bwn_phy_lp_rccal_r12(mac);
10826 	} else
10827 		bwn_phy_lp_set_rccap(mac);
10828 
10829 	error = bwn_phy_lp_switch_channel(mac, 7);
10830 	if (error)
10831 		device_printf(sc->sc_dev,
10832 		    "failed to change channel 7 (%d)\n", error);
10833 	bwn_phy_lp_txpctl_init(mac);
10834 	bwn_phy_lp_calib(mac);
10835 	return (0);
10836 }
10837 
10838 static uint16_t
10839 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10840 {
10841 
10842 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10843 	return (BWN_READ_2(mac, BWN_PHYDATA));
10844 }
10845 
10846 static void
10847 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10848 {
10849 
10850 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10851 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10852 }
10853 
10854 static void
10855 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10856     uint16_t set)
10857 {
10858 
10859 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10860 	BWN_WRITE_2(mac, BWN_PHYDATA,
10861 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10862 }
10863 
10864 static uint16_t
10865 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10866 {
10867 
10868 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10869 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10870 		reg |= 0x100;
10871 	if (mac->mac_phy.rev >= 2)
10872 		reg |= 0x200;
10873 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10874 	return BWN_READ_2(mac, BWN_RFDATALO);
10875 }
10876 
10877 static void
10878 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10879 {
10880 
10881 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10882 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10883 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10884 }
10885 
10886 static void
10887 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10888 {
10889 
10890 	if (on) {
10891 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10892 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10893 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10894 		return;
10895 	}
10896 
10897 	if (mac->mac_phy.rev >= 2) {
10898 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10899 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10900 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10901 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10902 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10903 		return;
10904 	}
10905 
10906 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10907 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10908 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10909 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10910 }
10911 
10912 static int
10913 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10914 {
10915 	struct bwn_phy *phy = &mac->mac_phy;
10916 	struct bwn_phy_lp *plp = &phy->phy_lp;
10917 	int error;
10918 
10919 	if (phy->rf_ver == 0x2063) {
10920 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10921 		if (error)
10922 			return (error);
10923 	} else {
10924 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10925 		if (error)
10926 			return (error);
10927 		bwn_phy_lp_set_anafilter(mac, chan);
10928 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10929 	}
10930 
10931 	plp->plp_chan = chan;
10932 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10933 	return (0);
10934 }
10935 
10936 static uint32_t
10937 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10938 {
10939 	struct bwn_softc *sc = mac->mac_sc;
10940 	struct ifnet *ifp = sc->sc_ifp;
10941 	struct ieee80211com *ic = ifp->if_l2com;
10942 
10943 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10944 }
10945 
10946 static void
10947 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10948 {
10949 	struct bwn_phy *phy = &mac->mac_phy;
10950 	struct bwn_phy_lp *plp = &phy->phy_lp;
10951 
10952 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10953 		return;
10954 
10955 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10956 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10957 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10958 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10959 	plp->plp_antenna = antenna;
10960 }
10961 
10962 static void
10963 bwn_phy_lp_task_60s(struct bwn_mac *mac)
10964 {
10965 
10966 	bwn_phy_lp_calib(mac);
10967 }
10968 
10969 static void
10970 bwn_phy_lp_readsprom(struct bwn_mac *mac)
10971 {
10972 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10973 	struct bwn_softc *sc = mac->mac_sc;
10974 	struct ifnet *ifp = sc->sc_ifp;
10975 	struct ieee80211com *ic = ifp->if_l2com;
10976 
10977 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10978 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10979 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10980 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10981 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10982 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10983 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10984 		return;
10985 	}
10986 
10987 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10988 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10989 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10990 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10991 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10992 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10993 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10994 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10995 }
10996 
10997 static void
10998 bwn_phy_lp_bbinit(struct bwn_mac *mac)
10999 {
11000 
11001 	bwn_phy_lp_tblinit(mac);
11002 	if (mac->mac_phy.rev >= 2)
11003 		bwn_phy_lp_bbinit_r2(mac);
11004 	else
11005 		bwn_phy_lp_bbinit_r01(mac);
11006 }
11007 
11008 static void
11009 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11010 {
11011 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11012 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11013 	struct bwn_softc *sc = mac->mac_sc;
11014 	struct ifnet *ifp = sc->sc_ifp;
11015 	struct ieee80211com *ic = ifp->if_l2com;
11016 
11017 	bwn_phy_lp_set_txgain(mac,
11018 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11019 	bwn_phy_lp_set_bbmult(mac, 150);
11020 }
11021 
11022 static void
11023 bwn_phy_lp_calib(struct bwn_mac *mac)
11024 {
11025 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11026 	struct bwn_softc *sc = mac->mac_sc;
11027 	struct ifnet *ifp = sc->sc_ifp;
11028 	struct ieee80211com *ic = ifp->if_l2com;
11029 	const struct bwn_rxcompco *rc = NULL;
11030 	struct bwn_txgain ogain;
11031 	int i, omode, oafeovr, orf, obbmult;
11032 	uint8_t mode, fc = 0;
11033 
11034 	if (plp->plp_chanfullcal != plp->plp_chan) {
11035 		plp->plp_chanfullcal = plp->plp_chan;
11036 		fc = 1;
11037 	}
11038 
11039 	bwn_mac_suspend(mac);
11040 
11041 	/* BlueTooth Coexistance Override */
11042 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11043 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11044 
11045 	if (mac->mac_phy.rev >= 2)
11046 		bwn_phy_lp_digflt_save(mac);
11047 	bwn_phy_lp_get_txpctlmode(mac);
11048 	mode = plp->plp_txpctlmode;
11049 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11050 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11051 		bwn_phy_lp_bugfix(mac);
11052 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11053 		bwn_phy_lp_get_txpctlmode(mac);
11054 		omode = plp->plp_txpctlmode;
11055 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11056 		if (oafeovr)
11057 			ogain = bwn_phy_lp_get_txgain(mac);
11058 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11059 		obbmult = bwn_phy_lp_get_bbmult(mac);
11060 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11061 		if (oafeovr)
11062 			bwn_phy_lp_set_txgain(mac, &ogain);
11063 		bwn_phy_lp_set_bbmult(mac, obbmult);
11064 		bwn_phy_lp_set_txpctlmode(mac, omode);
11065 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11066 	}
11067 	bwn_phy_lp_set_txpctlmode(mac, mode);
11068 	if (mac->mac_phy.rev >= 2)
11069 		bwn_phy_lp_digflt_restore(mac);
11070 
11071 	/* do RX IQ Calculation; assumes that noise is true. */
11072 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11073 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11074 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11075 				rc = &bwn_rxcompco_5354[i];
11076 		}
11077 	} else if (mac->mac_phy.rev >= 2)
11078 		rc = &bwn_rxcompco_r2;
11079 	else {
11080 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11081 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11082 				rc = &bwn_rxcompco_r12[i];
11083 		}
11084 	}
11085 	if (rc == NULL)
11086 		goto fail;
11087 
11088 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11089 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11090 
11091 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11092 
11093 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11094 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11095 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11096 	} else {
11097 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11098 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11099 	}
11100 
11101 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11102 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11103 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11104 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11105 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11106 	bwn_phy_lp_set_deaf(mac, 0);
11107 	/* XXX no checking return value? */
11108 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11109 	bwn_phy_lp_clear_deaf(mac, 0);
11110 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11111 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11112 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11113 
11114 	/* disable RX GAIN override. */
11115 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11116 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11117 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11118 	if (mac->mac_phy.rev >= 2) {
11119 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11120 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11121 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11122 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11123 		}
11124 	} else {
11125 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11126 	}
11127 
11128 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11129 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11130 fail:
11131 	bwn_mac_enable(mac);
11132 }
11133 
11134 static void
11135 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11136 {
11137 
11138 	if (on) {
11139 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11140 		return;
11141 	}
11142 
11143 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11144 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11145 }
11146 
11147 static int
11148 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11149 {
11150 	static const struct bwn_b206x_chan *bc = NULL;
11151 	struct bwn_softc *sc = mac->mac_sc;
11152 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11153 	    tmp[6];
11154 	uint16_t old, scale, tmp16;
11155 	int i, div;
11156 
11157 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11158 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11159 			bc = &bwn_b2063_chantable[i];
11160 			break;
11161 		}
11162 	}
11163 	if (bc == NULL)
11164 		return (EINVAL);
11165 
11166 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11167 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11168 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11169 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11170 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11171 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11172 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11173 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11174 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11175 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11176 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11177 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11178 
11179 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11180 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11181 
11182 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11183 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11184 	freqref = freqxtal * 3;
11185 	div = (freqxtal <= 26000000 ? 1 : 2);
11186 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11187 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11188 		999999) / 1000000) + 1;
11189 
11190 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11191 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11192 	    0xfff8, timeout >> 2);
11193 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11194 	    0xff9f,timeout << 5);
11195 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11196 
11197 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11198 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11199 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11200 
11201 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11202 	    (timeoutref + 1)) - 1;
11203 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11204 	    0xf0, count >> 8);
11205 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11206 
11207 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11208 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11209 	while (tmp[1] >= freqref) {
11210 		tmp[0]++;
11211 		tmp[1] -= freqref;
11212 	}
11213 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11214 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11215 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11216 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11217 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11218 
11219 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11220 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11221 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11222 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11223 
11224 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11225 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11226 
11227 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11228 		scale = 1;
11229 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11230 	} else {
11231 		scale = 0;
11232 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11233 	}
11234 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11235 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11236 
11237 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11238 	    (scale + 1);
11239 	if (tmp[5] > 150)
11240 		tmp[5] = 0;
11241 
11242 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11243 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11244 
11245 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11246 	if (freqxtal > 26000000)
11247 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11248 	else
11249 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11250 
11251 	if (val[0] == 45)
11252 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11253 	else
11254 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11255 
11256 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11257 	DELAY(1);
11258 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11259 
11260 	/* VCO Calibration */
11261 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11262 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11263 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11264 	DELAY(1);
11265 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11266 	DELAY(1);
11267 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11268 	DELAY(1);
11269 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11270 	DELAY(300);
11271 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11272 
11273 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11274 	return (0);
11275 }
11276 
11277 static int
11278 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11279 {
11280 	struct bwn_softc *sc = mac->mac_sc;
11281 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11282 	const struct bwn_b206x_chan *bc = NULL;
11283 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11284 	uint32_t tmp[9];
11285 	int i;
11286 
11287 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11288 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11289 			bc = &bwn_b2062_chantable[i];
11290 			break;
11291 		}
11292 	}
11293 
11294 	if (bc == NULL)
11295 		return (EINVAL);
11296 
11297 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11298 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11299 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11300 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11301 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11302 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11303 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11304 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11305 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11306 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11307 
11308 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11309 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11310 	bwn_phy_lp_b2062_reset_pllbias(mac);
11311 	tmp[0] = freqxtal / 1000;
11312 	tmp[1] = plp->plp_div * 1000;
11313 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11314 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11315 		tmp[2] *= 2;
11316 	tmp[3] = 48 * tmp[0];
11317 	tmp[5] = tmp[2] / tmp[3];
11318 	tmp[6] = tmp[2] % tmp[3];
11319 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11320 	tmp[4] = tmp[6] * 0x100;
11321 	tmp[5] = tmp[4] / tmp[3];
11322 	tmp[6] = tmp[4] % tmp[3];
11323 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11324 	tmp[4] = tmp[6] * 0x100;
11325 	tmp[5] = tmp[4] / tmp[3];
11326 	tmp[6] = tmp[4] % tmp[3];
11327 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11328 	tmp[4] = tmp[6] * 0x100;
11329 	tmp[5] = tmp[4] / tmp[3];
11330 	tmp[6] = tmp[4] % tmp[3];
11331 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11332 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11333 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11334 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11335 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11336 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11337 
11338 	bwn_phy_lp_b2062_vco_calib(mac);
11339 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11340 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11341 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11342 		bwn_phy_lp_b2062_reset_pllbias(mac);
11343 		bwn_phy_lp_b2062_vco_calib(mac);
11344 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11345 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11346 			return (EIO);
11347 		}
11348 	}
11349 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11350 	return (0);
11351 }
11352 
11353 static void
11354 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11355 {
11356 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11357 	uint16_t tmp = (channel == 14);
11358 
11359 	if (mac->mac_phy.rev < 2) {
11360 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11361 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11362 			bwn_phy_lp_set_rccap(mac);
11363 		return;
11364 	}
11365 
11366 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11367 }
11368 
11369 static void
11370 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11371 {
11372 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11373 	struct bwn_softc *sc = mac->mac_sc;
11374 	struct ifnet *ifp = sc->sc_ifp;
11375 	struct ieee80211com *ic = ifp->if_l2com;
11376 	uint16_t iso, tmp[3];
11377 
11378 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11379 
11380 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11381 		iso = plp->plp_txisoband_m;
11382 	else if (freq <= 5320)
11383 		iso = plp->plp_txisoband_l;
11384 	else if (freq <= 5700)
11385 		iso = plp->plp_txisoband_m;
11386 	else
11387 		iso = plp->plp_txisoband_h;
11388 
11389 	tmp[0] = ((iso - 26) / 12) << 12;
11390 	tmp[1] = tmp[0] + 0x1000;
11391 	tmp[2] = tmp[0] + 0x2000;
11392 
11393 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11394 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11395 }
11396 
11397 static void
11398 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11399 {
11400 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11401 	int i;
11402 	static const uint16_t addr[] = {
11403 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11404 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11405 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11406 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11407 		BWN_PHY_OFDM(0xcf),
11408 	};
11409 	static const uint16_t val[] = {
11410 		0xde5e, 0xe832, 0xe331, 0x4d26,
11411 		0x0026, 0x1420, 0x0020, 0xfe08,
11412 		0x0008,
11413 	};
11414 
11415 	for (i = 0; i < N(addr); i++) {
11416 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11417 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11418 	}
11419 }
11420 
11421 static void
11422 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11423 {
11424 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11425 	struct bwn_softc *sc = mac->mac_sc;
11426 	uint16_t ctl;
11427 
11428 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11429 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11430 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11431 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11432 		break;
11433 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11434 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11435 		break;
11436 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11437 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11438 		break;
11439 	default:
11440 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11441 		device_printf(sc->sc_dev, "unknown command mode\n");
11442 		break;
11443 	}
11444 }
11445 
11446 static void
11447 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11448 {
11449 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11450 	uint16_t ctl;
11451 	uint8_t old;
11452 
11453 	bwn_phy_lp_get_txpctlmode(mac);
11454 	old = plp->plp_txpctlmode;
11455 	if (old == mode)
11456 		return;
11457 	plp->plp_txpctlmode = mode;
11458 
11459 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11460 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11461 		    plp->plp_tssiidx);
11462 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11463 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11464 
11465 		/* disable TX GAIN override */
11466 		if (mac->mac_phy.rev < 2)
11467 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11468 		else {
11469 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11470 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11471 		}
11472 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11473 
11474 		plp->plp_txpwridx = -1;
11475 	}
11476 	if (mac->mac_phy.rev >= 2) {
11477 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11478 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11479 		else
11480 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11481 	}
11482 
11483 	/* writes TX Power Control mode */
11484 	switch (plp->plp_txpctlmode) {
11485 	case BWN_PHYLP_TXPCTL_OFF:
11486 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11487 		break;
11488 	case BWN_PHYLP_TXPCTL_ON_HW:
11489 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11490 		break;
11491 	case BWN_PHYLP_TXPCTL_ON_SW:
11492 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11493 		break;
11494 	default:
11495 		ctl = 0;
11496 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11497 	}
11498 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11499 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11500 }
11501 
11502 static void
11503 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11504 {
11505 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11506 	const unsigned int size = 256;
11507 	struct bwn_txgain tg;
11508 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11509 	uint16_t tssinpt, tssiidx, value[2];
11510 	uint8_t mode;
11511 	int8_t txpwridx;
11512 
11513 	tabs = (uint32_t *)kmalloc(sizeof(uint32_t) * size, M_DEVBUF,
11514 	    M_INTWAIT | M_ZERO);
11515 
11516 	bwn_phy_lp_get_txpctlmode(mac);
11517 	mode = plp->plp_txpctlmode;
11518 	txpwridx = plp->plp_txpwridx;
11519 	tssinpt = plp->plp_tssinpt;
11520 	tssiidx = plp->plp_tssiidx;
11521 
11522 	bwn_tab_read_multi(mac,
11523 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11524 	    BWN_TAB_4(7, 0x140), size, tabs);
11525 
11526 	bwn_phy_lp_tblinit(mac);
11527 	bwn_phy_lp_bbinit(mac);
11528 	bwn_phy_lp_txpctl_init(mac);
11529 	bwn_phy_lp_rf_onoff(mac, 1);
11530 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11531 
11532 	bwn_tab_write_multi(mac,
11533 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11534 	    BWN_TAB_4(7, 0x140), size, tabs);
11535 
11536 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11537 	plp->plp_tssinpt = tssinpt;
11538 	plp->plp_tssiidx = tssiidx;
11539 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11540 	if (txpwridx != -1) {
11541 		/* set TX power by index */
11542 		plp->plp_txpwridx = txpwridx;
11543 		bwn_phy_lp_get_txpctlmode(mac);
11544 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11545 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11546 		if (mac->mac_phy.rev >= 2) {
11547 			rxcomp = bwn_tab_read(mac,
11548 			    BWN_TAB_4(7, txpwridx + 320));
11549 			txgain = bwn_tab_read(mac,
11550 			    BWN_TAB_4(7, txpwridx + 192));
11551 			tg.tg_pad = (txgain >> 16) & 0xff;
11552 			tg.tg_gm = txgain & 0xff;
11553 			tg.tg_pga = (txgain >> 8) & 0xff;
11554 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11555 			bwn_phy_lp_set_txgain(mac, &tg);
11556 		} else {
11557 			rxcomp = bwn_tab_read(mac,
11558 			    BWN_TAB_4(10, txpwridx + 320));
11559 			txgain = bwn_tab_read(mac,
11560 			    BWN_TAB_4(10, txpwridx + 192));
11561 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11562 			    0xf800, (txgain >> 4) & 0x7fff);
11563 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11564 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11565 		}
11566 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11567 
11568 		/* set TX IQCC */
11569 		value[0] = (rxcomp >> 10) & 0x3ff;
11570 		value[1] = rxcomp & 0x3ff;
11571 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11572 
11573 		coeff = bwn_tab_read(mac,
11574 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11575 		    BWN_TAB_4(10, txpwridx + 448));
11576 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11577 		if (mac->mac_phy.rev >= 2) {
11578 			rfpwr = bwn_tab_read(mac,
11579 			    BWN_TAB_4(7, txpwridx + 576));
11580 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11581 			    rfpwr & 0xffff);
11582 		}
11583 		bwn_phy_lp_set_txgain_override(mac);
11584 	}
11585 	if (plp->plp_rccap)
11586 		bwn_phy_lp_set_rccap(mac);
11587 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11588 	bwn_phy_lp_set_txpctlmode(mac, mode);
11589 	kfree(tabs, M_DEVBUF);
11590 }
11591 
11592 static void
11593 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11594 {
11595 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11596 	int i;
11597 	static const uint16_t addr[] = {
11598 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11599 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11600 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11601 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11602 		BWN_PHY_OFDM(0xcf),
11603 	};
11604 
11605 	for (i = 0; i < N(addr); i++)
11606 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11607 }
11608 
11609 static void
11610 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11611 {
11612 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11613 
11614 	if (mac->mac_phy.rev < 2) {
11615 		bwn_phy_lp_tblinit_r01(mac);
11616 		bwn_phy_lp_tblinit_txgain(mac);
11617 		bwn_phy_lp_set_gaintbl(mac, freq);
11618 		return;
11619 	}
11620 
11621 	bwn_phy_lp_tblinit_r2(mac);
11622 	bwn_phy_lp_tblinit_txgain(mac);
11623 }
11624 
11625 struct bwn_wpair {
11626 	uint16_t		reg;
11627 	uint16_t		value;
11628 };
11629 
11630 struct bwn_smpair {
11631 	uint16_t		offset;
11632 	uint16_t		mask;
11633 	uint16_t		set;
11634 };
11635 
11636 static void
11637 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11638 {
11639 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11640 	struct bwn_softc *sc = mac->mac_sc;
11641 	struct ifnet *ifp = sc->sc_ifp;
11642 	struct ieee80211com *ic = ifp->if_l2com;
11643 	static const struct bwn_wpair v1[] = {
11644 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11645 		{ BWN_PHY_AFE_CTL, 0x8800 },
11646 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11647 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11648 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11649 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11650 		{ BWN_PHY_OFDM(0xf9), 0 },
11651 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11652 	};
11653 	static const struct bwn_smpair v2[] = {
11654 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11655 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11656 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11657 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11658 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11659 	};
11660 	static const struct bwn_smpair v3[] = {
11661 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11662 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11663 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11664 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11665 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11666 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11667 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11668 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11669 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11670 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11671 
11672 	};
11673 	int i;
11674 
11675 	for (i = 0; i < N(v1); i++)
11676 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11677 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11678 	for (i = 0; i < N(v2); i++)
11679 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11680 
11681 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11682 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11683 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11684 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11685 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11686 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11687 	} else {
11688 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11689 	}
11690 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11691 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11692 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11693 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11694 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11695 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11696 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11697 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11698 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11699 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11700 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11701 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11702 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11703 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11704 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11705 	} else {
11706 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11707 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11708 	}
11709 	for (i = 0; i < N(v3); i++)
11710 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11711 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11712 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11713 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11714 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11715 	}
11716 
11717 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11718 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11719 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11720 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11721 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11722 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11723 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11724 	} else
11725 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11726 
11727 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11728 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11729 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11730 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11731 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11732 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11733 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11734 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11735 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11736 
11737 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11738 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11739 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11740 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11741 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11742 	}
11743 
11744 	bwn_phy_lp_digflt_save(mac);
11745 }
11746 
11747 static void
11748 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11749 {
11750 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11751 	struct bwn_softc *sc = mac->mac_sc;
11752 	struct ifnet *ifp = sc->sc_ifp;
11753 	struct ieee80211com *ic = ifp->if_l2com;
11754 	static const struct bwn_smpair v1[] = {
11755 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11756 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11757 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11758 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11759 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11760 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11761 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11762 	};
11763 	static const struct bwn_smpair v2[] = {
11764 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11765 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11766 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11767 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11768 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11769 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11770 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11771 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11772 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11773 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11774 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11775 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11776 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11777 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11778 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11779 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11780 	};
11781 	static const struct bwn_smpair v3[] = {
11782 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11783 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11784 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11785 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11786 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11787 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11788 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11789 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11790 	};
11791 	static const struct bwn_smpair v4[] = {
11792 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11793 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11794 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11795 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11796 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11797 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11798 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11799 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11800 	};
11801 	static const struct bwn_smpair v5[] = {
11802 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11803 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11804 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11805 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11806 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11807 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11808 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11809 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11810 	};
11811 	int i;
11812 	uint16_t tmp, tmp2;
11813 
11814 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11815 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11816 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11817 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11818 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11819 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11820 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11821 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11822 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11823 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11824 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11825 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11826 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11827 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11828 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11829 	for (i = 0; i < N(v1); i++)
11830 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11831 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11832 	    0xff00, plp->plp_rxpwroffset);
11833 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11834 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11835 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11836 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11837 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11838 		if (mac->mac_phy.rev == 0)
11839 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11840 			    0xffcf, 0x0010);
11841 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11842 	} else {
11843 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11844 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11845 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11846 	}
11847 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11848 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11849 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11850 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11851 	else
11852 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11853 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11854 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11855 	    0xfff9, (plp->plp_bxarch << 1));
11856 	if (mac->mac_phy.rev == 1 &&
11857 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11858 		for (i = 0; i < N(v2); i++)
11859 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11860 			    v2[i].set);
11861 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11862 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11863 	    ((mac->mac_phy.rev == 0) &&
11864 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11865 		for (i = 0; i < N(v3); i++)
11866 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11867 			    v3[i].set);
11868 	} else if (mac->mac_phy.rev == 1 ||
11869 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11870 		for (i = 0; i < N(v4); i++)
11871 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11872 			    v4[i].set);
11873 	} else {
11874 		for (i = 0; i < N(v5); i++)
11875 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11876 			    v5[i].set);
11877 	}
11878 	if (mac->mac_phy.rev == 1 &&
11879 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11880 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11881 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11882 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11883 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11884 	}
11885 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11886 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11887 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11888 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11889 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11890 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11891 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11892 	}
11893 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11894 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11895 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11896 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11897 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11898 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11899 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11900 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11901 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11902 	} else {
11903 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11904 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11905 	}
11906 	if (mac->mac_phy.rev == 1) {
11907 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11908 		tmp2 = (tmp & 0x03e0) >> 5;
11909 		tmp2 |= tmp2 << 5;
11910 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11911 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11912 		tmp2 = (tmp & 0x1f00) >> 8;
11913 		tmp2 |= tmp2 << 5;
11914 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11915 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11916 		tmp2 = tmp & 0x00ff;
11917 		tmp2 |= tmp << 8;
11918 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11919 	}
11920 }
11921 
11922 struct bwn_b2062_freq {
11923 	uint16_t		freq;
11924 	uint8_t			value[6];
11925 };
11926 
11927 static void
11928 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11929 {
11930 #define	CALC_CTL7(freq, div)						\
11931 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11932 #define	CALC_CTL18(freq, div)						\
11933 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11934 #define	CALC_CTL19(freq, div)						\
11935 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11936 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11937 	struct bwn_softc *sc = mac->mac_sc;
11938 	struct ifnet *ifp = sc->sc_ifp;
11939 	struct ieee80211com *ic = ifp->if_l2com;
11940 	static const struct bwn_b2062_freq freqdata_tab[] = {
11941 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11942 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11943 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11944 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11945 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11946 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11947 	};
11948 	static const struct bwn_wpair v1[] = {
11949 		{ BWN_B2062_N_TXCTL3, 0 },
11950 		{ BWN_B2062_N_TXCTL4, 0 },
11951 		{ BWN_B2062_N_TXCTL5, 0 },
11952 		{ BWN_B2062_N_TXCTL6, 0 },
11953 		{ BWN_B2062_N_PDNCTL0, 0x40 },
11954 		{ BWN_B2062_N_PDNCTL0, 0 },
11955 		{ BWN_B2062_N_CALIB_TS, 0x10 },
11956 		{ BWN_B2062_N_CALIB_TS, 0 }
11957 	};
11958 	const struct bwn_b2062_freq *f = NULL;
11959 	uint32_t xtalfreq, ref;
11960 	unsigned int i;
11961 
11962 	bwn_phy_lp_b2062_tblinit(mac);
11963 
11964 	for (i = 0; i < N(v1); i++)
11965 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11966 	if (mac->mac_phy.rev > 0)
11967 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11968 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11969 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11970 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11971 	else
11972 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11973 
11974 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11975 	    ("%s:%d: fail", __func__, __LINE__));
11976 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11977 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11978 
11979 	if (xtalfreq <= 30000000) {
11980 		plp->plp_div = 1;
11981 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11982 	} else {
11983 		plp->plp_div = 2;
11984 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11985 	}
11986 
11987 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11988 	    CALC_CTL7(xtalfreq, plp->plp_div));
11989 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11990 	    CALC_CTL18(xtalfreq, plp->plp_div));
11991 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11992 	    CALC_CTL19(xtalfreq, plp->plp_div));
11993 
11994 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11995 	ref &= 0xffff;
11996 	for (i = 0; i < N(freqdata_tab); i++) {
11997 		if (ref < freqdata_tab[i].freq) {
11998 			f = &freqdata_tab[i];
11999 			break;
12000 		}
12001 	}
12002 	if (f == NULL)
12003 		f = &freqdata_tab[N(freqdata_tab) - 1];
12004 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12005 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12006 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12007 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12008 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12009 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12010 #undef CALC_CTL7
12011 #undef CALC_CTL18
12012 #undef CALC_CTL19
12013 }
12014 
12015 static void
12016 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12017 {
12018 
12019 	bwn_phy_lp_b2063_tblinit(mac);
12020 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12021 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12022 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12023 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12024 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12025 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12026 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12027 	if (mac->mac_phy.rev == 2) {
12028 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12029 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12030 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12031 	} else {
12032 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12033 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12034 	}
12035 }
12036 
12037 static void
12038 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12039 {
12040 	struct bwn_softc *sc = mac->mac_sc;
12041 	static const struct bwn_wpair v1[] = {
12042 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12043 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12044 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12045 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12046 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12047 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12048 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12049 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12050 	};
12051 	static const struct bwn_wpair v2[] = {
12052 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12053 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12054 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12055 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12056 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12057 	};
12058 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12059 	int i;
12060 	uint8_t tmp;
12061 
12062 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12063 
12064 	for (i = 0; i < 2; i++)
12065 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12066 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12067 	for (i = 2; i < N(v1); i++)
12068 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12069 	for (i = 0; i < 10000; i++) {
12070 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12071 			break;
12072 		DELAY(1000);
12073 	}
12074 
12075 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12076 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12077 
12078 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12079 
12080 	for (i = 0; i < N(v2); i++)
12081 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12082 	if (freqxtal == 24000000) {
12083 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12084 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12085 	} else {
12086 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12087 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12088 	}
12089 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12090 	for (i = 0; i < 10000; i++) {
12091 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12092 			break;
12093 		DELAY(1000);
12094 	}
12095 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12096 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12097 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12098 }
12099 
12100 static void
12101 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12102 {
12103 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12104 	struct bwn_softc *sc = mac->mac_sc;
12105 	struct bwn_phy_lp_iq_est ie;
12106 	struct bwn_txgain tx_gains;
12107 	static const uint32_t pwrtbl[21] = {
12108 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12109 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12110 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12111 		0x0004c, 0x0002c, 0x0001a,
12112 	};
12113 	uint32_t npwr, ipwr, sqpwr, tmp;
12114 	int loopback, i, j, sum, error;
12115 	uint16_t save[7];
12116 	uint8_t txo, bbmult, txpctlmode;
12117 
12118 	error = bwn_phy_lp_switch_channel(mac, 7);
12119 	if (error)
12120 		device_printf(sc->sc_dev,
12121 		    "failed to change channel to 7 (%d)\n", error);
12122 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12123 	bbmult = bwn_phy_lp_get_bbmult(mac);
12124 	if (txo)
12125 		tx_gains = bwn_phy_lp_get_txgain(mac);
12126 
12127 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12128 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12129 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12130 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12131 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12132 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12133 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12134 
12135 	bwn_phy_lp_get_txpctlmode(mac);
12136 	txpctlmode = plp->plp_txpctlmode;
12137 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12138 
12139 	/* disable CRS */
12140 	bwn_phy_lp_set_deaf(mac, 1);
12141 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12142 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12143 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12144 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12145 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12146 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12147 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12148 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12149 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12150 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12151 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12152 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12153 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12154 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12155 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12156 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12157 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12158 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12159 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12160 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12161 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12162 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12163 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12164 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12165 
12166 	loopback = bwn_phy_lp_loopback(mac);
12167 	if (loopback == -1)
12168 		goto done;
12169 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12170 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12171 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12172 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12173 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12174 
12175 	tmp = 0;
12176 	memset(&ie, 0, sizeof(ie));
12177 	for (i = 128; i <= 159; i++) {
12178 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12179 		sum = 0;
12180 		for (j = 5; j <= 25; j++) {
12181 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12182 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12183 				goto done;
12184 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12185 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12186 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12187 			    12);
12188 			sum += ((ipwr - npwr) * (ipwr - npwr));
12189 			if ((i == 128) || (sum < tmp)) {
12190 				plp->plp_rccap = i;
12191 				tmp = sum;
12192 			}
12193 		}
12194 	}
12195 	bwn_phy_lp_ddfs_turnoff(mac);
12196 done:
12197 	/* restore CRS */
12198 	bwn_phy_lp_clear_deaf(mac, 1);
12199 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12200 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12201 
12202 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12203 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12204 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12205 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12206 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12207 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12208 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12209 
12210 	bwn_phy_lp_set_bbmult(mac, bbmult);
12211 	if (txo)
12212 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12213 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12214 	if (plp->plp_rccap)
12215 		bwn_phy_lp_set_rccap(mac);
12216 }
12217 
12218 static void
12219 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12220 {
12221 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12222 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12223 
12224 	if (mac->mac_phy.rev == 1)
12225 		rc_cap = MIN(rc_cap + 5, 15);
12226 
12227 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12228 	    MAX(plp->plp_rccap - 4, 0x80));
12229 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12230 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12231 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12232 }
12233 
12234 static uint32_t
12235 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12236 {
12237 	uint32_t i, q, r;
12238 
12239 	if (div == 0)
12240 		return (0);
12241 
12242 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12243 		q <<= 1;
12244 		if (r << 1 >= div) {
12245 			q++;
12246 			r = (r << 1) - div;
12247 		}
12248 	}
12249 	if (r << 1 >= div)
12250 		q++;
12251 	return (q);
12252 }
12253 
12254 static void
12255 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12256 {
12257 	struct bwn_softc *sc = mac->mac_sc;
12258 
12259 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12260 	DELAY(20);
12261 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12262 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12263 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12264 	} else {
12265 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12266 	}
12267 	DELAY(5);
12268 }
12269 
12270 static void
12271 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12272 {
12273 
12274 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12275 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12276 	DELAY(200);
12277 }
12278 
12279 static void
12280 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12281 {
12282 #define	FLAG_A	0x01
12283 #define	FLAG_G	0x02
12284 	struct bwn_softc *sc = mac->mac_sc;
12285 	struct ifnet *ifp = sc->sc_ifp;
12286 	struct ieee80211com *ic = ifp->if_l2com;
12287 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12288 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12289 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12290 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12291 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12292 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12293 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12294 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12295 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12296 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12297 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12298 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12299 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12300 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12301 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12302 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12303 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12304 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12305 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12306 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12307 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12308 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12309 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12310 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12311 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12312 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12313 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12314 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12315 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12316 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12317 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12318 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12319 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12320 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12321 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12322 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12323 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12324 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12325 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12326 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12327 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12328 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12329 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12330 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12331 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12332 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12333 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12334 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12335 	};
12336 	const struct bwn_b206x_rfinit_entry *br;
12337 	unsigned int i;
12338 
12339 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12340 		br = &bwn_b2062_init_tab[i];
12341 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12342 			if (br->br_flags & FLAG_G)
12343 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12344 		} else {
12345 			if (br->br_flags & FLAG_A)
12346 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12347 		}
12348 	}
12349 #undef FLAG_A
12350 #undef FLAG_B
12351 }
12352 
12353 static void
12354 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12355 {
12356 #define	FLAG_A	0x01
12357 #define	FLAG_G	0x02
12358 	struct bwn_softc *sc = mac->mac_sc;
12359 	struct ifnet *ifp = sc->sc_ifp;
12360 	struct ieee80211com *ic = ifp->if_l2com;
12361 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12362 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12363 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12364 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12365 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12366 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12367 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12368 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12369 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12370 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12371 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12372 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12373 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12374 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12375 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12376 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12377 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12378 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12379 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12380 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12381 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12382 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12383 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12384 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12385 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12386 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12387 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12388 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12389 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12390 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12391 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12392 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12393 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12394 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12395 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12396 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12397 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12398 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12399 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12400 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12401 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12402 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12403 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12404 	};
12405 	const struct bwn_b206x_rfinit_entry *br;
12406 	unsigned int i;
12407 
12408 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12409 		br = &bwn_b2063_init_tab[i];
12410 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12411 			if (br->br_flags & FLAG_G)
12412 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12413 		} else {
12414 			if (br->br_flags & FLAG_A)
12415 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12416 		}
12417 	}
12418 #undef FLAG_A
12419 #undef FLAG_B
12420 }
12421 
12422 static void
12423 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12424     int count, void *_data)
12425 {
12426 	unsigned int i;
12427 	uint32_t offset, type;
12428 	uint8_t *data = _data;
12429 
12430 	type = BWN_TAB_GETTYPE(typenoffset);
12431 	offset = BWN_TAB_GETOFFSET(typenoffset);
12432 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12433 
12434 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12435 
12436 	for (i = 0; i < count; i++) {
12437 		switch (type) {
12438 		case BWN_TAB_8BIT:
12439 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12440 			data++;
12441 			break;
12442 		case BWN_TAB_16BIT:
12443 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12444 			    BWN_PHY_TABLEDATALO);
12445 			data += 2;
12446 			break;
12447 		case BWN_TAB_32BIT:
12448 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12449 			    BWN_PHY_TABLEDATAHI);
12450 			*((uint32_t *)data) <<= 16;
12451 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12452 			    BWN_PHY_TABLEDATALO);
12453 			data += 4;
12454 			break;
12455 		default:
12456 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12457 		}
12458 	}
12459 }
12460 
12461 static void
12462 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12463     int count, const void *_data)
12464 {
12465 	uint32_t offset, type, value;
12466 	const uint8_t *data = _data;
12467 	unsigned int i;
12468 
12469 	type = BWN_TAB_GETTYPE(typenoffset);
12470 	offset = BWN_TAB_GETOFFSET(typenoffset);
12471 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12472 
12473 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12474 
12475 	for (i = 0; i < count; i++) {
12476 		switch (type) {
12477 		case BWN_TAB_8BIT:
12478 			value = *data;
12479 			data++;
12480 			KASSERT(!(value & ~0xff),
12481 			    ("%s:%d: fail", __func__, __LINE__));
12482 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12483 			break;
12484 		case BWN_TAB_16BIT:
12485 			value = *((const uint16_t *)data);
12486 			data += 2;
12487 			KASSERT(!(value & ~0xffff),
12488 			    ("%s:%d: fail", __func__, __LINE__));
12489 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12490 			break;
12491 		case BWN_TAB_32BIT:
12492 			value = *((const uint32_t *)data);
12493 			data += 4;
12494 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12495 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12496 			break;
12497 		default:
12498 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12499 		}
12500 	}
12501 }
12502 
12503 static struct bwn_txgain
12504 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12505 {
12506 	struct bwn_txgain tg;
12507 	uint16_t tmp;
12508 
12509 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12510 	if (mac->mac_phy.rev < 2) {
12511 		tmp = BWN_PHY_READ(mac,
12512 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12513 		tg.tg_gm = tmp & 0x0007;
12514 		tg.tg_pga = (tmp & 0x0078) >> 3;
12515 		tg.tg_pad = (tmp & 0x780) >> 7;
12516 		return (tg);
12517 	}
12518 
12519 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12520 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12521 	tg.tg_gm = tmp & 0xff;
12522 	tg.tg_pga = (tmp >> 8) & 0xff;
12523 	return (tg);
12524 }
12525 
12526 static uint8_t
12527 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12528 {
12529 
12530 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12531 }
12532 
12533 static void
12534 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12535 {
12536 	uint16_t pa;
12537 
12538 	if (mac->mac_phy.rev < 2) {
12539 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12540 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12541 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12542 		bwn_phy_lp_set_txgain_override(mac);
12543 		return;
12544 	}
12545 
12546 	pa = bwn_phy_lp_get_pa_gain(mac);
12547 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12548 	    (tg->tg_pga << 8) | tg->tg_gm);
12549 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12550 	    tg->tg_pad | (pa << 6));
12551 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12552 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12553 	    tg->tg_pad | (pa << 8));
12554 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12555 	bwn_phy_lp_set_txgain_override(mac);
12556 }
12557 
12558 static void
12559 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12560 {
12561 
12562 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12563 }
12564 
12565 static void
12566 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12567 {
12568 	uint16_t trsw = (tx << 1) | rx;
12569 
12570 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12571 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12572 }
12573 
12574 static void
12575 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12576 {
12577 	struct bwn_softc *sc = mac->mac_sc;
12578 	struct ifnet *ifp = sc->sc_ifp;
12579 	struct ieee80211com *ic = ifp->if_l2com;
12580 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12581 
12582 	if (mac->mac_phy.rev < 2) {
12583 		trsw = gain & 0x1;
12584 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12585 		ext_lna = (gain & 2) >> 1;
12586 
12587 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12588 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12589 		    0xfbff, ext_lna << 10);
12590 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12591 		    0xf7ff, ext_lna << 11);
12592 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12593 	} else {
12594 		low_gain = gain & 0xffff;
12595 		high_gain = (gain >> 16) & 0xf;
12596 		ext_lna = (gain >> 21) & 0x1;
12597 		trsw = ~(gain >> 20) & 0x1;
12598 
12599 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12600 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12601 		    0xfdff, ext_lna << 9);
12602 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12603 		    0xfbff, ext_lna << 10);
12604 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12605 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12606 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12607 			tmp = (gain >> 2) & 0x3;
12608 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12609 			    0xe7ff, tmp<<11);
12610 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12611 			    tmp << 3);
12612 		}
12613 	}
12614 
12615 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12616 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12617 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12618 	if (mac->mac_phy.rev >= 2) {
12619 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12620 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12621 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12622 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12623 		}
12624 		return;
12625 	}
12626 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12627 }
12628 
12629 static void
12630 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12631 {
12632 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12633 
12634 	if (user)
12635 		plp->plp_crsusr_off = 1;
12636 	else
12637 		plp->plp_crssys_off = 1;
12638 
12639 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12640 }
12641 
12642 static void
12643 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12644 {
12645 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12646 	struct bwn_softc *sc = mac->mac_sc;
12647 	struct ifnet *ifp = sc->sc_ifp;
12648 	struct ieee80211com *ic = ifp->if_l2com;
12649 
12650 	if (user)
12651 		plp->plp_crsusr_off = 0;
12652 	else
12653 		plp->plp_crssys_off = 0;
12654 
12655 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12656 		return;
12657 
12658 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12659 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12660 	else
12661 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12662 }
12663 
12664 static unsigned int
12665 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12666 {
12667 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12668 	static uint8_t sqrt_table[256] = {
12669 		10, 14, 17, 20, 22, 24, 26, 28,
12670 		30, 31, 33, 34, 36, 37, 38, 40,
12671 		41, 42, 43, 44, 45, 46, 47, 48,
12672 		50, 50, 51, 52, 53, 54, 55, 56,
12673 		57, 58, 59, 60, 60, 61, 62, 63,
12674 		64, 64, 65, 66, 67, 67, 68, 69,
12675 		70, 70, 71, 72, 72, 73, 74, 74,
12676 		75, 76, 76, 77, 78, 78, 79, 80,
12677 		80, 81, 81, 82, 83, 83, 84, 84,
12678 		85, 86, 86, 87, 87, 88, 88, 89,
12679 		90, 90, 91, 91, 92, 92, 93, 93,
12680 		94, 94, 95, 95, 96, 96, 97, 97,
12681 		98, 98, 99, 100, 100, 100, 101, 101,
12682 		102, 102, 103, 103, 104, 104, 105, 105,
12683 		106, 106, 107, 107, 108, 108, 109, 109,
12684 		110, 110, 110, 111, 111, 112, 112, 113,
12685 		113, 114, 114, 114, 115, 115, 116, 116,
12686 		117, 117, 117, 118, 118, 119, 119, 120,
12687 		120, 120, 121, 121, 122, 122, 122, 123,
12688 		123, 124, 124, 124, 125, 125, 126, 126,
12689 		126, 127, 127, 128, 128, 128, 129, 129,
12690 		130, 130, 130, 131, 131, 131, 132, 132,
12691 		133, 133, 133, 134, 134, 134, 135, 135,
12692 		136, 136, 136, 137, 137, 137, 138, 138,
12693 		138, 139, 139, 140, 140, 140, 141, 141,
12694 		141, 142, 142, 142, 143, 143, 143, 144,
12695 		144, 144, 145, 145, 145, 146, 146, 146,
12696 		147, 147, 147, 148, 148, 148, 149, 149,
12697 		150, 150, 150, 150, 151, 151, 151, 152,
12698 		152, 152, 153, 153, 153, 154, 154, 154,
12699 		155, 155, 155, 156, 156, 156, 157, 157,
12700 		157, 158, 158, 158, 159, 159, 159, 160
12701 	};
12702 
12703 	if (x == 0)
12704 		return (0);
12705 	if (x >= 256) {
12706 		unsigned int tmp;
12707 
12708 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12709 			/* do nothing */ ;
12710 		return (tmp);
12711 	}
12712 	return (sqrt_table[x - 1] / 10);
12713 }
12714 
12715 static int
12716 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12717 {
12718 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12719 	int _t;								\
12720 	_t = _x - 20;							\
12721 	if (_t >= 0) {							\
12722 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12723 	} else {							\
12724 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12725 	}								\
12726 } while (0)
12727 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12728 	int _t;								\
12729 	_t = _x - 11;							\
12730 	if (_t >= 0)							\
12731 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12732 	else								\
12733 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12734 } while (0)
12735 	struct bwn_phy_lp_iq_est ie;
12736 	uint16_t v0, v1;
12737 	int tmp[2], ret;
12738 
12739 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12740 	v0 = v1 >> 8;
12741 	v1 |= 0xff;
12742 
12743 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12744 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12745 
12746 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12747 	if (ret == 0)
12748 		goto done;
12749 
12750 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12751 		ret = 0;
12752 		goto done;
12753 	}
12754 
12755 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12756 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12757 
12758 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12759 	v0 = tmp[0] >> 3;
12760 	v1 = tmp[1] >> 4;
12761 done:
12762 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12763 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12764 	return ret;
12765 #undef CALC_COEFF
12766 #undef CALC_COEFF2
12767 }
12768 
12769 static void
12770 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12771 {
12772 	static const uint16_t noisescale[] = {
12773 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12774 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12775 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12776 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12777 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12778 	};
12779 	static const uint16_t crsgainnft[] = {
12780 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12781 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12782 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12783 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12784 		0x013d,
12785 	};
12786 	static const uint16_t filterctl[] = {
12787 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12788 		0xff53, 0x0127,
12789 	};
12790 	static const uint32_t psctl[] = {
12791 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12792 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12793 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12794 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12795 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12796 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12797 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12798 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12799 	};
12800 	static const uint16_t ofdmcckgain_r0[] = {
12801 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12802 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12803 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12804 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12805 		0x755d,
12806 	};
12807 	static const uint16_t ofdmcckgain_r1[] = {
12808 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12809 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12810 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12811 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12812 		0x755d,
12813 	};
12814 	static const uint16_t gaindelta[] = {
12815 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12816 		0x0000,
12817 	};
12818 	static const uint32_t txpwrctl[] = {
12819 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12820 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12821 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12822 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12823 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12824 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12825 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12826 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12827 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12828 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12829 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12830 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12831 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12832 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12833 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12834 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12835 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12836 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12837 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12838 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12839 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12840 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12841 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12842 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12843 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12844 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12845 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12846 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12847 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12848 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12849 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12850 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12851 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12852 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12853 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12854 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12855 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12856 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12857 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12858 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12859 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12860 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12861 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12862 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12863 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12864 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12865 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12866 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12867 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12868 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12869 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12870 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12871 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12872 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12873 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12874 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12875 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12876 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12877 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12878 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12879 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12880 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12881 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12882 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12883 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12884 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12885 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12886 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12887 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12888 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12889 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12890 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12891 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12892 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12893 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12894 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12895 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12896 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12897 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12898 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12899 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12900 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12901 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12902 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12903 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12904 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12905 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12906 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12907 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12908 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12909 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12910 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12911 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12912 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12913 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12914 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12915 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12916 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12917 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12918 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12919 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12920 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12921 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12922 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12923 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12924 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12925 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12926 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12927 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12928 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12929 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12930 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12931 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12932 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12933 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12934 		0x00000702,
12935 	};
12936 
12937 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12938 
12939 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12940 	    bwn_tab_sigsq_tbl);
12941 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12942 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12943 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12944 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12945 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12946 	    bwn_tab_pllfrac_tbl);
12947 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12948 	    bwn_tabl_iqlocal_tbl);
12949 	if (mac->mac_phy.rev == 0) {
12950 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12951 		    ofdmcckgain_r0);
12952 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12953 		    ofdmcckgain_r0);
12954 	} else {
12955 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12956 		    ofdmcckgain_r1);
12957 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12958 		    ofdmcckgain_r1);
12959 	}
12960 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12961 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12962 }
12963 
12964 static void
12965 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12966 {
12967 	struct bwn_softc *sc = mac->mac_sc;
12968 	int i;
12969 	static const uint16_t noisescale[] = {
12970 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12971 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12972 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12973 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12974 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12975 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12976 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12977 	};
12978 	static const uint32_t filterctl[] = {
12979 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12980 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12981 	};
12982 	static const uint32_t psctl[] = {
12983 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12984 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12985 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12986 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12987 	};
12988 	static const uint32_t gainidx[] = {
12989 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12990 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12991 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12992 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12993 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12994 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12995 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12996 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12997 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12998 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12999 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13000 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13001 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13002 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13003 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13004 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13005 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13006 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13007 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13008 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13009 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13010 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13011 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13012 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13013 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13014 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13015 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13016 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13017 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13018 		0x0000001a, 0x64ca55ad, 0x0000001a
13019 	};
13020 	static const uint16_t auxgainidx[] = {
13021 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13022 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13023 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13024 		0x0004, 0x0016
13025 	};
13026 	static const uint16_t swctl[] = {
13027 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13028 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13029 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13030 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13031 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13032 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13033 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13034 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13035 	};
13036 	static const uint8_t hf[] = {
13037 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13038 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13039 	};
13040 	static const uint32_t gainval[] = {
13041 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13042 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13043 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13044 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13045 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13046 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13047 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13048 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13049 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13050 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13051 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13052 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13053 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13054 		0x000000f1, 0x00000000, 0x00000000
13055 	};
13056 	static const uint16_t gain[] = {
13057 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13058 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13059 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13060 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13061 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13062 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13063 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13064 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13065 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13066 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13067 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13068 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13069 	};
13070 	static const uint32_t papdeps[] = {
13071 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13072 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13073 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13074 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13075 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13076 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13077 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13078 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13079 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13080 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13081 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13082 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13083 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13084 	};
13085 	static const uint32_t papdmult[] = {
13086 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13087 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13088 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13089 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13090 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13091 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13092 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13093 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13094 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13095 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13096 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13097 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13098 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13099 	};
13100 	static const uint32_t gainidx_a0[] = {
13101 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13102 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13103 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13104 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13105 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13106 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13107 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13108 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13109 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13110 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13111 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13112 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13113 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13114 	};
13115 	static const uint16_t auxgainidx_a0[] = {
13116 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13117 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13118 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13119 		0x0002, 0x0014
13120 	};
13121 	static const uint32_t gainval_a0[] = {
13122 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13123 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13124 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13125 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13126 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13127 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13128 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13129 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13130 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13131 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13132 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13133 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13134 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13135 		0x000000f7, 0x00000000, 0x00000000
13136 	};
13137 	static const uint16_t gain_a0[] = {
13138 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13139 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13140 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13141 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13142 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13143 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13144 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13145 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13146 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13147 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13148 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13149 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13150 	};
13151 
13152 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13153 
13154 	for (i = 0; i < 704; i++)
13155 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13156 
13157 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13158 	    bwn_tab_sigsq_tbl);
13159 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13160 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13161 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13162 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13163 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13164 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13165 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13166 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13167 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13168 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13169 	    bwn_tab_pllfrac_tbl);
13170 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13171 	    bwn_tabl_iqlocal_tbl);
13172 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13173 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13174 
13175 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13176 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13177 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13178 		    gainidx_a0);
13179 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13180 		    auxgainidx_a0);
13181 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13182 		    gainval_a0);
13183 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13184 	}
13185 }
13186 
13187 static void
13188 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13189 {
13190 	struct bwn_softc *sc = mac->mac_sc;
13191 	struct ifnet *ifp = sc->sc_ifp;
13192 	struct ieee80211com *ic = ifp->if_l2com;
13193 	static struct bwn_txgain_entry txgain_r2[] = {
13194 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13195 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13196 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13197 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13198 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13199 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13200 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13201 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13202 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13203 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13204 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13205 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13206 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13207 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13208 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13209 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13210 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13211 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13212 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13213 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13214 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13215 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13216 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13217 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13218 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13219 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13220 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13221 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13222 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13223 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13224 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13225 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13226 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13227 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13228 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13229 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13230 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13231 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13232 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13233 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13234 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13235 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13236 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13237 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13238 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13239 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13240 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13241 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13242 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13243 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13244 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13245 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13246 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13247 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13248 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13249 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13250 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13251 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13252 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13253 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13254 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13255 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13256 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13257 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13258 	};
13259 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13260 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13261 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13262 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13263 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13264 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13265 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13266 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13267 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13268 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13269 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13270 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13271 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13272 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13273 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13274 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13275 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13276 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13277 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13278 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13279 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13280 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13281 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13282 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13283 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13284 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13285 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13286 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13287 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13288 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13289 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13290 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13291 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13292 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13293 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13294 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13295 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13296 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13297 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13298 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13299 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13300 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13301 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13302 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13303 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13304 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13305 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13306 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13307 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13308 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13309 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13310 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13311 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13312 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13313 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13314 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13315 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13316 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13317 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13318 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13319 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13320 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13321 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13322 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13323 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13324 	};
13325 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13326 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13327 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13328 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13329 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13330 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13331 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13332 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13333 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13334 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13335 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13336 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13337 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13338 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13339 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13340 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13341 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13342 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13343 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13344 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13345 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13346 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13347 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13348 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13349 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13350 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13351 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13352 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13353 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13354 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13355 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13356 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13357 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13358 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13359 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13360 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13361 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13362 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13363 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13364 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13365 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13366 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13367 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13368 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13369 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13370 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13371 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13372 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13373 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13374 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13375 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13376 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13377 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13378 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13379 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13380 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13381 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13382 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13383 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13384 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13385 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13386 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13387 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13388 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13389 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13390 	};
13391 	static struct bwn_txgain_entry txgain_r0[] = {
13392 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13393 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13394 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13395 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13396 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13397 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13398 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13399 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13400 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13401 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13402 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13403 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13404 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13405 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13406 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13407 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13408 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13409 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13410 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13411 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13412 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13413 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13414 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13415 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13416 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13417 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13418 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13419 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13420 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13421 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13422 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13423 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13424 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13425 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13426 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13427 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13428 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13429 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13430 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13431 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13432 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13433 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13434 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13435 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13436 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13437 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13438 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13439 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13440 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13441 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13442 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13443 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13444 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13445 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13446 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13447 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13448 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13449 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13450 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13451 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13452 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13453 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13454 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13455 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13456 	};
13457 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13458 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13459 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13460 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13461 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13462 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13463 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13464 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13465 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13466 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13467 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13468 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13469 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13470 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13471 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13472 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13473 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13474 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13475 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13476 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13477 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13478 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13479 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13480 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13481 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13482 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13483 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13484 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13485 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13486 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13487 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13488 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13489 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13490 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13491 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13492 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13493 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13494 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13495 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13496 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13497 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13498 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13499 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13500 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13501 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13502 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13503 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13504 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13505 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13506 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13507 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13508 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13509 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13510 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13511 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13512 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13513 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13514 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13515 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13516 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13517 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13518 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13519 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13520 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13521 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13522 	};
13523 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13524 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13525 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13526 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13527 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13528 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13529 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13530 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13531 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13532 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13533 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13534 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13535 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13536 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13537 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13538 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13539 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13540 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13541 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13542 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13543 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13544 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13545 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13546 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13547 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13548 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13549 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13550 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13551 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13552 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13553 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13554 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13555 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13556 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13557 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13558 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13559 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13560 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13561 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13562 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13563 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13564 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13565 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13566 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13567 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13568 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13569 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13570 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13571 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13572 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13573 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13574 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13575 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13576 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13577 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13578 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13579 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13580 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13581 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13582 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13583 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13584 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13585 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13586 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13587 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13588 	};
13589 	static struct bwn_txgain_entry txgain_r1[] = {
13590 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13591 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13592 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13593 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13594 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13595 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13596 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13597 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13598 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13599 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13600 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13601 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13602 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13603 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13604 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13605 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13606 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13607 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13608 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13609 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13610 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13611 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13612 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13613 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13614 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13615 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13616 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13617 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13618 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13619 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13620 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13621 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13622 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13623 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13624 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13625 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13626 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13627 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13628 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13629 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13630 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13631 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13632 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13633 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13634 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13635 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13636 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13637 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13638 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13639 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13640 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13641 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13642 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13643 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13644 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13645 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13646 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13647 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13648 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13649 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13650 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13651 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13652 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13653 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13654 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13655 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13656 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13657 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13658 		{ 7, 11, 6, 0, 71 }
13659 	};
13660 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13661 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13662 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13663 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13664 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13665 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13666 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13667 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13668 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13669 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13670 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13671 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13672 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13673 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13674 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13675 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13676 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13677 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13678 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13679 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13680 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13681 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13682 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13683 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13684 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13685 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13686 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13687 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13688 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13689 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13690 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13691 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13692 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13693 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13694 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13695 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13696 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13697 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13698 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13699 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13700 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13701 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13702 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13703 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13704 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13705 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13706 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13707 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13708 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13709 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13710 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13711 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13712 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13713 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13714 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13715 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13716 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13717 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13718 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13719 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13720 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13721 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13722 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13723 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13724 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13725 	};
13726 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13727 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13728 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13729 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13730 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13731 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13732 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13733 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13734 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13735 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13736 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13737 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13738 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13739 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13740 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13741 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13742 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13743 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13744 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13745 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13746 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13747 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13748 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13749 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13750 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13751 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13752 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13753 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13754 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13755 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13756 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13757 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13758 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13759 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13760 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13761 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13762 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13763 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13764 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13765 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13766 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13767 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13768 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13769 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13770 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13771 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13772 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13773 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13774 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13775 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13776 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13777 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13778 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13779 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13780 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13781 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13782 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13783 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13784 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13785 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13786 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13787 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13788 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13789 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13790 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13791 	};
13792 
13793 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13794 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13795 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13796 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13797 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13798 			    txgain_2ghz_r2);
13799 		else
13800 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13801 			    txgain_5ghz_r2);
13802 		return;
13803 	}
13804 
13805 	if (mac->mac_phy.rev == 0) {
13806 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13807 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13808 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13809 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13810 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13811 			    txgain_2ghz_r0);
13812 		else
13813 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13814 			    txgain_5ghz_r0);
13815 		return;
13816 	}
13817 
13818 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13819 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13820 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13821 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13822 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13823 	else
13824 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13825 }
13826 
13827 static void
13828 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13829 {
13830 	uint32_t offset, type;
13831 
13832 	type = BWN_TAB_GETTYPE(typeoffset);
13833 	offset = BWN_TAB_GETOFFSET(typeoffset);
13834 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13835 
13836 	switch (type) {
13837 	case BWN_TAB_8BIT:
13838 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13839 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13840 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13841 		break;
13842 	case BWN_TAB_16BIT:
13843 		KASSERT(!(value & ~0xffff),
13844 		    ("%s:%d: fail", __func__, __LINE__));
13845 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13846 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13847 		break;
13848 	case BWN_TAB_32BIT:
13849 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13850 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13851 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13852 		break;
13853 	default:
13854 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13855 	}
13856 }
13857 
13858 static int
13859 bwn_phy_lp_loopback(struct bwn_mac *mac)
13860 {
13861 	struct bwn_phy_lp_iq_est ie;
13862 	int i, index = -1;
13863 	uint32_t tmp;
13864 
13865 	memset(&ie, 0, sizeof(ie));
13866 
13867 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13868 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13869 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13870 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13871 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13872 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13873 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13874 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13875 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13876 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13877 	for (i = 0; i < 32; i++) {
13878 		bwn_phy_lp_set_rxgain_idx(mac, i);
13879 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13880 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13881 			continue;
13882 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13883 		if ((tmp > 4000) && (tmp < 10000)) {
13884 			index = i;
13885 			break;
13886 		}
13887 	}
13888 	bwn_phy_lp_ddfs_turnoff(mac);
13889 	return (index);
13890 }
13891 
13892 static void
13893 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13894 {
13895 
13896 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13897 }
13898 
13899 static void
13900 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13901     int incr1, int incr2, int scale_idx)
13902 {
13903 
13904 	bwn_phy_lp_ddfs_turnoff(mac);
13905 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13906 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13907 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13908 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13909 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13910 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13911 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13912 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13913 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13914 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13915 }
13916 
13917 static uint8_t
13918 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13919     struct bwn_phy_lp_iq_est *ie)
13920 {
13921 	int i;
13922 
13923 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13924 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13925 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13926 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13927 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13928 
13929 	for (i = 0; i < 500; i++) {
13930 		if (!(BWN_PHY_READ(mac,
13931 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13932 			break;
13933 		DELAY(1000);
13934 	}
13935 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13936 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13937 		return 0;
13938 	}
13939 
13940 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13941 	ie->ie_iqprod <<= 16;
13942 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13943 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13944 	ie->ie_ipwr <<= 16;
13945 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13946 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13947 	ie->ie_qpwr <<= 16;
13948 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13949 
13950 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13951 	return 1;
13952 }
13953 
13954 static uint32_t
13955 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13956 {
13957 	uint32_t offset, type, value;
13958 
13959 	type = BWN_TAB_GETTYPE(typeoffset);
13960 	offset = BWN_TAB_GETOFFSET(typeoffset);
13961 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13962 
13963 	switch (type) {
13964 	case BWN_TAB_8BIT:
13965 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13966 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13967 		break;
13968 	case BWN_TAB_16BIT:
13969 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13970 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13971 		break;
13972 	case BWN_TAB_32BIT:
13973 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13974 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13975 		value <<= 16;
13976 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13977 		break;
13978 	default:
13979 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13980 		value = 0;
13981 	}
13982 
13983 	return (value);
13984 }
13985 
13986 static void
13987 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13988 {
13989 
13990 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13991 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13992 }
13993 
13994 static void
13995 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13996 {
13997 	uint16_t ctl;
13998 
13999 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14000 	ctl |= dac << 7;
14001 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14002 }
14003 
14004 static void
14005 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14006 {
14007 
14008 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14009 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14010 }
14011 
14012 static void
14013 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14014 {
14015 
14016 	if (mac->mac_phy.rev < 2)
14017 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14018 	else {
14019 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14020 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14021 	}
14022 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14023 }
14024 
14025 static uint16_t
14026 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14027 {
14028 
14029 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14030 }
14031 
14032 static uint8_t
14033 bwn_nbits(int32_t val)
14034 {
14035 	uint32_t tmp;
14036 	uint8_t nbits = 0;
14037 
14038 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14039 		nbits++;
14040 	return (nbits);
14041 }
14042 
14043 static void
14044 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14045     struct bwn_txgain_entry *table)
14046 {
14047 	int i;
14048 
14049 	for (i = offset; i < count; i++)
14050 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14051 }
14052 
14053 static void
14054 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14055     struct bwn_txgain_entry data)
14056 {
14057 
14058 	if (mac->mac_phy.rev >= 2)
14059 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14060 	else
14061 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14062 }
14063 
14064 static void
14065 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14066     struct bwn_txgain_entry te)
14067 {
14068 	struct bwn_softc *sc = mac->mac_sc;
14069 	struct ifnet *ifp = sc->sc_ifp;
14070 	struct ieee80211com *ic = ifp->if_l2com;
14071 	uint32_t tmp;
14072 
14073 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14074 
14075 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14076 	if (mac->mac_phy.rev >= 3) {
14077 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14078 		    (0x10 << 24) : (0x70 << 24));
14079 	} else {
14080 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14081 		    (0x14 << 24) : (0x7f << 24));
14082 	}
14083 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14084 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14085 	    te.te_bbmult << 20 | te.te_dac << 28);
14086 }
14087 
14088 static void
14089 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14090     struct bwn_txgain_entry te)
14091 {
14092 
14093 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14094 
14095 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14096 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14097 	    te.te_dac);
14098 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14099 }
14100 
14101 static void
14102 bwn_sysctl_node(struct bwn_softc *sc)
14103 {
14104 	struct bwn_mac *mac;
14105 	struct bwn_stats *stats;
14106 	struct sysctl_ctx_list *ctx;
14107 	struct sysctl_oid *tree;
14108 
14109 	/* XXX assume that count of MAC is only 1. */
14110 
14111 	if ((mac = sc->sc_curmac) == NULL)
14112 		return;
14113 	stats = &mac->mac_stats;
14114 
14115 	ctx = &sc->sc_sysctl_ctx;
14116 	tree = sc->sc_sysctl_tree;
14117 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
14118 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14119 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
14120 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14121 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
14122 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14123 
14124 #ifdef BWN_DEBUG
14125 	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
14126 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14127 #endif
14128 }
14129 
14130 static device_method_t bwn_methods[] = {
14131 	/* Device interface */
14132 	DEVMETHOD(device_probe,		bwn_probe),
14133 	DEVMETHOD(device_attach,	bwn_attach),
14134 	DEVMETHOD(device_detach,	bwn_detach),
14135 	DEVMETHOD(device_suspend,	bwn_suspend),
14136 	DEVMETHOD(device_resume,	bwn_resume),
14137 	DEVMETHOD_END
14138 };
14139 static driver_t bwn_driver = {
14140 	"bwn",
14141 	bwn_methods,
14142 	sizeof(struct bwn_softc)
14143 };
14144 static devclass_t bwn_devclass;
14145 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14146 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14147 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14148 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14149 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14150