xref: /freebsd/sys/dev/bwn/if_bwn.c (revision 87c1627502a5dde91e5284118eec8682b60f27a2)
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * The Broadcom Wireless LAN controller driver.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/module.h>
40 #include <sys/kernel.h>
41 #include <sys/endian.h>
42 #include <sys/errno.h>
43 #include <sys/firmware.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_arp.h>
56 #include <net/if_dl.h>
57 #include <net/if_llc.h>
58 #include <net/if_media.h>
59 #include <net/if_types.h>
60 
61 #include <dev/pci/pcivar.h>
62 #include <dev/pci/pcireg.h>
63 #include <dev/siba/siba_ids.h>
64 #include <dev/siba/sibareg.h>
65 #include <dev/siba/sibavar.h>
66 
67 #include <net80211/ieee80211_var.h>
68 #include <net80211/ieee80211_radiotap.h>
69 #include <net80211/ieee80211_regdomain.h>
70 #include <net80211/ieee80211_phy.h>
71 #include <net80211/ieee80211_ratectl.h>
72 
73 #include <dev/bwn/if_bwnreg.h>
74 #include <dev/bwn/if_bwnvar.h>
75 
76 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
77     "Broadcom driver parameters");
78 
79 /*
80  * Tunable & sysctl variables.
81  */
82 
83 #ifdef BWN_DEBUG
84 static	int bwn_debug = 0;
85 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
86     "Broadcom debugging printfs");
87 TUNABLE_INT("hw.bwn.debug", &bwn_debug);
88 enum {
89 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107 	BWN_DEBUG_ANY		= 0xffffffff
108 };
109 #define	DPRINTF(sc, m, fmt, ...) do {			\
110 	if (sc->sc_debug & (m))				\
111 		printf(fmt, __VA_ARGS__);		\
112 } while (0)
113 #else
114 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115 #endif
116 
117 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119     "uses Bad Frames Preemption");
120 static int	bwn_bluetooth = 1;
121 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122     "turns on Bluetooth Coexistence");
123 static int	bwn_hwpctl = 0;
124 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125     "uses H/W power control");
126 static int	bwn_msi_disable = 0;		/* MSI disabled  */
127 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128 static int	bwn_usedma = 1;
129 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130     "uses DMA");
131 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132 static int	bwn_wme = 1;
133 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134     "uses WME support");
135 
136 static int	bwn_attach_pre(struct bwn_softc *);
137 static int	bwn_attach_post(struct bwn_softc *);
138 static void	bwn_sprom_bugfixes(device_t);
139 static void	bwn_init(void *);
140 static int	bwn_init_locked(struct bwn_softc *);
141 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
142 static void	bwn_start(struct ifnet *);
143 static int	bwn_attach_core(struct bwn_mac *);
144 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145 static int	bwn_phy_getinfo(struct bwn_mac *, int);
146 static int	bwn_chiptest(struct bwn_mac *);
147 static int	bwn_setup_channels(struct bwn_mac *, int, int);
148 static int	bwn_phy_g_attach(struct bwn_mac *);
149 static void	bwn_phy_g_detach(struct bwn_mac *);
150 static void	bwn_phy_g_init_pre(struct bwn_mac *);
151 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152 static int	bwn_phy_g_init(struct bwn_mac *);
153 static void	bwn_phy_g_exit(struct bwn_mac *);
154 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156 		    uint16_t);
157 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159 		    uint16_t);
160 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165 static int	bwn_phy_g_im(struct bwn_mac *, int);
166 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168 static void	bwn_phy_g_task_15s(struct bwn_mac *);
169 static void	bwn_phy_g_task_60s(struct bwn_mac *);
170 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174 		    uint16_t);
175 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177 		    uint32_t);
178 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179 		    uint16_t);
180 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181 		    const struct bwn_channelinfo *, int);
182 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183 		    const struct ieee80211_bpf_params *);
184 static void	bwn_updateslot(struct ifnet *);
185 static void	bwn_update_promisc(struct ifnet *);
186 static void	bwn_wme_init(struct bwn_mac *);
187 static int	bwn_wme_update(struct ieee80211com *);
188 static void	bwn_wme_clear(struct bwn_softc *);
189 static void	bwn_wme_load(struct bwn_mac *);
190 static void	bwn_wme_loadparams(struct bwn_mac *,
191 		    const struct wmeParams *, uint16_t);
192 static void	bwn_scan_start(struct ieee80211com *);
193 static void	bwn_scan_end(struct ieee80211com *);
194 static void	bwn_set_channel(struct ieee80211com *);
195 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197 		    const uint8_t [IEEE80211_ADDR_LEN],
198 		    const uint8_t [IEEE80211_ADDR_LEN]);
199 static void	bwn_vap_delete(struct ieee80211vap *);
200 static void	bwn_stop(struct bwn_softc *, int);
201 static void	bwn_stop_locked(struct bwn_softc *, int);
202 static int	bwn_core_init(struct bwn_mac *);
203 static void	bwn_core_start(struct bwn_mac *);
204 static void	bwn_core_exit(struct bwn_mac *);
205 static void	bwn_bt_disable(struct bwn_mac *);
206 static int	bwn_chip_init(struct bwn_mac *);
207 static uint64_t	bwn_hf_read(struct bwn_mac *);
208 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
209 static void	bwn_set_txretry(struct bwn_mac *, int, int);
210 static void	bwn_rate_init(struct bwn_mac *);
211 static void	bwn_set_phytxctl(struct bwn_mac *);
212 static void	bwn_spu_setdelay(struct bwn_mac *, int);
213 static void	bwn_bt_enable(struct bwn_mac *);
214 static void	bwn_set_macaddr(struct bwn_mac *);
215 static void	bwn_crypt_init(struct bwn_mac *);
216 static void	bwn_chip_exit(struct bwn_mac *);
217 static int	bwn_fw_fillinfo(struct bwn_mac *);
218 static int	bwn_fw_loaducode(struct bwn_mac *);
219 static int	bwn_gpio_init(struct bwn_mac *);
220 static int	bwn_fw_loadinitvals(struct bwn_mac *);
221 static int	bwn_phy_init(struct bwn_mac *);
222 static void	bwn_set_txantenna(struct bwn_mac *, int);
223 static void	bwn_set_opmode(struct bwn_mac *);
224 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
225 static uint8_t	bwn_plcp_getcck(const uint8_t);
226 static uint8_t	bwn_plcp_getofdm(const uint8_t);
227 static void	bwn_pio_init(struct bwn_mac *);
228 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
229 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
230 		    int);
231 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
232 		    struct bwn_pio_rxqueue *, int);
233 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
234 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
235 		    uint16_t);
236 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
237 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
238 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
239 static void	bwn_pio_handle_txeof(struct bwn_mac *,
240 		    const struct bwn_txstatus *);
241 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
242 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
243 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
244 		    uint16_t);
245 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
246 		    uint32_t);
247 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
248 		    struct mbuf *);
249 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
250 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
251 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
252 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
253 		    uint16_t, uint32_t);
254 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
255 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
256 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
257 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
258 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
259 		    uint16_t, struct bwn_pio_txpkt **);
260 static void	bwn_dma_init(struct bwn_mac *);
261 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
262 static int	bwn_dma_mask2type(uint64_t);
263 static uint64_t	bwn_dma_mask(struct bwn_mac *);
264 static uint16_t	bwn_dma_base(int, int);
265 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
266 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
267 		    int, struct bwn_dmadesc_generic **,
268 		    struct bwn_dmadesc_meta **);
269 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
270 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
271 		    int, int);
272 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
273 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
274 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
275 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
276 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
277 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
278 		    int, struct bwn_dmadesc_generic **,
279 		    struct bwn_dmadesc_meta **);
280 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
281 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
282 		    int, int);
283 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
284 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
285 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
286 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
287 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
288 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
289 static void	bwn_dma_setup(struct bwn_dma_ring *);
290 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
291 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
292 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
293 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
294 static void	bwn_dma_rx(struct bwn_dma_ring *);
295 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
296 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
297 		    struct bwn_dmadesc_meta *);
298 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
299 static int	bwn_dma_gettype(struct bwn_mac *);
300 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
301 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
302 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
303 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
304 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
305 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
306 		    int);
307 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
308 		    bus_size_t, int);
309 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
310 static void	bwn_dma_handle_txeof(struct bwn_mac *,
311 		    const struct bwn_txstatus *);
312 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
313 		    struct mbuf *);
314 static int	bwn_dma_getslot(struct bwn_dma_ring *);
315 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
316 		    uint8_t);
317 static int	bwn_dma_attach(struct bwn_mac *);
318 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
319 		    int, int, int);
320 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
321 		    const struct bwn_txstatus *, uint16_t, int *);
322 static void	bwn_dma_free(struct bwn_mac *);
323 static void	bwn_phy_g_init_sub(struct bwn_mac *);
324 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
325 static void	bwn_phy_init_b5(struct bwn_mac *);
326 static void	bwn_phy_init_b6(struct bwn_mac *);
327 static void	bwn_phy_init_a(struct bwn_mac *);
328 static void	bwn_loopback_calcgain(struct bwn_mac *);
329 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
330 static void	bwn_lo_g_init(struct bwn_mac *);
331 static void	bwn_lo_g_adjust(struct bwn_mac *);
332 static void	bwn_lo_get_powervector(struct bwn_mac *);
333 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
334 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
335 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
336 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
337 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
338 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
339 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
340 		    uint8_t);
341 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
342 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
343 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
344 static void	bwn_wa_init(struct bwn_mac *);
345 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
346 		    uint16_t);
347 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
348 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
349 		    uint32_t);
350 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
351 		    uint16_t);
352 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
353 static void	bwn_mac_suspend(struct bwn_mac *);
354 static void	bwn_mac_enable(struct bwn_mac *);
355 static void	bwn_psctl(struct bwn_mac *, uint32_t);
356 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
357 static void	bwn_nrssi_offset(struct bwn_mac *);
358 static void	bwn_nrssi_threshold(struct bwn_mac *);
359 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
360 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
361 		    int16_t);
362 static void	bwn_set_original_gains(struct bwn_mac *);
363 static void	bwn_hwpctl_early_init(struct bwn_mac *);
364 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
365 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
366 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
367 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
368 		    const char *, struct bwn_fwfile *);
369 static void	bwn_release_firmware(struct bwn_mac *);
370 static void	bwn_do_release_fw(struct bwn_fwfile *);
371 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
372 static int	bwn_fwinitvals_write(struct bwn_mac *,
373 		    const struct bwn_fwinitvals *, size_t, size_t);
374 static int	bwn_switch_channel(struct bwn_mac *, int);
375 static uint16_t	bwn_ant2phy(int);
376 static void	bwn_mac_write_bssid(struct bwn_mac *);
377 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
378 		    const uint8_t *);
379 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
380 		    const uint8_t *, size_t, const uint8_t *);
381 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
382 		    const uint8_t *);
383 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
384 		    const uint8_t *);
385 static void	bwn_phy_exit(struct bwn_mac *);
386 static void	bwn_core_stop(struct bwn_mac *);
387 static int	bwn_switch_band(struct bwn_softc *,
388 		    struct ieee80211_channel *);
389 static void	bwn_phy_reset(struct bwn_mac *);
390 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
391 static void	bwn_set_pretbtt(struct bwn_mac *);
392 static int	bwn_intr(void *);
393 static void	bwn_intrtask(void *, int);
394 static void	bwn_restart(struct bwn_mac *, const char *);
395 static void	bwn_intr_ucode_debug(struct bwn_mac *);
396 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
397 static void	bwn_intr_atim_end(struct bwn_mac *);
398 static void	bwn_intr_beacon(struct bwn_mac *);
399 static void	bwn_intr_pmq(struct bwn_mac *);
400 static void	bwn_intr_noise(struct bwn_mac *);
401 static void	bwn_intr_txeof(struct bwn_mac *);
402 static void	bwn_hwreset(void *, int);
403 static void	bwn_handle_fwpanic(struct bwn_mac *);
404 static void	bwn_load_beacon0(struct bwn_mac *);
405 static void	bwn_load_beacon1(struct bwn_mac *);
406 static uint32_t	bwn_jssi_read(struct bwn_mac *);
407 static void	bwn_noise_gensample(struct bwn_mac *);
408 static void	bwn_handle_txeof(struct bwn_mac *,
409 		    const struct bwn_txstatus *);
410 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
411 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
412 static void	bwn_start_locked(struct ifnet *);
413 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
414 		    struct mbuf *);
415 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
416 static int	bwn_set_txhdr(struct bwn_mac *,
417 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
418 		    uint16_t);
419 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
420 		    const uint8_t);
421 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
422 static uint8_t	bwn_get_fbrate(uint8_t);
423 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
424 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
425 static void	bwn_phy_lock(struct bwn_mac *);
426 static void	bwn_phy_unlock(struct bwn_mac *);
427 static void	bwn_rf_lock(struct bwn_mac *);
428 static void	bwn_rf_unlock(struct bwn_mac *);
429 static void	bwn_txpwr(void *, int);
430 static void	bwn_tasks(void *);
431 static void	bwn_task_15s(struct bwn_mac *);
432 static void	bwn_task_30s(struct bwn_mac *);
433 static void	bwn_task_60s(struct bwn_mac *);
434 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
435 		    uint8_t);
436 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
437 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
438 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
439 		    int, int);
440 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
441 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
442 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
443 static void	bwn_watchdog(void *);
444 static void	bwn_dma_stop(struct bwn_mac *);
445 static void	bwn_pio_stop(struct bwn_mac *);
446 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
447 static void	bwn_led_attach(struct bwn_mac *);
448 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
449 static void	bwn_led_event(struct bwn_mac *, int);
450 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
451 static void	bwn_led_blink_next(void *);
452 static void	bwn_led_blink_end(void *);
453 static void	bwn_rfswitch(void *);
454 static void	bwn_rf_turnon(struct bwn_mac *);
455 static void	bwn_rf_turnoff(struct bwn_mac *);
456 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
457 static int	bwn_phy_lp_init(struct bwn_mac *);
458 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
459 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
460 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
461 		    uint16_t);
462 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
463 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
464 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
465 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
466 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
467 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
468 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
469 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
470 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
471 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
472 static void	bwn_phy_lp_calib(struct bwn_mac *);
473 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
474 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
475 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
476 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
477 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
478 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
479 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
480 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
481 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
482 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
483 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
484 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
485 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
486 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
487 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
488 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
489 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
490 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
491 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
492 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
493 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
494 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
495 		    const void *);
496 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
497 static struct bwn_txgain
498 		bwn_phy_lp_get_txgain(struct bwn_mac *);
499 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
500 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
501 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
502 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
503 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
504 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
505 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
506 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
507 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
508 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
509 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
510 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
511 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
512 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
513 static int	bwn_phy_lp_loopback(struct bwn_mac *);
514 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
515 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
516 		    int);
517 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
518 		    struct bwn_phy_lp_iq_est *);
519 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
520 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
521 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
522 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
523 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
524 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
525 static uint8_t	bwn_nbits(int32_t);
526 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
527 		    struct bwn_txgain_entry *);
528 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
529 		    struct bwn_txgain_entry);
530 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
531 		    struct bwn_txgain_entry);
532 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
533 		    struct bwn_txgain_entry);
534 static void	bwn_sysctl_node(struct bwn_softc *);
535 
536 static struct resource_spec bwn_res_spec_legacy[] = {
537 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
538 	{ -1,			0,		0 }
539 };
540 
541 static struct resource_spec bwn_res_spec_msi[] = {
542 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
543 	{ -1,			0,		0 }
544 };
545 
546 static const struct bwn_channelinfo bwn_chantable_bg = {
547 	.channels = {
548 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
549 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
550 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
551 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
552 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
553 	.nchannels = 14
554 };
555 
556 static const struct bwn_channelinfo bwn_chantable_a = {
557 	.channels = {
558 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
559 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
560 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
561 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
562 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
563 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
564 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
565 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
566 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
567 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
568 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
569 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
570 		{ 6080, 216, 30 } },
571 	.nchannels = 37
572 };
573 
574 static const struct bwn_channelinfo bwn_chantable_n = {
575 	.channels = {
576 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
577 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
578 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
579 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
580 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
581 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
582 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
583 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
584 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
585 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
586 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
587 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
588 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
589 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
590 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
591 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
592 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
593 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
594 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
595 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
596 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
597 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
598 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
599 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
600 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
601 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
602 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
603 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
604 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
605 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
606 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
607 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
608 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
609 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
610 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
611 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
612 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
613 	.nchannels = 110
614 };
615 
616 static const uint8_t bwn_b2063_chantable_data[33][12] = {
617 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
622 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
623 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
624 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
625 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
626 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
627 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
628 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
629 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
630 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
631 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
633 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
634 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
635 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
636 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
638 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
641 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
642 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
644 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
647 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
649 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
650 };
651 
652 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
653 	{ 1, 2412, bwn_b2063_chantable_data[0] },
654 	{ 2, 2417, bwn_b2063_chantable_data[0] },
655 	{ 3, 2422, bwn_b2063_chantable_data[0] },
656 	{ 4, 2427, bwn_b2063_chantable_data[1] },
657 	{ 5, 2432, bwn_b2063_chantable_data[1] },
658 	{ 6, 2437, bwn_b2063_chantable_data[1] },
659 	{ 7, 2442, bwn_b2063_chantable_data[1] },
660 	{ 8, 2447, bwn_b2063_chantable_data[1] },
661 	{ 9, 2452, bwn_b2063_chantable_data[2] },
662 	{ 10, 2457, bwn_b2063_chantable_data[2] },
663 	{ 11, 2462, bwn_b2063_chantable_data[3] },
664 	{ 12, 2467, bwn_b2063_chantable_data[3] },
665 	{ 13, 2472, bwn_b2063_chantable_data[3] },
666 	{ 14, 2484, bwn_b2063_chantable_data[4] },
667 	{ 34, 5170, bwn_b2063_chantable_data[5] },
668 	{ 36, 5180, bwn_b2063_chantable_data[6] },
669 	{ 38, 5190, bwn_b2063_chantable_data[7] },
670 	{ 40, 5200, bwn_b2063_chantable_data[8] },
671 	{ 42, 5210, bwn_b2063_chantable_data[9] },
672 	{ 44, 5220, bwn_b2063_chantable_data[10] },
673 	{ 46, 5230, bwn_b2063_chantable_data[11] },
674 	{ 48, 5240, bwn_b2063_chantable_data[12] },
675 	{ 52, 5260, bwn_b2063_chantable_data[13] },
676 	{ 56, 5280, bwn_b2063_chantable_data[14] },
677 	{ 60, 5300, bwn_b2063_chantable_data[14] },
678 	{ 64, 5320, bwn_b2063_chantable_data[15] },
679 	{ 100, 5500, bwn_b2063_chantable_data[16] },
680 	{ 104, 5520, bwn_b2063_chantable_data[17] },
681 	{ 108, 5540, bwn_b2063_chantable_data[18] },
682 	{ 112, 5560, bwn_b2063_chantable_data[19] },
683 	{ 116, 5580, bwn_b2063_chantable_data[20] },
684 	{ 120, 5600, bwn_b2063_chantable_data[21] },
685 	{ 124, 5620, bwn_b2063_chantable_data[21] },
686 	{ 128, 5640, bwn_b2063_chantable_data[22] },
687 	{ 132, 5660, bwn_b2063_chantable_data[22] },
688 	{ 136, 5680, bwn_b2063_chantable_data[22] },
689 	{ 140, 5700, bwn_b2063_chantable_data[23] },
690 	{ 149, 5745, bwn_b2063_chantable_data[23] },
691 	{ 153, 5765, bwn_b2063_chantable_data[23] },
692 	{ 157, 5785, bwn_b2063_chantable_data[23] },
693 	{ 161, 5805, bwn_b2063_chantable_data[23] },
694 	{ 165, 5825, bwn_b2063_chantable_data[23] },
695 	{ 184, 4920, bwn_b2063_chantable_data[24] },
696 	{ 188, 4940, bwn_b2063_chantable_data[25] },
697 	{ 192, 4960, bwn_b2063_chantable_data[26] },
698 	{ 196, 4980, bwn_b2063_chantable_data[27] },
699 	{ 200, 5000, bwn_b2063_chantable_data[28] },
700 	{ 204, 5020, bwn_b2063_chantable_data[29] },
701 	{ 208, 5040, bwn_b2063_chantable_data[30] },
702 	{ 212, 5060, bwn_b2063_chantable_data[31] },
703 	{ 216, 5080, bwn_b2063_chantable_data[32] }
704 };
705 
706 static const uint8_t bwn_b2062_chantable_data[22][12] = {
707 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
708 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
716 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
720 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
727 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
728 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
729 };
730 
731 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
732 	{ 1, 2412, bwn_b2062_chantable_data[0] },
733 	{ 2, 2417, bwn_b2062_chantable_data[0] },
734 	{ 3, 2422, bwn_b2062_chantable_data[0] },
735 	{ 4, 2427, bwn_b2062_chantable_data[0] },
736 	{ 5, 2432, bwn_b2062_chantable_data[0] },
737 	{ 6, 2437, bwn_b2062_chantable_data[0] },
738 	{ 7, 2442, bwn_b2062_chantable_data[0] },
739 	{ 8, 2447, bwn_b2062_chantable_data[0] },
740 	{ 9, 2452, bwn_b2062_chantable_data[0] },
741 	{ 10, 2457, bwn_b2062_chantable_data[0] },
742 	{ 11, 2462, bwn_b2062_chantable_data[0] },
743 	{ 12, 2467, bwn_b2062_chantable_data[0] },
744 	{ 13, 2472, bwn_b2062_chantable_data[0] },
745 	{ 14, 2484, bwn_b2062_chantable_data[0] },
746 	{ 34, 5170, bwn_b2062_chantable_data[1] },
747 	{ 38, 5190, bwn_b2062_chantable_data[2] },
748 	{ 42, 5210, bwn_b2062_chantable_data[2] },
749 	{ 46, 5230, bwn_b2062_chantable_data[3] },
750 	{ 36, 5180, bwn_b2062_chantable_data[4] },
751 	{ 40, 5200, bwn_b2062_chantable_data[5] },
752 	{ 44, 5220, bwn_b2062_chantable_data[6] },
753 	{ 48, 5240, bwn_b2062_chantable_data[3] },
754 	{ 52, 5260, bwn_b2062_chantable_data[3] },
755 	{ 56, 5280, bwn_b2062_chantable_data[3] },
756 	{ 60, 5300, bwn_b2062_chantable_data[7] },
757 	{ 64, 5320, bwn_b2062_chantable_data[8] },
758 	{ 100, 5500, bwn_b2062_chantable_data[9] },
759 	{ 104, 5520, bwn_b2062_chantable_data[10] },
760 	{ 108, 5540, bwn_b2062_chantable_data[10] },
761 	{ 112, 5560, bwn_b2062_chantable_data[10] },
762 	{ 116, 5580, bwn_b2062_chantable_data[11] },
763 	{ 120, 5600, bwn_b2062_chantable_data[12] },
764 	{ 124, 5620, bwn_b2062_chantable_data[12] },
765 	{ 128, 5640, bwn_b2062_chantable_data[12] },
766 	{ 132, 5660, bwn_b2062_chantable_data[12] },
767 	{ 136, 5680, bwn_b2062_chantable_data[12] },
768 	{ 140, 5700, bwn_b2062_chantable_data[12] },
769 	{ 149, 5745, bwn_b2062_chantable_data[12] },
770 	{ 153, 5765, bwn_b2062_chantable_data[12] },
771 	{ 157, 5785, bwn_b2062_chantable_data[12] },
772 	{ 161, 5805, bwn_b2062_chantable_data[12] },
773 	{ 165, 5825, bwn_b2062_chantable_data[12] },
774 	{ 184, 4920, bwn_b2062_chantable_data[13] },
775 	{ 188, 4940, bwn_b2062_chantable_data[14] },
776 	{ 192, 4960, bwn_b2062_chantable_data[15] },
777 	{ 196, 4980, bwn_b2062_chantable_data[16] },
778 	{ 200, 5000, bwn_b2062_chantable_data[17] },
779 	{ 204, 5020, bwn_b2062_chantable_data[18] },
780 	{ 208, 5040, bwn_b2062_chantable_data[19] },
781 	{ 212, 5060, bwn_b2062_chantable_data[20] },
782 	{ 216, 5080, bwn_b2062_chantable_data[21] }
783 };
784 
785 /* for LP PHY */
786 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
787 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
788 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
789 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
790 	{ 13, -66, 13 }, { 14, -66, 13 },
791 };
792 
793 /* for LP PHY */
794 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
795 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
796 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
797 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
798 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
799 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
800 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
801 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
802 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
803 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
804 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
805 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
806 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
807 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
808 };
809 
810 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
811 
812 static const uint8_t bwn_tab_sigsq_tbl[] = {
813 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
814 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
816 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
817 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
818 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
819 };
820 
821 static const uint8_t bwn_tab_pllfrac_tbl[] = {
822 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
823 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
824 };
825 
826 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
827 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
828 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
829 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
830 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
831 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
832 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
833 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
834 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
835 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
837 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
839 };
840 
841 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
842 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
843 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
844 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
845 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
846 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
847 
848 #define	VENDOR_LED_ACT(vendor)				\
849 {							\
850 	.vid = PCI_VENDOR_##vendor,			\
851 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
852 }
853 
854 static const struct {
855 	uint16_t	vid;
856 	uint8_t		led_act[BWN_LED_MAX];
857 } bwn_vendor_led_act[] = {
858 	VENDOR_LED_ACT(COMPAQ),
859 	VENDOR_LED_ACT(ASUSTEK)
860 };
861 
862 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
863 	{ BWN_VENDOR_LED_ACT_DEFAULT };
864 
865 #undef VENDOR_LED_ACT
866 
867 static const struct {
868 	int		on_dur;
869 	int		off_dur;
870 } bwn_led_duration[109] = {
871 	[0]	= { 400, 100 },
872 	[2]	= { 150, 75 },
873 	[4]	= { 90, 45 },
874 	[11]	= { 66, 34 },
875 	[12]	= { 53, 26 },
876 	[18]	= { 42, 21 },
877 	[22]	= { 35, 17 },
878 	[24]	= { 32, 16 },
879 	[36]	= { 21, 10 },
880 	[48]	= { 16, 8 },
881 	[72]	= { 11, 5 },
882 	[96]	= { 9, 4 },
883 	[108]	= { 7, 3 }
884 };
885 
886 static const uint16_t bwn_wme_shm_offsets[] = {
887 	[0] = BWN_WME_BESTEFFORT,
888 	[1] = BWN_WME_BACKGROUND,
889 	[2] = BWN_WME_VOICE,
890 	[3] = BWN_WME_VIDEO,
891 };
892 
893 static const struct siba_devid bwn_devs[] = {
894 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
895 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
896 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
897 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
898 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
899 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
900 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
901 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
902 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
903 };
904 
905 static int
906 bwn_probe(device_t dev)
907 {
908 	int i;
909 
910 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
911 		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
912 		    siba_get_device(dev) == bwn_devs[i].sd_device &&
913 		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
914 			return (BUS_PROBE_DEFAULT);
915 	}
916 
917 	return (ENXIO);
918 }
919 
920 static int
921 bwn_attach(device_t dev)
922 {
923 	struct bwn_mac *mac;
924 	struct bwn_softc *sc = device_get_softc(dev);
925 	int error, i, msic, reg;
926 
927 	sc->sc_dev = dev;
928 #ifdef BWN_DEBUG
929 	sc->sc_debug = bwn_debug;
930 #endif
931 
932 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
933 		error = bwn_attach_pre(sc);
934 		if (error != 0)
935 			return (error);
936 		bwn_sprom_bugfixes(dev);
937 		sc->sc_flags |= BWN_FLAG_ATTACHED;
938 	}
939 
940 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
941 		if (siba_get_pci_device(dev) != 0x4313 &&
942 		    siba_get_pci_device(dev) != 0x431a &&
943 		    siba_get_pci_device(dev) != 0x4321) {
944 			device_printf(sc->sc_dev,
945 			    "skip 802.11 cores\n");
946 			return (ENODEV);
947 		}
948 	}
949 
950 	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
951 	    M_NOWAIT | M_ZERO);
952 	if (mac == NULL)
953 		return (ENOMEM);
954 	mac->mac_sc = sc;
955 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
956 	if (bwn_bfp != 0)
957 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
958 
959 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
960 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
961 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
962 
963 	error = bwn_attach_core(mac);
964 	if (error)
965 		goto fail0;
966 	bwn_led_attach(mac);
967 
968 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
969 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
970 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
971 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
972 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
973 	    mac->mac_phy.rf_rev);
974 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
975 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
976 		    mac->mac_method.dma.dmatype);
977 	else
978 		device_printf(sc->sc_dev, "PIO\n");
979 
980 	/*
981 	 * setup PCI resources and interrupt.
982 	 */
983 	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
984 		msic = pci_msi_count(dev);
985 		if (bootverbose)
986 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
987 	} else
988 		msic = 0;
989 
990 	mac->mac_intr_spec = bwn_res_spec_legacy;
991 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
992 		if (pci_alloc_msi(dev, &msic) == 0) {
993 			device_printf(sc->sc_dev,
994 			    "Using %d MSI messages\n", msic);
995 			mac->mac_intr_spec = bwn_res_spec_msi;
996 			mac->mac_msi = 1;
997 		}
998 	}
999 
1000 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1001 	    mac->mac_res_irq);
1002 	if (error) {
1003 		device_printf(sc->sc_dev,
1004 		    "couldn't allocate IRQ resources (%d)\n", error);
1005 		goto fail1;
1006 	}
1007 
1008 	if (mac->mac_msi == 0)
1009 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1010 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1011 		    &mac->mac_intrhand[0]);
1012 	else {
1013 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1014 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1015 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1016 			    &mac->mac_intrhand[i]);
1017 			if (error != 0) {
1018 				device_printf(sc->sc_dev,
1019 				    "couldn't setup interrupt (%d)\n", error);
1020 				break;
1021 			}
1022 		}
1023 	}
1024 
1025 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1026 
1027 	/*
1028 	 * calls attach-post routine
1029 	 */
1030 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1031 		bwn_attach_post(sc);
1032 
1033 	return (0);
1034 fail1:
1035 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1036 		pci_release_msi(dev);
1037 fail0:
1038 	free(mac, M_DEVBUF);
1039 	return (error);
1040 }
1041 
1042 static int
1043 bwn_is_valid_ether_addr(uint8_t *addr)
1044 {
1045 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1046 
1047 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1048 		return (FALSE);
1049 
1050 	return (TRUE);
1051 }
1052 
1053 static int
1054 bwn_attach_post(struct bwn_softc *sc)
1055 {
1056 	struct ieee80211com *ic;
1057 	struct ifnet *ifp = sc->sc_ifp;
1058 
1059 	ic = ifp->if_l2com;
1060 	ic->ic_ifp = ifp;
1061 	/* XXX not right but it's not used anywhere important */
1062 	ic->ic_phytype = IEEE80211_T_OFDM;
1063 	ic->ic_opmode = IEEE80211_M_STA;
1064 	ic->ic_caps =
1065 		  IEEE80211_C_STA		/* station mode supported */
1066 		| IEEE80211_C_MONITOR		/* monitor mode */
1067 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1068 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1069 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1070 		| IEEE80211_C_WME		/* WME/WMM supported */
1071 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1072 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1073 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1074 		;
1075 
1076 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1077 
1078 	/* call MI attach routine. */
1079 	ieee80211_ifattach(ic,
1080 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1081 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1082 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1083 
1084 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1085 
1086 	/* override default methods */
1087 	ic->ic_raw_xmit = bwn_raw_xmit;
1088 	ic->ic_updateslot = bwn_updateslot;
1089 	ic->ic_update_promisc = bwn_update_promisc;
1090 	ic->ic_wme.wme_update = bwn_wme_update;
1091 
1092 	ic->ic_scan_start = bwn_scan_start;
1093 	ic->ic_scan_end = bwn_scan_end;
1094 	ic->ic_set_channel = bwn_set_channel;
1095 
1096 	ic->ic_vap_create = bwn_vap_create;
1097 	ic->ic_vap_delete = bwn_vap_delete;
1098 
1099 	ieee80211_radiotap_attach(ic,
1100 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1101 	    BWN_TX_RADIOTAP_PRESENT,
1102 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1103 	    BWN_RX_RADIOTAP_PRESENT);
1104 
1105 	bwn_sysctl_node(sc);
1106 
1107 	if (bootverbose)
1108 		ieee80211_announce(ic);
1109 	return (0);
1110 }
1111 
1112 static void
1113 bwn_phy_detach(struct bwn_mac *mac)
1114 {
1115 
1116 	if (mac->mac_phy.detach != NULL)
1117 		mac->mac_phy.detach(mac);
1118 }
1119 
1120 static int
1121 bwn_detach(device_t dev)
1122 {
1123 	struct bwn_softc *sc = device_get_softc(dev);
1124 	struct bwn_mac *mac = sc->sc_curmac;
1125 	struct ifnet *ifp = sc->sc_ifp;
1126 	struct ieee80211com *ic = ifp->if_l2com;
1127 	int i;
1128 
1129 	sc->sc_flags |= BWN_FLAG_INVALID;
1130 
1131 	if (device_is_attached(sc->sc_dev)) {
1132 		bwn_stop(sc, 1);
1133 		bwn_dma_free(mac);
1134 		callout_drain(&sc->sc_led_blink_ch);
1135 		callout_drain(&sc->sc_rfswitch_ch);
1136 		callout_drain(&sc->sc_task_ch);
1137 		callout_drain(&sc->sc_watchdog_ch);
1138 		bwn_phy_detach(mac);
1139 		if (ifp != NULL) {
1140 			ieee80211_draintask(ic, &mac->mac_hwreset);
1141 			ieee80211_draintask(ic, &mac->mac_txpower);
1142 			ieee80211_ifdetach(ic);
1143 			if_free(ifp);
1144 		}
1145 	}
1146 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1147 	taskqueue_free(sc->sc_tq);
1148 
1149 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1150 		if (mac->mac_intrhand[i] != NULL) {
1151 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1152 			    mac->mac_intrhand[i]);
1153 			mac->mac_intrhand[i] = NULL;
1154 		}
1155 	}
1156 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1157 	if (mac->mac_msi != 0)
1158 		pci_release_msi(dev);
1159 
1160 	BWN_LOCK_DESTROY(sc);
1161 	return (0);
1162 }
1163 
1164 static int
1165 bwn_attach_pre(struct bwn_softc *sc)
1166 {
1167 	struct ifnet *ifp;
1168 	int error = 0;
1169 
1170 	BWN_LOCK_INIT(sc);
1171 	TAILQ_INIT(&sc->sc_maclist);
1172 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1173 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1174 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1175 
1176 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1177 		taskqueue_thread_enqueue, &sc->sc_tq);
1178 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1179 		"%s taskq", device_get_nameunit(sc->sc_dev));
1180 
1181 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1182 	if (ifp == NULL) {
1183 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1184 		error = ENOSPC;
1185 		goto fail;
1186 	}
1187 
1188 	/* set these up early for if_printf use */
1189 	if_initname(ifp, device_get_name(sc->sc_dev),
1190 	    device_get_unit(sc->sc_dev));
1191 
1192 	ifp->if_softc = sc;
1193 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1194 	ifp->if_init = bwn_init;
1195 	ifp->if_ioctl = bwn_ioctl;
1196 	ifp->if_start = bwn_start;
1197 	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1198 	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1199 	IFQ_SET_READY(&ifp->if_snd);
1200 
1201 	return (0);
1202 
1203 fail:	BWN_LOCK_DESTROY(sc);
1204 	return (error);
1205 }
1206 
1207 static void
1208 bwn_sprom_bugfixes(device_t dev)
1209 {
1210 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1211 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1212 	 (siba_get_pci_device(dev) == _device) &&			\
1213 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1214 	 (siba_get_pci_subdevice(dev) == _subdevice))
1215 
1216 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1217 	    siba_get_pci_subdevice(dev) == 0x4e &&
1218 	    siba_get_pci_revid(dev) > 0x40)
1219 		siba_sprom_set_bf_lo(dev,
1220 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1221 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1222 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1223 		siba_sprom_set_bf_lo(dev,
1224 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1225 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1226 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1227 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1228 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1229 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1230 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1231 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1232 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1233 			siba_sprom_set_bf_lo(dev,
1234 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1235 	}
1236 #undef	BWN_ISDEV
1237 }
1238 
1239 static int
1240 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1241 {
1242 #define	IS_RUNNING(ifp) \
1243 	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1244 	struct bwn_softc *sc = ifp->if_softc;
1245 	struct ieee80211com *ic = ifp->if_l2com;
1246 	struct ifreq *ifr = (struct ifreq *)data;
1247 	int error = 0, startall;
1248 
1249 	switch (cmd) {
1250 	case SIOCSIFFLAGS:
1251 		startall = 0;
1252 		if (IS_RUNNING(ifp)) {
1253 			bwn_update_promisc(ifp);
1254 		} else if (ifp->if_flags & IFF_UP) {
1255 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1256 				bwn_init(sc);
1257 				startall = 1;
1258 			}
1259 		} else
1260 			bwn_stop(sc, 1);
1261 		if (startall)
1262 			ieee80211_start_all(ic);
1263 		break;
1264 	case SIOCGIFMEDIA:
1265 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1266 		break;
1267 	case SIOCGIFADDR:
1268 		error = ether_ioctl(ifp, cmd, data);
1269 		break;
1270 	default:
1271 		error = EINVAL;
1272 		break;
1273 	}
1274 	return (error);
1275 }
1276 
1277 static void
1278 bwn_start(struct ifnet *ifp)
1279 {
1280 	struct bwn_softc *sc = ifp->if_softc;
1281 
1282 	BWN_LOCK(sc);
1283 	bwn_start_locked(ifp);
1284 	BWN_UNLOCK(sc);
1285 }
1286 
1287 static void
1288 bwn_start_locked(struct ifnet *ifp)
1289 {
1290 	struct bwn_softc *sc = ifp->if_softc;
1291 	struct bwn_mac *mac = sc->sc_curmac;
1292 	struct ieee80211_frame *wh;
1293 	struct ieee80211_node *ni;
1294 	struct ieee80211_key *k;
1295 	struct mbuf *m;
1296 
1297 	BWN_ASSERT_LOCKED(sc);
1298 
1299 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1300 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1301 		return;
1302 
1303 	for (;;) {
1304 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1305 		if (m == NULL)
1306 			break;
1307 
1308 		if (bwn_tx_isfull(sc, m))
1309 			break;
1310 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1311 		if (ni == NULL) {
1312 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1313 			m_freem(m);
1314 			ifp->if_oerrors++;
1315 			continue;
1316 		}
1317 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1318 		wh = mtod(m, struct ieee80211_frame *);
1319 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1320 			k = ieee80211_crypto_encap(ni, m);
1321 			if (k == NULL) {
1322 				ieee80211_free_node(ni);
1323 				m_freem(m);
1324 				ifp->if_oerrors++;
1325 				continue;
1326 			}
1327 		}
1328 		wh = NULL;	/* Catch any invalid use */
1329 
1330 		if (bwn_tx_start(sc, ni, m) != 0) {
1331 			if (ni != NULL)
1332 				ieee80211_free_node(ni);
1333 			ifp->if_oerrors++;
1334 			continue;
1335 		}
1336 
1337 		sc->sc_watchdog_timer = 5;
1338 	}
1339 }
1340 
1341 static int
1342 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1343 {
1344 	struct bwn_dma_ring *dr;
1345 	struct bwn_mac *mac = sc->sc_curmac;
1346 	struct bwn_pio_txqueue *tq;
1347 	struct ifnet *ifp = sc->sc_ifp;
1348 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1349 
1350 	BWN_ASSERT_LOCKED(sc);
1351 
1352 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1353 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1354 		if (dr->dr_stop == 1 ||
1355 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1356 			dr->dr_stop = 1;
1357 			goto full;
1358 		}
1359 	} else {
1360 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1361 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1362 		    pktlen > (tq->tq_size - tq->tq_used)) {
1363 			tq->tq_stop = 1;
1364 			goto full;
1365 		}
1366 	}
1367 	return (0);
1368 full:
1369 	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1370 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1371 	return (1);
1372 }
1373 
1374 static int
1375 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1376 {
1377 	struct bwn_mac *mac = sc->sc_curmac;
1378 	int error;
1379 
1380 	BWN_ASSERT_LOCKED(sc);
1381 
1382 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1383 		m_freem(m);
1384 		return (ENXIO);
1385 	}
1386 
1387 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1388 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1389 	if (error) {
1390 		m_freem(m);
1391 		return (error);
1392 	}
1393 	return (0);
1394 }
1395 
1396 static int
1397 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1398 {
1399 	struct bwn_pio_txpkt *tp;
1400 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1401 	struct bwn_softc *sc = mac->mac_sc;
1402 	struct bwn_txhdr txhdr;
1403 	struct mbuf *m_new;
1404 	uint32_t ctl32;
1405 	int error;
1406 	uint16_t ctl16;
1407 
1408 	BWN_ASSERT_LOCKED(sc);
1409 
1410 	/* XXX TODO send packets after DTIM */
1411 
1412 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1413 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1414 	tp->tp_ni = ni;
1415 	tp->tp_m = m;
1416 
1417 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1418 	if (error) {
1419 		device_printf(sc->sc_dev, "tx fail\n");
1420 		return (error);
1421 	}
1422 
1423 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1424 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1425 	tq->tq_free--;
1426 
1427 	if (siba_get_revid(sc->sc_dev) >= 8) {
1428 		/*
1429 		 * XXX please removes m_defrag(9)
1430 		 */
1431 		m_new = m_defrag(m, M_NOWAIT);
1432 		if (m_new == NULL) {
1433 			device_printf(sc->sc_dev,
1434 			    "%s: can't defrag TX buffer\n",
1435 			    __func__);
1436 			return (ENOBUFS);
1437 		}
1438 		if (m_new->m_next != NULL)
1439 			device_printf(sc->sc_dev,
1440 			    "TODO: fragmented packets for PIO\n");
1441 		tp->tp_m = m_new;
1442 
1443 		/* send HEADER */
1444 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1445 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1446 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1447 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1448 		/* send BODY */
1449 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1450 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1451 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1452 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1453 	} else {
1454 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1455 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1456 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1457 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1458 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1459 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1460 		    ctl16 | BWN_PIO_TXCTL_EOF);
1461 	}
1462 
1463 	return (0);
1464 }
1465 
1466 static struct bwn_pio_txqueue *
1467 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1468 {
1469 
1470 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1471 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1472 
1473 	switch (prio) {
1474 	case 0:
1475 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1476 	case 1:
1477 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1478 	case 2:
1479 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1480 	case 3:
1481 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1482 	}
1483 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1484 	return (NULL);
1485 }
1486 
1487 static int
1488 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1489 {
1490 #define	BWN_GET_TXHDRCACHE(slot)					\
1491 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1492 	struct bwn_dma *dma = &mac->mac_method.dma;
1493 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1494 	struct bwn_dmadesc_generic *desc;
1495 	struct bwn_dmadesc_meta *mt;
1496 	struct bwn_softc *sc = mac->mac_sc;
1497 	struct ifnet *ifp = sc->sc_ifp;
1498 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1499 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1500 
1501 	BWN_ASSERT_LOCKED(sc);
1502 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1503 
1504 	/* XXX send after DTIM */
1505 
1506 	slot = bwn_dma_getslot(dr);
1507 	dr->getdesc(dr, slot, &desc, &mt);
1508 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1509 	    ("%s:%d: fail", __func__, __LINE__));
1510 
1511 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1512 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1513 	    BWN_DMA_COOKIE(dr, slot));
1514 	if (error)
1515 		goto fail;
1516 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1517 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1518 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1519 	if (error) {
1520 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1521 		    __func__, error);
1522 		goto fail;
1523 	}
1524 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1525 	    BUS_DMASYNC_PREWRITE);
1526 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1527 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1528 	    BUS_DMASYNC_PREWRITE);
1529 
1530 	slot = bwn_dma_getslot(dr);
1531 	dr->getdesc(dr, slot, &desc, &mt);
1532 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1533 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1534 	mt->mt_m = m;
1535 	mt->mt_ni = ni;
1536 
1537 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1538 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1539 	if (error && error != EFBIG) {
1540 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1541 		    __func__, error);
1542 		goto fail;
1543 	}
1544 	if (error) {    /* error == EFBIG */
1545 		struct mbuf *m_new;
1546 
1547 		m_new = m_defrag(m, M_NOWAIT);
1548 		if (m_new == NULL) {
1549 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1550 			    __func__);
1551 			error = ENOBUFS;
1552 			goto fail;
1553 		} else {
1554 			m = m_new;
1555 		}
1556 
1557 		mt->mt_m = m;
1558 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1559 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1560 		if (error) {
1561 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1562 			    __func__, error);
1563 			goto fail;
1564 		}
1565 	}
1566 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1567 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1568 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1569 	    BUS_DMASYNC_PREWRITE);
1570 
1571 	/* XXX send after DTIM */
1572 
1573 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1574 	return (0);
1575 fail:
1576 	dr->dr_curslot = backup[0];
1577 	dr->dr_usedslot = backup[1];
1578 	return (error);
1579 #undef BWN_GET_TXHDRCACHE
1580 }
1581 
1582 static void
1583 bwn_watchdog(void *arg)
1584 {
1585 	struct bwn_softc *sc = arg;
1586 	struct ifnet *ifp = sc->sc_ifp;
1587 
1588 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1589 		if_printf(ifp, "device timeout\n");
1590 		ifp->if_oerrors++;
1591 	}
1592 	callout_schedule(&sc->sc_watchdog_ch, hz);
1593 }
1594 
1595 static int
1596 bwn_attach_core(struct bwn_mac *mac)
1597 {
1598 	struct bwn_softc *sc = mac->mac_sc;
1599 	int error, have_bg = 0, have_a = 0;
1600 	uint32_t high;
1601 
1602 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1603 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1604 
1605 	siba_powerup(sc->sc_dev, 0);
1606 
1607 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1608 	bwn_reset_core(mac,
1609 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1610 	error = bwn_phy_getinfo(mac, high);
1611 	if (error)
1612 		goto fail;
1613 
1614 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1615 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1616 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1617 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1618 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1619 		have_a = have_bg = 0;
1620 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1621 			have_a = 1;
1622 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1623 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1624 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1625 			have_bg = 1;
1626 		else
1627 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1628 			    mac->mac_phy.type));
1629 	}
1630 	/* XXX turns off PHY A because it's not supported */
1631 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1632 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1633 		have_a = 0;
1634 		have_bg = 1;
1635 	}
1636 
1637 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1638 		mac->mac_phy.attach = bwn_phy_g_attach;
1639 		mac->mac_phy.detach = bwn_phy_g_detach;
1640 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1641 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1642 		mac->mac_phy.init = bwn_phy_g_init;
1643 		mac->mac_phy.exit = bwn_phy_g_exit;
1644 		mac->mac_phy.phy_read = bwn_phy_g_read;
1645 		mac->mac_phy.phy_write = bwn_phy_g_write;
1646 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1647 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1648 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1649 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1650 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1651 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1652 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1653 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1654 		mac->mac_phy.set_im = bwn_phy_g_im;
1655 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1656 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1657 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1658 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1659 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1660 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1661 		mac->mac_phy.init = bwn_phy_lp_init;
1662 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1663 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1664 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1665 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1666 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1667 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1668 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1669 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1670 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1671 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1672 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1673 	} else {
1674 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1675 		    mac->mac_phy.type);
1676 		error = ENXIO;
1677 		goto fail;
1678 	}
1679 
1680 	mac->mac_phy.gmode = have_bg;
1681 	if (mac->mac_phy.attach != NULL) {
1682 		error = mac->mac_phy.attach(mac);
1683 		if (error) {
1684 			device_printf(sc->sc_dev, "failed\n");
1685 			goto fail;
1686 		}
1687 	}
1688 
1689 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1690 
1691 	error = bwn_chiptest(mac);
1692 	if (error)
1693 		goto fail;
1694 	error = bwn_setup_channels(mac, have_bg, have_a);
1695 	if (error) {
1696 		device_printf(sc->sc_dev, "failed to setup channels\n");
1697 		goto fail;
1698 	}
1699 
1700 	if (sc->sc_curmac == NULL)
1701 		sc->sc_curmac = mac;
1702 
1703 	error = bwn_dma_attach(mac);
1704 	if (error != 0) {
1705 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1706 		goto fail;
1707 	}
1708 
1709 	mac->mac_phy.switch_analog(mac, 0);
1710 
1711 	siba_dev_down(sc->sc_dev, 0);
1712 fail:
1713 	siba_powerdown(sc->sc_dev);
1714 	return (error);
1715 }
1716 
1717 static void
1718 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1719 {
1720 	struct bwn_softc *sc = mac->mac_sc;
1721 	uint32_t low, ctl;
1722 
1723 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1724 
1725 	siba_dev_up(sc->sc_dev, flags);
1726 	DELAY(2000);
1727 
1728 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1729 	    ~BWN_TGSLOW_PHYRESET;
1730 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1731 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1732 	DELAY(1000);
1733 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1734 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1735 	DELAY(1000);
1736 
1737 	if (mac->mac_phy.switch_analog != NULL)
1738 		mac->mac_phy.switch_analog(mac, 1);
1739 
1740 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1741 	if (flags & BWN_TGSLOW_SUPPORT_G)
1742 		ctl |= BWN_MACCTL_GMODE;
1743 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1744 }
1745 
1746 static int
1747 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1748 {
1749 	struct bwn_phy *phy = &mac->mac_phy;
1750 	struct bwn_softc *sc = mac->mac_sc;
1751 	uint32_t tmp;
1752 
1753 	/* PHY */
1754 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1755 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1756 	phy->rf_on = 1;
1757 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1758 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1759 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1760 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1761 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1762 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1763 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1764 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1765 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1766 		goto unsupphy;
1767 
1768 	/* RADIO */
1769 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1770 		if (siba_get_chiprev(sc->sc_dev) == 0)
1771 			tmp = 0x3205017f;
1772 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1773 			tmp = 0x4205017f;
1774 		else
1775 			tmp = 0x5205017f;
1776 	} else {
1777 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1778 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1779 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1780 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1781 	}
1782 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1783 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1784 	phy->rf_manuf = (tmp & 0x00000fff);
1785 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1786 		goto unsupradio;
1787 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1788 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1789 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1790 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1791 	    (phy->type == BWN_PHYTYPE_N &&
1792 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1793 	    (phy->type == BWN_PHYTYPE_LP &&
1794 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1795 		goto unsupradio;
1796 
1797 	return (0);
1798 unsupphy:
1799 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1800 	    "analog %#x)\n",
1801 	    phy->type, phy->rev, phy->analog);
1802 	return (ENXIO);
1803 unsupradio:
1804 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1805 	    "rev %#x)\n",
1806 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1807 	return (ENXIO);
1808 }
1809 
1810 static int
1811 bwn_chiptest(struct bwn_mac *mac)
1812 {
1813 #define	TESTVAL0	0x55aaaa55
1814 #define	TESTVAL1	0xaa5555aa
1815 	struct bwn_softc *sc = mac->mac_sc;
1816 	uint32_t v, backup;
1817 
1818 	BWN_LOCK(sc);
1819 
1820 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1821 
1822 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1823 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1824 		goto error;
1825 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1826 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1827 		goto error;
1828 
1829 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1830 
1831 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1832 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1833 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1834 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1835 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1836 			goto error;
1837 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1838 			goto error;
1839 	}
1840 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1841 
1842 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1843 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1844 		goto error;
1845 
1846 	BWN_UNLOCK(sc);
1847 	return (0);
1848 error:
1849 	BWN_UNLOCK(sc);
1850 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1851 	return (ENODEV);
1852 }
1853 
1854 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1855 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1856 
1857 static int
1858 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1859 {
1860 	struct bwn_softc *sc = mac->mac_sc;
1861 	struct ifnet *ifp = sc->sc_ifp;
1862 	struct ieee80211com *ic = ifp->if_l2com;
1863 
1864 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1865 	ic->ic_nchans = 0;
1866 
1867 	if (have_bg)
1868 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1869 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1870 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1871 		if (have_a)
1872 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1873 			    &ic->ic_nchans, &bwn_chantable_n,
1874 			    IEEE80211_CHAN_HTA);
1875 	} else {
1876 		if (have_a)
1877 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1878 			    &ic->ic_nchans, &bwn_chantable_a,
1879 			    IEEE80211_CHAN_A);
1880 	}
1881 
1882 	mac->mac_phy.supports_2ghz = have_bg;
1883 	mac->mac_phy.supports_5ghz = have_a;
1884 
1885 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1886 }
1887 
1888 static uint32_t
1889 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1890 {
1891 	uint32_t ret;
1892 
1893 	BWN_ASSERT_LOCKED(mac->mac_sc);
1894 
1895 	if (way == BWN_SHARED) {
1896 		KASSERT((offset & 0x0001) == 0,
1897 		    ("%s:%d warn", __func__, __LINE__));
1898 		if (offset & 0x0003) {
1899 			bwn_shm_ctlword(mac, way, offset >> 2);
1900 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1901 			ret <<= 16;
1902 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1903 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1904 			goto out;
1905 		}
1906 		offset >>= 2;
1907 	}
1908 	bwn_shm_ctlword(mac, way, offset);
1909 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1910 out:
1911 	return (ret);
1912 }
1913 
1914 static uint16_t
1915 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1916 {
1917 	uint16_t ret;
1918 
1919 	BWN_ASSERT_LOCKED(mac->mac_sc);
1920 
1921 	if (way == BWN_SHARED) {
1922 		KASSERT((offset & 0x0001) == 0,
1923 		    ("%s:%d warn", __func__, __LINE__));
1924 		if (offset & 0x0003) {
1925 			bwn_shm_ctlword(mac, way, offset >> 2);
1926 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1927 			goto out;
1928 		}
1929 		offset >>= 2;
1930 	}
1931 	bwn_shm_ctlword(mac, way, offset);
1932 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1933 out:
1934 
1935 	return (ret);
1936 }
1937 
1938 static void
1939 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1940     uint16_t offset)
1941 {
1942 	uint32_t control;
1943 
1944 	control = way;
1945 	control <<= 16;
1946 	control |= offset;
1947 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1948 }
1949 
1950 static void
1951 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1952     uint32_t value)
1953 {
1954 	BWN_ASSERT_LOCKED(mac->mac_sc);
1955 
1956 	if (way == BWN_SHARED) {
1957 		KASSERT((offset & 0x0001) == 0,
1958 		    ("%s:%d warn", __func__, __LINE__));
1959 		if (offset & 0x0003) {
1960 			bwn_shm_ctlword(mac, way, offset >> 2);
1961 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1962 				    (value >> 16) & 0xffff);
1963 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1964 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1965 			return;
1966 		}
1967 		offset >>= 2;
1968 	}
1969 	bwn_shm_ctlword(mac, way, offset);
1970 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1971 }
1972 
1973 static void
1974 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1975     uint16_t value)
1976 {
1977 	BWN_ASSERT_LOCKED(mac->mac_sc);
1978 
1979 	if (way == BWN_SHARED) {
1980 		KASSERT((offset & 0x0001) == 0,
1981 		    ("%s:%d warn", __func__, __LINE__));
1982 		if (offset & 0x0003) {
1983 			bwn_shm_ctlword(mac, way, offset >> 2);
1984 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1985 			return;
1986 		}
1987 		offset >>= 2;
1988 	}
1989 	bwn_shm_ctlword(mac, way, offset);
1990 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1991 }
1992 
1993 static void
1994 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1995     int txpow)
1996 {
1997 
1998 	c->ic_freq = freq;
1999 	c->ic_flags = flags;
2000 	c->ic_ieee = ieee;
2001 	c->ic_minpower = 0;
2002 	c->ic_maxpower = 2 * txpow;
2003 	c->ic_maxregpower = txpow;
2004 }
2005 
2006 static void
2007 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2008     const struct bwn_channelinfo *ci, int flags)
2009 {
2010 	struct ieee80211_channel *c;
2011 	int i;
2012 
2013 	c = &chans[*nchans];
2014 
2015 	for (i = 0; i < ci->nchannels; i++) {
2016 		const struct bwn_channel *hc;
2017 
2018 		hc = &ci->channels[i];
2019 		if (*nchans >= maxchans)
2020 			break;
2021 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2022 		c++, (*nchans)++;
2023 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2024 			/* g channel have a separate b-only entry */
2025 			if (*nchans >= maxchans)
2026 				break;
2027 			c[0] = c[-1];
2028 			c[-1].ic_flags = IEEE80211_CHAN_B;
2029 			c++, (*nchans)++;
2030 		}
2031 		if (flags == IEEE80211_CHAN_HTG) {
2032 			/* HT g channel have a separate g-only entry */
2033 			if (*nchans >= maxchans)
2034 				break;
2035 			c[-1].ic_flags = IEEE80211_CHAN_G;
2036 			c[0] = c[-1];
2037 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2038 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2039 			c++, (*nchans)++;
2040 		}
2041 		if (flags == IEEE80211_CHAN_HTA) {
2042 			/* HT a channel have a separate a-only entry */
2043 			if (*nchans >= maxchans)
2044 				break;
2045 			c[-1].ic_flags = IEEE80211_CHAN_A;
2046 			c[0] = c[-1];
2047 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2048 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2049 			c++, (*nchans)++;
2050 		}
2051 	}
2052 }
2053 
2054 static int
2055 bwn_phy_g_attach(struct bwn_mac *mac)
2056 {
2057 	struct bwn_softc *sc = mac->mac_sc;
2058 	struct bwn_phy *phy = &mac->mac_phy;
2059 	struct bwn_phy_g *pg = &phy->phy_g;
2060 	unsigned int i;
2061 	int16_t pab0, pab1, pab2;
2062 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2063 	int8_t bg;
2064 
2065 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2066 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2067 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2068 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2069 
2070 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2071 		device_printf(sc->sc_dev, "not supported anymore\n");
2072 
2073 	pg->pg_flags = 0;
2074 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2075 	    pab2 == -1) {
2076 		pg->pg_idletssi = 52;
2077 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2078 		return (0);
2079 	}
2080 
2081 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2082 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2083 	if (pg->pg_tssi2dbm == NULL) {
2084 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2085 		return (ENOMEM);
2086 	}
2087 	for (i = 0; i < 64; i++) {
2088 		int32_t m1, m2, f, q, delta;
2089 		int8_t j = 0;
2090 
2091 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2092 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2093 		f = 256;
2094 
2095 		do {
2096 			if (j > 15) {
2097 				device_printf(sc->sc_dev,
2098 				    "failed to generate tssi2dBm\n");
2099 				free(pg->pg_tssi2dbm, M_DEVBUF);
2100 				return (ENOMEM);
2101 			}
2102 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2103 			    f, 2048);
2104 			delta = abs(q - f);
2105 			f = q;
2106 			j++;
2107 		} while (delta >= 2);
2108 
2109 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2110 		    128);
2111 	}
2112 
2113 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2114 	return (0);
2115 }
2116 
2117 static void
2118 bwn_phy_g_detach(struct bwn_mac *mac)
2119 {
2120 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2121 
2122 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2123 		free(pg->pg_tssi2dbm, M_DEVBUF);
2124 		pg->pg_tssi2dbm = NULL;
2125 	}
2126 	pg->pg_flags = 0;
2127 }
2128 
2129 static void
2130 bwn_phy_g_init_pre(struct bwn_mac *mac)
2131 {
2132 	struct bwn_phy *phy = &mac->mac_phy;
2133 	struct bwn_phy_g *pg = &phy->phy_g;
2134 	void *tssi2dbm;
2135 	int idletssi;
2136 	unsigned int i;
2137 
2138 	tssi2dbm = pg->pg_tssi2dbm;
2139 	idletssi = pg->pg_idletssi;
2140 
2141 	memset(pg, 0, sizeof(*pg));
2142 
2143 	pg->pg_tssi2dbm = tssi2dbm;
2144 	pg->pg_idletssi = idletssi;
2145 
2146 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2147 
2148 	for (i = 0; i < N(pg->pg_nrssi); i++)
2149 		pg->pg_nrssi[i] = -1000;
2150 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2151 		pg->pg_nrssi_lt[i] = i;
2152 	pg->pg_lofcal = 0xffff;
2153 	pg->pg_initval = 0xffff;
2154 	pg->pg_immode = BWN_IMMODE_NONE;
2155 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2156 	pg->pg_avgtssi = 0xff;
2157 
2158 	pg->pg_loctl.tx_bias = 0xff;
2159 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2160 }
2161 
2162 static int
2163 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2164 {
2165 	struct bwn_phy *phy = &mac->mac_phy;
2166 	struct bwn_phy_g *pg = &phy->phy_g;
2167 	struct bwn_softc *sc = mac->mac_sc;
2168 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2169 	static const struct bwn_rfatt rfatt0[] = {
2170 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2171 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2172 		{ 3, 1 }, { 4, 1 }
2173 	};
2174 	static const struct bwn_rfatt rfatt1[] = {
2175 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2176 		{ 14, 1 }
2177 	};
2178 	static const struct bwn_rfatt rfatt2[] = {
2179 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2180 		{ 9, 1 }
2181 	};
2182 	static const struct bwn_bbatt bbatt_0[] = {
2183 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2184 	};
2185 
2186 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2187 
2188 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2189 		pg->pg_bbatt.att = 0;
2190 	else
2191 		pg->pg_bbatt.att = 2;
2192 
2193 	/* prepare Radio Attenuation */
2194 	pg->pg_rfatt.padmix = 0;
2195 
2196 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2197 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2198 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2199 			pg->pg_rfatt.att = 2;
2200 			goto done;
2201 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2202 			pg->pg_rfatt.att = 3;
2203 			goto done;
2204 		}
2205 	}
2206 
2207 	if (phy->type == BWN_PHYTYPE_A) {
2208 		pg->pg_rfatt.att = 0x60;
2209 		goto done;
2210 	}
2211 
2212 	switch (phy->rf_ver) {
2213 	case 0x2050:
2214 		switch (phy->rf_rev) {
2215 		case 0:
2216 			pg->pg_rfatt.att = 5;
2217 			goto done;
2218 		case 1:
2219 			if (phy->type == BWN_PHYTYPE_G) {
2220 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2221 				    SIBA_BOARDVENDOR_BCM &&
2222 				    siba_get_pci_subdevice(sc->sc_dev) ==
2223 				    SIBA_BOARD_BCM4309G &&
2224 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2225 					pg->pg_rfatt.att = 3;
2226 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2227 				    SIBA_BOARDVENDOR_BCM &&
2228 				    siba_get_pci_subdevice(sc->sc_dev) ==
2229 				    SIBA_BOARD_BU4306)
2230 					pg->pg_rfatt.att = 3;
2231 				else
2232 					pg->pg_rfatt.att = 1;
2233 			} else {
2234 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2235 				    SIBA_BOARDVENDOR_BCM &&
2236 				    siba_get_pci_subdevice(sc->sc_dev) ==
2237 				    SIBA_BOARD_BCM4309G &&
2238 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2239 					pg->pg_rfatt.att = 7;
2240 				else
2241 					pg->pg_rfatt.att = 6;
2242 			}
2243 			goto done;
2244 		case 2:
2245 			if (phy->type == BWN_PHYTYPE_G) {
2246 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2247 				    SIBA_BOARDVENDOR_BCM &&
2248 				    siba_get_pci_subdevice(sc->sc_dev) ==
2249 				    SIBA_BOARD_BCM4309G &&
2250 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2251 					pg->pg_rfatt.att = 3;
2252 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2253 				    SIBA_BOARDVENDOR_BCM &&
2254 				    siba_get_pci_subdevice(sc->sc_dev) ==
2255 				    SIBA_BOARD_BU4306)
2256 					pg->pg_rfatt.att = 5;
2257 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2258 					pg->pg_rfatt.att = 4;
2259 				else
2260 					pg->pg_rfatt.att = 3;
2261 			} else
2262 				pg->pg_rfatt.att = 6;
2263 			goto done;
2264 		case 3:
2265 			pg->pg_rfatt.att = 5;
2266 			goto done;
2267 		case 4:
2268 		case 5:
2269 			pg->pg_rfatt.att = 1;
2270 			goto done;
2271 		case 6:
2272 		case 7:
2273 			pg->pg_rfatt.att = 5;
2274 			goto done;
2275 		case 8:
2276 			pg->pg_rfatt.att = 0xa;
2277 			pg->pg_rfatt.padmix = 1;
2278 			goto done;
2279 		case 9:
2280 		default:
2281 			pg->pg_rfatt.att = 5;
2282 			goto done;
2283 		}
2284 		break;
2285 	case 0x2053:
2286 		switch (phy->rf_rev) {
2287 		case 1:
2288 			pg->pg_rfatt.att = 6;
2289 			goto done;
2290 		}
2291 		break;
2292 	}
2293 	pg->pg_rfatt.att = 5;
2294 done:
2295 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2296 
2297 	if (!bwn_has_hwpctl(mac)) {
2298 		lo->rfatt.array = rfatt0;
2299 		lo->rfatt.len = N(rfatt0);
2300 		lo->rfatt.min = 0;
2301 		lo->rfatt.max = 9;
2302 		goto genbbatt;
2303 	}
2304 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2305 		lo->rfatt.array = rfatt1;
2306 		lo->rfatt.len = N(rfatt1);
2307 		lo->rfatt.min = 0;
2308 		lo->rfatt.max = 14;
2309 		goto genbbatt;
2310 	}
2311 	lo->rfatt.array = rfatt2;
2312 	lo->rfatt.len = N(rfatt2);
2313 	lo->rfatt.min = 0;
2314 	lo->rfatt.max = 9;
2315 genbbatt:
2316 	lo->bbatt.array = bbatt_0;
2317 	lo->bbatt.len = N(bbatt_0);
2318 	lo->bbatt.min = 0;
2319 	lo->bbatt.max = 8;
2320 
2321 	BWN_READ_4(mac, BWN_MACCTL);
2322 	if (phy->rev == 1) {
2323 		phy->gmode = 0;
2324 		bwn_reset_core(mac, 0);
2325 		bwn_phy_g_init_sub(mac);
2326 		phy->gmode = 1;
2327 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2328 	}
2329 	return (0);
2330 }
2331 
2332 static uint16_t
2333 bwn_phy_g_txctl(struct bwn_mac *mac)
2334 {
2335 	struct bwn_phy *phy = &mac->mac_phy;
2336 
2337 	if (phy->rf_ver != 0x2050)
2338 		return (0);
2339 	if (phy->rf_rev == 1)
2340 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2341 	if (phy->rf_rev < 6)
2342 		return (BWN_TXCTL_PA2DB);
2343 	if (phy->rf_rev == 8)
2344 		return (BWN_TXCTL_TXMIX);
2345 	return (0);
2346 }
2347 
2348 static int
2349 bwn_phy_g_init(struct bwn_mac *mac)
2350 {
2351 
2352 	bwn_phy_g_init_sub(mac);
2353 	return (0);
2354 }
2355 
2356 static void
2357 bwn_phy_g_exit(struct bwn_mac *mac)
2358 {
2359 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2360 	struct bwn_lo_calib *cal, *tmp;
2361 
2362 	if (lo == NULL)
2363 		return;
2364 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2365 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2366 		free(cal, M_DEVBUF);
2367 	}
2368 }
2369 
2370 static uint16_t
2371 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2372 {
2373 
2374 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2375 	return (BWN_READ_2(mac, BWN_PHYDATA));
2376 }
2377 
2378 static void
2379 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2380 {
2381 
2382 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2383 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2384 }
2385 
2386 static uint16_t
2387 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2388 {
2389 
2390 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2391 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2392 	return (BWN_READ_2(mac, BWN_RFDATALO));
2393 }
2394 
2395 static void
2396 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2397 {
2398 
2399 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2400 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2401 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2402 }
2403 
2404 static int
2405 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2406 {
2407 
2408 	return (mac->mac_phy.rev >= 6);
2409 }
2410 
2411 static void
2412 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2413 {
2414 	struct bwn_phy *phy = &mac->mac_phy;
2415 	struct bwn_phy_g *pg = &phy->phy_g;
2416 	unsigned int channel;
2417 	uint16_t rfover, rfoverval;
2418 
2419 	if (on) {
2420 		if (phy->rf_on)
2421 			return;
2422 
2423 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2424 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2425 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2426 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2427 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2428 			    pg->pg_radioctx_over);
2429 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2430 			    pg->pg_radioctx_overval);
2431 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2432 		}
2433 		channel = phy->chan;
2434 		bwn_phy_g_switch_chan(mac, 6, 1);
2435 		bwn_phy_g_switch_chan(mac, channel, 0);
2436 		return;
2437 	}
2438 
2439 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2440 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2441 	pg->pg_radioctx_over = rfover;
2442 	pg->pg_radioctx_overval = rfoverval;
2443 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2444 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2445 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2446 }
2447 
2448 static int
2449 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2450 {
2451 
2452 	if ((newchan < 1) || (newchan > 14))
2453 		return (EINVAL);
2454 	bwn_phy_g_switch_chan(mac, newchan, 0);
2455 
2456 	return (0);
2457 }
2458 
2459 static uint32_t
2460 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2461 {
2462 
2463 	return (1);
2464 }
2465 
2466 static void
2467 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2468 {
2469 	struct bwn_phy *phy = &mac->mac_phy;
2470 	uint64_t hf;
2471 	int autodiv = 0;
2472 	uint16_t tmp;
2473 
2474 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2475 		autodiv = 1;
2476 
2477 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2478 	bwn_hf_write(mac, hf);
2479 
2480 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2481 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2482 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2483 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2484 
2485 	if (autodiv) {
2486 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2487 		if (antenna == BWN_ANTAUTO1)
2488 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2489 		else
2490 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2491 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2492 	}
2493 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2494 	if (autodiv)
2495 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2496 	else
2497 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2498 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2499 	if (phy->rev >= 2) {
2500 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2501 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2502 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2503 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2504 		    0x15);
2505 		if (phy->rev == 2)
2506 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2507 		else
2508 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2509 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2510 			    8);
2511 	}
2512 	if (phy->rev >= 6)
2513 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2514 
2515 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2516 	bwn_hf_write(mac, hf);
2517 }
2518 
2519 static int
2520 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2521 {
2522 	struct bwn_phy *phy = &mac->mac_phy;
2523 	struct bwn_phy_g *pg = &phy->phy_g;
2524 
2525 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2526 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2527 
2528 	if (phy->rev == 0 || !phy->gmode)
2529 		return (ENODEV);
2530 
2531 	pg->pg_aci_wlan_automatic = 0;
2532 	return (0);
2533 }
2534 
2535 static int
2536 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2537 {
2538 	struct bwn_phy *phy = &mac->mac_phy;
2539 	struct bwn_phy_g *pg = &phy->phy_g;
2540 	struct bwn_softc *sc = mac->mac_sc;
2541 	unsigned int tssi;
2542 	int cck, ofdm;
2543 	int power;
2544 	int rfatt, bbatt;
2545 	unsigned int max;
2546 
2547 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2548 
2549 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2550 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2551 	if (cck < 0 && ofdm < 0) {
2552 		if (ignore_tssi == 0)
2553 			return (BWN_TXPWR_RES_DONE);
2554 		cck = 0;
2555 		ofdm = 0;
2556 	}
2557 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2558 	if (pg->pg_avgtssi != 0xff)
2559 		tssi = (tssi + pg->pg_avgtssi) / 2;
2560 	pg->pg_avgtssi = tssi;
2561 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2562 
2563 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2564 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2565 		max -= 3;
2566 	if (max >= 120) {
2567 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2568 		max = 80;
2569 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2570 	}
2571 
2572 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2573 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2574 	     tssi, 0x00), 0x3f)]);
2575 	if (power == 0)
2576 		return (BWN_TXPWR_RES_DONE);
2577 
2578 	rfatt = -((power + 7) / 8);
2579 	bbatt = (-(power / 2)) - (4 * rfatt);
2580 	if ((rfatt == 0) && (bbatt == 0))
2581 		return (BWN_TXPWR_RES_DONE);
2582 	pg->pg_bbatt_delta = bbatt;
2583 	pg->pg_rfatt_delta = rfatt;
2584 	return (BWN_TXPWR_RES_NEED_ADJUST);
2585 }
2586 
2587 static void
2588 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2589 {
2590 	struct bwn_phy *phy = &mac->mac_phy;
2591 	struct bwn_phy_g *pg = &phy->phy_g;
2592 	struct bwn_softc *sc = mac->mac_sc;
2593 	int rfatt, bbatt;
2594 	uint8_t txctl;
2595 
2596 	bwn_mac_suspend(mac);
2597 
2598 	BWN_ASSERT_LOCKED(sc);
2599 
2600 	bbatt = pg->pg_bbatt.att;
2601 	bbatt += pg->pg_bbatt_delta;
2602 	rfatt = pg->pg_rfatt.att;
2603 	rfatt += pg->pg_rfatt_delta;
2604 
2605 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2606 	txctl = pg->pg_txctl;
2607 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2608 		if (rfatt <= 1) {
2609 			if (txctl == 0) {
2610 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2611 				rfatt += 2;
2612 				bbatt += 2;
2613 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2614 			    BWN_BFL_PACTRL) {
2615 				bbatt += 4 * (rfatt - 2);
2616 				rfatt = 2;
2617 			}
2618 		} else if (rfatt > 4 && txctl) {
2619 			txctl = 0;
2620 			if (bbatt < 3) {
2621 				rfatt -= 3;
2622 				bbatt += 2;
2623 			} else {
2624 				rfatt -= 2;
2625 				bbatt -= 2;
2626 			}
2627 		}
2628 	}
2629 	pg->pg_txctl = txctl;
2630 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2631 	pg->pg_rfatt.att = rfatt;
2632 	pg->pg_bbatt.att = bbatt;
2633 
2634 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2635 
2636 	bwn_phy_lock(mac);
2637 	bwn_rf_lock(mac);
2638 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2639 	    pg->pg_txctl);
2640 	bwn_rf_unlock(mac);
2641 	bwn_phy_unlock(mac);
2642 
2643 	bwn_mac_enable(mac);
2644 }
2645 
2646 static void
2647 bwn_phy_g_task_15s(struct bwn_mac *mac)
2648 {
2649 	struct bwn_phy *phy = &mac->mac_phy;
2650 	struct bwn_phy_g *pg = &phy->phy_g;
2651 	struct bwn_softc *sc = mac->mac_sc;
2652 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2653 	unsigned long expire, now;
2654 	struct bwn_lo_calib *cal, *tmp;
2655 	uint8_t expired = 0;
2656 
2657 	bwn_mac_suspend(mac);
2658 
2659 	if (lo == NULL)
2660 		goto fail;
2661 
2662 	BWN_GETTIME(now);
2663 	if (bwn_has_hwpctl(mac)) {
2664 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2665 		if (time_before(lo->pwr_vec_read_time, expire)) {
2666 			bwn_lo_get_powervector(mac);
2667 			bwn_phy_g_dc_lookup_init(mac, 0);
2668 		}
2669 		goto fail;
2670 	}
2671 
2672 	expire = now - BWN_LO_CALIB_EXPIRE;
2673 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2674 		if (!time_before(cal->calib_time, expire))
2675 			continue;
2676 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2677 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2678 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2679 			expired = 1;
2680 		}
2681 
2682 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2683 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2684 		    cal->ctl.i, cal->ctl.q);
2685 
2686 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2687 		free(cal, M_DEVBUF);
2688 	}
2689 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2690 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2691 		    &pg->pg_rfatt);
2692 		if (cal == NULL) {
2693 			device_printf(sc->sc_dev,
2694 			    "failed to recalibrate LO\n");
2695 			goto fail;
2696 		}
2697 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2698 		bwn_lo_write(mac, &cal->ctl);
2699 	}
2700 
2701 fail:
2702 	bwn_mac_enable(mac);
2703 }
2704 
2705 static void
2706 bwn_phy_g_task_60s(struct bwn_mac *mac)
2707 {
2708 	struct bwn_phy *phy = &mac->mac_phy;
2709 	struct bwn_softc *sc = mac->mac_sc;
2710 	uint8_t old = phy->chan;
2711 
2712 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2713 		return;
2714 
2715 	bwn_mac_suspend(mac);
2716 	bwn_nrssi_slope_11g(mac);
2717 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2718 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2719 		bwn_switch_channel(mac, old);
2720 	}
2721 	bwn_mac_enable(mac);
2722 }
2723 
2724 static void
2725 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2726 {
2727 
2728 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2729 }
2730 
2731 static int
2732 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2733 	const struct ieee80211_bpf_params *params)
2734 {
2735 	struct ieee80211com *ic = ni->ni_ic;
2736 	struct ifnet *ifp = ic->ic_ifp;
2737 	struct bwn_softc *sc = ifp->if_softc;
2738 	struct bwn_mac *mac = sc->sc_curmac;
2739 
2740 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2741 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2742 		ieee80211_free_node(ni);
2743 		m_freem(m);
2744 		return (ENETDOWN);
2745 	}
2746 
2747 	BWN_LOCK(sc);
2748 	if (bwn_tx_isfull(sc, m)) {
2749 		ieee80211_free_node(ni);
2750 		m_freem(m);
2751 		ifp->if_oerrors++;
2752 		BWN_UNLOCK(sc);
2753 		return (ENOBUFS);
2754 	}
2755 
2756 	if (bwn_tx_start(sc, ni, m) != 0) {
2757 		if (ni != NULL)
2758 			ieee80211_free_node(ni);
2759 		ifp->if_oerrors++;
2760 	}
2761 	sc->sc_watchdog_timer = 5;
2762 	BWN_UNLOCK(sc);
2763 	return (0);
2764 }
2765 
2766 /*
2767  * Callback from the 802.11 layer to update the slot time
2768  * based on the current setting.  We use it to notify the
2769  * firmware of ERP changes and the f/w takes care of things
2770  * like slot time and preamble.
2771  */
2772 static void
2773 bwn_updateslot(struct ifnet *ifp)
2774 {
2775 	struct bwn_softc *sc = ifp->if_softc;
2776 	struct ieee80211com *ic = ifp->if_l2com;
2777 	struct bwn_mac *mac;
2778 
2779 	BWN_LOCK(sc);
2780 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2781 		mac = (struct bwn_mac *)sc->sc_curmac;
2782 		bwn_set_slot_time(mac,
2783 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2784 	}
2785 	BWN_UNLOCK(sc);
2786 }
2787 
2788 /*
2789  * Callback from the 802.11 layer after a promiscuous mode change.
2790  * Note this interface does not check the operating mode as this
2791  * is an internal callback and we are expected to honor the current
2792  * state (e.g. this is used for setting the interface in promiscuous
2793  * mode when operating in hostap mode to do ACS).
2794  */
2795 static void
2796 bwn_update_promisc(struct ifnet *ifp)
2797 {
2798 	struct bwn_softc *sc = ifp->if_softc;
2799 	struct bwn_mac *mac = sc->sc_curmac;
2800 
2801 	BWN_LOCK(sc);
2802 	mac = sc->sc_curmac;
2803 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2804 		if (ifp->if_flags & IFF_PROMISC)
2805 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2806 		else
2807 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2808 		bwn_set_opmode(mac);
2809 	}
2810 	BWN_UNLOCK(sc);
2811 }
2812 
2813 /*
2814  * Callback from the 802.11 layer to update WME parameters.
2815  */
2816 static int
2817 bwn_wme_update(struct ieee80211com *ic)
2818 {
2819 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2820 	struct bwn_mac *mac = sc->sc_curmac;
2821 	struct wmeParams *wmep;
2822 	int i;
2823 
2824 	BWN_LOCK(sc);
2825 	mac = sc->sc_curmac;
2826 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2827 		bwn_mac_suspend(mac);
2828 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2829 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2830 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2831 		}
2832 		bwn_mac_enable(mac);
2833 	}
2834 	BWN_UNLOCK(sc);
2835 	return (0);
2836 }
2837 
2838 static void
2839 bwn_scan_start(struct ieee80211com *ic)
2840 {
2841 	struct ifnet *ifp = ic->ic_ifp;
2842 	struct bwn_softc *sc = ifp->if_softc;
2843 	struct bwn_mac *mac;
2844 
2845 	BWN_LOCK(sc);
2846 	mac = sc->sc_curmac;
2847 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2848 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2849 		bwn_set_opmode(mac);
2850 		/* disable CFP update during scan */
2851 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2852 	}
2853 	BWN_UNLOCK(sc);
2854 }
2855 
2856 static void
2857 bwn_scan_end(struct ieee80211com *ic)
2858 {
2859 	struct ifnet *ifp = ic->ic_ifp;
2860 	struct bwn_softc *sc = ifp->if_softc;
2861 	struct bwn_mac *mac;
2862 
2863 	BWN_LOCK(sc);
2864 	mac = sc->sc_curmac;
2865 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2866 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2867 		bwn_set_opmode(mac);
2868 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2869 	}
2870 	BWN_UNLOCK(sc);
2871 }
2872 
2873 static void
2874 bwn_set_channel(struct ieee80211com *ic)
2875 {
2876 	struct ifnet *ifp = ic->ic_ifp;
2877 	struct bwn_softc *sc = ifp->if_softc;
2878 	struct bwn_mac *mac = sc->sc_curmac;
2879 	struct bwn_phy *phy = &mac->mac_phy;
2880 	int chan, error;
2881 
2882 	BWN_LOCK(sc);
2883 
2884 	error = bwn_switch_band(sc, ic->ic_curchan);
2885 	if (error)
2886 		goto fail;
2887 	bwn_mac_suspend(mac);
2888 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2889 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2890 	if (chan != phy->chan)
2891 		bwn_switch_channel(mac, chan);
2892 
2893 	/* TX power level */
2894 	if (ic->ic_curchan->ic_maxpower != 0 &&
2895 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2896 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2897 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2898 		    BWN_TXPWR_IGNORE_TSSI);
2899 	}
2900 
2901 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2902 	if (phy->set_antenna)
2903 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2904 
2905 	if (sc->sc_rf_enabled != phy->rf_on) {
2906 		if (sc->sc_rf_enabled) {
2907 			bwn_rf_turnon(mac);
2908 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2909 				device_printf(sc->sc_dev,
2910 				    "please turn on the RF switch\n");
2911 		} else
2912 			bwn_rf_turnoff(mac);
2913 	}
2914 
2915 	bwn_mac_enable(mac);
2916 
2917 fail:
2918 	/*
2919 	 * Setup radio tap channel freq and flags
2920 	 */
2921 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2922 		htole16(ic->ic_curchan->ic_freq);
2923 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2924 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2925 
2926 	BWN_UNLOCK(sc);
2927 }
2928 
2929 static struct ieee80211vap *
2930 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2931     enum ieee80211_opmode opmode, int flags,
2932     const uint8_t bssid[IEEE80211_ADDR_LEN],
2933     const uint8_t mac0[IEEE80211_ADDR_LEN])
2934 {
2935 	struct ifnet *ifp = ic->ic_ifp;
2936 	struct bwn_softc *sc = ifp->if_softc;
2937 	struct ieee80211vap *vap;
2938 	struct bwn_vap *bvp;
2939 	uint8_t mac[IEEE80211_ADDR_LEN];
2940 
2941 	IEEE80211_ADDR_COPY(mac, mac0);
2942 	switch (opmode) {
2943 	case IEEE80211_M_HOSTAP:
2944 	case IEEE80211_M_MBSS:
2945 	case IEEE80211_M_STA:
2946 	case IEEE80211_M_WDS:
2947 	case IEEE80211_M_MONITOR:
2948 	case IEEE80211_M_IBSS:
2949 	case IEEE80211_M_AHDEMO:
2950 		break;
2951 	default:
2952 		return (NULL);
2953 	}
2954 
2955 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2956 
2957 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2958 	    M_80211_VAP, M_NOWAIT | M_ZERO);
2959 	if (bvp == NULL) {
2960 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2961 		return (NULL);
2962 	}
2963 	vap = &bvp->bv_vap;
2964 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2965 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2966 	/* override with driver methods */
2967 	bvp->bv_newstate = vap->iv_newstate;
2968 	vap->iv_newstate = bwn_newstate;
2969 
2970 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2971 	vap->iv_max_aid = BWN_STAID_MAX;
2972 
2973 	ieee80211_ratectl_init(vap);
2974 
2975 	/* complete setup */
2976 	ieee80211_vap_attach(vap, ieee80211_media_change,
2977 	    ieee80211_media_status);
2978 	return (vap);
2979 }
2980 
2981 static void
2982 bwn_vap_delete(struct ieee80211vap *vap)
2983 {
2984 	struct bwn_vap *bvp = BWN_VAP(vap);
2985 
2986 	ieee80211_ratectl_deinit(vap);
2987 	ieee80211_vap_detach(vap);
2988 	free(bvp, M_80211_VAP);
2989 }
2990 
2991 static void
2992 bwn_init(void *arg)
2993 {
2994 	struct bwn_softc *sc = arg;
2995 	struct ifnet *ifp = sc->sc_ifp;
2996 	struct ieee80211com *ic = ifp->if_l2com;
2997 	int error = 0;
2998 
2999 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
3000 		__func__, ifp->if_flags);
3001 
3002 	BWN_LOCK(sc);
3003 	error = bwn_init_locked(sc);
3004 	BWN_UNLOCK(sc);
3005 
3006 	if (error == 0)
3007 		ieee80211_start_all(ic);	/* start all vap's */
3008 }
3009 
3010 static int
3011 bwn_init_locked(struct bwn_softc *sc)
3012 {
3013 	struct bwn_mac *mac;
3014 	struct ifnet *ifp = sc->sc_ifp;
3015 	int error;
3016 
3017 	BWN_ASSERT_LOCKED(sc);
3018 
3019 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3020 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3021 	sc->sc_filters = 0;
3022 	bwn_wme_clear(sc);
3023 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3024 	sc->sc_rf_enabled = 1;
3025 
3026 	mac = sc->sc_curmac;
3027 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3028 		error = bwn_core_init(mac);
3029 		if (error != 0)
3030 			return (error);
3031 	}
3032 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3033 		bwn_core_start(mac);
3034 
3035 	bwn_set_opmode(mac);
3036 	bwn_set_pretbtt(mac);
3037 	bwn_spu_setdelay(mac, 0);
3038 	bwn_set_macaddr(mac);
3039 
3040 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3041 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3042 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3043 
3044 	return (0);
3045 }
3046 
3047 static void
3048 bwn_stop(struct bwn_softc *sc, int statechg)
3049 {
3050 
3051 	BWN_LOCK(sc);
3052 	bwn_stop_locked(sc, statechg);
3053 	BWN_UNLOCK(sc);
3054 }
3055 
3056 static void
3057 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3058 {
3059 	struct bwn_mac *mac = sc->sc_curmac;
3060 	struct ifnet *ifp = sc->sc_ifp;
3061 
3062 	BWN_ASSERT_LOCKED(sc);
3063 
3064 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3065 		/* XXX FIXME opmode not based on VAP */
3066 		bwn_set_opmode(mac);
3067 		bwn_set_macaddr(mac);
3068 	}
3069 
3070 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3071 		bwn_core_stop(mac);
3072 
3073 	callout_stop(&sc->sc_led_blink_ch);
3074 	sc->sc_led_blinking = 0;
3075 
3076 	bwn_core_exit(mac);
3077 	sc->sc_rf_enabled = 0;
3078 
3079 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3080 }
3081 
3082 static void
3083 bwn_wme_clear(struct bwn_softc *sc)
3084 {
3085 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3086 	struct wmeParams *p;
3087 	unsigned int i;
3088 
3089 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3090 	    ("%s:%d: fail", __func__, __LINE__));
3091 
3092 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3093 		p = &(sc->sc_wmeParams[i]);
3094 
3095 		switch (bwn_wme_shm_offsets[i]) {
3096 		case BWN_WME_VOICE:
3097 			p->wmep_txopLimit = 0;
3098 			p->wmep_aifsn = 2;
3099 			/* XXX FIXME: log2(cwmin) */
3100 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3101 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3102 			break;
3103 		case BWN_WME_VIDEO:
3104 			p->wmep_txopLimit = 0;
3105 			p->wmep_aifsn = 2;
3106 			/* XXX FIXME: log2(cwmin) */
3107 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3108 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3109 			break;
3110 		case BWN_WME_BESTEFFORT:
3111 			p->wmep_txopLimit = 0;
3112 			p->wmep_aifsn = 3;
3113 			/* XXX FIXME: log2(cwmin) */
3114 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3115 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3116 			break;
3117 		case BWN_WME_BACKGROUND:
3118 			p->wmep_txopLimit = 0;
3119 			p->wmep_aifsn = 7;
3120 			/* XXX FIXME: log2(cwmin) */
3121 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3122 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3123 			break;
3124 		default:
3125 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3126 		}
3127 	}
3128 }
3129 
3130 static int
3131 bwn_core_init(struct bwn_mac *mac)
3132 {
3133 	struct bwn_softc *sc = mac->mac_sc;
3134 	uint64_t hf;
3135 	int error;
3136 
3137 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3138 	    ("%s:%d: fail", __func__, __LINE__));
3139 
3140 	siba_powerup(sc->sc_dev, 0);
3141 	if (!siba_dev_isup(sc->sc_dev))
3142 		bwn_reset_core(mac,
3143 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3144 
3145 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3146 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3147 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3148 	BWN_GETTIME(mac->mac_phy.nexttime);
3149 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3150 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3151 	mac->mac_stats.link_noise = -95;
3152 	mac->mac_reason_intr = 0;
3153 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3154 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3155 #ifdef BWN_DEBUG
3156 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3157 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3158 #endif
3159 	mac->mac_suspended = 1;
3160 	mac->mac_task_state = 0;
3161 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3162 
3163 	mac->mac_phy.init_pre(mac);
3164 
3165 	siba_pcicore_intr(sc->sc_dev);
3166 
3167 	siba_fix_imcfglobug(sc->sc_dev);
3168 	bwn_bt_disable(mac);
3169 	if (mac->mac_phy.prepare_hw) {
3170 		error = mac->mac_phy.prepare_hw(mac);
3171 		if (error)
3172 			goto fail0;
3173 	}
3174 	error = bwn_chip_init(mac);
3175 	if (error)
3176 		goto fail0;
3177 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3178 	    siba_get_revid(sc->sc_dev));
3179 	hf = bwn_hf_read(mac);
3180 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3181 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3182 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3183 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3184 		if (mac->mac_phy.rev == 1)
3185 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3186 	}
3187 	if (mac->mac_phy.rf_ver == 0x2050) {
3188 		if (mac->mac_phy.rf_rev < 6)
3189 			hf |= BWN_HF_FORCE_VCO_RECALC;
3190 		if (mac->mac_phy.rf_rev == 6)
3191 			hf |= BWN_HF_4318_TSSI;
3192 	}
3193 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3194 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3195 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3196 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3197 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3198 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3199 	bwn_hf_write(mac, hf);
3200 
3201 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3202 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3203 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3204 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3205 
3206 	bwn_rate_init(mac);
3207 	bwn_set_phytxctl(mac);
3208 
3209 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3210 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3211 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3212 
3213 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3214 		bwn_pio_init(mac);
3215 	else
3216 		bwn_dma_init(mac);
3217 	bwn_wme_init(mac);
3218 	bwn_spu_setdelay(mac, 1);
3219 	bwn_bt_enable(mac);
3220 
3221 	siba_powerup(sc->sc_dev,
3222 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3223 	bwn_set_macaddr(mac);
3224 	bwn_crypt_init(mac);
3225 
3226 	/* XXX LED initializatin */
3227 
3228 	mac->mac_status = BWN_MAC_STATUS_INITED;
3229 
3230 	return (error);
3231 
3232 fail0:
3233 	siba_powerdown(sc->sc_dev);
3234 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3235 	    ("%s:%d: fail", __func__, __LINE__));
3236 	return (error);
3237 }
3238 
3239 static void
3240 bwn_core_start(struct bwn_mac *mac)
3241 {
3242 	struct bwn_softc *sc = mac->mac_sc;
3243 	uint32_t tmp;
3244 
3245 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3246 	    ("%s:%d: fail", __func__, __LINE__));
3247 
3248 	if (siba_get_revid(sc->sc_dev) < 5)
3249 		return;
3250 
3251 	while (1) {
3252 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3253 		if (!(tmp & 0x00000001))
3254 			break;
3255 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3256 	}
3257 
3258 	bwn_mac_enable(mac);
3259 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3260 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3261 
3262 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3263 }
3264 
3265 static void
3266 bwn_core_exit(struct bwn_mac *mac)
3267 {
3268 	struct bwn_softc *sc = mac->mac_sc;
3269 	uint32_t macctl;
3270 
3271 	BWN_ASSERT_LOCKED(mac->mac_sc);
3272 
3273 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3274 	    ("%s:%d: fail", __func__, __LINE__));
3275 
3276 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3277 		return;
3278 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3279 
3280 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3281 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3282 	macctl |= BWN_MACCTL_MCODE_JMP0;
3283 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3284 
3285 	bwn_dma_stop(mac);
3286 	bwn_pio_stop(mac);
3287 	bwn_chip_exit(mac);
3288 	mac->mac_phy.switch_analog(mac, 0);
3289 	siba_dev_down(sc->sc_dev, 0);
3290 	siba_powerdown(sc->sc_dev);
3291 }
3292 
3293 static void
3294 bwn_bt_disable(struct bwn_mac *mac)
3295 {
3296 	struct bwn_softc *sc = mac->mac_sc;
3297 
3298 	(void)sc;
3299 	/* XXX do nothing yet */
3300 }
3301 
3302 static int
3303 bwn_chip_init(struct bwn_mac *mac)
3304 {
3305 	struct bwn_softc *sc = mac->mac_sc;
3306 	struct bwn_phy *phy = &mac->mac_phy;
3307 	uint32_t macctl;
3308 	int error;
3309 
3310 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3311 	if (phy->gmode)
3312 		macctl |= BWN_MACCTL_GMODE;
3313 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3314 
3315 	error = bwn_fw_fillinfo(mac);
3316 	if (error)
3317 		return (error);
3318 	error = bwn_fw_loaducode(mac);
3319 	if (error)
3320 		return (error);
3321 
3322 	error = bwn_gpio_init(mac);
3323 	if (error)
3324 		return (error);
3325 
3326 	error = bwn_fw_loadinitvals(mac);
3327 	if (error) {
3328 		siba_gpio_set(sc->sc_dev, 0);
3329 		return (error);
3330 	}
3331 	phy->switch_analog(mac, 1);
3332 	error = bwn_phy_init(mac);
3333 	if (error) {
3334 		siba_gpio_set(sc->sc_dev, 0);
3335 		return (error);
3336 	}
3337 	if (phy->set_im)
3338 		phy->set_im(mac, BWN_IMMODE_NONE);
3339 	if (phy->set_antenna)
3340 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3341 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3342 
3343 	if (phy->type == BWN_PHYTYPE_B)
3344 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3345 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3346 	if (siba_get_revid(sc->sc_dev) < 5)
3347 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3348 
3349 	BWN_WRITE_4(mac, BWN_MACCTL,
3350 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3351 	BWN_WRITE_4(mac, BWN_MACCTL,
3352 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3353 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3354 
3355 	bwn_set_opmode(mac);
3356 	if (siba_get_revid(sc->sc_dev) < 3) {
3357 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3358 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3359 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3360 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3361 	} else {
3362 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3363 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3364 	}
3365 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3366 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3367 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3368 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3369 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3370 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3371 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3372 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3373 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3374 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3375 	return (error);
3376 }
3377 
3378 /* read hostflags */
3379 static uint64_t
3380 bwn_hf_read(struct bwn_mac *mac)
3381 {
3382 	uint64_t ret;
3383 
3384 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3385 	ret <<= 16;
3386 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3387 	ret <<= 16;
3388 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3389 	return (ret);
3390 }
3391 
3392 static void
3393 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3394 {
3395 
3396 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3397 	    (value & 0x00000000ffffull));
3398 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3399 	    (value & 0x0000ffff0000ull) >> 16);
3400 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3401 	    (value & 0xffff00000000ULL) >> 32);
3402 }
3403 
3404 static void
3405 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3406 {
3407 
3408 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3409 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3410 }
3411 
3412 static void
3413 bwn_rate_init(struct bwn_mac *mac)
3414 {
3415 
3416 	switch (mac->mac_phy.type) {
3417 	case BWN_PHYTYPE_A:
3418 	case BWN_PHYTYPE_G:
3419 	case BWN_PHYTYPE_LP:
3420 	case BWN_PHYTYPE_N:
3421 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3422 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3423 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3424 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3425 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3426 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3427 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3428 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3429 			break;
3430 		/* FALLTHROUGH */
3431 	case BWN_PHYTYPE_B:
3432 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3433 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3434 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3435 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3436 		break;
3437 	default:
3438 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3439 	}
3440 }
3441 
3442 static void
3443 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3444 {
3445 	uint16_t offset;
3446 
3447 	if (ofdm) {
3448 		offset = 0x480;
3449 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3450 	} else {
3451 		offset = 0x4c0;
3452 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3453 	}
3454 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3455 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3456 }
3457 
3458 static uint8_t
3459 bwn_plcp_getcck(const uint8_t bitrate)
3460 {
3461 
3462 	switch (bitrate) {
3463 	case BWN_CCK_RATE_1MB:
3464 		return (0x0a);
3465 	case BWN_CCK_RATE_2MB:
3466 		return (0x14);
3467 	case BWN_CCK_RATE_5MB:
3468 		return (0x37);
3469 	case BWN_CCK_RATE_11MB:
3470 		return (0x6e);
3471 	}
3472 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3473 	return (0);
3474 }
3475 
3476 static uint8_t
3477 bwn_plcp_getofdm(const uint8_t bitrate)
3478 {
3479 
3480 	switch (bitrate) {
3481 	case BWN_OFDM_RATE_6MB:
3482 		return (0xb);
3483 	case BWN_OFDM_RATE_9MB:
3484 		return (0xf);
3485 	case BWN_OFDM_RATE_12MB:
3486 		return (0xa);
3487 	case BWN_OFDM_RATE_18MB:
3488 		return (0xe);
3489 	case BWN_OFDM_RATE_24MB:
3490 		return (0x9);
3491 	case BWN_OFDM_RATE_36MB:
3492 		return (0xd);
3493 	case BWN_OFDM_RATE_48MB:
3494 		return (0x8);
3495 	case BWN_OFDM_RATE_54MB:
3496 		return (0xc);
3497 	}
3498 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3499 	return (0);
3500 }
3501 
3502 static void
3503 bwn_set_phytxctl(struct bwn_mac *mac)
3504 {
3505 	uint16_t ctl;
3506 
3507 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3508 	    BWN_TX_PHY_TXPWR);
3509 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3510 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3511 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3512 }
3513 
3514 static void
3515 bwn_pio_init(struct bwn_mac *mac)
3516 {
3517 	struct bwn_pio *pio = &mac->mac_method.pio;
3518 
3519 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3520 	    & ~BWN_MACCTL_BIGENDIAN);
3521 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3522 
3523 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3524 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3525 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3526 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3527 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3528 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3529 }
3530 
3531 static void
3532 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3533     int index)
3534 {
3535 	struct bwn_pio_txpkt *tp;
3536 	struct bwn_softc *sc = mac->mac_sc;
3537 	unsigned int i;
3538 
3539 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3540 	tq->tq_index = index;
3541 
3542 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3543 	if (siba_get_revid(sc->sc_dev) >= 8)
3544 		tq->tq_size = 1920;
3545 	else {
3546 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3547 		tq->tq_size -= 80;
3548 	}
3549 
3550 	TAILQ_INIT(&tq->tq_pktlist);
3551 	for (i = 0; i < N(tq->tq_pkts); i++) {
3552 		tp = &(tq->tq_pkts[i]);
3553 		tp->tp_index = i;
3554 		tp->tp_queue = tq;
3555 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3556 	}
3557 }
3558 
3559 static uint16_t
3560 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3561 {
3562 	struct bwn_softc *sc = mac->mac_sc;
3563 	static const uint16_t bases[] = {
3564 		BWN_PIO_BASE0,
3565 		BWN_PIO_BASE1,
3566 		BWN_PIO_BASE2,
3567 		BWN_PIO_BASE3,
3568 		BWN_PIO_BASE4,
3569 		BWN_PIO_BASE5,
3570 		BWN_PIO_BASE6,
3571 		BWN_PIO_BASE7,
3572 	};
3573 	static const uint16_t bases_rev11[] = {
3574 		BWN_PIO11_BASE0,
3575 		BWN_PIO11_BASE1,
3576 		BWN_PIO11_BASE2,
3577 		BWN_PIO11_BASE3,
3578 		BWN_PIO11_BASE4,
3579 		BWN_PIO11_BASE5,
3580 	};
3581 
3582 	if (siba_get_revid(sc->sc_dev) >= 11) {
3583 		if (index >= N(bases_rev11))
3584 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3585 		return (bases_rev11[index]);
3586 	}
3587 	if (index >= N(bases))
3588 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3589 	return (bases[index]);
3590 }
3591 
3592 static void
3593 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3594     int index)
3595 {
3596 	struct bwn_softc *sc = mac->mac_sc;
3597 
3598 	prq->prq_mac = mac;
3599 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3600 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3601 	bwn_dma_rxdirectfifo(mac, index, 1);
3602 }
3603 
3604 static void
3605 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3606 {
3607 	if (tq == NULL)
3608 		return;
3609 	bwn_pio_cancel_tx_packets(tq);
3610 }
3611 
3612 static void
3613 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3614 {
3615 
3616 	bwn_destroy_pioqueue_tx(pio);
3617 }
3618 
3619 static uint16_t
3620 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3621     uint16_t offset)
3622 {
3623 
3624 	return (BWN_READ_2(mac, tq->tq_base + offset));
3625 }
3626 
3627 static void
3628 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3629 {
3630 	uint32_t ctl;
3631 	int type;
3632 	uint16_t base;
3633 
3634 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3635 	base = bwn_dma_base(type, idx);
3636 	if (type == BWN_DMA_64BIT) {
3637 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3638 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3639 		if (enable)
3640 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3641 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3642 	} else {
3643 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3644 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3645 		if (enable)
3646 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3647 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3648 	}
3649 }
3650 
3651 static uint64_t
3652 bwn_dma_mask(struct bwn_mac *mac)
3653 {
3654 	uint32_t tmp;
3655 	uint16_t base;
3656 
3657 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3658 	if (tmp & SIBA_TGSHIGH_DMA64)
3659 		return (BWN_DMA_BIT_MASK(64));
3660 	base = bwn_dma_base(0, 0);
3661 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3662 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3663 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3664 		return (BWN_DMA_BIT_MASK(32));
3665 
3666 	return (BWN_DMA_BIT_MASK(30));
3667 }
3668 
3669 static int
3670 bwn_dma_mask2type(uint64_t dmamask)
3671 {
3672 
3673 	if (dmamask == BWN_DMA_BIT_MASK(30))
3674 		return (BWN_DMA_30BIT);
3675 	if (dmamask == BWN_DMA_BIT_MASK(32))
3676 		return (BWN_DMA_32BIT);
3677 	if (dmamask == BWN_DMA_BIT_MASK(64))
3678 		return (BWN_DMA_64BIT);
3679 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3680 	return (BWN_DMA_30BIT);
3681 }
3682 
3683 static void
3684 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3685 {
3686 	struct bwn_pio_txpkt *tp;
3687 	unsigned int i;
3688 
3689 	for (i = 0; i < N(tq->tq_pkts); i++) {
3690 		tp = &(tq->tq_pkts[i]);
3691 		if (tp->tp_m) {
3692 			m_freem(tp->tp_m);
3693 			tp->tp_m = NULL;
3694 		}
3695 	}
3696 }
3697 
3698 static uint16_t
3699 bwn_dma_base(int type, int controller_idx)
3700 {
3701 	static const uint16_t map64[] = {
3702 		BWN_DMA64_BASE0,
3703 		BWN_DMA64_BASE1,
3704 		BWN_DMA64_BASE2,
3705 		BWN_DMA64_BASE3,
3706 		BWN_DMA64_BASE4,
3707 		BWN_DMA64_BASE5,
3708 	};
3709 	static const uint16_t map32[] = {
3710 		BWN_DMA32_BASE0,
3711 		BWN_DMA32_BASE1,
3712 		BWN_DMA32_BASE2,
3713 		BWN_DMA32_BASE3,
3714 		BWN_DMA32_BASE4,
3715 		BWN_DMA32_BASE5,
3716 	};
3717 
3718 	if (type == BWN_DMA_64BIT) {
3719 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3720 		    ("%s:%d: fail", __func__, __LINE__));
3721 		return (map64[controller_idx]);
3722 	}
3723 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3724 	    ("%s:%d: fail", __func__, __LINE__));
3725 	return (map32[controller_idx]);
3726 }
3727 
3728 static void
3729 bwn_dma_init(struct bwn_mac *mac)
3730 {
3731 	struct bwn_dma *dma = &mac->mac_method.dma;
3732 
3733 	/* setup TX DMA channels. */
3734 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3735 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3736 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3737 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3738 	bwn_dma_setup(dma->mcast);
3739 	/* setup RX DMA channel. */
3740 	bwn_dma_setup(dma->rx);
3741 }
3742 
3743 static struct bwn_dma_ring *
3744 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3745     int for_tx, int type)
3746 {
3747 	struct bwn_dma *dma = &mac->mac_method.dma;
3748 	struct bwn_dma_ring *dr;
3749 	struct bwn_dmadesc_generic *desc;
3750 	struct bwn_dmadesc_meta *mt;
3751 	struct bwn_softc *sc = mac->mac_sc;
3752 	int error, i;
3753 
3754 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3755 	if (dr == NULL)
3756 		goto out;
3757 	dr->dr_numslots = BWN_RXRING_SLOTS;
3758 	if (for_tx)
3759 		dr->dr_numslots = BWN_TXRING_SLOTS;
3760 
3761 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3762 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3763 	if (dr->dr_meta == NULL)
3764 		goto fail0;
3765 
3766 	dr->dr_type = type;
3767 	dr->dr_mac = mac;
3768 	dr->dr_base = bwn_dma_base(type, controller_index);
3769 	dr->dr_index = controller_index;
3770 	if (type == BWN_DMA_64BIT) {
3771 		dr->getdesc = bwn_dma_64_getdesc;
3772 		dr->setdesc = bwn_dma_64_setdesc;
3773 		dr->start_transfer = bwn_dma_64_start_transfer;
3774 		dr->suspend = bwn_dma_64_suspend;
3775 		dr->resume = bwn_dma_64_resume;
3776 		dr->get_curslot = bwn_dma_64_get_curslot;
3777 		dr->set_curslot = bwn_dma_64_set_curslot;
3778 	} else {
3779 		dr->getdesc = bwn_dma_32_getdesc;
3780 		dr->setdesc = bwn_dma_32_setdesc;
3781 		dr->start_transfer = bwn_dma_32_start_transfer;
3782 		dr->suspend = bwn_dma_32_suspend;
3783 		dr->resume = bwn_dma_32_resume;
3784 		dr->get_curslot = bwn_dma_32_get_curslot;
3785 		dr->set_curslot = bwn_dma_32_set_curslot;
3786 	}
3787 	if (for_tx) {
3788 		dr->dr_tx = 1;
3789 		dr->dr_curslot = -1;
3790 	} else {
3791 		if (dr->dr_index == 0) {
3792 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3793 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3794 		} else
3795 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3796 	}
3797 
3798 	error = bwn_dma_allocringmemory(dr);
3799 	if (error)
3800 		goto fail2;
3801 
3802 	if (for_tx) {
3803 		/*
3804 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3805 		 * BWN_TX_SLOTS_PER_FRAME
3806 		 */
3807 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3808 		    ("%s:%d: fail", __func__, __LINE__));
3809 
3810 		dr->dr_txhdr_cache =
3811 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3812 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3813 		KASSERT(dr->dr_txhdr_cache != NULL,
3814 		    ("%s:%d: fail", __func__, __LINE__));
3815 
3816 		/*
3817 		 * Create TX ring DMA stuffs
3818 		 */
3819 		error = bus_dma_tag_create(dma->parent_dtag,
3820 				    BWN_ALIGN, 0,
3821 				    BUS_SPACE_MAXADDR,
3822 				    BUS_SPACE_MAXADDR,
3823 				    NULL, NULL,
3824 				    BWN_HDRSIZE(mac),
3825 				    1,
3826 				    BUS_SPACE_MAXSIZE_32BIT,
3827 				    0,
3828 				    NULL, NULL,
3829 				    &dr->dr_txring_dtag);
3830 		if (error) {
3831 			device_printf(sc->sc_dev,
3832 			    "can't create TX ring DMA tag: TODO frees\n");
3833 			goto fail1;
3834 		}
3835 
3836 		for (i = 0; i < dr->dr_numslots; i += 2) {
3837 			dr->getdesc(dr, i, &desc, &mt);
3838 
3839 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3840 			mt->mt_m = NULL;
3841 			mt->mt_ni = NULL;
3842 			mt->mt_islast = 0;
3843 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3844 			    &mt->mt_dmap);
3845 			if (error) {
3846 				device_printf(sc->sc_dev,
3847 				     "can't create RX buf DMA map\n");
3848 				goto fail1;
3849 			}
3850 
3851 			dr->getdesc(dr, i + 1, &desc, &mt);
3852 
3853 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3854 			mt->mt_m = NULL;
3855 			mt->mt_ni = NULL;
3856 			mt->mt_islast = 1;
3857 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3858 			    &mt->mt_dmap);
3859 			if (error) {
3860 				device_printf(sc->sc_dev,
3861 				     "can't create RX buf DMA map\n");
3862 				goto fail1;
3863 			}
3864 		}
3865 	} else {
3866 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3867 		    &dr->dr_spare_dmap);
3868 		if (error) {
3869 			device_printf(sc->sc_dev,
3870 			    "can't create RX buf DMA map\n");
3871 			goto out;		/* XXX wrong! */
3872 		}
3873 
3874 		for (i = 0; i < dr->dr_numslots; i++) {
3875 			dr->getdesc(dr, i, &desc, &mt);
3876 
3877 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3878 			    &mt->mt_dmap);
3879 			if (error) {
3880 				device_printf(sc->sc_dev,
3881 				    "can't create RX buf DMA map\n");
3882 				goto out;	/* XXX wrong! */
3883 			}
3884 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3885 			if (error) {
3886 				device_printf(sc->sc_dev,
3887 				    "failed to allocate RX buf\n");
3888 				goto out;	/* XXX wrong! */
3889 			}
3890 		}
3891 
3892 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3893 		    BUS_DMASYNC_PREWRITE);
3894 
3895 		dr->dr_usedslot = dr->dr_numslots;
3896 	}
3897 
3898       out:
3899 	return (dr);
3900 
3901 fail2:
3902 	free(dr->dr_txhdr_cache, M_DEVBUF);
3903 fail1:
3904 	free(dr->dr_meta, M_DEVBUF);
3905 fail0:
3906 	free(dr, M_DEVBUF);
3907 	return (NULL);
3908 }
3909 
3910 static void
3911 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3912 {
3913 
3914 	if (dr == NULL)
3915 		return;
3916 
3917 	bwn_dma_free_descbufs(*dr);
3918 	bwn_dma_free_ringmemory(*dr);
3919 
3920 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3921 	free((*dr)->dr_meta, M_DEVBUF);
3922 	free(*dr, M_DEVBUF);
3923 
3924 	*dr = NULL;
3925 }
3926 
3927 static void
3928 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3929     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3930 {
3931 	struct bwn_dmadesc32 *desc;
3932 
3933 	*meta = &(dr->dr_meta[slot]);
3934 	desc = dr->dr_ring_descbase;
3935 	desc = &(desc[slot]);
3936 
3937 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3938 }
3939 
3940 static void
3941 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3942     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3943     int start, int end, int irq)
3944 {
3945 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3946 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3947 	uint32_t addr, addrext, ctl;
3948 	int slot;
3949 
3950 	slot = (int)(&(desc->dma.dma32) - descbase);
3951 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3952 	    ("%s:%d: fail", __func__, __LINE__));
3953 
3954 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3955 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3956 	addr |= siba_dma_translation(sc->sc_dev);
3957 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3958 	if (slot == dr->dr_numslots - 1)
3959 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3960 	if (start)
3961 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3962 	if (end)
3963 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3964 	if (irq)
3965 		ctl |= BWN_DMA32_DCTL_IRQ;
3966 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3967 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3968 
3969 	desc->dma.dma32.control = htole32(ctl);
3970 	desc->dma.dma32.address = htole32(addr);
3971 }
3972 
3973 static void
3974 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3975 {
3976 
3977 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3978 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3979 }
3980 
3981 static void
3982 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3983 {
3984 
3985 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3986 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3987 }
3988 
3989 static void
3990 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3991 {
3992 
3993 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3994 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3995 }
3996 
3997 static int
3998 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3999 {
4000 	uint32_t val;
4001 
4002 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4003 	val &= BWN_DMA32_RXDPTR;
4004 
4005 	return (val / sizeof(struct bwn_dmadesc32));
4006 }
4007 
4008 static void
4009 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4010 {
4011 
4012 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4013 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4014 }
4015 
4016 static void
4017 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4018     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4019 {
4020 	struct bwn_dmadesc64 *desc;
4021 
4022 	*meta = &(dr->dr_meta[slot]);
4023 	desc = dr->dr_ring_descbase;
4024 	desc = &(desc[slot]);
4025 
4026 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4027 }
4028 
4029 static void
4030 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4031     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4032     int start, int end, int irq)
4033 {
4034 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4035 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4036 	int slot;
4037 	uint32_t ctl0 = 0, ctl1 = 0;
4038 	uint32_t addrlo, addrhi;
4039 	uint32_t addrext;
4040 
4041 	slot = (int)(&(desc->dma.dma64) - descbase);
4042 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4043 	    ("%s:%d: fail", __func__, __LINE__));
4044 
4045 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4046 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4047 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4048 	    30;
4049 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4050 	if (slot == dr->dr_numslots - 1)
4051 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4052 	if (start)
4053 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4054 	if (end)
4055 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4056 	if (irq)
4057 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4058 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4059 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4060 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4061 
4062 	desc->dma.dma64.control0 = htole32(ctl0);
4063 	desc->dma.dma64.control1 = htole32(ctl1);
4064 	desc->dma.dma64.address_low = htole32(addrlo);
4065 	desc->dma.dma64.address_high = htole32(addrhi);
4066 }
4067 
4068 static void
4069 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4070 {
4071 
4072 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4073 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4074 }
4075 
4076 static void
4077 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4078 {
4079 
4080 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4081 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4082 }
4083 
4084 static void
4085 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4086 {
4087 
4088 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4089 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4090 }
4091 
4092 static int
4093 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4094 {
4095 	uint32_t val;
4096 
4097 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4098 	val &= BWN_DMA64_RXSTATDPTR;
4099 
4100 	return (val / sizeof(struct bwn_dmadesc64));
4101 }
4102 
4103 static void
4104 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4105 {
4106 
4107 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4108 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4109 }
4110 
4111 static int
4112 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4113 {
4114 	struct bwn_mac *mac = dr->dr_mac;
4115 	struct bwn_dma *dma = &mac->mac_method.dma;
4116 	struct bwn_softc *sc = mac->mac_sc;
4117 	int error;
4118 
4119 	error = bus_dma_tag_create(dma->parent_dtag,
4120 			    BWN_ALIGN, 0,
4121 			    BUS_SPACE_MAXADDR,
4122 			    BUS_SPACE_MAXADDR,
4123 			    NULL, NULL,
4124 			    BWN_DMA_RINGMEMSIZE,
4125 			    1,
4126 			    BUS_SPACE_MAXSIZE_32BIT,
4127 			    0,
4128 			    NULL, NULL,
4129 			    &dr->dr_ring_dtag);
4130 	if (error) {
4131 		device_printf(sc->sc_dev,
4132 		    "can't create TX ring DMA tag: TODO frees\n");
4133 		return (-1);
4134 	}
4135 
4136 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4137 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4138 	    &dr->dr_ring_dmap);
4139 	if (error) {
4140 		device_printf(sc->sc_dev,
4141 		    "can't allocate DMA mem: TODO frees\n");
4142 		return (-1);
4143 	}
4144 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4145 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4146 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4147 	if (error) {
4148 		device_printf(sc->sc_dev,
4149 		    "can't load DMA mem: TODO free\n");
4150 		return (-1);
4151 	}
4152 
4153 	return (0);
4154 }
4155 
4156 static void
4157 bwn_dma_setup(struct bwn_dma_ring *dr)
4158 {
4159 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4160 	uint64_t ring64;
4161 	uint32_t addrext, ring32, value;
4162 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4163 
4164 	if (dr->dr_tx) {
4165 		dr->dr_curslot = -1;
4166 
4167 		if (dr->dr_type == BWN_DMA_64BIT) {
4168 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4169 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4170 			    >> 30;
4171 			value = BWN_DMA64_TXENABLE;
4172 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4173 			    & BWN_DMA64_TXADDREXT_MASK;
4174 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4175 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4176 			    (ring64 & 0xffffffff));
4177 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4178 			    ((ring64 >> 32) &
4179 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4180 		} else {
4181 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4182 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4183 			value = BWN_DMA32_TXENABLE;
4184 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4185 			    & BWN_DMA32_TXADDREXT_MASK;
4186 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4187 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4188 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4189 		}
4190 		return;
4191 	}
4192 
4193 	/*
4194 	 * set for RX
4195 	 */
4196 	dr->dr_usedslot = dr->dr_numslots;
4197 
4198 	if (dr->dr_type == BWN_DMA_64BIT) {
4199 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4200 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4201 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4202 		value |= BWN_DMA64_RXENABLE;
4203 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4204 		    & BWN_DMA64_RXADDREXT_MASK;
4205 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4206 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4207 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4208 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4209 		    | (trans << 1));
4210 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4211 		    sizeof(struct bwn_dmadesc64));
4212 	} else {
4213 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4214 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4215 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4216 		value |= BWN_DMA32_RXENABLE;
4217 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4218 		    & BWN_DMA32_RXADDREXT_MASK;
4219 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4220 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4221 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4222 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4223 		    sizeof(struct bwn_dmadesc32));
4224 	}
4225 }
4226 
4227 static void
4228 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4229 {
4230 
4231 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4232 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4233 	    dr->dr_ring_dmap);
4234 }
4235 
4236 static void
4237 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4238 {
4239 
4240 	if (dr->dr_tx) {
4241 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4242 		if (dr->dr_type == BWN_DMA_64BIT) {
4243 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4244 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4245 		} else
4246 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4247 	} else {
4248 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4249 		if (dr->dr_type == BWN_DMA_64BIT) {
4250 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4251 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4252 		} else
4253 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4254 	}
4255 }
4256 
4257 static void
4258 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4259 {
4260 	struct bwn_dmadesc_generic *desc;
4261 	struct bwn_dmadesc_meta *meta;
4262 	struct bwn_mac *mac = dr->dr_mac;
4263 	struct bwn_dma *dma = &mac->mac_method.dma;
4264 	struct bwn_softc *sc = mac->mac_sc;
4265 	int i;
4266 
4267 	if (!dr->dr_usedslot)
4268 		return;
4269 	for (i = 0; i < dr->dr_numslots; i++) {
4270 		dr->getdesc(dr, i, &desc, &meta);
4271 
4272 		if (meta->mt_m == NULL) {
4273 			if (!dr->dr_tx)
4274 				device_printf(sc->sc_dev, "%s: not TX?\n",
4275 				    __func__);
4276 			continue;
4277 		}
4278 		if (dr->dr_tx) {
4279 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4280 				bus_dmamap_unload(dr->dr_txring_dtag,
4281 				    meta->mt_dmap);
4282 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4283 				bus_dmamap_unload(dma->txbuf_dtag,
4284 				    meta->mt_dmap);
4285 		} else
4286 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4287 		bwn_dma_free_descbuf(dr, meta);
4288 	}
4289 }
4290 
4291 static int
4292 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4293     int type)
4294 {
4295 	struct bwn_softc *sc = mac->mac_sc;
4296 	uint32_t value;
4297 	int i;
4298 	uint16_t offset;
4299 
4300 	for (i = 0; i < 10; i++) {
4301 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4302 		    BWN_DMA32_TXSTATUS;
4303 		value = BWN_READ_4(mac, base + offset);
4304 		if (type == BWN_DMA_64BIT) {
4305 			value &= BWN_DMA64_TXSTAT;
4306 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4307 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4308 			    value == BWN_DMA64_TXSTAT_STOPPED)
4309 				break;
4310 		} else {
4311 			value &= BWN_DMA32_TXSTATE;
4312 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4313 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4314 			    value == BWN_DMA32_TXSTAT_STOPPED)
4315 				break;
4316 		}
4317 		DELAY(1000);
4318 	}
4319 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4320 	BWN_WRITE_4(mac, base + offset, 0);
4321 	for (i = 0; i < 10; i++) {
4322 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4323 						   BWN_DMA32_TXSTATUS;
4324 		value = BWN_READ_4(mac, base + offset);
4325 		if (type == BWN_DMA_64BIT) {
4326 			value &= BWN_DMA64_TXSTAT;
4327 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4328 				i = -1;
4329 				break;
4330 			}
4331 		} else {
4332 			value &= BWN_DMA32_TXSTATE;
4333 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4334 				i = -1;
4335 				break;
4336 			}
4337 		}
4338 		DELAY(1000);
4339 	}
4340 	if (i != -1) {
4341 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4342 		return (ENODEV);
4343 	}
4344 	DELAY(1000);
4345 
4346 	return (0);
4347 }
4348 
4349 static int
4350 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4351     int type)
4352 {
4353 	struct bwn_softc *sc = mac->mac_sc;
4354 	uint32_t value;
4355 	int i;
4356 	uint16_t offset;
4357 
4358 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4359 	BWN_WRITE_4(mac, base + offset, 0);
4360 	for (i = 0; i < 10; i++) {
4361 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4362 		    BWN_DMA32_RXSTATUS;
4363 		value = BWN_READ_4(mac, base + offset);
4364 		if (type == BWN_DMA_64BIT) {
4365 			value &= BWN_DMA64_RXSTAT;
4366 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4367 				i = -1;
4368 				break;
4369 			}
4370 		} else {
4371 			value &= BWN_DMA32_RXSTATE;
4372 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4373 				i = -1;
4374 				break;
4375 			}
4376 		}
4377 		DELAY(1000);
4378 	}
4379 	if (i != -1) {
4380 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4381 		return (ENODEV);
4382 	}
4383 
4384 	return (0);
4385 }
4386 
4387 static void
4388 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4389     struct bwn_dmadesc_meta *meta)
4390 {
4391 
4392 	if (meta->mt_m != NULL) {
4393 		m_freem(meta->mt_m);
4394 		meta->mt_m = NULL;
4395 	}
4396 	if (meta->mt_ni != NULL) {
4397 		ieee80211_free_node(meta->mt_ni);
4398 		meta->mt_ni = NULL;
4399 	}
4400 }
4401 
4402 static void
4403 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4404 {
4405 	struct bwn_rxhdr4 *rxhdr;
4406 	unsigned char *frame;
4407 
4408 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4409 	rxhdr->frame_len = 0;
4410 
4411 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4412 	    sizeof(struct bwn_plcp6) + 2,
4413 	    ("%s:%d: fail", __func__, __LINE__));
4414 	frame = mtod(m, char *) + dr->dr_frameoffset;
4415 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4416 }
4417 
4418 static uint8_t
4419 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4420 {
4421 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4422 
4423 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4424 	    == 0xff);
4425 }
4426 
4427 static void
4428 bwn_wme_init(struct bwn_mac *mac)
4429 {
4430 
4431 	bwn_wme_load(mac);
4432 
4433 	/* enable WME support. */
4434 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4435 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4436 	    BWN_IFSCTL_USE_EDCF);
4437 }
4438 
4439 static void
4440 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4441 {
4442 	struct bwn_softc *sc = mac->mac_sc;
4443 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4444 	uint16_t delay;	/* microsec */
4445 
4446 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4447 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4448 		delay = 500;
4449 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4450 		delay = max(delay, (uint16_t)2400);
4451 
4452 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4453 }
4454 
4455 static void
4456 bwn_bt_enable(struct bwn_mac *mac)
4457 {
4458 	struct bwn_softc *sc = mac->mac_sc;
4459 	uint64_t hf;
4460 
4461 	if (bwn_bluetooth == 0)
4462 		return;
4463 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4464 		return;
4465 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4466 		return;
4467 
4468 	hf = bwn_hf_read(mac);
4469 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4470 		hf |= BWN_HF_BT_COEXISTALT;
4471 	else
4472 		hf |= BWN_HF_BT_COEXIST;
4473 	bwn_hf_write(mac, hf);
4474 }
4475 
4476 static void
4477 bwn_set_macaddr(struct bwn_mac *mac)
4478 {
4479 
4480 	bwn_mac_write_bssid(mac);
4481 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4482 }
4483 
4484 static void
4485 bwn_clear_keys(struct bwn_mac *mac)
4486 {
4487 	int i;
4488 
4489 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4490 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4491 		    ("%s:%d: fail", __func__, __LINE__));
4492 
4493 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4494 		    NULL, BWN_SEC_KEYSIZE, NULL);
4495 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4496 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4497 			    NULL, BWN_SEC_KEYSIZE, NULL);
4498 		}
4499 		mac->mac_key[i].keyconf = NULL;
4500 	}
4501 }
4502 
4503 static void
4504 bwn_crypt_init(struct bwn_mac *mac)
4505 {
4506 	struct bwn_softc *sc = mac->mac_sc;
4507 
4508 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4509 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4510 	    ("%s:%d: fail", __func__, __LINE__));
4511 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4512 	mac->mac_ktp *= 2;
4513 	if (siba_get_revid(sc->sc_dev) >= 5)
4514 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4515 	bwn_clear_keys(mac);
4516 }
4517 
4518 static void
4519 bwn_chip_exit(struct bwn_mac *mac)
4520 {
4521 	struct bwn_softc *sc = mac->mac_sc;
4522 
4523 	bwn_phy_exit(mac);
4524 	siba_gpio_set(sc->sc_dev, 0);
4525 }
4526 
4527 static int
4528 bwn_fw_fillinfo(struct bwn_mac *mac)
4529 {
4530 	int error;
4531 
4532 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4533 	if (error == 0)
4534 		return (0);
4535 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4536 	if (error == 0)
4537 		return (0);
4538 	return (error);
4539 }
4540 
4541 static int
4542 bwn_gpio_init(struct bwn_mac *mac)
4543 {
4544 	struct bwn_softc *sc = mac->mac_sc;
4545 	uint32_t mask = 0x1f, set = 0xf, value;
4546 
4547 	BWN_WRITE_4(mac, BWN_MACCTL,
4548 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4549 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4550 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4551 
4552 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4553 		mask |= 0x0060;
4554 		set |= 0x0060;
4555 	}
4556 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4557 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4558 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4559 		mask |= 0x0200;
4560 		set |= 0x0200;
4561 	}
4562 	if (siba_get_revid(sc->sc_dev) >= 2)
4563 		mask |= 0x0010;
4564 
4565 	value = siba_gpio_get(sc->sc_dev);
4566 	if (value == -1)
4567 		return (0);
4568 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4569 
4570 	return (0);
4571 }
4572 
4573 static int
4574 bwn_fw_loadinitvals(struct bwn_mac *mac)
4575 {
4576 #define	GETFWOFFSET(fwp, offset)				\
4577 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4578 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4579 	const struct bwn_fwhdr *hdr;
4580 	struct bwn_fw *fw = &mac->mac_fw;
4581 	int error;
4582 
4583 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4584 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4585 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4586 	if (error)
4587 		return (error);
4588 	if (fw->initvals_band.fw) {
4589 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4590 		error = bwn_fwinitvals_write(mac,
4591 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4592 		    be32toh(hdr->size),
4593 		    fw->initvals_band.fw->datasize - hdr_len);
4594 	}
4595 	return (error);
4596 #undef GETFWOFFSET
4597 }
4598 
4599 static int
4600 bwn_phy_init(struct bwn_mac *mac)
4601 {
4602 	struct bwn_softc *sc = mac->mac_sc;
4603 	int error;
4604 
4605 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4606 	mac->mac_phy.rf_onoff(mac, 1);
4607 	error = mac->mac_phy.init(mac);
4608 	if (error) {
4609 		device_printf(sc->sc_dev, "PHY init failed\n");
4610 		goto fail0;
4611 	}
4612 	error = bwn_switch_channel(mac,
4613 	    mac->mac_phy.get_default_chan(mac));
4614 	if (error) {
4615 		device_printf(sc->sc_dev,
4616 		    "failed to switch default channel\n");
4617 		goto fail1;
4618 	}
4619 	return (0);
4620 fail1:
4621 	if (mac->mac_phy.exit)
4622 		mac->mac_phy.exit(mac);
4623 fail0:
4624 	mac->mac_phy.rf_onoff(mac, 0);
4625 
4626 	return (error);
4627 }
4628 
4629 static void
4630 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4631 {
4632 	uint16_t ant;
4633 	uint16_t tmp;
4634 
4635 	ant = bwn_ant2phy(antenna);
4636 
4637 	/* For ACK/CTS */
4638 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4639 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4640 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4641 	/* For Probe Resposes */
4642 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4643 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4644 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4645 }
4646 
4647 static void
4648 bwn_set_opmode(struct bwn_mac *mac)
4649 {
4650 	struct bwn_softc *sc = mac->mac_sc;
4651 	struct ifnet *ifp = sc->sc_ifp;
4652 	struct ieee80211com *ic = ifp->if_l2com;
4653 	uint32_t ctl;
4654 	uint16_t cfp_pretbtt;
4655 
4656 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4657 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4658 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4659 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4660 	ctl |= BWN_MACCTL_STA;
4661 
4662 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4663 	    ic->ic_opmode == IEEE80211_M_MBSS)
4664 		ctl |= BWN_MACCTL_HOSTAP;
4665 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4666 		ctl &= ~BWN_MACCTL_STA;
4667 	ctl |= sc->sc_filters;
4668 
4669 	if (siba_get_revid(sc->sc_dev) <= 4)
4670 		ctl |= BWN_MACCTL_PROMISC;
4671 
4672 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4673 
4674 	cfp_pretbtt = 2;
4675 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4676 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4677 		    siba_get_chiprev(sc->sc_dev) == 3)
4678 			cfp_pretbtt = 100;
4679 		else
4680 			cfp_pretbtt = 50;
4681 	}
4682 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4683 }
4684 
4685 static int
4686 bwn_dma_gettype(struct bwn_mac *mac)
4687 {
4688 	uint32_t tmp;
4689 	uint16_t base;
4690 
4691 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4692 	if (tmp & SIBA_TGSHIGH_DMA64)
4693 		return (BWN_DMA_64BIT);
4694 	base = bwn_dma_base(0, 0);
4695 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4696 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4697 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4698 		return (BWN_DMA_32BIT);
4699 
4700 	return (BWN_DMA_30BIT);
4701 }
4702 
4703 static void
4704 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4705 {
4706 	if (!error) {
4707 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4708 		*((bus_addr_t *)arg) = seg->ds_addr;
4709 	}
4710 }
4711 
4712 static void
4713 bwn_phy_g_init_sub(struct bwn_mac *mac)
4714 {
4715 	struct bwn_phy *phy = &mac->mac_phy;
4716 	struct bwn_phy_g *pg = &phy->phy_g;
4717 	struct bwn_softc *sc = mac->mac_sc;
4718 	uint16_t i, tmp;
4719 
4720 	if (phy->rev == 1)
4721 		bwn_phy_init_b5(mac);
4722 	else
4723 		bwn_phy_init_b6(mac);
4724 
4725 	if (phy->rev >= 2 || phy->gmode)
4726 		bwn_phy_init_a(mac);
4727 
4728 	if (phy->rev >= 2) {
4729 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4730 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4731 	}
4732 	if (phy->rev == 2) {
4733 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4734 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4735 	}
4736 	if (phy->rev > 5) {
4737 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4738 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4739 	}
4740 	if (phy->gmode || phy->rev >= 2) {
4741 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4742 		tmp &= BWN_PHYVER_VERSION;
4743 		if (tmp == 3 || tmp == 5) {
4744 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4745 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4746 		}
4747 		if (tmp == 5) {
4748 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4749 			    0x1f00);
4750 		}
4751 	}
4752 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4753 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4754 	if (phy->rf_rev == 8) {
4755 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4756 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4757 	}
4758 	if (BWN_HAS_LOOPBACK(phy))
4759 		bwn_loopback_calcgain(mac);
4760 
4761 	if (phy->rf_rev != 8) {
4762 		if (pg->pg_initval == 0xffff)
4763 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4764 		else
4765 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4766 	}
4767 	bwn_lo_g_init(mac);
4768 	if (BWN_HAS_TXMAG(phy)) {
4769 		BWN_RF_WRITE(mac, 0x52,
4770 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4771 		    | pg->pg_loctl.tx_bias |
4772 		    pg->pg_loctl.tx_magn);
4773 	} else {
4774 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4775 	}
4776 	if (phy->rev >= 6) {
4777 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4778 		    (pg->pg_loctl.tx_bias << 12));
4779 	}
4780 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4781 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4782 	else
4783 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4784 	if (phy->rev < 2)
4785 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4786 	else
4787 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4788 	if (phy->gmode || phy->rev >= 2) {
4789 		bwn_lo_g_adjust(mac);
4790 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4791 	}
4792 
4793 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4794 		for (i = 0; i < 64; i++) {
4795 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4796 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4797 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4798 			    -32), 31));
4799 		}
4800 		bwn_nrssi_threshold(mac);
4801 	} else if (phy->gmode || phy->rev >= 2) {
4802 		if (pg->pg_nrssi[0] == -1000) {
4803 			KASSERT(pg->pg_nrssi[1] == -1000,
4804 			    ("%s:%d: fail", __func__, __LINE__));
4805 			bwn_nrssi_slope_11g(mac);
4806 		} else
4807 			bwn_nrssi_threshold(mac);
4808 	}
4809 	if (phy->rf_rev == 8)
4810 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4811 	bwn_phy_hwpctl_init(mac);
4812 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4813 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4814 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4815 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4816 	}
4817 }
4818 
4819 static uint8_t
4820 bwn_has_hwpctl(struct bwn_mac *mac)
4821 {
4822 
4823 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4824 		return (0);
4825 	return (mac->mac_phy.use_hwpctl(mac));
4826 }
4827 
4828 static void
4829 bwn_phy_init_b5(struct bwn_mac *mac)
4830 {
4831 	struct bwn_phy *phy = &mac->mac_phy;
4832 	struct bwn_phy_g *pg = &phy->phy_g;
4833 	struct bwn_softc *sc = mac->mac_sc;
4834 	uint16_t offset, value;
4835 	uint8_t old_channel;
4836 
4837 	if (phy->analog == 1)
4838 		BWN_RF_SET(mac, 0x007a, 0x0050);
4839 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4840 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4841 		value = 0x2120;
4842 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4843 			BWN_PHY_WRITE(mac, offset, value);
4844 			value += 0x202;
4845 		}
4846 	}
4847 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4848 	if (phy->rf_ver == 0x2050)
4849 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4850 
4851 	if (phy->gmode || phy->rev >= 2) {
4852 		if (phy->rf_ver == 0x2050) {
4853 			BWN_RF_SET(mac, 0x007a, 0x0020);
4854 			BWN_RF_SET(mac, 0x0051, 0x0004);
4855 		}
4856 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4857 
4858 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4859 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4860 
4861 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4862 
4863 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4864 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4865 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4866 	}
4867 
4868 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4869 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4870 
4871 	if (phy->analog == 1) {
4872 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4873 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4874 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4875 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4876 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4877 	} else
4878 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4879 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4880 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4881 
4882 	if (phy->analog == 1)
4883 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4884 	else
4885 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4886 
4887 	if (phy->analog == 0)
4888 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4889 
4890 	old_channel = phy->chan;
4891 	bwn_phy_g_switch_chan(mac, 7, 0);
4892 
4893 	if (phy->rf_ver != 0x2050) {
4894 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4895 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4896 	}
4897 
4898 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4899 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4900 
4901 	if (phy->rf_ver == 0x2050) {
4902 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4903 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4904 	}
4905 
4906 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4907 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4908 	BWN_RF_SET(mac, 0x007a, 0x0007);
4909 
4910 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4911 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4912 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4913 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4914 
4915 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4916 	    pg->pg_txctl);
4917 
4918 	if (phy->rf_ver == 0x2050)
4919 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4920 
4921 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4922 }
4923 
4924 static void
4925 bwn_loopback_calcgain(struct bwn_mac *mac)
4926 {
4927 	struct bwn_phy *phy = &mac->mac_phy;
4928 	struct bwn_phy_g *pg = &phy->phy_g;
4929 	struct bwn_softc *sc = mac->mac_sc;
4930 	uint16_t backup_phy[16] = { 0 };
4931 	uint16_t backup_radio[3];
4932 	uint16_t backup_bband;
4933 	uint16_t i, j, loop_i_max;
4934 	uint16_t trsw_rx;
4935 	uint16_t loop1_outer_done, loop1_inner_done;
4936 
4937 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4938 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4939 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4940 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4941 	if (phy->rev != 1) {
4942 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4943 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4944 	}
4945 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4946 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4947 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4948 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4949 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4950 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4951 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4952 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4953 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4954 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4955 	backup_bband = pg->pg_bbatt.att;
4956 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4957 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4958 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4959 
4960 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4961 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4962 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4963 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4964 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4965 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4966 	if (phy->rev != 1) {
4967 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4968 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4969 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4970 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4971 	}
4972 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4973 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4974 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4975 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4976 
4977 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4978 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4979 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4980 
4981 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4982 	if (phy->rev != 1) {
4983 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4984 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4985 	}
4986 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4987 
4988 	if (phy->rf_rev == 8)
4989 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4990 	else {
4991 		BWN_RF_WRITE(mac, 0x52, 0);
4992 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4993 	}
4994 	bwn_phy_g_set_bbatt(mac, 11);
4995 
4996 	if (phy->rev >= 3)
4997 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4998 	else
4999 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5000 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5001 
5002 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5003 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5004 
5005 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5006 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5007 
5008 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5009 		if (phy->rev >= 7) {
5010 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5011 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5012 		}
5013 	}
5014 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5015 
5016 	j = 0;
5017 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5018 	for (i = 0; i < loop_i_max; i++) {
5019 		for (j = 0; j < 16; j++) {
5020 			BWN_RF_WRITE(mac, 0x43, i);
5021 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5022 			    (j << 8));
5023 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5024 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5025 			DELAY(20);
5026 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5027 				goto done0;
5028 		}
5029 	}
5030 done0:
5031 	loop1_outer_done = i;
5032 	loop1_inner_done = j;
5033 	if (j >= 8) {
5034 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5035 		trsw_rx = 0x1b;
5036 		for (j = j - 8; j < 16; j++) {
5037 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5038 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5039 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5040 			DELAY(20);
5041 			trsw_rx -= 3;
5042 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5043 				goto done1;
5044 		}
5045 	} else
5046 		trsw_rx = 0x18;
5047 done1:
5048 
5049 	if (phy->rev != 1) {
5050 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5051 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5052 	}
5053 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5054 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5055 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5056 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5057 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5058 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5059 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5060 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5061 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5062 
5063 	bwn_phy_g_set_bbatt(mac, backup_bband);
5064 
5065 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5066 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5067 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5068 
5069 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5070 	DELAY(10);
5071 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5072 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5073 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5074 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5075 
5076 	pg->pg_max_lb_gain =
5077 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5078 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5079 }
5080 
5081 static uint16_t
5082 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5083 {
5084 	struct bwn_phy *phy = &mac->mac_phy;
5085 	uint32_t tmp1 = 0, tmp2 = 0;
5086 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5087 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5088 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5089 	static const uint8_t rcc_table[] = {
5090 		0x02, 0x03, 0x01, 0x0f,
5091 		0x06, 0x07, 0x05, 0x0f,
5092 		0x0a, 0x0b, 0x09, 0x0f,
5093 		0x0e, 0x0f, 0x0d, 0x0f,
5094 	};
5095 
5096 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5097 	    rfoverval = rfover = cck3 = 0;
5098 	radio0 = BWN_RF_READ(mac, 0x43);
5099 	radio1 = BWN_RF_READ(mac, 0x51);
5100 	radio2 = BWN_RF_READ(mac, 0x52);
5101 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5102 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5103 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5104 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5105 
5106 	if (phy->type == BWN_PHYTYPE_B) {
5107 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5108 		reg0 = BWN_READ_2(mac, 0x3ec);
5109 
5110 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5111 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5112 	} else if (phy->gmode || phy->rev >= 2) {
5113 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5114 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5115 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5116 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5117 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5118 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5119 
5120 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5121 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5122 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5123 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5124 		if (BWN_HAS_LOOPBACK(phy)) {
5125 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5126 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5127 			if (phy->rev >= 3)
5128 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5129 			else
5130 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5131 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5132 		}
5133 
5134 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5135 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5136 			BWN_LPD(0, 1, 1)));
5137 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5138 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5139 	}
5140 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5141 
5142 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5143 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5144 	reg1 = BWN_READ_2(mac, 0x3e6);
5145 	reg2 = BWN_READ_2(mac, 0x3f4);
5146 
5147 	if (phy->analog == 0)
5148 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5149 	else {
5150 		if (phy->analog >= 2)
5151 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5152 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5153 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5154 	}
5155 
5156 	reg = BWN_RF_READ(mac, 0x60);
5157 	index = (reg & 0x001e) >> 1;
5158 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5159 
5160 	if (phy->type == BWN_PHYTYPE_B)
5161 		BWN_RF_WRITE(mac, 0x78, 0x26);
5162 	if (phy->gmode || phy->rev >= 2) {
5163 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5164 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5165 			BWN_LPD(0, 1, 1)));
5166 	}
5167 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5168 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5169 	if (phy->gmode || phy->rev >= 2) {
5170 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5171 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5172 			BWN_LPD(0, 0, 1)));
5173 	}
5174 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5175 	BWN_RF_SET(mac, 0x51, 0x0004);
5176 	if (phy->rf_rev == 8)
5177 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5178 	else {
5179 		BWN_RF_WRITE(mac, 0x52, 0);
5180 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5181 	}
5182 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5183 
5184 	for (i = 0; i < 16; i++) {
5185 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5186 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5187 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5188 		if (phy->gmode || phy->rev >= 2) {
5189 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5190 			    bwn_rf_2050_rfoverval(mac,
5191 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5192 		}
5193 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5194 		DELAY(10);
5195 		if (phy->gmode || phy->rev >= 2) {
5196 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5197 			    bwn_rf_2050_rfoverval(mac,
5198 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5199 		}
5200 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5201 		DELAY(10);
5202 		if (phy->gmode || phy->rev >= 2) {
5203 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5204 			    bwn_rf_2050_rfoverval(mac,
5205 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5206 		}
5207 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5208 		DELAY(20);
5209 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5210 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5211 		if (phy->gmode || phy->rev >= 2) {
5212 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5213 			    bwn_rf_2050_rfoverval(mac,
5214 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5215 		}
5216 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5217 	}
5218 	DELAY(10);
5219 
5220 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5221 	tmp1++;
5222 	tmp1 >>= 9;
5223 
5224 	for (i = 0; i < 16; i++) {
5225 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5226 		BWN_RF_WRITE(mac, 0x78, radio78);
5227 		DELAY(10);
5228 		for (j = 0; j < 16; j++) {
5229 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5230 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5231 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5232 			if (phy->gmode || phy->rev >= 2) {
5233 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5234 				    bwn_rf_2050_rfoverval(mac,
5235 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5236 			}
5237 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5238 			DELAY(10);
5239 			if (phy->gmode || phy->rev >= 2) {
5240 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5241 				    bwn_rf_2050_rfoverval(mac,
5242 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5243 			}
5244 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5245 			DELAY(10);
5246 			if (phy->gmode || phy->rev >= 2) {
5247 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5248 				    bwn_rf_2050_rfoverval(mac,
5249 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5250 			}
5251 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5252 			DELAY(10);
5253 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5254 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5255 			if (phy->gmode || phy->rev >= 2) {
5256 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5257 				    bwn_rf_2050_rfoverval(mac,
5258 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5259 			}
5260 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5261 		}
5262 		tmp2++;
5263 		tmp2 >>= 8;
5264 		if (tmp1 < tmp2)
5265 			break;
5266 	}
5267 
5268 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5269 	BWN_RF_WRITE(mac, 0x51, radio1);
5270 	BWN_RF_WRITE(mac, 0x52, radio2);
5271 	BWN_RF_WRITE(mac, 0x43, radio0);
5272 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5273 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5274 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5275 	BWN_WRITE_2(mac, 0x3e6, reg1);
5276 	if (phy->analog != 0)
5277 		BWN_WRITE_2(mac, 0x3f4, reg2);
5278 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5279 	bwn_spu_workaround(mac, phy->chan);
5280 	if (phy->type == BWN_PHYTYPE_B) {
5281 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5282 		BWN_WRITE_2(mac, 0x3ec, reg0);
5283 	} else if (phy->gmode) {
5284 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5285 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5286 			    & 0x7fff);
5287 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5288 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5289 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5290 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5291 			      analogoverval);
5292 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5293 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5294 		if (BWN_HAS_LOOPBACK(phy)) {
5295 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5296 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5297 		}
5298 	}
5299 
5300 	return ((i > 15) ? radio78 : rcc);
5301 }
5302 
5303 static void
5304 bwn_phy_init_b6(struct bwn_mac *mac)
5305 {
5306 	struct bwn_phy *phy = &mac->mac_phy;
5307 	struct bwn_phy_g *pg = &phy->phy_g;
5308 	struct bwn_softc *sc = mac->mac_sc;
5309 	uint16_t offset, val;
5310 	uint8_t old_channel;
5311 
5312 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5313 	    ("%s:%d: fail", __func__, __LINE__));
5314 
5315 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5316 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5317 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5318 		BWN_RF_WRITE(mac, 0x51, 0x37);
5319 		BWN_RF_WRITE(mac, 0x52, 0x70);
5320 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5321 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5322 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5323 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5324 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5325 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5326 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5327 		bwn_hf_write(mac,
5328 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5329 	}
5330 	if (phy->rf_rev == 8) {
5331 		BWN_RF_WRITE(mac, 0x51, 0);
5332 		BWN_RF_WRITE(mac, 0x52, 0x40);
5333 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5334 		BWN_RF_WRITE(mac, 0x54, 0x98);
5335 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5336 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5337 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5338 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5339 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5340 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5341 		} else {
5342 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5343 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5344 		}
5345 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5346 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5347 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5348 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5349 	}
5350 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5351 		BWN_PHY_WRITE(mac, offset, val);
5352 		val -= 0x0202;
5353 	}
5354 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5355 		BWN_PHY_WRITE(mac, offset, val);
5356 		val -= 0x0202;
5357 	}
5358 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5359 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5360 		val += 0x0202;
5361 	}
5362 	if (phy->type == BWN_PHYTYPE_G) {
5363 		BWN_RF_SET(mac, 0x007a, 0x0020);
5364 		BWN_RF_SET(mac, 0x0051, 0x0004);
5365 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5366 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5367 		BWN_PHY_WRITE(mac, 0x5b, 0);
5368 		BWN_PHY_WRITE(mac, 0x5c, 0);
5369 	}
5370 
5371 	old_channel = phy->chan;
5372 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5373 
5374 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5375 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5376 	DELAY(40);
5377 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5378 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5379 		BWN_RF_WRITE(mac, 0x50, 0x20);
5380 	}
5381 	if (phy->rf_rev <= 2) {
5382 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5383 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5384 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5385 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5386 	}
5387 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5388 
5389 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5390 
5391 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5392 	if (phy->rf_rev >= 6)
5393 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5394 	else
5395 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5396 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5397 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5398 	    pg->pg_txctl);
5399 	if (phy->rf_rev <= 5)
5400 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5401 	if (phy->rf_rev <= 2)
5402 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5403 
5404 	if (phy->analog == 4) {
5405 		BWN_WRITE_2(mac, 0x3e4, 9);
5406 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5407 	} else
5408 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5409 	if (phy->type == BWN_PHYTYPE_B)
5410 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5411 	else if (phy->type == BWN_PHYTYPE_G)
5412 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5413 }
5414 
5415 static void
5416 bwn_phy_init_a(struct bwn_mac *mac)
5417 {
5418 	struct bwn_phy *phy = &mac->mac_phy;
5419 	struct bwn_softc *sc = mac->mac_sc;
5420 
5421 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5422 	    ("%s:%d: fail", __func__, __LINE__));
5423 
5424 	if (phy->rev >= 6) {
5425 		if (phy->type == BWN_PHYTYPE_A)
5426 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5427 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5428 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5429 		else
5430 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5431 	}
5432 
5433 	bwn_wa_init(mac);
5434 
5435 	if (phy->type == BWN_PHYTYPE_G &&
5436 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5437 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5438 }
5439 
5440 static void
5441 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5442 {
5443 	int i;
5444 
5445 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5446 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5447 }
5448 
5449 static void
5450 bwn_wa_agc(struct bwn_mac *mac)
5451 {
5452 	struct bwn_phy *phy = &mac->mac_phy;
5453 
5454 	if (phy->rev == 1) {
5455 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5456 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5457 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5458 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5459 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5460 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5461 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5462 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5463 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5464 	} else {
5465 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5466 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5467 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5468 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5469 	}
5470 
5471 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5472 	    0x5700);
5473 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5474 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5475 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5476 	BWN_RF_SET(mac, 0x7a, 0x0008);
5477 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5478 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5479 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5480 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5481 	if (phy->rev == 1)
5482 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5483 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5484 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5485 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5486 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5487 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5488 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5489 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5490 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5491 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5492 	if (phy->rev == 1) {
5493 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5494 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5495 	} else {
5496 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5497 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5498 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5499 		if (phy->rev >= 6) {
5500 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5501 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5502 			    (uint16_t)~0xf000, 0x3000);
5503 		}
5504 	}
5505 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5506 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5507 	if (phy->rev == 1) {
5508 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5509 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5510 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5511 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5512 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5513 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5514 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5515 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5516 	} else {
5517 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5518 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5519 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5520 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5521 	}
5522 	if (phy->rev >= 6) {
5523 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5524 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5525 	}
5526 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5527 }
5528 
5529 static void
5530 bwn_wa_grev1(struct bwn_mac *mac)
5531 {
5532 	struct bwn_phy *phy = &mac->mac_phy;
5533 	int i;
5534 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5535 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5536 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5537 
5538 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5539 
5540 	/* init CRSTHRES and ANTDWELL */
5541 	if (phy->rev == 1) {
5542 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5543 	} else if (phy->rev == 2) {
5544 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5545 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5546 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5547 	} else {
5548 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5549 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5550 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5551 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5552 	}
5553 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5554 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5555 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5556 
5557 	/* XXX support PHY-A??? */
5558 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5559 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5560 		    bwn_tab_finefreqg[i]);
5561 
5562 	/* XXX support PHY-A??? */
5563 	if (phy->rev == 1)
5564 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5565 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5566 			    bwn_tab_noise_g1[i]);
5567 	else
5568 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5569 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5570 			    bwn_tab_noise_g2[i]);
5571 
5572 
5573 	for (i = 0; i < N(bwn_tab_rotor); i++)
5574 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5575 		    bwn_tab_rotor[i]);
5576 
5577 	/* XXX support PHY-A??? */
5578 	if (phy->rev >= 6) {
5579 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5580 		    BWN_PHY_ENCORE_EN)
5581 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5582 		else
5583 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5584 	} else
5585 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5586 
5587 	for (i = 0; i < N(bwn_tab_retard); i++)
5588 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5589 		    bwn_tab_retard[i]);
5590 
5591 	if (phy->rev == 1) {
5592 		for (i = 0; i < 16; i++)
5593 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5594 			    i, 0x0020);
5595 	} else {
5596 		for (i = 0; i < 32; i++)
5597 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5598 	}
5599 
5600 	bwn_wa_agc(mac);
5601 }
5602 
5603 static void
5604 bwn_wa_grev26789(struct bwn_mac *mac)
5605 {
5606 	struct bwn_phy *phy = &mac->mac_phy;
5607 	int i;
5608 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5609 	uint16_t ofdmrev;
5610 
5611 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5612 
5613 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5614 
5615 	/* init CRSTHRES and ANTDWELL */
5616 	if (phy->rev == 1)
5617 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5618 	else if (phy->rev == 2) {
5619 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5620 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5621 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5622 	} else {
5623 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5624 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5625 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5626 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5627 	}
5628 
5629 	for (i = 0; i < 64; i++)
5630 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5631 
5632 	/* XXX support PHY-A??? */
5633 	if (phy->rev == 1)
5634 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5635 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5636 			    bwn_tab_noise_g1[i]);
5637 	else
5638 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5639 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5640 			    bwn_tab_noise_g2[i]);
5641 
5642 	/* XXX support PHY-A??? */
5643 	if (phy->rev >= 6) {
5644 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5645 		    BWN_PHY_ENCORE_EN)
5646 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5647 		else
5648 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5649 	} else
5650 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5651 
5652 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5653 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5654 		    bwn_tab_sigmasqr2[i]);
5655 
5656 	if (phy->rev == 1) {
5657 		for (i = 0; i < 16; i++)
5658 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5659 			    0x0020);
5660 	} else {
5661 		for (i = 0; i < 32; i++)
5662 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5663 	}
5664 
5665 	bwn_wa_agc(mac);
5666 
5667 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5668 	if (ofdmrev > 2) {
5669 		if (phy->type == BWN_PHYTYPE_A)
5670 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5671 		else
5672 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5673 	} else {
5674 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5675 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5676 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5677 	}
5678 
5679 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5680 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5681 }
5682 
5683 static void
5684 bwn_wa_init(struct bwn_mac *mac)
5685 {
5686 	struct bwn_phy *phy = &mac->mac_phy;
5687 	struct bwn_softc *sc = mac->mac_sc;
5688 
5689 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5690 
5691 	switch (phy->rev) {
5692 	case 1:
5693 		bwn_wa_grev1(mac);
5694 		break;
5695 	case 2:
5696 	case 6:
5697 	case 7:
5698 	case 8:
5699 	case 9:
5700 		bwn_wa_grev26789(mac);
5701 		break;
5702 	default:
5703 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5704 	}
5705 
5706 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5707 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5708 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5709 		if (phy->rev < 2) {
5710 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5711 			    0x0002);
5712 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5713 			    0x0001);
5714 		} else {
5715 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5716 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5717 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5718 			     BWN_BFL_EXTLNA) &&
5719 			    (phy->rev >= 7)) {
5720 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5721 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5722 				    0x0020, 0x0001);
5723 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5724 				    0x0021, 0x0001);
5725 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5726 				    0x0022, 0x0001);
5727 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5728 				    0x0023, 0x0000);
5729 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5730 				    0x0000, 0x0000);
5731 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5732 				    0x0003, 0x0002);
5733 			}
5734 		}
5735 	}
5736 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5737 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5738 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5739 	}
5740 
5741 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5742 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5743 }
5744 
5745 static void
5746 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5747     uint16_t value)
5748 {
5749 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5750 	uint16_t addr;
5751 
5752 	addr = table + offset;
5753 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5754 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5755 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5756 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5757 	}
5758 	pg->pg_ofdmtab_addr = addr;
5759 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5760 }
5761 
5762 static void
5763 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5764     uint32_t value)
5765 {
5766 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5767 	uint16_t addr;
5768 
5769 	addr = table + offset;
5770 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5771 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5772 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5773 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5774 	}
5775 	pg->pg_ofdmtab_addr = addr;
5776 
5777 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5778 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5779 }
5780 
5781 static void
5782 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5783     uint16_t value)
5784 {
5785 
5786 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5787 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5788 }
5789 
5790 static void
5791 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5792 {
5793 	struct bwn_phy *phy = &mac->mac_phy;
5794 	struct bwn_softc *sc = mac->mac_sc;
5795 	unsigned int i, max_loop;
5796 	uint16_t value;
5797 	uint32_t buffer[5] = {
5798 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5799 	};
5800 
5801 	if (ofdm) {
5802 		max_loop = 0x1e;
5803 		buffer[0] = 0x000201cc;
5804 	} else {
5805 		max_loop = 0xfa;
5806 		buffer[0] = 0x000b846e;
5807 	}
5808 
5809 	BWN_ASSERT_LOCKED(mac->mac_sc);
5810 
5811 	for (i = 0; i < 5; i++)
5812 		bwn_ram_write(mac, i * 4, buffer[i]);
5813 
5814 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5815 	BWN_WRITE_2(mac, 0x07c0,
5816 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5817 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5818 	BWN_WRITE_2(mac, 0x050c, value);
5819 	if (phy->type == BWN_PHYTYPE_LP)
5820 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5821 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5822 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5823 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5824 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5825 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5826 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5827 	if (phy->type == BWN_PHYTYPE_LP)
5828 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5829 	else
5830 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5831 
5832 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5833 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5834 	for (i = 0x00; i < max_loop; i++) {
5835 		value = BWN_READ_2(mac, 0x050e);
5836 		if (value & 0x0080)
5837 			break;
5838 		DELAY(10);
5839 	}
5840 	for (i = 0x00; i < 0x0a; i++) {
5841 		value = BWN_READ_2(mac, 0x050e);
5842 		if (value & 0x0400)
5843 			break;
5844 		DELAY(10);
5845 	}
5846 	for (i = 0x00; i < 0x19; i++) {
5847 		value = BWN_READ_2(mac, 0x0690);
5848 		if (!(value & 0x0100))
5849 			break;
5850 		DELAY(10);
5851 	}
5852 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5853 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5854 }
5855 
5856 static void
5857 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5858 {
5859 	uint32_t macctl;
5860 
5861 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5862 
5863 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5864 	if (macctl & BWN_MACCTL_BIGENDIAN)
5865 		printf("TODO: need swap\n");
5866 
5867 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5868 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5869 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5870 }
5871 
5872 static void
5873 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5874 {
5875 	uint16_t value;
5876 
5877 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5878 	    ("%s:%d: fail", __func__, __LINE__));
5879 
5880 	value = (uint8_t) (ctl->q);
5881 	value |= ((uint8_t) (ctl->i)) << 8;
5882 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5883 }
5884 
5885 static uint16_t
5886 bwn_lo_calcfeed(struct bwn_mac *mac,
5887     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5888 {
5889 	struct bwn_phy *phy = &mac->mac_phy;
5890 	struct bwn_softc *sc = mac->mac_sc;
5891 	uint16_t rfover;
5892 	uint16_t feedthrough;
5893 
5894 	if (phy->gmode) {
5895 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5896 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5897 
5898 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5899 		    ("%s:%d: fail", __func__, __LINE__));
5900 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5901 		    ("%s:%d: fail", __func__, __LINE__));
5902 
5903 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5904 
5905 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5906 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5907 		    phy->rev > 6)
5908 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5909 
5910 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5911 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5912 		DELAY(10);
5913 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5914 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5915 		DELAY(10);
5916 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5917 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5918 		DELAY(10);
5919 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5920 	} else {
5921 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5922 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5923 		DELAY(10);
5924 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5925 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5926 		DELAY(10);
5927 		pga |= BWN_PHY_PGACTL_LPF;
5928 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5929 	}
5930 	DELAY(21);
5931 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5932 
5933 	return (feedthrough);
5934 }
5935 
5936 static uint16_t
5937 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5938     uint16_t *value, uint16_t *pad_mix_gain)
5939 {
5940 	struct bwn_phy *phy = &mac->mac_phy;
5941 	uint16_t reg, v, padmix;
5942 
5943 	if (phy->type == BWN_PHYTYPE_B) {
5944 		v = 0x30;
5945 		if (phy->rf_rev <= 5) {
5946 			reg = 0x43;
5947 			padmix = 0;
5948 		} else {
5949 			reg = 0x52;
5950 			padmix = 5;
5951 		}
5952 	} else {
5953 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5954 			reg = 0x43;
5955 			v = 0x10;
5956 			padmix = 2;
5957 		} else {
5958 			reg = 0x52;
5959 			v = 0x30;
5960 			padmix = 5;
5961 		}
5962 	}
5963 	if (value)
5964 		*value = v;
5965 	if (pad_mix_gain)
5966 		*pad_mix_gain = padmix;
5967 
5968 	return (reg);
5969 }
5970 
5971 static void
5972 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5973 {
5974 	struct bwn_phy *phy = &mac->mac_phy;
5975 	struct bwn_phy_g *pg = &phy->phy_g;
5976 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5977 	uint16_t reg, mask;
5978 	uint16_t trsw_rx, pga;
5979 	uint16_t rf_pctl_reg;
5980 
5981 	static const uint8_t tx_bias_values[] = {
5982 		0x09, 0x08, 0x0a, 0x01, 0x00,
5983 		0x02, 0x05, 0x04, 0x06,
5984 	};
5985 	static const uint8_t tx_magn_values[] = {
5986 		0x70, 0x40,
5987 	};
5988 
5989 	if (!BWN_HAS_LOOPBACK(phy)) {
5990 		rf_pctl_reg = 6;
5991 		trsw_rx = 2;
5992 		pga = 0;
5993 	} else {
5994 		int lb_gain;
5995 
5996 		trsw_rx = 0;
5997 		lb_gain = pg->pg_max_lb_gain / 2;
5998 		if (lb_gain > 10) {
5999 			rf_pctl_reg = 0;
6000 			pga = abs(10 - lb_gain) / 6;
6001 			pga = MIN(MAX(pga, 0), 15);
6002 		} else {
6003 			int cmp_val;
6004 			int tmp;
6005 
6006 			pga = 0;
6007 			cmp_val = 0x24;
6008 			if ((phy->rev >= 2) &&
6009 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6010 				cmp_val = 0x3c;
6011 			tmp = lb_gain;
6012 			if ((10 - lb_gain) < cmp_val)
6013 				tmp = (10 - lb_gain);
6014 			if (tmp < 0)
6015 				tmp += 6;
6016 			else
6017 				tmp += 3;
6018 			cmp_val /= 4;
6019 			tmp /= 4;
6020 			if (tmp >= cmp_val)
6021 				rf_pctl_reg = cmp_val;
6022 			else
6023 				rf_pctl_reg = tmp;
6024 		}
6025 	}
6026 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6027 	bwn_phy_g_set_bbatt(mac, 2);
6028 
6029 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6030 	mask = ~mask;
6031 	BWN_RF_MASK(mac, reg, mask);
6032 
6033 	if (BWN_HAS_TXMAG(phy)) {
6034 		int i, j;
6035 		int feedthrough;
6036 		int min_feedth = 0xffff;
6037 		uint8_t tx_magn, tx_bias;
6038 
6039 		for (i = 0; i < N(tx_magn_values); i++) {
6040 			tx_magn = tx_magn_values[i];
6041 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6042 			for (j = 0; j < N(tx_bias_values); j++) {
6043 				tx_bias = tx_bias_values[j];
6044 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6045 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6046 				    trsw_rx);
6047 				if (feedthrough < min_feedth) {
6048 					lo->tx_bias = tx_bias;
6049 					lo->tx_magn = tx_magn;
6050 					min_feedth = feedthrough;
6051 				}
6052 				if (lo->tx_bias == 0)
6053 					break;
6054 			}
6055 			BWN_RF_WRITE(mac, 0x52,
6056 					  (BWN_RF_READ(mac, 0x52)
6057 					   & 0xff00) | lo->tx_bias | lo->
6058 					  tx_magn);
6059 		}
6060 	} else {
6061 		lo->tx_magn = 0;
6062 		lo->tx_bias = 0;
6063 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6064 	}
6065 
6066 	BWN_GETTIME(lo->txctl_measured_time);
6067 }
6068 
6069 static void
6070 bwn_lo_get_powervector(struct bwn_mac *mac)
6071 {
6072 	struct bwn_phy *phy = &mac->mac_phy;
6073 	struct bwn_phy_g *pg = &phy->phy_g;
6074 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6075 	int i;
6076 	uint64_t tmp;
6077 	uint64_t power_vector = 0;
6078 
6079 	for (i = 0; i < 8; i += 2) {
6080 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6081 		power_vector |= (tmp << (i * 8));
6082 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6083 	}
6084 	if (power_vector)
6085 		lo->power_vector = power_vector;
6086 
6087 	BWN_GETTIME(lo->pwr_vec_read_time);
6088 }
6089 
6090 static void
6091 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6092     int use_trsw_rx)
6093 {
6094 	struct bwn_phy *phy = &mac->mac_phy;
6095 	struct bwn_phy_g *pg = &phy->phy_g;
6096 	uint16_t tmp;
6097 
6098 	if (max_rx_gain < 0)
6099 		max_rx_gain = 0;
6100 
6101 	if (BWN_HAS_LOOPBACK(phy)) {
6102 		int trsw_rx = 0;
6103 		int trsw_rx_gain;
6104 
6105 		if (use_trsw_rx) {
6106 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6107 			if (max_rx_gain >= trsw_rx_gain) {
6108 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6109 				trsw_rx = 0x20;
6110 			}
6111 		} else
6112 			trsw_rx_gain = max_rx_gain;
6113 		if (trsw_rx_gain < 9) {
6114 			pg->pg_lna_lod_gain = 0;
6115 		} else {
6116 			pg->pg_lna_lod_gain = 1;
6117 			trsw_rx_gain -= 8;
6118 		}
6119 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6120 		pg->pg_pga_gain = trsw_rx_gain / 3;
6121 		if (pg->pg_pga_gain >= 5) {
6122 			pg->pg_pga_gain -= 5;
6123 			pg->pg_lna_gain = 2;
6124 		} else
6125 			pg->pg_lna_gain = 0;
6126 	} else {
6127 		pg->pg_lna_gain = 0;
6128 		pg->pg_trsw_rx_gain = 0x20;
6129 		if (max_rx_gain >= 0x14) {
6130 			pg->pg_lna_lod_gain = 1;
6131 			pg->pg_pga_gain = 2;
6132 		} else if (max_rx_gain >= 0x12) {
6133 			pg->pg_lna_lod_gain = 1;
6134 			pg->pg_pga_gain = 1;
6135 		} else if (max_rx_gain >= 0xf) {
6136 			pg->pg_lna_lod_gain = 1;
6137 			pg->pg_pga_gain = 0;
6138 		} else {
6139 			pg->pg_lna_lod_gain = 0;
6140 			pg->pg_pga_gain = 0;
6141 		}
6142 	}
6143 
6144 	tmp = BWN_RF_READ(mac, 0x7a);
6145 	if (pg->pg_lna_lod_gain == 0)
6146 		tmp &= ~0x0008;
6147 	else
6148 		tmp |= 0x0008;
6149 	BWN_RF_WRITE(mac, 0x7a, tmp);
6150 }
6151 
6152 static void
6153 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6154 {
6155 	struct bwn_phy *phy = &mac->mac_phy;
6156 	struct bwn_phy_g *pg = &phy->phy_g;
6157 	struct bwn_softc *sc = mac->mac_sc;
6158 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6159 	struct timespec ts;
6160 	uint16_t tmp;
6161 
6162 	if (bwn_has_hwpctl(mac)) {
6163 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6164 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6165 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6166 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6167 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6168 
6169 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6170 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6171 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6172 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6173 	}
6174 	if (phy->type == BWN_PHYTYPE_B &&
6175 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6176 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6177 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6178 	}
6179 	if (phy->rev >= 2) {
6180 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6181 		sav->phy_analogoverval =
6182 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6183 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6184 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6185 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6186 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6187 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6188 
6189 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6190 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6191 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6192 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6193 		if (phy->type == BWN_PHYTYPE_G) {
6194 			if ((phy->rev >= 7) &&
6195 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6196 			     BWN_BFL_EXTLNA)) {
6197 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6198 			} else {
6199 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6200 			}
6201 		} else {
6202 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6203 		}
6204 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6205 	}
6206 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6207 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6208 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6209 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6210 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6211 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6212 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6213 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6214 
6215 	if (!BWN_HAS_TXMAG(phy)) {
6216 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6217 		sav->rf2 &= 0x00f0;
6218 	}
6219 	if (phy->type == BWN_PHYTYPE_B) {
6220 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6221 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6222 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6223 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6224 	} else {
6225 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6226 			    | 0x8000);
6227 	}
6228 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6229 		    & 0xf000);
6230 
6231 	tmp =
6232 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6233 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6234 
6235 	tmp = sav->phy_syncctl;
6236 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6237 	tmp = sav->rf1;
6238 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6239 
6240 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6241 	if (phy->type == BWN_PHYTYPE_G ||
6242 	    (phy->type == BWN_PHYTYPE_B &&
6243 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6244 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6245 	} else
6246 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6247 	if (phy->rev >= 2)
6248 		bwn_dummy_transmission(mac, 0, 1);
6249 	bwn_phy_g_switch_chan(mac, 6, 0);
6250 	BWN_RF_READ(mac, 0x51);
6251 	if (phy->type == BWN_PHYTYPE_G)
6252 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6253 
6254 	nanouptime(&ts);
6255 	if (time_before(lo->txctl_measured_time,
6256 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6257 		bwn_lo_measure_txctl_values(mac);
6258 
6259 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6260 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6261 	else {
6262 		if (phy->type == BWN_PHYTYPE_B)
6263 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6264 		else
6265 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6266 	}
6267 }
6268 
6269 static void
6270 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6271 {
6272 	struct bwn_phy *phy = &mac->mac_phy;
6273 	struct bwn_phy_g *pg = &phy->phy_g;
6274 	uint16_t tmp;
6275 
6276 	if (phy->rev >= 2) {
6277 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6278 		tmp = (pg->pg_pga_gain << 8);
6279 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6280 		DELAY(5);
6281 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6282 		DELAY(2);
6283 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6284 	} else {
6285 		tmp = (pg->pg_pga_gain | 0xefa0);
6286 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6287 	}
6288 	if (phy->type == BWN_PHYTYPE_G) {
6289 		if (phy->rev >= 3)
6290 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6291 		else
6292 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6293 		if (phy->rev >= 2)
6294 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6295 		else
6296 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6297 	}
6298 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6299 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6300 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6301 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6302 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6303 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6304 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6305 	if (!BWN_HAS_TXMAG(phy)) {
6306 		tmp = sav->rf2;
6307 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6308 	}
6309 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6310 	if (phy->type == BWN_PHYTYPE_B &&
6311 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6312 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6313 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6314 	}
6315 	if (phy->rev >= 2) {
6316 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6317 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6318 			      sav->phy_analogoverval);
6319 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6320 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6321 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6322 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6323 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6324 	}
6325 	if (bwn_has_hwpctl(mac)) {
6326 		tmp = (sav->phy_lomask & 0xbfff);
6327 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6328 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6329 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6330 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6331 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6332 	}
6333 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6334 }
6335 
6336 static int
6337 bwn_lo_probe_loctl(struct bwn_mac *mac,
6338     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6339 {
6340 	struct bwn_phy *phy = &mac->mac_phy;
6341 	struct bwn_phy_g *pg = &phy->phy_g;
6342 	struct bwn_loctl orig, test;
6343 	struct bwn_loctl prev = { -100, -100 };
6344 	static const struct bwn_loctl modifiers[] = {
6345 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6346 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6347 	};
6348 	int begin, end, lower = 0, i;
6349 	uint16_t feedth;
6350 
6351 	if (d->curstate == 0) {
6352 		begin = 1;
6353 		end = 8;
6354 	} else if (d->curstate % 2 == 0) {
6355 		begin = d->curstate - 1;
6356 		end = d->curstate + 1;
6357 	} else {
6358 		begin = d->curstate - 2;
6359 		end = d->curstate + 2;
6360 	}
6361 	if (begin < 1)
6362 		begin += 8;
6363 	if (end > 8)
6364 		end -= 8;
6365 
6366 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6367 	i = begin;
6368 	d->curstate = i;
6369 	while (1) {
6370 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6371 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6372 		test.i += modifiers[i - 1].i * d->multipler;
6373 		test.q += modifiers[i - 1].q * d->multipler;
6374 		if ((test.i != prev.i || test.q != prev.q) &&
6375 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6376 			bwn_lo_write(mac, &test);
6377 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6378 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6379 			if (feedth < d->feedth) {
6380 				memcpy(probe, &test,
6381 				    sizeof(struct bwn_loctl));
6382 				lower = 1;
6383 				d->feedth = feedth;
6384 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6385 					break;
6386 			}
6387 		}
6388 		memcpy(&prev, &test, sizeof(prev));
6389 		if (i == end)
6390 			break;
6391 		if (i == 8)
6392 			i = 1;
6393 		else
6394 			i++;
6395 		d->curstate = i;
6396 	}
6397 
6398 	return (lower);
6399 }
6400 
6401 static void
6402 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6403 {
6404 	struct bwn_phy *phy = &mac->mac_phy;
6405 	struct bwn_phy_g *pg = &phy->phy_g;
6406 	struct bwn_lo_g_sm d;
6407 	struct bwn_loctl probe;
6408 	int lower, repeat, cnt = 0;
6409 	uint16_t feedth;
6410 
6411 	d.nmeasure = 0;
6412 	d.multipler = 1;
6413 	if (BWN_HAS_LOOPBACK(phy))
6414 		d.multipler = 3;
6415 
6416 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6417 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6418 
6419 	do {
6420 		bwn_lo_write(mac, &d.loctl);
6421 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6422 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6423 		if (feedth < 0x258) {
6424 			if (feedth >= 0x12c)
6425 				*rxgain += 6;
6426 			else
6427 				*rxgain += 3;
6428 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6429 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6430 		}
6431 		d.feedth = feedth;
6432 		d.curstate = 0;
6433 		do {
6434 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6435 			    ("%s:%d: fail", __func__, __LINE__));
6436 			memcpy(&probe, &d.loctl,
6437 			       sizeof(struct bwn_loctl));
6438 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6439 			if (!lower)
6440 				break;
6441 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6442 				break;
6443 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6444 			d.nmeasure++;
6445 		} while (d.nmeasure < 24);
6446 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6447 
6448 		if (BWN_HAS_LOOPBACK(phy)) {
6449 			if (d.feedth > 0x1194)
6450 				*rxgain -= 6;
6451 			else if (d.feedth < 0x5dc)
6452 				*rxgain += 3;
6453 			if (cnt == 0) {
6454 				if (d.feedth <= 0x5dc) {
6455 					d.multipler = 1;
6456 					cnt++;
6457 				} else
6458 					d.multipler = 2;
6459 			} else if (cnt == 2)
6460 				d.multipler = 1;
6461 		}
6462 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6463 	} while (++cnt < repeat);
6464 }
6465 
6466 static struct bwn_lo_calib *
6467 bwn_lo_calibset(struct bwn_mac *mac,
6468     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6469 {
6470 	struct bwn_phy *phy = &mac->mac_phy;
6471 	struct bwn_phy_g *pg = &phy->phy_g;
6472 	struct bwn_loctl loctl = { 0, 0 };
6473 	struct bwn_lo_calib *cal;
6474 	struct bwn_lo_g_value sval = { 0 };
6475 	int rxgain;
6476 	uint16_t pad, reg, value;
6477 
6478 	sval.old_channel = phy->chan;
6479 	bwn_mac_suspend(mac);
6480 	bwn_lo_save(mac, &sval);
6481 
6482 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6483 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6484 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6485 
6486 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6487 	if (rfatt->padmix)
6488 		rxgain -= pad;
6489 	if (BWN_HAS_LOOPBACK(phy))
6490 		rxgain += pg->pg_max_lb_gain;
6491 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6492 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6493 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6494 
6495 	bwn_lo_restore(mac, &sval);
6496 	bwn_mac_enable(mac);
6497 
6498 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6499 	if (!cal) {
6500 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6501 		return (NULL);
6502 	}
6503 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6504 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6505 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6506 
6507 	BWN_GETTIME(cal->calib_time);
6508 
6509 	return (cal);
6510 }
6511 
6512 static struct bwn_lo_calib *
6513 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6514     const struct bwn_rfatt *rfatt)
6515 {
6516 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6517 	struct bwn_lo_calib *c;
6518 
6519 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6520 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6521 			continue;
6522 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6523 			continue;
6524 		return (c);
6525 	}
6526 
6527 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6528 	if (!c)
6529 		return (NULL);
6530 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6531 
6532 	return (c);
6533 }
6534 
6535 static void
6536 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6537 {
6538 	struct bwn_phy *phy = &mac->mac_phy;
6539 	struct bwn_phy_g *pg = &phy->phy_g;
6540 	struct bwn_softc *sc = mac->mac_sc;
6541 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6542 	const struct bwn_rfatt *rfatt;
6543 	const struct bwn_bbatt *bbatt;
6544 	uint64_t pvector;
6545 	int i;
6546 	int rf_offset, bb_offset;
6547 	uint8_t changed = 0;
6548 
6549 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6550 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6551 	    ("%s:%d: fail", __func__, __LINE__));
6552 
6553 	pvector = lo->power_vector;
6554 	if (!update && !pvector)
6555 		return;
6556 
6557 	bwn_mac_suspend(mac);
6558 
6559 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6560 		struct bwn_lo_calib *cal;
6561 		int idx;
6562 		uint16_t val;
6563 
6564 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6565 			continue;
6566 		bb_offset = i / lo->rfatt.len;
6567 		rf_offset = i % lo->rfatt.len;
6568 		bbatt = &(lo->bbatt.array[bb_offset]);
6569 		rfatt = &(lo->rfatt.array[rf_offset]);
6570 
6571 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6572 		if (!cal) {
6573 			device_printf(sc->sc_dev, "LO: Could not "
6574 			    "calibrate DC table entry\n");
6575 			continue;
6576 		}
6577 		val = (uint8_t)(cal->ctl.q);
6578 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6579 		free(cal, M_DEVBUF);
6580 
6581 		idx = i / 2;
6582 		if (i % 2)
6583 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6584 			    | ((val & 0x00ff) << 8);
6585 		else
6586 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6587 			    | (val & 0x00ff);
6588 		changed = 1;
6589 	}
6590 	if (changed) {
6591 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6592 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6593 	}
6594 	bwn_mac_enable(mac);
6595 }
6596 
6597 static void
6598 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6599 {
6600 
6601 	if (!rf->padmix)
6602 		return;
6603 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6604 		rf->att = 4;
6605 }
6606 
6607 static void
6608 bwn_lo_g_adjust(struct bwn_mac *mac)
6609 {
6610 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6611 	struct bwn_lo_calib *cal;
6612 	struct bwn_rfatt rf;
6613 
6614 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6615 	bwn_lo_fixup_rfatt(&rf);
6616 
6617 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6618 	if (!cal)
6619 		return;
6620 	bwn_lo_write(mac, &cal->ctl);
6621 }
6622 
6623 static void
6624 bwn_lo_g_init(struct bwn_mac *mac)
6625 {
6626 
6627 	if (!bwn_has_hwpctl(mac))
6628 		return;
6629 
6630 	bwn_lo_get_powervector(mac);
6631 	bwn_phy_g_dc_lookup_init(mac, 1);
6632 }
6633 
6634 static void
6635 bwn_mac_suspend(struct bwn_mac *mac)
6636 {
6637 	struct bwn_softc *sc = mac->mac_sc;
6638 	int i;
6639 	uint32_t tmp;
6640 
6641 	KASSERT(mac->mac_suspended >= 0,
6642 	    ("%s:%d: fail", __func__, __LINE__));
6643 
6644 	if (mac->mac_suspended == 0) {
6645 		bwn_psctl(mac, BWN_PS_AWAKE);
6646 		BWN_WRITE_4(mac, BWN_MACCTL,
6647 			    BWN_READ_4(mac, BWN_MACCTL)
6648 			    & ~BWN_MACCTL_ON);
6649 		BWN_READ_4(mac, BWN_MACCTL);
6650 		for (i = 35; i; i--) {
6651 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6652 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6653 				goto out;
6654 			DELAY(10);
6655 		}
6656 		for (i = 40; i; i--) {
6657 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6658 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6659 				goto out;
6660 			DELAY(1000);
6661 		}
6662 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6663 	}
6664 out:
6665 	mac->mac_suspended++;
6666 }
6667 
6668 static void
6669 bwn_mac_enable(struct bwn_mac *mac)
6670 {
6671 	struct bwn_softc *sc = mac->mac_sc;
6672 	uint16_t state;
6673 
6674 	state = bwn_shm_read_2(mac, BWN_SHARED,
6675 	    BWN_SHARED_UCODESTAT);
6676 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6677 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6678 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6679 
6680 	mac->mac_suspended--;
6681 	KASSERT(mac->mac_suspended >= 0,
6682 	    ("%s:%d: fail", __func__, __LINE__));
6683 	if (mac->mac_suspended == 0) {
6684 		BWN_WRITE_4(mac, BWN_MACCTL,
6685 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6686 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6687 		BWN_READ_4(mac, BWN_MACCTL);
6688 		BWN_READ_4(mac, BWN_INTR_REASON);
6689 		bwn_psctl(mac, 0);
6690 	}
6691 }
6692 
6693 static void
6694 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6695 {
6696 	struct bwn_softc *sc = mac->mac_sc;
6697 	int i;
6698 	uint16_t ucstat;
6699 
6700 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6701 	    ("%s:%d: fail", __func__, __LINE__));
6702 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6703 	    ("%s:%d: fail", __func__, __LINE__));
6704 
6705 	/* XXX forcibly awake and hwps-off */
6706 
6707 	BWN_WRITE_4(mac, BWN_MACCTL,
6708 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6709 	    ~BWN_MACCTL_HWPS);
6710 	BWN_READ_4(mac, BWN_MACCTL);
6711 	if (siba_get_revid(sc->sc_dev) >= 5) {
6712 		for (i = 0; i < 100; i++) {
6713 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6714 			    BWN_SHARED_UCODESTAT);
6715 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6716 				break;
6717 			DELAY(10);
6718 		}
6719 	}
6720 }
6721 
6722 static int16_t
6723 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6724 {
6725 
6726 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6727 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6728 }
6729 
6730 static void
6731 bwn_nrssi_threshold(struct bwn_mac *mac)
6732 {
6733 	struct bwn_phy *phy = &mac->mac_phy;
6734 	struct bwn_phy_g *pg = &phy->phy_g;
6735 	struct bwn_softc *sc = mac->mac_sc;
6736 	int32_t a, b;
6737 	int16_t tmp16;
6738 	uint16_t tmpu16;
6739 
6740 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6741 
6742 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6743 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6744 			a = 0x13;
6745 			b = 0x12;
6746 		} else {
6747 			a = 0xe;
6748 			b = 0x11;
6749 		}
6750 
6751 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6752 		a += (pg->pg_nrssi[0] << 6);
6753 		a += (a < 32) ? 31 : 32;
6754 		a = a >> 6;
6755 		a = MIN(MAX(a, -31), 31);
6756 
6757 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6758 		b += (pg->pg_nrssi[0] << 6);
6759 		if (b < 32)
6760 			b += 31;
6761 		else
6762 			b += 32;
6763 		b = b >> 6;
6764 		b = MIN(MAX(b, -31), 31);
6765 
6766 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6767 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6768 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6769 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6770 		return;
6771 	}
6772 
6773 	tmp16 = bwn_nrssi_read(mac, 0x20);
6774 	if (tmp16 >= 0x20)
6775 		tmp16 -= 0x40;
6776 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6777 }
6778 
6779 static void
6780 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6781 {
6782 #define	SAVE_RF_MAX		3
6783 #define	SAVE_PHY_COMM_MAX	4
6784 #define	SAVE_PHY3_MAX		8
6785 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6786 		{ 0x7a, 0x52, 0x43 };
6787 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6788 		{ 0x15, 0x5a, 0x59, 0x58 };
6789 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6790 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6791 		0x0801, 0x0060, 0x0014, 0x0478
6792 	};
6793 	struct bwn_phy *phy = &mac->mac_phy;
6794 	struct bwn_phy_g *pg = &phy->phy_g;
6795 	int32_t i, tmp32, phy3_idx = 0;
6796 	uint16_t delta, tmp;
6797 	uint16_t save_rf[SAVE_RF_MAX];
6798 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6799 	uint16_t save_phy3[SAVE_PHY3_MAX];
6800 	uint16_t ant_div, phy0, chan_ex;
6801 	int16_t nrssi0, nrssi1;
6802 
6803 	KASSERT(phy->type == BWN_PHYTYPE_G,
6804 	    ("%s:%d: fail", __func__, __LINE__));
6805 
6806 	if (phy->rf_rev >= 9)
6807 		return;
6808 	if (phy->rf_rev == 8)
6809 		bwn_nrssi_offset(mac);
6810 
6811 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6812 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6813 
6814 	/*
6815 	 * Save RF/PHY registers for later restoration
6816 	 */
6817 	ant_div = BWN_READ_2(mac, 0x03e2);
6818 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6819 	for (i = 0; i < SAVE_RF_MAX; ++i)
6820 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6821 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6822 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6823 
6824 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6825 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6826 	if (phy->rev >= 3) {
6827 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6828 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6829 		BWN_PHY_WRITE(mac, 0x002e, 0);
6830 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6831 		switch (phy->rev) {
6832 		case 4:
6833 		case 6:
6834 		case 7:
6835 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6836 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6837 			break;
6838 		case 3:
6839 		case 5:
6840 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6841 			break;
6842 		}
6843 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6844 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6845 	}
6846 	/*
6847 	 * Calculate nrssi0
6848 	 */
6849 	BWN_RF_SET(mac, 0x007a, 0x0070);
6850 	bwn_set_all_gains(mac, 0, 8, 0);
6851 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6852 	if (phy->rev >= 2) {
6853 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6854 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6855 	}
6856 	BWN_RF_SET(mac, 0x007a, 0x0080);
6857 	DELAY(20);
6858 
6859 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6860 	if (nrssi0 >= 0x0020)
6861 		nrssi0 -= 0x0040;
6862 
6863 	/*
6864 	 * Calculate nrssi1
6865 	 */
6866 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6867 	if (phy->rev >= 2)
6868 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6869 
6870 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6871 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6872 	BWN_RF_SET(mac, 0x007a, 0x000f);
6873 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6874 	if (phy->rev >= 2) {
6875 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6876 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6877 	}
6878 
6879 	bwn_set_all_gains(mac, 3, 0, 1);
6880 	if (phy->rf_rev == 8) {
6881 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6882 	} else {
6883 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6884 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6885 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6886 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6887 	}
6888 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6889 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6890 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6891 	DELAY(20);
6892 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6893 
6894 	/*
6895 	 * Install calculated narrow RSSI values
6896 	 */
6897 	if (nrssi1 >= 0x0020)
6898 		nrssi1 -= 0x0040;
6899 	if (nrssi0 == nrssi1)
6900 		pg->pg_nrssi_slope = 0x00010000;
6901 	else
6902 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6903 	if (nrssi0 >= -4) {
6904 		pg->pg_nrssi[0] = nrssi1;
6905 		pg->pg_nrssi[1] = nrssi0;
6906 	}
6907 
6908 	/*
6909 	 * Restore saved RF/PHY registers
6910 	 */
6911 	if (phy->rev >= 3) {
6912 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6913 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6914 			    save_phy3[phy3_idx]);
6915 		}
6916 	}
6917 	if (phy->rev >= 2) {
6918 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6919 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6920 	}
6921 
6922 	for (i = 0; i < SAVE_RF_MAX; ++i)
6923 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6924 
6925 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6926 	BWN_WRITE_2(mac, 0x03e6, phy0);
6927 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6928 
6929 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6930 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6931 
6932 	bwn_spu_workaround(mac, phy->chan);
6933 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6934 	bwn_set_original_gains(mac);
6935 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6936 	if (phy->rev >= 3) {
6937 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6938 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6939 			    save_phy3[phy3_idx]);
6940 		}
6941 	}
6942 
6943 	delta = 0x1f - pg->pg_nrssi[0];
6944 	for (i = 0; i < 64; i++) {
6945 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6946 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6947 		pg->pg_nrssi_lt[i] = tmp32;
6948 	}
6949 
6950 	bwn_nrssi_threshold(mac);
6951 #undef SAVE_RF_MAX
6952 #undef SAVE_PHY_COMM_MAX
6953 #undef SAVE_PHY3_MAX
6954 }
6955 
6956 static void
6957 bwn_nrssi_offset(struct bwn_mac *mac)
6958 {
6959 #define	SAVE_RF_MAX		2
6960 #define	SAVE_PHY_COMM_MAX	10
6961 #define	SAVE_PHY6_MAX		8
6962 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6963 		{ 0x7a, 0x43 };
6964 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6965 		0x0001, 0x0811, 0x0812, 0x0814,
6966 		0x0815, 0x005a, 0x0059, 0x0058,
6967 		0x000a, 0x0003
6968 	};
6969 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6970 		0x002e, 0x002f, 0x080f, 0x0810,
6971 		0x0801, 0x0060, 0x0014, 0x0478
6972 	};
6973 	struct bwn_phy *phy = &mac->mac_phy;
6974 	int i, phy6_idx = 0;
6975 	uint16_t save_rf[SAVE_RF_MAX];
6976 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6977 	uint16_t save_phy6[SAVE_PHY6_MAX];
6978 	int16_t nrssi;
6979 	uint16_t saved = 0xffff;
6980 
6981 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6982 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6983 	for (i = 0; i < SAVE_RF_MAX; ++i)
6984 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6985 
6986 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6987 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6988 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6989 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6990 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6991 	if (phy->rev >= 6) {
6992 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6993 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6994 
6995 		BWN_PHY_WRITE(mac, 0x002e, 0);
6996 		BWN_PHY_WRITE(mac, 0x002f, 0);
6997 		BWN_PHY_WRITE(mac, 0x080f, 0);
6998 		BWN_PHY_WRITE(mac, 0x0810, 0);
6999 		BWN_PHY_SET(mac, 0x0478, 0x0100);
7000 		BWN_PHY_SET(mac, 0x0801, 0x0040);
7001 		BWN_PHY_SET(mac, 0x0060, 0x0040);
7002 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7003 	}
7004 	BWN_RF_SET(mac, 0x007a, 0x0070);
7005 	BWN_RF_SET(mac, 0x007a, 0x0080);
7006 	DELAY(30);
7007 
7008 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7009 	if (nrssi >= 0x20)
7010 		nrssi -= 0x40;
7011 	if (nrssi == 31) {
7012 		for (i = 7; i >= 4; i--) {
7013 			BWN_RF_WRITE(mac, 0x007b, i);
7014 			DELAY(20);
7015 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7016 			    0x003f);
7017 			if (nrssi >= 0x20)
7018 				nrssi -= 0x40;
7019 			if (nrssi < 31 && saved == 0xffff)
7020 				saved = i;
7021 		}
7022 		if (saved == 0xffff)
7023 			saved = 4;
7024 	} else {
7025 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7026 		if (phy->rev != 1) {
7027 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7028 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7029 		}
7030 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7031 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7032 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7033 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7034 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7035 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7036 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7037 		if (phy->rev == 0)
7038 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7039 		else
7040 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7041 		if (phy->rev != 1) {
7042 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7043 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7044 		}
7045 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7046 		BWN_RF_SET(mac, 0x007a, 0x000f);
7047 		bwn_set_all_gains(mac, 3, 0, 1);
7048 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7049 		DELAY(30);
7050 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7051 		if (nrssi >= 0x20)
7052 			nrssi -= 0x40;
7053 		if (nrssi == -32) {
7054 			for (i = 0; i < 4; i++) {
7055 				BWN_RF_WRITE(mac, 0x007b, i);
7056 				DELAY(20);
7057 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7058 				    0x047f) >> 8) & 0x003f);
7059 				if (nrssi >= 0x20)
7060 					nrssi -= 0x40;
7061 				if (nrssi > -31 && saved == 0xffff)
7062 					saved = i;
7063 			}
7064 			if (saved == 0xffff)
7065 				saved = 3;
7066 		} else
7067 			saved = 0;
7068 	}
7069 	BWN_RF_WRITE(mac, 0x007b, saved);
7070 
7071 	/*
7072 	 * Restore saved RF/PHY registers
7073 	 */
7074 	if (phy->rev >= 6) {
7075 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7076 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7077 			    save_phy6[phy6_idx]);
7078 		}
7079 	}
7080 	if (phy->rev != 1) {
7081 		for (i = 3; i < 5; i++)
7082 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7083 			    save_phy_comm[i]);
7084 	}
7085 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7086 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7087 
7088 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7089 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7090 
7091 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7092 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7093 	bwn_set_original_gains(mac);
7094 	if (phy->rev >= 6) {
7095 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7096 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7097 			    save_phy6[phy6_idx]);
7098 		}
7099 	}
7100 
7101 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7102 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7103 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7104 }
7105 
7106 static void
7107 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7108     int16_t third)
7109 {
7110 	struct bwn_phy *phy = &mac->mac_phy;
7111 	uint16_t i;
7112 	uint16_t start = 0x08, end = 0x18;
7113 	uint16_t tmp;
7114 	uint16_t table;
7115 
7116 	if (phy->rev <= 1) {
7117 		start = 0x10;
7118 		end = 0x20;
7119 	}
7120 
7121 	table = BWN_OFDMTAB_GAINX;
7122 	if (phy->rev <= 1)
7123 		table = BWN_OFDMTAB_GAINX_R1;
7124 	for (i = 0; i < 4; i++)
7125 		bwn_ofdmtab_write_2(mac, table, i, first);
7126 
7127 	for (i = start; i < end; i++)
7128 		bwn_ofdmtab_write_2(mac, table, i, second);
7129 
7130 	if (third != -1) {
7131 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7132 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7133 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7134 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7135 	}
7136 	bwn_dummy_transmission(mac, 0, 1);
7137 }
7138 
7139 static void
7140 bwn_set_original_gains(struct bwn_mac *mac)
7141 {
7142 	struct bwn_phy *phy = &mac->mac_phy;
7143 	uint16_t i, tmp;
7144 	uint16_t table;
7145 	uint16_t start = 0x0008, end = 0x0018;
7146 
7147 	if (phy->rev <= 1) {
7148 		start = 0x0010;
7149 		end = 0x0020;
7150 	}
7151 
7152 	table = BWN_OFDMTAB_GAINX;
7153 	if (phy->rev <= 1)
7154 		table = BWN_OFDMTAB_GAINX_R1;
7155 	for (i = 0; i < 4; i++) {
7156 		tmp = (i & 0xfffc);
7157 		tmp |= (i & 0x0001) << 1;
7158 		tmp |= (i & 0x0002) >> 1;
7159 
7160 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7161 	}
7162 
7163 	for (i = start; i < end; i++)
7164 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7165 
7166 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7167 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7168 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7169 	bwn_dummy_transmission(mac, 0, 1);
7170 }
7171 
7172 static void
7173 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7174 {
7175 	struct bwn_phy *phy = &mac->mac_phy;
7176 	struct bwn_phy_g *pg = &phy->phy_g;
7177 	struct bwn_rfatt old_rfatt, rfatt;
7178 	struct bwn_bbatt old_bbatt, bbatt;
7179 	struct bwn_softc *sc = mac->mac_sc;
7180 	uint8_t old_txctl = 0;
7181 
7182 	KASSERT(phy->type == BWN_PHYTYPE_G,
7183 	    ("%s:%d: fail", __func__, __LINE__));
7184 
7185 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7186 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7187 		return;
7188 
7189 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7190 
7191 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7192 
7193 	if (!phy->gmode)
7194 		return;
7195 	bwn_hwpctl_early_init(mac);
7196 	if (pg->pg_curtssi == 0) {
7197 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7198 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7199 		} else {
7200 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7201 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7202 			old_txctl = pg->pg_txctl;
7203 
7204 			bbatt.att = 11;
7205 			if (phy->rf_rev == 8) {
7206 				rfatt.att = 15;
7207 				rfatt.padmix = 1;
7208 			} else {
7209 				rfatt.att = 9;
7210 				rfatt.padmix = 0;
7211 			}
7212 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7213 		}
7214 		bwn_dummy_transmission(mac, 0, 1);
7215 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7216 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7217 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7218 		else
7219 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7220 			    &old_rfatt, old_txctl);
7221 	}
7222 	bwn_hwpctl_init_gphy(mac);
7223 
7224 	/* clear TSSI */
7225 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7226 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7227 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7228 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7229 }
7230 
7231 static void
7232 bwn_hwpctl_early_init(struct bwn_mac *mac)
7233 {
7234 	struct bwn_phy *phy = &mac->mac_phy;
7235 
7236 	if (!bwn_has_hwpctl(mac)) {
7237 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7238 		return;
7239 	}
7240 
7241 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7242 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7243 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7244 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7245 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7246 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7247 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7248 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7249 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7250 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7251 	} else {
7252 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7253 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7254 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7255 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7256 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7257 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7258 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7259 	}
7260 }
7261 
7262 static void
7263 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7264 {
7265 	struct bwn_phy *phy = &mac->mac_phy;
7266 	struct bwn_phy_g *pg = &phy->phy_g;
7267 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7268 	int i;
7269 	uint16_t nr_written = 0, tmp, value;
7270 	uint8_t rf, bb;
7271 
7272 	if (!bwn_has_hwpctl(mac)) {
7273 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7274 		return;
7275 	}
7276 
7277 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7278 	    (pg->pg_idletssi - pg->pg_curtssi));
7279 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7280 	    (pg->pg_idletssi - pg->pg_curtssi));
7281 
7282 	for (i = 0; i < 32; i++)
7283 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7284 	for (i = 32; i < 64; i++)
7285 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7286 	for (i = 0; i < 64; i += 2) {
7287 		value = (uint16_t) pg->pg_tssi2dbm[i];
7288 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7289 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7290 	}
7291 
7292 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7293 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7294 			if (nr_written >= 0x40)
7295 				return;
7296 			tmp = lo->bbatt.array[bb].att;
7297 			tmp <<= 8;
7298 			if (phy->rf_rev == 8)
7299 				tmp |= 0x50;
7300 			else
7301 				tmp |= 0x40;
7302 			tmp |= lo->rfatt.array[rf].att;
7303 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7304 			nr_written++;
7305 		}
7306 	}
7307 
7308 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7309 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7310 
7311 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7312 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7313 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7314 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7315 
7316 	bwn_phy_g_dc_lookup_init(mac, 1);
7317 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7318 }
7319 
7320 static void
7321 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7322 {
7323 	struct bwn_softc *sc = mac->mac_sc;
7324 
7325 	if (spu != 0)
7326 		bwn_spu_workaround(mac, channel);
7327 
7328 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7329 
7330 	if (channel == 14) {
7331 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7332 			bwn_hf_write(mac,
7333 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7334 		else
7335 			bwn_hf_write(mac,
7336 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7337 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7338 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7339 		return;
7340 	}
7341 
7342 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7343 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7344 }
7345 
7346 static uint16_t
7347 bwn_phy_g_chan2freq(uint8_t channel)
7348 {
7349 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7350 
7351 	KASSERT(channel >= 1 && channel <= 14,
7352 	    ("%s:%d: fail", __func__, __LINE__));
7353 
7354 	return (bwn_phy_g_rf_channels[channel - 1]);
7355 }
7356 
7357 static void
7358 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7359     const struct bwn_rfatt *rfatt, uint8_t txctl)
7360 {
7361 	struct bwn_phy *phy = &mac->mac_phy;
7362 	struct bwn_phy_g *pg = &phy->phy_g;
7363 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7364 	uint16_t bb, rf;
7365 	uint16_t tx_bias, tx_magn;
7366 
7367 	bb = bbatt->att;
7368 	rf = rfatt->att;
7369 	tx_bias = lo->tx_bias;
7370 	tx_magn = lo->tx_magn;
7371 	if (tx_bias == 0xff)
7372 		tx_bias = 0;
7373 
7374 	pg->pg_txctl = txctl;
7375 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7376 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7377 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7378 	bwn_phy_g_set_bbatt(mac, bb);
7379 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7380 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7381 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7382 	else {
7383 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7384 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7385 	}
7386 	if (BWN_HAS_TXMAG(phy))
7387 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7388 	else
7389 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7390 	bwn_lo_g_adjust(mac);
7391 }
7392 
7393 static void
7394 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7395     uint16_t bbatt)
7396 {
7397 	struct bwn_phy *phy = &mac->mac_phy;
7398 
7399 	if (phy->analog == 0) {
7400 		BWN_WRITE_2(mac, BWN_PHY0,
7401 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7402 		return;
7403 	}
7404 	if (phy->analog > 1) {
7405 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7406 		return;
7407 	}
7408 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7409 }
7410 
7411 static uint16_t
7412 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7413 {
7414 	struct bwn_phy *phy = &mac->mac_phy;
7415 	struct bwn_phy_g *pg = &phy->phy_g;
7416 	struct bwn_softc *sc = mac->mac_sc;
7417 	int max_lb_gain;
7418 	uint16_t extlna;
7419 	uint16_t i;
7420 
7421 	if (phy->gmode == 0)
7422 		return (0);
7423 
7424 	if (BWN_HAS_LOOPBACK(phy)) {
7425 		max_lb_gain = pg->pg_max_lb_gain;
7426 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7427 		if (max_lb_gain >= 0x46) {
7428 			extlna = 0x3000;
7429 			max_lb_gain -= 0x46;
7430 		} else if (max_lb_gain >= 0x3a) {
7431 			extlna = 0x1000;
7432 			max_lb_gain -= 0x3a;
7433 		} else if (max_lb_gain >= 0x2e) {
7434 			extlna = 0x2000;
7435 			max_lb_gain -= 0x2e;
7436 		} else {
7437 			extlna = 0;
7438 			max_lb_gain -= 0x10;
7439 		}
7440 
7441 		for (i = 0; i < 16; i++) {
7442 			max_lb_gain -= (i * 6);
7443 			if (max_lb_gain < 6)
7444 				break;
7445 		}
7446 
7447 		if ((phy->rev < 7) ||
7448 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7449 			if (reg == BWN_PHY_RFOVER) {
7450 				return (0x1b3);
7451 			} else if (reg == BWN_PHY_RFOVERVAL) {
7452 				extlna |= (i << 8);
7453 				switch (lpd) {
7454 				case BWN_LPD(0, 1, 1):
7455 					return (0x0f92);
7456 				case BWN_LPD(0, 0, 1):
7457 				case BWN_LPD(1, 0, 1):
7458 					return (0x0092 | extlna);
7459 				case BWN_LPD(1, 0, 0):
7460 					return (0x0093 | extlna);
7461 				}
7462 				KASSERT(0 == 1,
7463 				    ("%s:%d: fail", __func__, __LINE__));
7464 			}
7465 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7466 		} else {
7467 			if (reg == BWN_PHY_RFOVER)
7468 				return (0x9b3);
7469 			if (reg == BWN_PHY_RFOVERVAL) {
7470 				if (extlna)
7471 					extlna |= 0x8000;
7472 				extlna |= (i << 8);
7473 				switch (lpd) {
7474 				case BWN_LPD(0, 1, 1):
7475 					return (0x8f92);
7476 				case BWN_LPD(0, 0, 1):
7477 					return (0x8092 | extlna);
7478 				case BWN_LPD(1, 0, 1):
7479 					return (0x2092 | extlna);
7480 				case BWN_LPD(1, 0, 0):
7481 					return (0x2093 | extlna);
7482 				}
7483 				KASSERT(0 == 1,
7484 				    ("%s:%d: fail", __func__, __LINE__));
7485 			}
7486 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7487 		}
7488 		return (0);
7489 	}
7490 
7491 	if ((phy->rev < 7) ||
7492 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7493 		if (reg == BWN_PHY_RFOVER) {
7494 			return (0x1b3);
7495 		} else if (reg == BWN_PHY_RFOVERVAL) {
7496 			switch (lpd) {
7497 			case BWN_LPD(0, 1, 1):
7498 				return (0x0fb2);
7499 			case BWN_LPD(0, 0, 1):
7500 				return (0x00b2);
7501 			case BWN_LPD(1, 0, 1):
7502 				return (0x30b2);
7503 			case BWN_LPD(1, 0, 0):
7504 				return (0x30b3);
7505 			}
7506 			KASSERT(0 == 1,
7507 			    ("%s:%d: fail", __func__, __LINE__));
7508 		}
7509 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7510 	} else {
7511 		if (reg == BWN_PHY_RFOVER) {
7512 			return (0x9b3);
7513 		} else if (reg == BWN_PHY_RFOVERVAL) {
7514 			switch (lpd) {
7515 			case BWN_LPD(0, 1, 1):
7516 				return (0x8fb2);
7517 			case BWN_LPD(0, 0, 1):
7518 				return (0x80b2);
7519 			case BWN_LPD(1, 0, 1):
7520 				return (0x20b2);
7521 			case BWN_LPD(1, 0, 0):
7522 				return (0x20b3);
7523 			}
7524 			KASSERT(0 == 1,
7525 			    ("%s:%d: fail", __func__, __LINE__));
7526 		}
7527 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7528 	}
7529 	return (0);
7530 }
7531 
7532 static void
7533 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7534 {
7535 
7536 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7537 		return;
7538 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7539 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7540 	DELAY(1000);
7541 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7542 }
7543 
7544 static int
7545 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7546 {
7547 	struct bwn_softc *sc = mac->mac_sc;
7548 	struct bwn_fw *fw = &mac->mac_fw;
7549 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7550 	const char *filename;
7551 	uint32_t high;
7552 	int error;
7553 
7554 	/* microcode */
7555 	if (rev >= 5 && rev <= 10)
7556 		filename = "ucode5";
7557 	else if (rev >= 11 && rev <= 12)
7558 		filename = "ucode11";
7559 	else if (rev == 13)
7560 		filename = "ucode13";
7561 	else if (rev == 14)
7562 		filename = "ucode14";
7563 	else if (rev >= 15)
7564 		filename = "ucode15";
7565 	else {
7566 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7567 		bwn_release_firmware(mac);
7568 		return (EOPNOTSUPP);
7569 	}
7570 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7571 	if (error) {
7572 		bwn_release_firmware(mac);
7573 		return (error);
7574 	}
7575 
7576 	/* PCM */
7577 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7578 	if (rev >= 5 && rev <= 10) {
7579 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7580 		if (error == ENOENT)
7581 			fw->no_pcmfile = 1;
7582 		else if (error) {
7583 			bwn_release_firmware(mac);
7584 			return (error);
7585 		}
7586 	} else if (rev < 11) {
7587 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7588 		return (EOPNOTSUPP);
7589 	}
7590 
7591 	/* initvals */
7592 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7593 	switch (mac->mac_phy.type) {
7594 	case BWN_PHYTYPE_A:
7595 		if (rev < 5 || rev > 10)
7596 			goto fail1;
7597 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7598 			filename = "a0g1initvals5";
7599 		else
7600 			filename = "a0g0initvals5";
7601 		break;
7602 	case BWN_PHYTYPE_G:
7603 		if (rev >= 5 && rev <= 10)
7604 			filename = "b0g0initvals5";
7605 		else if (rev >= 13)
7606 			filename = "b0g0initvals13";
7607 		else
7608 			goto fail1;
7609 		break;
7610 	case BWN_PHYTYPE_LP:
7611 		if (rev == 13)
7612 			filename = "lp0initvals13";
7613 		else if (rev == 14)
7614 			filename = "lp0initvals14";
7615 		else if (rev >= 15)
7616 			filename = "lp0initvals15";
7617 		else
7618 			goto fail1;
7619 		break;
7620 	case BWN_PHYTYPE_N:
7621 		if (rev >= 11 && rev <= 12)
7622 			filename = "n0initvals11";
7623 		else
7624 			goto fail1;
7625 		break;
7626 	default:
7627 		goto fail1;
7628 	}
7629 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7630 	if (error) {
7631 		bwn_release_firmware(mac);
7632 		return (error);
7633 	}
7634 
7635 	/* bandswitch initvals */
7636 	switch (mac->mac_phy.type) {
7637 	case BWN_PHYTYPE_A:
7638 		if (rev >= 5 && rev <= 10) {
7639 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7640 				filename = "a0g1bsinitvals5";
7641 			else
7642 				filename = "a0g0bsinitvals5";
7643 		} else if (rev >= 11)
7644 			filename = NULL;
7645 		else
7646 			goto fail1;
7647 		break;
7648 	case BWN_PHYTYPE_G:
7649 		if (rev >= 5 && rev <= 10)
7650 			filename = "b0g0bsinitvals5";
7651 		else if (rev >= 11)
7652 			filename = NULL;
7653 		else
7654 			goto fail1;
7655 		break;
7656 	case BWN_PHYTYPE_LP:
7657 		if (rev == 13)
7658 			filename = "lp0bsinitvals13";
7659 		else if (rev == 14)
7660 			filename = "lp0bsinitvals14";
7661 		else if (rev >= 15)
7662 			filename = "lp0bsinitvals15";
7663 		else
7664 			goto fail1;
7665 		break;
7666 	case BWN_PHYTYPE_N:
7667 		if (rev >= 11 && rev <= 12)
7668 			filename = "n0bsinitvals11";
7669 		else
7670 			goto fail1;
7671 		break;
7672 	default:
7673 		goto fail1;
7674 	}
7675 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7676 	if (error) {
7677 		bwn_release_firmware(mac);
7678 		return (error);
7679 	}
7680 	return (0);
7681 fail1:
7682 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7683 	bwn_release_firmware(mac);
7684 	return (EOPNOTSUPP);
7685 }
7686 
7687 static int
7688 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7689     const char *name, struct bwn_fwfile *bfw)
7690 {
7691 	const struct bwn_fwhdr *hdr;
7692 	struct bwn_softc *sc = mac->mac_sc;
7693 	const struct firmware *fw;
7694 	char namebuf[64];
7695 
7696 	if (name == NULL) {
7697 		bwn_do_release_fw(bfw);
7698 		return (0);
7699 	}
7700 	if (bfw->filename != NULL) {
7701 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7702 			return (0);
7703 		bwn_do_release_fw(bfw);
7704 	}
7705 
7706 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7707 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7708 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7709 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7710 	fw = firmware_get(namebuf);
7711 	if (fw == NULL) {
7712 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7713 		    namebuf);
7714 		return (ENOENT);
7715 	}
7716 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7717 		goto fail;
7718 	hdr = (const struct bwn_fwhdr *)(fw->data);
7719 	switch (hdr->type) {
7720 	case BWN_FWTYPE_UCODE:
7721 	case BWN_FWTYPE_PCM:
7722 		if (be32toh(hdr->size) !=
7723 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7724 			goto fail;
7725 		/* FALLTHROUGH */
7726 	case BWN_FWTYPE_IV:
7727 		if (hdr->ver != 1)
7728 			goto fail;
7729 		break;
7730 	default:
7731 		goto fail;
7732 	}
7733 	bfw->filename = name;
7734 	bfw->fw = fw;
7735 	bfw->type = type;
7736 	return (0);
7737 fail:
7738 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7739 	if (fw != NULL)
7740 		firmware_put(fw, FIRMWARE_UNLOAD);
7741 	return (EPROTO);
7742 }
7743 
7744 static void
7745 bwn_release_firmware(struct bwn_mac *mac)
7746 {
7747 
7748 	bwn_do_release_fw(&mac->mac_fw.ucode);
7749 	bwn_do_release_fw(&mac->mac_fw.pcm);
7750 	bwn_do_release_fw(&mac->mac_fw.initvals);
7751 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7752 }
7753 
7754 static void
7755 bwn_do_release_fw(struct bwn_fwfile *bfw)
7756 {
7757 
7758 	if (bfw->fw != NULL)
7759 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7760 	bfw->fw = NULL;
7761 	bfw->filename = NULL;
7762 }
7763 
7764 static int
7765 bwn_fw_loaducode(struct bwn_mac *mac)
7766 {
7767 #define	GETFWOFFSET(fwp, offset)	\
7768 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7769 #define	GETFWSIZE(fwp, offset)	\
7770 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7771 	struct bwn_softc *sc = mac->mac_sc;
7772 	const uint32_t *data;
7773 	unsigned int i;
7774 	uint32_t ctl;
7775 	uint16_t date, fwcaps, time;
7776 	int error = 0;
7777 
7778 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7779 	ctl |= BWN_MACCTL_MCODE_JMP0;
7780 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7781 	    __LINE__));
7782 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7783 	for (i = 0; i < 64; i++)
7784 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7785 	for (i = 0; i < 4096; i += 2)
7786 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7787 
7788 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7789 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7790 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7791 	     i++) {
7792 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7793 		DELAY(10);
7794 	}
7795 
7796 	if (mac->mac_fw.pcm.fw) {
7797 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7798 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7799 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7800 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7801 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7802 		    sizeof(struct bwn_fwhdr)); i++) {
7803 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7804 			DELAY(10);
7805 		}
7806 	}
7807 
7808 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7809 	BWN_WRITE_4(mac, BWN_MACCTL,
7810 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7811 	    BWN_MACCTL_MCODE_RUN);
7812 
7813 	for (i = 0; i < 21; i++) {
7814 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7815 			break;
7816 		if (i >= 20) {
7817 			device_printf(sc->sc_dev, "ucode timeout\n");
7818 			error = ENXIO;
7819 			goto error;
7820 		}
7821 		DELAY(50000);
7822 	}
7823 	BWN_READ_4(mac, BWN_INTR_REASON);
7824 
7825 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7826 	if (mac->mac_fw.rev <= 0x128) {
7827 		device_printf(sc->sc_dev, "the firmware is too old\n");
7828 		error = EOPNOTSUPP;
7829 		goto error;
7830 	}
7831 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7832 	    BWN_SHARED_UCODE_PATCH);
7833 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7834 	mac->mac_fw.opensource = (date == 0xffff);
7835 	if (bwn_wme != 0)
7836 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7837 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7838 
7839 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7840 	if (mac->mac_fw.opensource == 0) {
7841 		device_printf(sc->sc_dev,
7842 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7843 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7844 		if (mac->mac_fw.no_pcmfile)
7845 			device_printf(sc->sc_dev,
7846 			    "no HW crypto acceleration due to pcm5\n");
7847 	} else {
7848 		mac->mac_fw.patch = time;
7849 		fwcaps = bwn_fwcaps_read(mac);
7850 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7851 			device_printf(sc->sc_dev,
7852 			    "disabling HW crypto acceleration\n");
7853 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7854 		}
7855 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7856 			device_printf(sc->sc_dev, "disabling WME support\n");
7857 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7858 		}
7859 	}
7860 
7861 	if (BWN_ISOLDFMT(mac))
7862 		device_printf(sc->sc_dev, "using old firmware image\n");
7863 
7864 	return (0);
7865 
7866 error:
7867 	BWN_WRITE_4(mac, BWN_MACCTL,
7868 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7869 	    BWN_MACCTL_MCODE_JMP0);
7870 
7871 	return (error);
7872 #undef GETFWSIZE
7873 #undef GETFWOFFSET
7874 }
7875 
7876 /* OpenFirmware only */
7877 static uint16_t
7878 bwn_fwcaps_read(struct bwn_mac *mac)
7879 {
7880 
7881 	KASSERT(mac->mac_fw.opensource == 1,
7882 	    ("%s:%d: fail", __func__, __LINE__));
7883 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7884 }
7885 
7886 static int
7887 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7888     size_t count, size_t array_size)
7889 {
7890 #define	GET_NEXTIV16(iv)						\
7891 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7892 	    sizeof(uint16_t) + sizeof(uint16_t)))
7893 #define	GET_NEXTIV32(iv)						\
7894 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7895 	    sizeof(uint16_t) + sizeof(uint32_t)))
7896 	struct bwn_softc *sc = mac->mac_sc;
7897 	const struct bwn_fwinitvals *iv;
7898 	uint16_t offset;
7899 	size_t i;
7900 	uint8_t bit32;
7901 
7902 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7903 	    ("%s:%d: fail", __func__, __LINE__));
7904 	iv = ivals;
7905 	for (i = 0; i < count; i++) {
7906 		if (array_size < sizeof(iv->offset_size))
7907 			goto fail;
7908 		array_size -= sizeof(iv->offset_size);
7909 		offset = be16toh(iv->offset_size);
7910 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7911 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7912 		if (offset >= 0x1000)
7913 			goto fail;
7914 		if (bit32) {
7915 			if (array_size < sizeof(iv->data.d32))
7916 				goto fail;
7917 			array_size -= sizeof(iv->data.d32);
7918 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7919 			iv = GET_NEXTIV32(iv);
7920 		} else {
7921 
7922 			if (array_size < sizeof(iv->data.d16))
7923 				goto fail;
7924 			array_size -= sizeof(iv->data.d16);
7925 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7926 
7927 			iv = GET_NEXTIV16(iv);
7928 		}
7929 	}
7930 	if (array_size != 0)
7931 		goto fail;
7932 	return (0);
7933 fail:
7934 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7935 	return (EPROTO);
7936 #undef GET_NEXTIV16
7937 #undef GET_NEXTIV32
7938 }
7939 
7940 static int
7941 bwn_switch_channel(struct bwn_mac *mac, int chan)
7942 {
7943 	struct bwn_phy *phy = &(mac->mac_phy);
7944 	struct bwn_softc *sc = mac->mac_sc;
7945 	struct ifnet *ifp = sc->sc_ifp;
7946 	struct ieee80211com *ic = ifp->if_l2com;
7947 	uint16_t channelcookie, savedcookie;
7948 	int error;
7949 
7950 	if (chan == 0xffff)
7951 		chan = phy->get_default_chan(mac);
7952 
7953 	channelcookie = chan;
7954 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7955 		channelcookie |= 0x100;
7956 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7957 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7958 	error = phy->switch_channel(mac, chan);
7959 	if (error)
7960 		goto fail;
7961 
7962 	mac->mac_phy.chan = chan;
7963 	DELAY(8000);
7964 	return (0);
7965 fail:
7966 	device_printf(sc->sc_dev, "failed to switch channel\n");
7967 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7968 	return (error);
7969 }
7970 
7971 static uint16_t
7972 bwn_ant2phy(int antenna)
7973 {
7974 
7975 	switch (antenna) {
7976 	case BWN_ANT0:
7977 		return (BWN_TX_PHY_ANT0);
7978 	case BWN_ANT1:
7979 		return (BWN_TX_PHY_ANT1);
7980 	case BWN_ANT2:
7981 		return (BWN_TX_PHY_ANT2);
7982 	case BWN_ANT3:
7983 		return (BWN_TX_PHY_ANT3);
7984 	case BWN_ANTAUTO:
7985 		return (BWN_TX_PHY_ANT01AUTO);
7986 	}
7987 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7988 	return (0);
7989 }
7990 
7991 static void
7992 bwn_wme_load(struct bwn_mac *mac)
7993 {
7994 	struct bwn_softc *sc = mac->mac_sc;
7995 	int i;
7996 
7997 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7998 	    ("%s:%d: fail", __func__, __LINE__));
7999 
8000 	bwn_mac_suspend(mac);
8001 	for (i = 0; i < N(sc->sc_wmeParams); i++)
8002 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8003 		    bwn_wme_shm_offsets[i]);
8004 	bwn_mac_enable(mac);
8005 }
8006 
8007 static void
8008 bwn_wme_loadparams(struct bwn_mac *mac,
8009     const struct wmeParams *p, uint16_t shm_offset)
8010 {
8011 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8012 	struct bwn_softc *sc = mac->mac_sc;
8013 	uint16_t params[BWN_NR_WMEPARAMS];
8014 	int slot, tmp;
8015 	unsigned int i;
8016 
8017 	slot = BWN_READ_2(mac, BWN_RNG) &
8018 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8019 
8020 	memset(&params, 0, sizeof(params));
8021 
8022 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8023 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8024 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8025 
8026 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8027 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8028 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8029 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8030 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8031 	params[BWN_WMEPARAM_BSLOTS] = slot;
8032 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8033 
8034 	for (i = 0; i < N(params); i++) {
8035 		if (i == BWN_WMEPARAM_STATUS) {
8036 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8037 			    shm_offset + (i * 2));
8038 			tmp |= 0x100;
8039 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8040 			    tmp);
8041 		} else {
8042 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8043 			    params[i]);
8044 		}
8045 	}
8046 }
8047 
8048 static void
8049 bwn_mac_write_bssid(struct bwn_mac *mac)
8050 {
8051 	struct bwn_softc *sc = mac->mac_sc;
8052 	uint32_t tmp;
8053 	int i;
8054 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8055 
8056 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8057 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8058 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8059 	    IEEE80211_ADDR_LEN);
8060 
8061 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8062 		tmp = (uint32_t) (mac_bssid[i + 0]);
8063 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8064 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8065 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8066 		bwn_ram_write(mac, 0x20 + i, tmp);
8067 	}
8068 }
8069 
8070 static void
8071 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8072     const uint8_t *macaddr)
8073 {
8074 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8075 	uint16_t data;
8076 
8077 	if (!mac)
8078 		macaddr = zero;
8079 
8080 	offset |= 0x0020;
8081 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8082 
8083 	data = macaddr[0];
8084 	data |= macaddr[1] << 8;
8085 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8086 	data = macaddr[2];
8087 	data |= macaddr[3] << 8;
8088 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8089 	data = macaddr[4];
8090 	data |= macaddr[5] << 8;
8091 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8092 }
8093 
8094 static void
8095 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8096     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8097 {
8098 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8099 	uint8_t per_sta_keys_start = 8;
8100 
8101 	if (BWN_SEC_NEWAPI(mac))
8102 		per_sta_keys_start = 4;
8103 
8104 	KASSERT(index < mac->mac_max_nr_keys,
8105 	    ("%s:%d: fail", __func__, __LINE__));
8106 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8107 	    ("%s:%d: fail", __func__, __LINE__));
8108 
8109 	if (index >= per_sta_keys_start)
8110 		bwn_key_macwrite(mac, index, NULL);
8111 	if (key)
8112 		memcpy(buf, key, key_len);
8113 	bwn_key_write(mac, index, algorithm, buf);
8114 	if (index >= per_sta_keys_start)
8115 		bwn_key_macwrite(mac, index, mac_addr);
8116 
8117 	mac->mac_key[index].algorithm = algorithm;
8118 }
8119 
8120 static void
8121 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8122 {
8123 	struct bwn_softc *sc = mac->mac_sc;
8124 	uint32_t addrtmp[2] = { 0, 0 };
8125 	uint8_t start = 8;
8126 
8127 	if (BWN_SEC_NEWAPI(mac))
8128 		start = 4;
8129 
8130 	KASSERT(index >= start,
8131 	    ("%s:%d: fail", __func__, __LINE__));
8132 	index -= start;
8133 
8134 	if (addr) {
8135 		addrtmp[0] = addr[0];
8136 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8137 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8138 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8139 		addrtmp[1] = addr[4];
8140 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8141 	}
8142 
8143 	if (siba_get_revid(sc->sc_dev) >= 5) {
8144 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8145 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8146 	} else {
8147 		if (index >= 8) {
8148 			bwn_shm_write_4(mac, BWN_SHARED,
8149 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8150 			bwn_shm_write_2(mac, BWN_SHARED,
8151 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8152 		}
8153 	}
8154 }
8155 
8156 static void
8157 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8158     const uint8_t *key)
8159 {
8160 	unsigned int i;
8161 	uint32_t offset;
8162 	uint16_t kidx, value;
8163 
8164 	kidx = BWN_SEC_KEY2FW(mac, index);
8165 	bwn_shm_write_2(mac, BWN_SHARED,
8166 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8167 
8168 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8169 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8170 		value = key[i];
8171 		value |= (uint16_t)(key[i + 1]) << 8;
8172 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8173 	}
8174 }
8175 
8176 static void
8177 bwn_phy_exit(struct bwn_mac *mac)
8178 {
8179 
8180 	mac->mac_phy.rf_onoff(mac, 0);
8181 	if (mac->mac_phy.exit != NULL)
8182 		mac->mac_phy.exit(mac);
8183 }
8184 
8185 static void
8186 bwn_dma_free(struct bwn_mac *mac)
8187 {
8188 	struct bwn_dma *dma;
8189 
8190 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8191 		return;
8192 	dma = &mac->mac_method.dma;
8193 
8194 	bwn_dma_ringfree(&dma->rx);
8195 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8196 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8197 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8198 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8199 	bwn_dma_ringfree(&dma->mcast);
8200 }
8201 
8202 static void
8203 bwn_core_stop(struct bwn_mac *mac)
8204 {
8205 	struct bwn_softc *sc = mac->mac_sc;
8206 
8207 	BWN_ASSERT_LOCKED(sc);
8208 
8209 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8210 		return;
8211 
8212 	callout_stop(&sc->sc_rfswitch_ch);
8213 	callout_stop(&sc->sc_task_ch);
8214 	callout_stop(&sc->sc_watchdog_ch);
8215 	sc->sc_watchdog_timer = 0;
8216 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8217 	BWN_READ_4(mac, BWN_INTR_MASK);
8218 	bwn_mac_suspend(mac);
8219 
8220 	mac->mac_status = BWN_MAC_STATUS_INITED;
8221 }
8222 
8223 static int
8224 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8225 {
8226 	struct bwn_mac *up_dev = NULL;
8227 	struct bwn_mac *down_dev;
8228 	struct bwn_mac *mac;
8229 	int err, status;
8230 	uint8_t gmode;
8231 
8232 	BWN_ASSERT_LOCKED(sc);
8233 
8234 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8235 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8236 		    mac->mac_phy.supports_2ghz) {
8237 			up_dev = mac;
8238 			gmode = 1;
8239 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8240 		    mac->mac_phy.supports_5ghz) {
8241 			up_dev = mac;
8242 			gmode = 0;
8243 		} else {
8244 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8245 			return (EINVAL);
8246 		}
8247 		if (up_dev != NULL)
8248 			break;
8249 	}
8250 	if (up_dev == NULL) {
8251 		device_printf(sc->sc_dev, "Could not find a device\n");
8252 		return (ENODEV);
8253 	}
8254 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8255 		return (0);
8256 
8257 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8258 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8259 
8260 	down_dev = sc->sc_curmac;
8261 	status = down_dev->mac_status;
8262 	if (status >= BWN_MAC_STATUS_STARTED)
8263 		bwn_core_stop(down_dev);
8264 	if (status >= BWN_MAC_STATUS_INITED)
8265 		bwn_core_exit(down_dev);
8266 
8267 	if (down_dev != up_dev)
8268 		bwn_phy_reset(down_dev);
8269 
8270 	up_dev->mac_phy.gmode = gmode;
8271 	if (status >= BWN_MAC_STATUS_INITED) {
8272 		err = bwn_core_init(up_dev);
8273 		if (err) {
8274 			device_printf(sc->sc_dev,
8275 			    "fatal: failed to initialize for %s-GHz\n",
8276 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8277 			goto fail;
8278 		}
8279 	}
8280 	if (status >= BWN_MAC_STATUS_STARTED)
8281 		bwn_core_start(up_dev);
8282 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8283 	sc->sc_curmac = up_dev;
8284 
8285 	return (0);
8286 fail:
8287 	sc->sc_curmac = NULL;
8288 	return (err);
8289 }
8290 
8291 static void
8292 bwn_rf_turnon(struct bwn_mac *mac)
8293 {
8294 
8295 	bwn_mac_suspend(mac);
8296 	mac->mac_phy.rf_onoff(mac, 1);
8297 	mac->mac_phy.rf_on = 1;
8298 	bwn_mac_enable(mac);
8299 }
8300 
8301 static void
8302 bwn_rf_turnoff(struct bwn_mac *mac)
8303 {
8304 
8305 	bwn_mac_suspend(mac);
8306 	mac->mac_phy.rf_onoff(mac, 0);
8307 	mac->mac_phy.rf_on = 0;
8308 	bwn_mac_enable(mac);
8309 }
8310 
8311 static void
8312 bwn_phy_reset(struct bwn_mac *mac)
8313 {
8314 	struct bwn_softc *sc = mac->mac_sc;
8315 
8316 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8317 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8318 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8319 	DELAY(1000);
8320 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8321 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8322 	    BWN_TGSLOW_PHYRESET);
8323 	DELAY(1000);
8324 }
8325 
8326 static int
8327 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8328 {
8329 	struct bwn_vap *bvp = BWN_VAP(vap);
8330 	struct ieee80211com *ic= vap->iv_ic;
8331 	struct ifnet *ifp = ic->ic_ifp;
8332 	enum ieee80211_state ostate = vap->iv_state;
8333 	struct bwn_softc *sc = ifp->if_softc;
8334 	struct bwn_mac *mac = sc->sc_curmac;
8335 	int error;
8336 
8337 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8338 	    ieee80211_state_name[vap->iv_state],
8339 	    ieee80211_state_name[nstate]);
8340 
8341 	error = bvp->bv_newstate(vap, nstate, arg);
8342 	if (error != 0)
8343 		return (error);
8344 
8345 	BWN_LOCK(sc);
8346 
8347 	bwn_led_newstate(mac, nstate);
8348 
8349 	/*
8350 	 * Clear the BSSID when we stop a STA
8351 	 */
8352 	if (vap->iv_opmode == IEEE80211_M_STA) {
8353 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8354 			/*
8355 			 * Clear out the BSSID.  If we reassociate to
8356 			 * the same AP, this will reinialize things
8357 			 * correctly...
8358 			 */
8359 			if (ic->ic_opmode == IEEE80211_M_STA &&
8360 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8361 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8362 				bwn_set_macaddr(mac);
8363 			}
8364 		}
8365 	}
8366 
8367 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8368 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8369 		/* XXX nothing to do? */
8370 	} else if (nstate == IEEE80211_S_RUN) {
8371 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8372 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8373 		bwn_set_opmode(mac);
8374 		bwn_set_pretbtt(mac);
8375 		bwn_spu_setdelay(mac, 0);
8376 		bwn_set_macaddr(mac);
8377 	}
8378 
8379 	BWN_UNLOCK(sc);
8380 
8381 	return (error);
8382 }
8383 
8384 static void
8385 bwn_set_pretbtt(struct bwn_mac *mac)
8386 {
8387 	struct bwn_softc *sc = mac->mac_sc;
8388 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8389 	uint16_t pretbtt;
8390 
8391 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8392 		pretbtt = 2;
8393 	else
8394 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8395 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8396 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8397 }
8398 
8399 static int
8400 bwn_intr(void *arg)
8401 {
8402 	struct bwn_mac *mac = arg;
8403 	struct bwn_softc *sc = mac->mac_sc;
8404 	uint32_t reason;
8405 
8406 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8407 	    (sc->sc_flags & BWN_FLAG_INVALID))
8408 		return (FILTER_STRAY);
8409 
8410 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8411 	if (reason == 0xffffffff)	/* shared IRQ */
8412 		return (FILTER_STRAY);
8413 	reason &= mac->mac_intr_mask;
8414 	if (reason == 0)
8415 		return (FILTER_HANDLED);
8416 
8417 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8418 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8419 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8420 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8421 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8422 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8423 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8424 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8425 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8426 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8427 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8428 
8429 	/* Disable interrupts. */
8430 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8431 
8432 	mac->mac_reason_intr = reason;
8433 
8434 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8435 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8436 
8437 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8438 	return (FILTER_HANDLED);
8439 }
8440 
8441 static void
8442 bwn_intrtask(void *arg, int npending)
8443 {
8444 	struct bwn_mac *mac = arg;
8445 	struct bwn_softc *sc = mac->mac_sc;
8446 	struct ifnet *ifp = sc->sc_ifp;
8447 	uint32_t merged = 0;
8448 	int i, tx = 0, rx = 0;
8449 
8450 	BWN_LOCK(sc);
8451 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8452 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8453 		BWN_UNLOCK(sc);
8454 		return;
8455 	}
8456 
8457 	for (i = 0; i < N(mac->mac_reason); i++)
8458 		merged |= mac->mac_reason[i];
8459 
8460 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8461 		device_printf(sc->sc_dev, "MAC trans error\n");
8462 
8463 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8464 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8465 		mac->mac_phy.txerrors--;
8466 		if (mac->mac_phy.txerrors == 0) {
8467 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8468 			bwn_restart(mac, "PHY TX errors");
8469 		}
8470 	}
8471 
8472 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8473 		if (merged & BWN_DMAINTR_FATALMASK) {
8474 			device_printf(sc->sc_dev,
8475 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8476 			    mac->mac_reason[0], mac->mac_reason[1],
8477 			    mac->mac_reason[2], mac->mac_reason[3],
8478 			    mac->mac_reason[4], mac->mac_reason[5]);
8479 			bwn_restart(mac, "DMA error");
8480 			BWN_UNLOCK(sc);
8481 			return;
8482 		}
8483 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8484 			device_printf(sc->sc_dev,
8485 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8486 			    mac->mac_reason[0], mac->mac_reason[1],
8487 			    mac->mac_reason[2], mac->mac_reason[3],
8488 			    mac->mac_reason[4], mac->mac_reason[5]);
8489 		}
8490 	}
8491 
8492 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8493 		bwn_intr_ucode_debug(mac);
8494 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8495 		bwn_intr_tbtt_indication(mac);
8496 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8497 		bwn_intr_atim_end(mac);
8498 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8499 		bwn_intr_beacon(mac);
8500 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8501 		bwn_intr_pmq(mac);
8502 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8503 		bwn_intr_noise(mac);
8504 
8505 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8506 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8507 			bwn_dma_rx(mac->mac_method.dma.rx);
8508 			rx = 1;
8509 		}
8510 	} else
8511 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8512 
8513 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8518 
8519 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8520 		bwn_intr_txeof(mac);
8521 		tx = 1;
8522 	}
8523 
8524 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8525 
8526 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8527 		int evt = BWN_LED_EVENT_NONE;
8528 
8529 		if (tx && rx) {
8530 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8531 				evt = BWN_LED_EVENT_RX;
8532 			else
8533 				evt = BWN_LED_EVENT_TX;
8534 		} else if (tx) {
8535 			evt = BWN_LED_EVENT_TX;
8536 		} else if (rx) {
8537 			evt = BWN_LED_EVENT_RX;
8538 		} else if (rx == 0) {
8539 			evt = BWN_LED_EVENT_POLL;
8540 		}
8541 
8542 		if (evt != BWN_LED_EVENT_NONE)
8543 			bwn_led_event(mac, evt);
8544        }
8545 
8546 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8547 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8548 			bwn_start_locked(ifp);
8549 	}
8550 
8551 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8552 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8553 
8554 	BWN_UNLOCK(sc);
8555 }
8556 
8557 static void
8558 bwn_restart(struct bwn_mac *mac, const char *msg)
8559 {
8560 	struct bwn_softc *sc = mac->mac_sc;
8561 	struct ifnet *ifp = sc->sc_ifp;
8562 	struct ieee80211com *ic = ifp->if_l2com;
8563 
8564 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8565 		return;
8566 
8567 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8568 	ieee80211_runtask(ic, &mac->mac_hwreset);
8569 }
8570 
8571 static void
8572 bwn_intr_ucode_debug(struct bwn_mac *mac)
8573 {
8574 	struct bwn_softc *sc = mac->mac_sc;
8575 	uint16_t reason;
8576 
8577 	if (mac->mac_fw.opensource == 0)
8578 		return;
8579 
8580 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8581 	switch (reason) {
8582 	case BWN_DEBUGINTR_PANIC:
8583 		bwn_handle_fwpanic(mac);
8584 		break;
8585 	case BWN_DEBUGINTR_DUMP_SHM:
8586 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8587 		break;
8588 	case BWN_DEBUGINTR_DUMP_REGS:
8589 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8590 		break;
8591 	case BWN_DEBUGINTR_MARKER:
8592 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8593 		break;
8594 	default:
8595 		device_printf(sc->sc_dev,
8596 		    "ucode debug unknown reason: %#x\n", reason);
8597 	}
8598 
8599 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8600 	    BWN_DEBUGINTR_ACK);
8601 }
8602 
8603 static void
8604 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8605 {
8606 	struct bwn_softc *sc = mac->mac_sc;
8607 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8608 
8609 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8610 		bwn_psctl(mac, 0);
8611 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8612 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8613 }
8614 
8615 static void
8616 bwn_intr_atim_end(struct bwn_mac *mac)
8617 {
8618 
8619 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8620 		BWN_WRITE_4(mac, BWN_MACCMD,
8621 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8622 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8623 	}
8624 }
8625 
8626 static void
8627 bwn_intr_beacon(struct bwn_mac *mac)
8628 {
8629 	struct bwn_softc *sc = mac->mac_sc;
8630 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8631 	uint32_t cmd, beacon0, beacon1;
8632 
8633 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8634 	    ic->ic_opmode == IEEE80211_M_MBSS)
8635 		return;
8636 
8637 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8638 
8639 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8640 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8641 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8642 
8643 	if (beacon0 && beacon1) {
8644 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8645 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8646 		return;
8647 	}
8648 
8649 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8650 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8651 		bwn_load_beacon0(mac);
8652 		bwn_load_beacon1(mac);
8653 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8654 		cmd |= BWN_MACCMD_BEACON0_VALID;
8655 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8656 	} else {
8657 		if (!beacon0) {
8658 			bwn_load_beacon0(mac);
8659 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8660 			cmd |= BWN_MACCMD_BEACON0_VALID;
8661 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8662 		} else if (!beacon1) {
8663 			bwn_load_beacon1(mac);
8664 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8665 			cmd |= BWN_MACCMD_BEACON1_VALID;
8666 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8667 		}
8668 	}
8669 }
8670 
8671 static void
8672 bwn_intr_pmq(struct bwn_mac *mac)
8673 {
8674 	uint32_t tmp;
8675 
8676 	while (1) {
8677 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8678 		if (!(tmp & 0x00000008))
8679 			break;
8680 	}
8681 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8682 }
8683 
8684 static void
8685 bwn_intr_noise(struct bwn_mac *mac)
8686 {
8687 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8688 	uint16_t tmp;
8689 	uint8_t noise[4];
8690 	uint8_t i, j;
8691 	int32_t average;
8692 
8693 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8694 		return;
8695 
8696 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8697 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8698 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8699 	    noise[3] == 0x7f)
8700 		goto new;
8701 
8702 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8703 	    ("%s:%d: fail", __func__, __LINE__));
8704 	i = mac->mac_noise.noi_nsamples;
8705 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8706 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8707 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8708 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8709 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8710 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8711 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8712 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8713 	mac->mac_noise.noi_nsamples++;
8714 	if (mac->mac_noise.noi_nsamples == 8) {
8715 		average = 0;
8716 		for (i = 0; i < 8; i++) {
8717 			for (j = 0; j < 4; j++)
8718 				average += mac->mac_noise.noi_samples[i][j];
8719 		}
8720 		average = (((average / 32) * 125) + 64) / 128;
8721 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8722 		if (tmp >= 8)
8723 			average += 2;
8724 		else
8725 			average -= 25;
8726 		average -= (tmp == 8) ? 72 : 48;
8727 
8728 		mac->mac_stats.link_noise = average;
8729 		mac->mac_noise.noi_running = 0;
8730 		return;
8731 	}
8732 new:
8733 	bwn_noise_gensample(mac);
8734 }
8735 
8736 static int
8737 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8738 {
8739 	struct bwn_mac *mac = prq->prq_mac;
8740 	struct bwn_softc *sc = mac->mac_sc;
8741 	unsigned int i;
8742 
8743 	BWN_ASSERT_LOCKED(sc);
8744 
8745 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8746 		return (0);
8747 
8748 	for (i = 0; i < 5000; i++) {
8749 		if (bwn_pio_rxeof(prq) == 0)
8750 			break;
8751 	}
8752 	if (i >= 5000)
8753 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8754 	return ((i > 0) ? 1 : 0);
8755 }
8756 
8757 static void
8758 bwn_dma_rx(struct bwn_dma_ring *dr)
8759 {
8760 	int slot, curslot;
8761 
8762 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8763 	curslot = dr->get_curslot(dr);
8764 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8765 	    ("%s:%d: fail", __func__, __LINE__));
8766 
8767 	slot = dr->dr_curslot;
8768 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8769 		bwn_dma_rxeof(dr, &slot);
8770 
8771 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8772 	    BUS_DMASYNC_PREWRITE);
8773 
8774 	dr->set_curslot(dr, slot);
8775 	dr->dr_curslot = slot;
8776 }
8777 
8778 static void
8779 bwn_intr_txeof(struct bwn_mac *mac)
8780 {
8781 	struct bwn_txstatus stat;
8782 	uint32_t stat0, stat1;
8783 	uint16_t tmp;
8784 
8785 	BWN_ASSERT_LOCKED(mac->mac_sc);
8786 
8787 	while (1) {
8788 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8789 		if (!(stat0 & 0x00000001))
8790 			break;
8791 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8792 
8793 		stat.cookie = (stat0 >> 16);
8794 		stat.seq = (stat1 & 0x0000ffff);
8795 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8796 		tmp = (stat0 & 0x0000ffff);
8797 		stat.framecnt = ((tmp & 0xf000) >> 12);
8798 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8799 		stat.sreason = ((tmp & 0x001c) >> 2);
8800 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8801 		stat.im = (tmp & 0x0040) ? 1 : 0;
8802 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8803 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8804 
8805 		bwn_handle_txeof(mac, &stat);
8806 	}
8807 }
8808 
8809 static void
8810 bwn_hwreset(void *arg, int npending)
8811 {
8812 	struct bwn_mac *mac = arg;
8813 	struct bwn_softc *sc = mac->mac_sc;
8814 	int error = 0;
8815 	int prev_status;
8816 
8817 	BWN_LOCK(sc);
8818 
8819 	prev_status = mac->mac_status;
8820 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8821 		bwn_core_stop(mac);
8822 	if (prev_status >= BWN_MAC_STATUS_INITED)
8823 		bwn_core_exit(mac);
8824 
8825 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8826 		error = bwn_core_init(mac);
8827 		if (error)
8828 			goto out;
8829 	}
8830 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8831 		bwn_core_start(mac);
8832 out:
8833 	if (error) {
8834 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8835 		sc->sc_curmac = NULL;
8836 	}
8837 	BWN_UNLOCK(sc);
8838 }
8839 
8840 static void
8841 bwn_handle_fwpanic(struct bwn_mac *mac)
8842 {
8843 	struct bwn_softc *sc = mac->mac_sc;
8844 	uint16_t reason;
8845 
8846 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8847 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8848 
8849 	if (reason == BWN_FWPANIC_RESTART)
8850 		bwn_restart(mac, "ucode panic");
8851 }
8852 
8853 static void
8854 bwn_load_beacon0(struct bwn_mac *mac)
8855 {
8856 
8857 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8858 }
8859 
8860 static void
8861 bwn_load_beacon1(struct bwn_mac *mac)
8862 {
8863 
8864 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8865 }
8866 
8867 static uint32_t
8868 bwn_jssi_read(struct bwn_mac *mac)
8869 {
8870 	uint32_t val = 0;
8871 
8872 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8873 	val <<= 16;
8874 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8875 
8876 	return (val);
8877 }
8878 
8879 static void
8880 bwn_noise_gensample(struct bwn_mac *mac)
8881 {
8882 	uint32_t jssi = 0x7f7f7f7f;
8883 
8884 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8885 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8886 	BWN_WRITE_4(mac, BWN_MACCMD,
8887 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8888 }
8889 
8890 static int
8891 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8892 {
8893 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8894 
8895 	return (dr->dr_numslots - dr->dr_usedslot);
8896 }
8897 
8898 static int
8899 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8900 {
8901 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8902 
8903 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8904 	    ("%s:%d: fail", __func__, __LINE__));
8905 	if (slot == dr->dr_numslots - 1)
8906 		return (0);
8907 	return (slot + 1);
8908 }
8909 
8910 static void
8911 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8912 {
8913 	struct bwn_mac *mac = dr->dr_mac;
8914 	struct bwn_softc *sc = mac->mac_sc;
8915 	struct bwn_dma *dma = &mac->mac_method.dma;
8916 	struct bwn_dmadesc_generic *desc;
8917 	struct bwn_dmadesc_meta *meta;
8918 	struct bwn_rxhdr4 *rxhdr;
8919 	struct ifnet *ifp = sc->sc_ifp;
8920 	struct mbuf *m;
8921 	uint32_t macstat;
8922 	int32_t tmp;
8923 	int cnt = 0;
8924 	uint16_t len;
8925 
8926 	dr->getdesc(dr, *slot, &desc, &meta);
8927 
8928 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8929 	m = meta->mt_m;
8930 
8931 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8932 		ifp->if_ierrors++;
8933 		return;
8934 	}
8935 
8936 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8937 	len = le16toh(rxhdr->frame_len);
8938 	if (len <= 0) {
8939 		ifp->if_ierrors++;
8940 		return;
8941 	}
8942 	if (bwn_dma_check_redzone(dr, m)) {
8943 		device_printf(sc->sc_dev, "redzone error.\n");
8944 		bwn_dma_set_redzone(dr, m);
8945 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8946 		    BUS_DMASYNC_PREWRITE);
8947 		return;
8948 	}
8949 	if (len > dr->dr_rx_bufsize) {
8950 		tmp = len;
8951 		while (1) {
8952 			dr->getdesc(dr, *slot, &desc, &meta);
8953 			bwn_dma_set_redzone(dr, meta->mt_m);
8954 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8955 			    BUS_DMASYNC_PREWRITE);
8956 			*slot = bwn_dma_nextslot(dr, *slot);
8957 			cnt++;
8958 			tmp -= dr->dr_rx_bufsize;
8959 			if (tmp <= 0)
8960 				break;
8961 		}
8962 		device_printf(sc->sc_dev, "too small buffer "
8963 		       "(len %u buffer %u dropped %d)\n",
8964 		       len, dr->dr_rx_bufsize, cnt);
8965 		return;
8966 	}
8967 	macstat = le32toh(rxhdr->mac_status);
8968 	if (macstat & BWN_RX_MAC_FCSERR) {
8969 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8970 			device_printf(sc->sc_dev, "RX drop\n");
8971 			return;
8972 		}
8973 	}
8974 
8975 	m->m_pkthdr.rcvif = ifp;
8976 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8977 	m_adj(m, dr->dr_frameoffset);
8978 
8979 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8980 }
8981 
8982 static void
8983 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8984 {
8985 	struct bwn_dma_ring *dr;
8986 	struct bwn_dmadesc_generic *desc;
8987 	struct bwn_dmadesc_meta *meta;
8988 	struct bwn_pio_txqueue *tq;
8989 	struct bwn_pio_txpkt *tp = NULL;
8990 	struct bwn_softc *sc = mac->mac_sc;
8991 	struct bwn_stats *stats = &mac->mac_stats;
8992 	struct ieee80211_node *ni;
8993 	struct ieee80211vap *vap;
8994 	int retrycnt = 0, slot;
8995 
8996 	BWN_ASSERT_LOCKED(mac->mac_sc);
8997 
8998 	if (status->im)
8999 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
9000 	if (status->ampdu)
9001 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9002 	if (status->rtscnt) {
9003 		if (status->rtscnt == 0xf)
9004 			stats->rtsfail++;
9005 		else
9006 			stats->rts++;
9007 	}
9008 
9009 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9010 		if (status->ack) {
9011 			dr = bwn_dma_parse_cookie(mac, status,
9012 			    status->cookie, &slot);
9013 			if (dr == NULL) {
9014 				device_printf(sc->sc_dev,
9015 				    "failed to parse cookie\n");
9016 				return;
9017 			}
9018 			while (1) {
9019 				dr->getdesc(dr, slot, &desc, &meta);
9020 				if (meta->mt_islast) {
9021 					ni = meta->mt_ni;
9022 					vap = ni->ni_vap;
9023 					ieee80211_ratectl_tx_complete(vap, ni,
9024 					    status->ack ?
9025 					      IEEE80211_RATECTL_TX_SUCCESS :
9026 					      IEEE80211_RATECTL_TX_FAILURE,
9027 					    &retrycnt, 0);
9028 					break;
9029 				}
9030 				slot = bwn_dma_nextslot(dr, slot);
9031 			}
9032 		}
9033 		bwn_dma_handle_txeof(mac, status);
9034 	} else {
9035 		if (status->ack) {
9036 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9037 			if (tq == NULL) {
9038 				device_printf(sc->sc_dev,
9039 				    "failed to parse cookie\n");
9040 				return;
9041 			}
9042 			ni = tp->tp_ni;
9043 			vap = ni->ni_vap;
9044 			ieee80211_ratectl_tx_complete(vap, ni,
9045 			    status->ack ?
9046 			      IEEE80211_RATECTL_TX_SUCCESS :
9047 			      IEEE80211_RATECTL_TX_FAILURE,
9048 			    &retrycnt, 0);
9049 		}
9050 		bwn_pio_handle_txeof(mac, status);
9051 	}
9052 
9053 	bwn_phy_txpower_check(mac, 0);
9054 }
9055 
9056 static uint8_t
9057 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9058 {
9059 	struct bwn_mac *mac = prq->prq_mac;
9060 	struct bwn_softc *sc = mac->mac_sc;
9061 	struct bwn_rxhdr4 rxhdr;
9062 	struct ifnet *ifp = sc->sc_ifp;
9063 	struct mbuf *m;
9064 	uint32_t ctl32, macstat, v32;
9065 	unsigned int i, padding;
9066 	uint16_t ctl16, len, totlen, v16;
9067 	unsigned char *mp;
9068 	char *data;
9069 
9070 	memset(&rxhdr, 0, sizeof(rxhdr));
9071 
9072 	if (prq->prq_rev >= 8) {
9073 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9074 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9075 			return (0);
9076 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9077 		    BWN_PIO8_RXCTL_FRAMEREADY);
9078 		for (i = 0; i < 10; i++) {
9079 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9080 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9081 				goto ready;
9082 			DELAY(10);
9083 		}
9084 	} else {
9085 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9086 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9087 			return (0);
9088 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9089 		    BWN_PIO_RXCTL_FRAMEREADY);
9090 		for (i = 0; i < 10; i++) {
9091 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9092 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9093 				goto ready;
9094 			DELAY(10);
9095 		}
9096 	}
9097 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9098 	return (1);
9099 ready:
9100 	if (prq->prq_rev >= 8)
9101 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9102 		    prq->prq_base + BWN_PIO8_RXDATA);
9103 	else
9104 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9105 		    prq->prq_base + BWN_PIO_RXDATA);
9106 	len = le16toh(rxhdr.frame_len);
9107 	if (len > 0x700) {
9108 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9109 		goto error;
9110 	}
9111 	if (len == 0) {
9112 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9113 		goto error;
9114 	}
9115 
9116 	macstat = le32toh(rxhdr.mac_status);
9117 	if (macstat & BWN_RX_MAC_FCSERR) {
9118 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9119 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9120 			goto error;
9121 		}
9122 	}
9123 
9124 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9125 	totlen = len + padding;
9126 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9127 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9128 	if (m == NULL) {
9129 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9130 		goto error;
9131 	}
9132 	mp = mtod(m, unsigned char *);
9133 	if (prq->prq_rev >= 8) {
9134 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9135 		    prq->prq_base + BWN_PIO8_RXDATA);
9136 		if (totlen & 3) {
9137 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9138 			data = &(mp[totlen - 1]);
9139 			switch (totlen & 3) {
9140 			case 3:
9141 				*data = (v32 >> 16);
9142 				data--;
9143 			case 2:
9144 				*data = (v32 >> 8);
9145 				data--;
9146 			case 1:
9147 				*data = v32;
9148 			}
9149 		}
9150 	} else {
9151 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9152 		    prq->prq_base + BWN_PIO_RXDATA);
9153 		if (totlen & 1) {
9154 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9155 			mp[totlen - 1] = v16;
9156 		}
9157 	}
9158 
9159 	m->m_pkthdr.rcvif = ifp;
9160 	m->m_len = m->m_pkthdr.len = totlen;
9161 
9162 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9163 
9164 	return (1);
9165 error:
9166 	if (prq->prq_rev >= 8)
9167 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9168 		    BWN_PIO8_RXCTL_DATAREADY);
9169 	else
9170 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9171 	return (1);
9172 }
9173 
9174 static int
9175 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9176     struct bwn_dmadesc_meta *meta, int init)
9177 {
9178 	struct bwn_mac *mac = dr->dr_mac;
9179 	struct bwn_dma *dma = &mac->mac_method.dma;
9180 	struct bwn_rxhdr4 *hdr;
9181 	bus_dmamap_t map;
9182 	bus_addr_t paddr;
9183 	struct mbuf *m;
9184 	int error;
9185 
9186 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9187 	if (m == NULL) {
9188 		error = ENOBUFS;
9189 
9190 		/*
9191 		 * If the NIC is up and running, we need to:
9192 		 * - Clear RX buffer's header.
9193 		 * - Restore RX descriptor settings.
9194 		 */
9195 		if (init)
9196 			return (error);
9197 		else
9198 			goto back;
9199 	}
9200 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9201 
9202 	bwn_dma_set_redzone(dr, m);
9203 
9204 	/*
9205 	 * Try to load RX buf into temporary DMA map
9206 	 */
9207 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9208 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9209 	if (error) {
9210 		m_freem(m);
9211 
9212 		/*
9213 		 * See the comment above
9214 		 */
9215 		if (init)
9216 			return (error);
9217 		else
9218 			goto back;
9219 	}
9220 
9221 	if (!init)
9222 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9223 	meta->mt_m = m;
9224 	meta->mt_paddr = paddr;
9225 
9226 	/*
9227 	 * Swap RX buf's DMA map with the loaded temporary one
9228 	 */
9229 	map = meta->mt_dmap;
9230 	meta->mt_dmap = dr->dr_spare_dmap;
9231 	dr->dr_spare_dmap = map;
9232 
9233 back:
9234 	/*
9235 	 * Clear RX buf header
9236 	 */
9237 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9238 	bzero(hdr, sizeof(*hdr));
9239 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9240 	    BUS_DMASYNC_PREWRITE);
9241 
9242 	/*
9243 	 * Setup RX buf descriptor
9244 	 */
9245 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9246 	    sizeof(*hdr), 0, 0, 0);
9247 	return (error);
9248 }
9249 
9250 static void
9251 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9252 		 bus_size_t mapsz __unused, int error)
9253 {
9254 
9255 	if (!error) {
9256 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9257 		*((bus_addr_t *)arg) = seg->ds_addr;
9258 	}
9259 }
9260 
9261 static int
9262 bwn_hwrate2ieeerate(int rate)
9263 {
9264 
9265 	switch (rate) {
9266 	case BWN_CCK_RATE_1MB:
9267 		return (2);
9268 	case BWN_CCK_RATE_2MB:
9269 		return (4);
9270 	case BWN_CCK_RATE_5MB:
9271 		return (11);
9272 	case BWN_CCK_RATE_11MB:
9273 		return (22);
9274 	case BWN_OFDM_RATE_6MB:
9275 		return (12);
9276 	case BWN_OFDM_RATE_9MB:
9277 		return (18);
9278 	case BWN_OFDM_RATE_12MB:
9279 		return (24);
9280 	case BWN_OFDM_RATE_18MB:
9281 		return (36);
9282 	case BWN_OFDM_RATE_24MB:
9283 		return (48);
9284 	case BWN_OFDM_RATE_36MB:
9285 		return (72);
9286 	case BWN_OFDM_RATE_48MB:
9287 		return (96);
9288 	case BWN_OFDM_RATE_54MB:
9289 		return (108);
9290 	default:
9291 		printf("Ooops\n");
9292 		return (0);
9293 	}
9294 }
9295 
9296 static void
9297 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9298 {
9299 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9300 	struct bwn_plcp6 *plcp;
9301 	struct bwn_softc *sc = mac->mac_sc;
9302 	struct ieee80211_frame_min *wh;
9303 	struct ieee80211_node *ni;
9304 	struct ifnet *ifp = sc->sc_ifp;
9305 	struct ieee80211com *ic = ifp->if_l2com;
9306 	uint32_t macstat;
9307 	int padding, rate, rssi = 0, noise = 0, type;
9308 	uint16_t phytype, phystat0, phystat3, chanstat;
9309 	unsigned char *mp = mtod(m, unsigned char *);
9310 	static int rx_mac_dec_rpt = 0;
9311 
9312 	BWN_ASSERT_LOCKED(sc);
9313 
9314 	phystat0 = le16toh(rxhdr->phy_status0);
9315 	phystat3 = le16toh(rxhdr->phy_status3);
9316 	macstat = le32toh(rxhdr->mac_status);
9317 	chanstat = le16toh(rxhdr->channel);
9318 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9319 
9320 	if (macstat & BWN_RX_MAC_FCSERR)
9321 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9322 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9323 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9324 	if (macstat & BWN_RX_MAC_DECERR)
9325 		goto drop;
9326 
9327 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9328 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9329 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9330 		    m->m_pkthdr.len);
9331 		goto drop;
9332 	}
9333 	plcp = (struct bwn_plcp6 *)(mp + padding);
9334 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9335 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9336 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9337 		    m->m_pkthdr.len);
9338 		goto drop;
9339 	}
9340 	wh = mtod(m, struct ieee80211_frame_min *);
9341 
9342 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9343 		device_printf(sc->sc_dev,
9344 		    "RX decryption attempted (old %d keyidx %#x)\n",
9345 		    BWN_ISOLDFMT(mac),
9346 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9347 
9348 	/* XXX calculating RSSI & noise & antenna */
9349 
9350 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9351 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9352 		    phytype == BWN_PHYTYPE_A);
9353 	else
9354 		rate = bwn_plcp_get_cckrate(mac, plcp);
9355 	if (rate == -1) {
9356 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9357 			goto drop;
9358 	}
9359 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9360 
9361 	/* RX radio tap */
9362 	if (ieee80211_radiotap_active(ic))
9363 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9364 	m_adj(m, -IEEE80211_CRC_LEN);
9365 
9366 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9367 	noise = mac->mac_stats.link_noise;
9368 
9369 	ifp->if_ipackets++;
9370 
9371 	BWN_UNLOCK(sc);
9372 
9373 	ni = ieee80211_find_rxnode(ic, wh);
9374 	if (ni != NULL) {
9375 		type = ieee80211_input(ni, m, rssi, noise);
9376 		ieee80211_free_node(ni);
9377 	} else
9378 		type = ieee80211_input_all(ic, m, rssi, noise);
9379 
9380 	BWN_LOCK(sc);
9381 	return;
9382 drop:
9383 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9384 }
9385 
9386 static void
9387 bwn_dma_handle_txeof(struct bwn_mac *mac,
9388     const struct bwn_txstatus *status)
9389 {
9390 	struct bwn_dma *dma = &mac->mac_method.dma;
9391 	struct bwn_dma_ring *dr;
9392 	struct bwn_dmadesc_generic *desc;
9393 	struct bwn_dmadesc_meta *meta;
9394 	struct bwn_softc *sc = mac->mac_sc;
9395 	struct ieee80211_node *ni;
9396 	struct ifnet *ifp = sc->sc_ifp;
9397 	struct mbuf *m;
9398 	int slot;
9399 
9400 	BWN_ASSERT_LOCKED(sc);
9401 
9402 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9403 	if (dr == NULL) {
9404 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9405 		return;
9406 	}
9407 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9408 
9409 	while (1) {
9410 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9411 		    ("%s:%d: fail", __func__, __LINE__));
9412 		dr->getdesc(dr, slot, &desc, &meta);
9413 
9414 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9415 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9416 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9417 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9418 
9419 		if (meta->mt_islast) {
9420 			KASSERT(meta->mt_m != NULL,
9421 			    ("%s:%d: fail", __func__, __LINE__));
9422 
9423 			ni = meta->mt_ni;
9424 			m = meta->mt_m;
9425 			if (ni != NULL) {
9426 				/*
9427 				 * Do any tx complete callback. Note this must
9428 				 * be done before releasing the node reference.
9429 				 */
9430 				if (m->m_flags & M_TXCB)
9431 					ieee80211_process_callback(ni, m, 0);
9432 				ieee80211_free_node(ni);
9433 				meta->mt_ni = NULL;
9434 			}
9435 			m_freem(m);
9436 			meta->mt_m = NULL;
9437 		} else {
9438 			KASSERT(meta->mt_m == NULL,
9439 			    ("%s:%d: fail", __func__, __LINE__));
9440 		}
9441 
9442 		dr->dr_usedslot--;
9443 		if (meta->mt_islast) {
9444 			ifp->if_opackets++;
9445 			break;
9446 		}
9447 		slot = bwn_dma_nextslot(dr, slot);
9448 	}
9449 	sc->sc_watchdog_timer = 0;
9450 	if (dr->dr_stop) {
9451 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9452 		    ("%s:%d: fail", __func__, __LINE__));
9453 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9454 		dr->dr_stop = 0;
9455 	}
9456 }
9457 
9458 static void
9459 bwn_pio_handle_txeof(struct bwn_mac *mac,
9460     const struct bwn_txstatus *status)
9461 {
9462 	struct bwn_pio_txqueue *tq;
9463 	struct bwn_pio_txpkt *tp = NULL;
9464 	struct bwn_softc *sc = mac->mac_sc;
9465 	struct ifnet *ifp = sc->sc_ifp;
9466 
9467 	BWN_ASSERT_LOCKED(sc);
9468 
9469 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9470 	if (tq == NULL)
9471 		return;
9472 
9473 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9474 	tq->tq_free++;
9475 
9476 	if (tp->tp_ni != NULL) {
9477 		/*
9478 		 * Do any tx complete callback.  Note this must
9479 		 * be done before releasing the node reference.
9480 		 */
9481 		if (tp->tp_m->m_flags & M_TXCB)
9482 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9483 		ieee80211_free_node(tp->tp_ni);
9484 		tp->tp_ni = NULL;
9485 	}
9486 	m_freem(tp->tp_m);
9487 	tp->tp_m = NULL;
9488 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9489 
9490 	ifp->if_opackets++;
9491 
9492 	sc->sc_watchdog_timer = 0;
9493 	if (tq->tq_stop) {
9494 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9495 		tq->tq_stop = 0;
9496 	}
9497 }
9498 
9499 static void
9500 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9501 {
9502 	struct bwn_softc *sc = mac->mac_sc;
9503 	struct bwn_phy *phy = &mac->mac_phy;
9504 	struct ifnet *ifp = sc->sc_ifp;
9505 	struct ieee80211com *ic = ifp->if_l2com;
9506 	unsigned long now;
9507 	int result;
9508 
9509 	BWN_GETTIME(now);
9510 
9511 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9512 		return;
9513 	phy->nexttime = now + 2 * 1000;
9514 
9515 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9516 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9517 		return;
9518 
9519 	if (phy->recalc_txpwr != NULL) {
9520 		result = phy->recalc_txpwr(mac,
9521 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9522 		if (result == BWN_TXPWR_RES_DONE)
9523 			return;
9524 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9525 		    ("%s: fail", __func__));
9526 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9527 
9528 		ieee80211_runtask(ic, &mac->mac_txpower);
9529 	}
9530 }
9531 
9532 static uint16_t
9533 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9534 {
9535 
9536 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9537 }
9538 
9539 static uint32_t
9540 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9541 {
9542 
9543 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9544 }
9545 
9546 static void
9547 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9548 {
9549 
9550 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9551 }
9552 
9553 static void
9554 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9555 {
9556 
9557 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9558 }
9559 
9560 static int
9561 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9562 {
9563 
9564 	switch (rate) {
9565 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9566 	case 12:
9567 		return (BWN_OFDM_RATE_6MB);
9568 	case 18:
9569 		return (BWN_OFDM_RATE_9MB);
9570 	case 24:
9571 		return (BWN_OFDM_RATE_12MB);
9572 	case 36:
9573 		return (BWN_OFDM_RATE_18MB);
9574 	case 48:
9575 		return (BWN_OFDM_RATE_24MB);
9576 	case 72:
9577 		return (BWN_OFDM_RATE_36MB);
9578 	case 96:
9579 		return (BWN_OFDM_RATE_48MB);
9580 	case 108:
9581 		return (BWN_OFDM_RATE_54MB);
9582 	/* CCK rates (NB: not IEEE std, device-specific) */
9583 	case 2:
9584 		return (BWN_CCK_RATE_1MB);
9585 	case 4:
9586 		return (BWN_CCK_RATE_2MB);
9587 	case 11:
9588 		return (BWN_CCK_RATE_5MB);
9589 	case 22:
9590 		return (BWN_CCK_RATE_11MB);
9591 	}
9592 
9593 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9594 	return (BWN_CCK_RATE_1MB);
9595 }
9596 
9597 static int
9598 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9599     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9600 {
9601 	const struct bwn_phy *phy = &mac->mac_phy;
9602 	struct bwn_softc *sc = mac->mac_sc;
9603 	struct ieee80211_frame *wh;
9604 	struct ieee80211_frame *protwh;
9605 	struct ieee80211_frame_cts *cts;
9606 	struct ieee80211_frame_rts *rts;
9607 	const struct ieee80211_txparam *tp;
9608 	struct ieee80211vap *vap = ni->ni_vap;
9609 	struct ifnet *ifp = sc->sc_ifp;
9610 	struct ieee80211com *ic = ifp->if_l2com;
9611 	struct mbuf *mprot;
9612 	unsigned int len;
9613 	uint32_t macctl = 0;
9614 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9615 	uint16_t phyctl = 0;
9616 	uint8_t rate, rate_fb;
9617 
9618 	wh = mtod(m, struct ieee80211_frame *);
9619 	memset(txhdr, 0, sizeof(*txhdr));
9620 
9621 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9622 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9623 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9624 
9625 	/*
9626 	 * Find TX rate
9627 	 */
9628 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9629 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9630 		rate = rate_fb = tp->mgmtrate;
9631 	else if (ismcast)
9632 		rate = rate_fb = tp->mcastrate;
9633 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9634 		rate = rate_fb = tp->ucastrate;
9635 	else {
9636 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9637 		rate = ni->ni_txrate;
9638 
9639 		if (rix > 0)
9640 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9641 			    IEEE80211_RATE_VAL;
9642 		else
9643 			rate_fb = rate;
9644 	}
9645 
9646 	sc->sc_tx_rate = rate;
9647 
9648 	rate = bwn_ieeerate2hwrate(sc, rate);
9649 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9650 
9651 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9652 	    bwn_plcp_getcck(rate);
9653 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9654 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9655 
9656 	if ((rate_fb == rate) ||
9657 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9658 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9659 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9660 	else
9661 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9662 		    m->m_pkthdr.len, rate, isshort);
9663 
9664 	/* XXX TX encryption */
9665 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9666 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9667 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9668 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9669 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9670 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9671 
9672 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9673 	    BWN_TX_EFT_FB_CCK;
9674 	txhdr->chan = phy->chan;
9675 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9676 	    BWN_TX_PHY_ENC_CCK;
9677 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9678 	     rate == BWN_CCK_RATE_11MB))
9679 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9680 
9681 	/* XXX TX antenna selection */
9682 
9683 	switch (bwn_antenna_sanitize(mac, 0)) {
9684 	case 0:
9685 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9686 		break;
9687 	case 1:
9688 		phyctl |= BWN_TX_PHY_ANT0;
9689 		break;
9690 	case 2:
9691 		phyctl |= BWN_TX_PHY_ANT1;
9692 		break;
9693 	case 3:
9694 		phyctl |= BWN_TX_PHY_ANT2;
9695 		break;
9696 	case 4:
9697 		phyctl |= BWN_TX_PHY_ANT3;
9698 		break;
9699 	default:
9700 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9701 	}
9702 
9703 	if (!ismcast)
9704 		macctl |= BWN_TX_MAC_ACK;
9705 
9706 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9707 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9708 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9709 		macctl |= BWN_TX_MAC_LONGFRAME;
9710 
9711 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9712 		/* XXX RTS rate is always 1MB??? */
9713 		rts_rate = BWN_CCK_RATE_1MB;
9714 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9715 
9716 		protdur = ieee80211_compute_duration(ic->ic_rt,
9717 		    m->m_pkthdr.len, rate, isshort) +
9718 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9719 
9720 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9721 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9722 			    (txhdr->body.old.rts_frame) :
9723 			    (txhdr->body.new.rts_frame));
9724 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9725 			    protdur);
9726 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9727 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9728 			    mprot->m_pkthdr.len);
9729 			m_freem(mprot);
9730 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9731 			len = sizeof(struct ieee80211_frame_cts);
9732 		} else {
9733 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9734 			    (txhdr->body.old.rts_frame) :
9735 			    (txhdr->body.new.rts_frame));
9736 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9737 			    isshort);
9738 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9739 			    wh->i_addr2, protdur);
9740 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9741 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9742 			    mprot->m_pkthdr.len);
9743 			m_freem(mprot);
9744 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9745 			len = sizeof(struct ieee80211_frame_rts);
9746 		}
9747 		len += IEEE80211_CRC_LEN;
9748 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9749 		    &txhdr->body.old.rts_plcp :
9750 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9751 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9752 		    rts_rate_fb);
9753 
9754 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9755 		    (&txhdr->body.old.rts_frame) :
9756 		    (&txhdr->body.new.rts_frame));
9757 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9758 
9759 		if (BWN_ISOFDMRATE(rts_rate)) {
9760 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9761 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9762 		} else {
9763 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9764 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9765 		}
9766 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9767 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9768 	}
9769 
9770 	if (BWN_ISOLDFMT(mac))
9771 		txhdr->body.old.cookie = htole16(cookie);
9772 	else
9773 		txhdr->body.new.cookie = htole16(cookie);
9774 
9775 	txhdr->macctl = htole32(macctl);
9776 	txhdr->phyctl = htole16(phyctl);
9777 
9778 	/*
9779 	 * TX radio tap
9780 	 */
9781 	if (ieee80211_radiotap_active_vap(vap)) {
9782 		sc->sc_tx_th.wt_flags = 0;
9783 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9784 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9785 		if (isshort &&
9786 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9787 		     rate == BWN_CCK_RATE_11MB))
9788 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9789 		sc->sc_tx_th.wt_rate = rate;
9790 
9791 		ieee80211_radiotap_tx(vap, m);
9792 	}
9793 
9794 	return (0);
9795 }
9796 
9797 static void
9798 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9799     const uint8_t rate)
9800 {
9801 	uint32_t d, plen;
9802 	uint8_t *raw = plcp->o.raw;
9803 
9804 	if (BWN_ISOFDMRATE(rate)) {
9805 		d = bwn_plcp_getofdm(rate);
9806 		KASSERT(!(octets & 0xf000),
9807 		    ("%s:%d: fail", __func__, __LINE__));
9808 		d |= (octets << 5);
9809 		plcp->o.data = htole32(d);
9810 	} else {
9811 		plen = octets * 16 / rate;
9812 		if ((octets * 16 % rate) > 0) {
9813 			plen++;
9814 			if ((rate == BWN_CCK_RATE_11MB)
9815 			    && ((octets * 8 % 11) < 4)) {
9816 				raw[1] = 0x84;
9817 			} else
9818 				raw[1] = 0x04;
9819 		} else
9820 			raw[1] = 0x04;
9821 		plcp->o.data |= htole32(plen << 16);
9822 		raw[0] = bwn_plcp_getcck(rate);
9823 	}
9824 }
9825 
9826 static uint8_t
9827 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9828 {
9829 	struct bwn_softc *sc = mac->mac_sc;
9830 	uint8_t mask;
9831 
9832 	if (n == 0)
9833 		return (0);
9834 	if (mac->mac_phy.gmode)
9835 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9836 	else
9837 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9838 	if (!(mask & (1 << (n - 1))))
9839 		return (0);
9840 	return (n);
9841 }
9842 
9843 static uint8_t
9844 bwn_get_fbrate(uint8_t bitrate)
9845 {
9846 	switch (bitrate) {
9847 	case BWN_CCK_RATE_1MB:
9848 		return (BWN_CCK_RATE_1MB);
9849 	case BWN_CCK_RATE_2MB:
9850 		return (BWN_CCK_RATE_1MB);
9851 	case BWN_CCK_RATE_5MB:
9852 		return (BWN_CCK_RATE_2MB);
9853 	case BWN_CCK_RATE_11MB:
9854 		return (BWN_CCK_RATE_5MB);
9855 	case BWN_OFDM_RATE_6MB:
9856 		return (BWN_CCK_RATE_5MB);
9857 	case BWN_OFDM_RATE_9MB:
9858 		return (BWN_OFDM_RATE_6MB);
9859 	case BWN_OFDM_RATE_12MB:
9860 		return (BWN_OFDM_RATE_9MB);
9861 	case BWN_OFDM_RATE_18MB:
9862 		return (BWN_OFDM_RATE_12MB);
9863 	case BWN_OFDM_RATE_24MB:
9864 		return (BWN_OFDM_RATE_18MB);
9865 	case BWN_OFDM_RATE_36MB:
9866 		return (BWN_OFDM_RATE_24MB);
9867 	case BWN_OFDM_RATE_48MB:
9868 		return (BWN_OFDM_RATE_36MB);
9869 	case BWN_OFDM_RATE_54MB:
9870 		return (BWN_OFDM_RATE_48MB);
9871 	}
9872 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9873 	return (0);
9874 }
9875 
9876 static uint32_t
9877 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9878     uint32_t ctl, const void *_data, int len)
9879 {
9880 	struct bwn_softc *sc = mac->mac_sc;
9881 	uint32_t value = 0;
9882 	const uint8_t *data = _data;
9883 
9884 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9885 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9886 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9887 
9888 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9889 	    tq->tq_base + BWN_PIO8_TXDATA);
9890 	if (len & 3) {
9891 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9892 		    BWN_PIO8_TXCTL_24_31);
9893 		data = &(data[len - 1]);
9894 		switch (len & 3) {
9895 		case 3:
9896 			ctl |= BWN_PIO8_TXCTL_16_23;
9897 			value |= (uint32_t)(*data) << 16;
9898 			data--;
9899 		case 2:
9900 			ctl |= BWN_PIO8_TXCTL_8_15;
9901 			value |= (uint32_t)(*data) << 8;
9902 			data--;
9903 		case 1:
9904 			value |= (uint32_t)(*data);
9905 		}
9906 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9907 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9908 	}
9909 
9910 	return (ctl);
9911 }
9912 
9913 static void
9914 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9915     uint16_t offset, uint32_t value)
9916 {
9917 
9918 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9919 }
9920 
9921 static uint16_t
9922 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9923     uint16_t ctl, const void *_data, int len)
9924 {
9925 	struct bwn_softc *sc = mac->mac_sc;
9926 	const uint8_t *data = _data;
9927 
9928 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9929 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9930 
9931 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9932 	    tq->tq_base + BWN_PIO_TXDATA);
9933 	if (len & 1) {
9934 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9935 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9936 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9937 	}
9938 
9939 	return (ctl);
9940 }
9941 
9942 static uint16_t
9943 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9944     uint16_t ctl, struct mbuf *m0)
9945 {
9946 	int i, j = 0;
9947 	uint16_t data = 0;
9948 	const uint8_t *buf;
9949 	struct mbuf *m = m0;
9950 
9951 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9952 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9953 
9954 	for (; m != NULL; m = m->m_next) {
9955 		buf = mtod(m, const uint8_t *);
9956 		for (i = 0; i < m->m_len; i++) {
9957 			if (!((j++) % 2))
9958 				data |= buf[i];
9959 			else {
9960 				data |= (buf[i] << 8);
9961 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9962 				data = 0;
9963 			}
9964 		}
9965 	}
9966 	if (m0->m_pkthdr.len % 2) {
9967 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9968 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9969 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9970 	}
9971 
9972 	return (ctl);
9973 }
9974 
9975 static void
9976 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9977 {
9978 
9979 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9980 		return;
9981 	BWN_WRITE_2(mac, 0x684, 510 + time);
9982 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9983 }
9984 
9985 static struct bwn_dma_ring *
9986 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9987 {
9988 
9989 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9990 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9991 
9992 	switch (prio) {
9993 	case 3:
9994 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9995 	case 2:
9996 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9997 	case 0:
9998 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9999 	case 1:
10000 		return (mac->mac_method.dma.wme[WME_AC_BK]);
10001 	}
10002 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10003 	return (NULL);
10004 }
10005 
10006 static int
10007 bwn_dma_getslot(struct bwn_dma_ring *dr)
10008 {
10009 	int slot;
10010 
10011 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10012 
10013 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10014 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10015 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10016 
10017 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10018 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10019 	dr->dr_curslot = slot;
10020 	dr->dr_usedslot++;
10021 
10022 	return (slot);
10023 }
10024 
10025 static int
10026 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10027 {
10028 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10029 	unsigned int a, b, c, d;
10030 	unsigned int avg;
10031 	uint32_t tmp;
10032 
10033 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10034 	a = tmp & 0xff;
10035 	b = (tmp >> 8) & 0xff;
10036 	c = (tmp >> 16) & 0xff;
10037 	d = (tmp >> 24) & 0xff;
10038 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10039 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10040 		return (ENOENT);
10041 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10042 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10043 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10044 
10045 	if (ofdm) {
10046 		a = (a + 32) & 0x3f;
10047 		b = (b + 32) & 0x3f;
10048 		c = (c + 32) & 0x3f;
10049 		d = (d + 32) & 0x3f;
10050 	}
10051 
10052 	avg = (a + b + c + d + 2) / 4;
10053 	if (ofdm) {
10054 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10055 		    & BWN_HF_4DB_CCK_POWERBOOST)
10056 			avg = (avg >= 13) ? (avg - 13) : 0;
10057 	}
10058 	return (avg);
10059 }
10060 
10061 static void
10062 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10063 {
10064 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10065 	int rfatt = *rfattp;
10066 	int bbatt = *bbattp;
10067 
10068 	while (1) {
10069 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10070 			break;
10071 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10072 			break;
10073 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10074 			break;
10075 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10076 			break;
10077 		if (bbatt > lo->bbatt.max) {
10078 			bbatt -= 4;
10079 			rfatt += 1;
10080 			continue;
10081 		}
10082 		if (bbatt < lo->bbatt.min) {
10083 			bbatt += 4;
10084 			rfatt -= 1;
10085 			continue;
10086 		}
10087 		if (rfatt > lo->rfatt.max) {
10088 			rfatt -= 1;
10089 			bbatt += 4;
10090 			continue;
10091 		}
10092 		if (rfatt < lo->rfatt.min) {
10093 			rfatt += 1;
10094 			bbatt -= 4;
10095 			continue;
10096 		}
10097 		break;
10098 	}
10099 
10100 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10101 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10102 }
10103 
10104 static void
10105 bwn_phy_lock(struct bwn_mac *mac)
10106 {
10107 	struct bwn_softc *sc = mac->mac_sc;
10108 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10109 
10110 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10111 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10112 
10113 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10114 		bwn_psctl(mac, BWN_PS_AWAKE);
10115 }
10116 
10117 static void
10118 bwn_phy_unlock(struct bwn_mac *mac)
10119 {
10120 	struct bwn_softc *sc = mac->mac_sc;
10121 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10122 
10123 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10124 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10125 
10126 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10127 		bwn_psctl(mac, 0);
10128 }
10129 
10130 static void
10131 bwn_rf_lock(struct bwn_mac *mac)
10132 {
10133 
10134 	BWN_WRITE_4(mac, BWN_MACCTL,
10135 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10136 	BWN_READ_4(mac, BWN_MACCTL);
10137 	DELAY(10);
10138 }
10139 
10140 static void
10141 bwn_rf_unlock(struct bwn_mac *mac)
10142 {
10143 
10144 	BWN_READ_2(mac, BWN_PHYVER);
10145 	BWN_WRITE_4(mac, BWN_MACCTL,
10146 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10147 }
10148 
10149 static struct bwn_pio_txqueue *
10150 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10151     struct bwn_pio_txpkt **pack)
10152 {
10153 	struct bwn_pio *pio = &mac->mac_method.pio;
10154 	struct bwn_pio_txqueue *tq = NULL;
10155 	unsigned int index;
10156 
10157 	switch (cookie & 0xf000) {
10158 	case 0x1000:
10159 		tq = &pio->wme[WME_AC_BK];
10160 		break;
10161 	case 0x2000:
10162 		tq = &pio->wme[WME_AC_BE];
10163 		break;
10164 	case 0x3000:
10165 		tq = &pio->wme[WME_AC_VI];
10166 		break;
10167 	case 0x4000:
10168 		tq = &pio->wme[WME_AC_VO];
10169 		break;
10170 	case 0x5000:
10171 		tq = &pio->mcast;
10172 		break;
10173 	}
10174 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10175 	if (tq == NULL)
10176 		return (NULL);
10177 	index = (cookie & 0x0fff);
10178 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10179 	if (index >= N(tq->tq_pkts))
10180 		return (NULL);
10181 	*pack = &tq->tq_pkts[index];
10182 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10183 	return (tq);
10184 }
10185 
10186 static void
10187 bwn_txpwr(void *arg, int npending)
10188 {
10189 	struct bwn_mac *mac = arg;
10190 	struct bwn_softc *sc = mac->mac_sc;
10191 
10192 	BWN_LOCK(sc);
10193 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10194 	    mac->mac_phy.set_txpwr != NULL)
10195 		mac->mac_phy.set_txpwr(mac);
10196 	BWN_UNLOCK(sc);
10197 }
10198 
10199 static void
10200 bwn_task_15s(struct bwn_mac *mac)
10201 {
10202 	uint16_t reg;
10203 
10204 	if (mac->mac_fw.opensource) {
10205 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10206 		if (reg) {
10207 			bwn_restart(mac, "fw watchdog");
10208 			return;
10209 		}
10210 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10211 	}
10212 	if (mac->mac_phy.task_15s)
10213 		mac->mac_phy.task_15s(mac);
10214 
10215 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10216 }
10217 
10218 static void
10219 bwn_task_30s(struct bwn_mac *mac)
10220 {
10221 
10222 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10223 		return;
10224 	mac->mac_noise.noi_running = 1;
10225 	mac->mac_noise.noi_nsamples = 0;
10226 
10227 	bwn_noise_gensample(mac);
10228 }
10229 
10230 static void
10231 bwn_task_60s(struct bwn_mac *mac)
10232 {
10233 
10234 	if (mac->mac_phy.task_60s)
10235 		mac->mac_phy.task_60s(mac);
10236 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10237 }
10238 
10239 static void
10240 bwn_tasks(void *arg)
10241 {
10242 	struct bwn_mac *mac = arg;
10243 	struct bwn_softc *sc = mac->mac_sc;
10244 
10245 	BWN_ASSERT_LOCKED(sc);
10246 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10247 		return;
10248 
10249 	if (mac->mac_task_state % 4 == 0)
10250 		bwn_task_60s(mac);
10251 	if (mac->mac_task_state % 2 == 0)
10252 		bwn_task_30s(mac);
10253 	bwn_task_15s(mac);
10254 
10255 	mac->mac_task_state++;
10256 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10257 }
10258 
10259 static int
10260 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10261 {
10262 	struct bwn_softc *sc = mac->mac_sc;
10263 
10264 	KASSERT(a == 0, ("not support APHY\n"));
10265 
10266 	switch (plcp->o.raw[0] & 0xf) {
10267 	case 0xb:
10268 		return (BWN_OFDM_RATE_6MB);
10269 	case 0xf:
10270 		return (BWN_OFDM_RATE_9MB);
10271 	case 0xa:
10272 		return (BWN_OFDM_RATE_12MB);
10273 	case 0xe:
10274 		return (BWN_OFDM_RATE_18MB);
10275 	case 0x9:
10276 		return (BWN_OFDM_RATE_24MB);
10277 	case 0xd:
10278 		return (BWN_OFDM_RATE_36MB);
10279 	case 0x8:
10280 		return (BWN_OFDM_RATE_48MB);
10281 	case 0xc:
10282 		return (BWN_OFDM_RATE_54MB);
10283 	}
10284 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10285 	    plcp->o.raw[0] & 0xf);
10286 	return (-1);
10287 }
10288 
10289 static int
10290 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10291 {
10292 	struct bwn_softc *sc = mac->mac_sc;
10293 
10294 	switch (plcp->o.raw[0]) {
10295 	case 0x0a:
10296 		return (BWN_CCK_RATE_1MB);
10297 	case 0x14:
10298 		return (BWN_CCK_RATE_2MB);
10299 	case 0x37:
10300 		return (BWN_CCK_RATE_5MB);
10301 	case 0x6e:
10302 		return (BWN_CCK_RATE_11MB);
10303 	}
10304 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10305 	return (-1);
10306 }
10307 
10308 static void
10309 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10310     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10311     int rssi, int noise)
10312 {
10313 	struct bwn_softc *sc = mac->mac_sc;
10314 	const struct ieee80211_frame_min *wh;
10315 	uint64_t tsf;
10316 	uint16_t low_mactime_now;
10317 
10318 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10319 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10320 
10321 	wh = mtod(m, const struct ieee80211_frame_min *);
10322 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10323 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10324 
10325 	bwn_tsf_read(mac, &tsf);
10326 	low_mactime_now = tsf;
10327 	tsf = tsf & ~0xffffULL;
10328 	tsf += le16toh(rxhdr->mac_time);
10329 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10330 		tsf -= 0x10000;
10331 
10332 	sc->sc_rx_th.wr_tsf = tsf;
10333 	sc->sc_rx_th.wr_rate = rate;
10334 	sc->sc_rx_th.wr_antsignal = rssi;
10335 	sc->sc_rx_th.wr_antnoise = noise;
10336 }
10337 
10338 static void
10339 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10340 {
10341 	uint32_t low, high;
10342 
10343 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10344 	    ("%s:%d: fail", __func__, __LINE__));
10345 
10346 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10347 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10348 	*tsf = high;
10349 	*tsf <<= 32;
10350 	*tsf |= low;
10351 }
10352 
10353 static int
10354 bwn_dma_attach(struct bwn_mac *mac)
10355 {
10356 	struct bwn_dma *dma = &mac->mac_method.dma;
10357 	struct bwn_softc *sc = mac->mac_sc;
10358 	bus_addr_t lowaddr = 0;
10359 	int error;
10360 
10361 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10362 		return (0);
10363 
10364 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10365 
10366 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10367 
10368 	dma->dmatype = bwn_dma_gettype(mac);
10369 	if (dma->dmatype == BWN_DMA_30BIT)
10370 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10371 	else if (dma->dmatype == BWN_DMA_32BIT)
10372 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10373 	else
10374 		lowaddr = BUS_SPACE_MAXADDR;
10375 
10376 	/*
10377 	 * Create top level DMA tag
10378 	 */
10379 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10380 			       BWN_ALIGN, 0,		/* alignment, bounds */
10381 			       lowaddr,			/* lowaddr */
10382 			       BUS_SPACE_MAXADDR,	/* highaddr */
10383 			       NULL, NULL,		/* filter, filterarg */
10384 			       MAXBSIZE,		/* maxsize */
10385 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10386 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10387 			       0,			/* flags */
10388 			       NULL, NULL,		/* lockfunc, lockarg */
10389 			       &dma->parent_dtag);
10390 	if (error) {
10391 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10392 		return (error);
10393 	}
10394 
10395 	/*
10396 	 * Create TX/RX mbuf DMA tag
10397 	 */
10398 	error = bus_dma_tag_create(dma->parent_dtag,
10399 				1,
10400 				0,
10401 				BUS_SPACE_MAXADDR,
10402 				BUS_SPACE_MAXADDR,
10403 				NULL, NULL,
10404 				MCLBYTES,
10405 				1,
10406 				BUS_SPACE_MAXSIZE_32BIT,
10407 				0,
10408 				NULL, NULL,
10409 				&dma->rxbuf_dtag);
10410 	if (error) {
10411 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10412 		goto fail0;
10413 	}
10414 	error = bus_dma_tag_create(dma->parent_dtag,
10415 				1,
10416 				0,
10417 				BUS_SPACE_MAXADDR,
10418 				BUS_SPACE_MAXADDR,
10419 				NULL, NULL,
10420 				MCLBYTES,
10421 				1,
10422 				BUS_SPACE_MAXSIZE_32BIT,
10423 				0,
10424 				NULL, NULL,
10425 				&dma->txbuf_dtag);
10426 	if (error) {
10427 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10428 		goto fail1;
10429 	}
10430 
10431 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10432 	if (!dma->wme[WME_AC_BK])
10433 		goto fail2;
10434 
10435 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10436 	if (!dma->wme[WME_AC_BE])
10437 		goto fail3;
10438 
10439 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10440 	if (!dma->wme[WME_AC_VI])
10441 		goto fail4;
10442 
10443 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10444 	if (!dma->wme[WME_AC_VO])
10445 		goto fail5;
10446 
10447 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10448 	if (!dma->mcast)
10449 		goto fail6;
10450 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10451 	if (!dma->rx)
10452 		goto fail7;
10453 
10454 	return (error);
10455 
10456 fail7:	bwn_dma_ringfree(&dma->mcast);
10457 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10458 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10459 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10460 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10461 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10462 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10463 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10464 	return (error);
10465 }
10466 
10467 static struct bwn_dma_ring *
10468 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10469     uint16_t cookie, int *slot)
10470 {
10471 	struct bwn_dma *dma = &mac->mac_method.dma;
10472 	struct bwn_dma_ring *dr;
10473 	struct bwn_softc *sc = mac->mac_sc;
10474 
10475 	BWN_ASSERT_LOCKED(mac->mac_sc);
10476 
10477 	switch (cookie & 0xf000) {
10478 	case 0x1000:
10479 		dr = dma->wme[WME_AC_BK];
10480 		break;
10481 	case 0x2000:
10482 		dr = dma->wme[WME_AC_BE];
10483 		break;
10484 	case 0x3000:
10485 		dr = dma->wme[WME_AC_VI];
10486 		break;
10487 	case 0x4000:
10488 		dr = dma->wme[WME_AC_VO];
10489 		break;
10490 	case 0x5000:
10491 		dr = dma->mcast;
10492 		break;
10493 	default:
10494 		dr = NULL;
10495 		KASSERT(0 == 1,
10496 		    ("invalid cookie value %d", cookie & 0xf000));
10497 	}
10498 	*slot = (cookie & 0x0fff);
10499 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10500 		/*
10501 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10502 		 * that it occurs events which have same H/W sequence numbers.
10503 		 * When it's occurred just prints a WARNING msgs and ignores.
10504 		 */
10505 		KASSERT(status->seq == dma->lastseq,
10506 		    ("%s:%d: fail", __func__, __LINE__));
10507 		device_printf(sc->sc_dev,
10508 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10509 		    dr->dr_numslots);
10510 		return (NULL);
10511 	}
10512 	dma->lastseq = status->seq;
10513 	return (dr);
10514 }
10515 
10516 static void
10517 bwn_dma_stop(struct bwn_mac *mac)
10518 {
10519 	struct bwn_dma *dma;
10520 
10521 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10522 		return;
10523 	dma = &mac->mac_method.dma;
10524 
10525 	bwn_dma_ringstop(&dma->rx);
10526 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10527 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10528 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10529 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10530 	bwn_dma_ringstop(&dma->mcast);
10531 }
10532 
10533 static void
10534 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10535 {
10536 
10537 	if (dr == NULL)
10538 		return;
10539 
10540 	bwn_dma_cleanup(*dr);
10541 }
10542 
10543 static void
10544 bwn_pio_stop(struct bwn_mac *mac)
10545 {
10546 	struct bwn_pio *pio;
10547 
10548 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10549 		return;
10550 	pio = &mac->mac_method.pio;
10551 
10552 	bwn_destroy_queue_tx(&pio->mcast);
10553 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10554 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10555 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10556 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10557 }
10558 
10559 static void
10560 bwn_led_attach(struct bwn_mac *mac)
10561 {
10562 	struct bwn_softc *sc = mac->mac_sc;
10563 	const uint8_t *led_act = NULL;
10564 	uint16_t val[BWN_LED_MAX];
10565 	int i;
10566 
10567 	sc->sc_led_idle = (2350 * hz) / 1000;
10568 	sc->sc_led_blink = 1;
10569 
10570 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10571 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10572 		    bwn_vendor_led_act[i].vid) {
10573 			led_act = bwn_vendor_led_act[i].led_act;
10574 			break;
10575 		}
10576 	}
10577 	if (led_act == NULL)
10578 		led_act = bwn_default_led_act;
10579 
10580 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10581 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10582 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10583 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10584 
10585 	for (i = 0; i < BWN_LED_MAX; ++i) {
10586 		struct bwn_led *led = &sc->sc_leds[i];
10587 
10588 		if (val[i] == 0xff) {
10589 			led->led_act = led_act[i];
10590 		} else {
10591 			if (val[i] & BWN_LED_ACT_LOW)
10592 				led->led_flags |= BWN_LED_F_ACTLOW;
10593 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10594 		}
10595 		led->led_mask = (1 << i);
10596 
10597 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10598 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10599 		    led->led_act == BWN_LED_ACT_BLINK) {
10600 			led->led_flags |= BWN_LED_F_BLINK;
10601 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10602 				led->led_flags |= BWN_LED_F_POLLABLE;
10603 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10604 				led->led_flags |= BWN_LED_F_SLOW;
10605 
10606 			if (sc->sc_blink_led == NULL) {
10607 				sc->sc_blink_led = led;
10608 				if (led->led_flags & BWN_LED_F_SLOW)
10609 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10610 			}
10611 		}
10612 
10613 		DPRINTF(sc, BWN_DEBUG_LED,
10614 		    "%dth led, act %d, lowact %d\n", i,
10615 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10616 	}
10617 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10618 }
10619 
10620 static __inline uint16_t
10621 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10622 {
10623 
10624 	if (led->led_flags & BWN_LED_F_ACTLOW)
10625 		on = !on;
10626 	if (on)
10627 		val |= led->led_mask;
10628 	else
10629 		val &= ~led->led_mask;
10630 	return val;
10631 }
10632 
10633 static void
10634 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10635 {
10636 	struct bwn_softc *sc = mac->mac_sc;
10637 	struct ifnet *ifp = sc->sc_ifp;
10638 	struct ieee80211com *ic = ifp->if_l2com;
10639 	uint16_t val;
10640 	int i;
10641 
10642 	if (nstate == IEEE80211_S_INIT) {
10643 		callout_stop(&sc->sc_led_blink_ch);
10644 		sc->sc_led_blinking = 0;
10645 	}
10646 
10647 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10648 		return;
10649 
10650 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10651 	for (i = 0; i < BWN_LED_MAX; ++i) {
10652 		struct bwn_led *led = &sc->sc_leds[i];
10653 		int on;
10654 
10655 		if (led->led_act == BWN_LED_ACT_UNKN ||
10656 		    led->led_act == BWN_LED_ACT_NULL)
10657 			continue;
10658 
10659 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10660 		    nstate != IEEE80211_S_INIT)
10661 			continue;
10662 
10663 		switch (led->led_act) {
10664 		case BWN_LED_ACT_ON:    /* Always on */
10665 			on = 1;
10666 			break;
10667 		case BWN_LED_ACT_OFF:   /* Always off */
10668 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10669 			on = 0;
10670 			break;
10671 		default:
10672 			on = 1;
10673 			switch (nstate) {
10674 			case IEEE80211_S_INIT:
10675 				on = 0;
10676 				break;
10677 			case IEEE80211_S_RUN:
10678 				if (led->led_act == BWN_LED_ACT_11G &&
10679 				    ic->ic_curmode != IEEE80211_MODE_11G)
10680 					on = 0;
10681 				break;
10682 			default:
10683 				if (led->led_act == BWN_LED_ACT_ASSOC)
10684 					on = 0;
10685 				break;
10686 			}
10687 			break;
10688 		}
10689 
10690 		val = bwn_led_onoff(led, val, on);
10691 	}
10692 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10693 }
10694 
10695 static void
10696 bwn_led_event(struct bwn_mac *mac, int event)
10697 {
10698 	struct bwn_softc *sc = mac->mac_sc;
10699 	struct bwn_led *led = sc->sc_blink_led;
10700 	int rate;
10701 
10702 	if (event == BWN_LED_EVENT_POLL) {
10703 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10704 			return;
10705 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10706 			return;
10707 	}
10708 
10709 	sc->sc_led_ticks = ticks;
10710 	if (sc->sc_led_blinking)
10711 		return;
10712 
10713 	switch (event) {
10714 	case BWN_LED_EVENT_RX:
10715 		rate = sc->sc_rx_rate;
10716 		break;
10717 	case BWN_LED_EVENT_TX:
10718 		rate = sc->sc_tx_rate;
10719 		break;
10720 	case BWN_LED_EVENT_POLL:
10721 		rate = 0;
10722 		break;
10723 	default:
10724 		panic("unknown LED event %d\n", event);
10725 		break;
10726 	}
10727 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10728 	    bwn_led_duration[rate].off_dur);
10729 }
10730 
10731 static void
10732 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10733 {
10734 	struct bwn_softc *sc = mac->mac_sc;
10735 	struct bwn_led *led = sc->sc_blink_led;
10736 	uint16_t val;
10737 
10738 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10739 	val = bwn_led_onoff(led, val, 1);
10740 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10741 
10742 	if (led->led_flags & BWN_LED_F_SLOW) {
10743 		BWN_LED_SLOWDOWN(on_dur);
10744 		BWN_LED_SLOWDOWN(off_dur);
10745 	}
10746 
10747 	sc->sc_led_blinking = 1;
10748 	sc->sc_led_blink_offdur = off_dur;
10749 
10750 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10751 }
10752 
10753 static void
10754 bwn_led_blink_next(void *arg)
10755 {
10756 	struct bwn_mac *mac = arg;
10757 	struct bwn_softc *sc = mac->mac_sc;
10758 	uint16_t val;
10759 
10760 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10761 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10762 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10763 
10764 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10765 	    bwn_led_blink_end, mac);
10766 }
10767 
10768 static void
10769 bwn_led_blink_end(void *arg)
10770 {
10771 	struct bwn_mac *mac = arg;
10772 	struct bwn_softc *sc = mac->mac_sc;
10773 
10774 	sc->sc_led_blinking = 0;
10775 }
10776 
10777 static int
10778 bwn_suspend(device_t dev)
10779 {
10780 	struct bwn_softc *sc = device_get_softc(dev);
10781 
10782 	bwn_stop(sc, 1);
10783 	return (0);
10784 }
10785 
10786 static int
10787 bwn_resume(device_t dev)
10788 {
10789 	struct bwn_softc *sc = device_get_softc(dev);
10790 	struct ifnet *ifp = sc->sc_ifp;
10791 
10792 	if (ifp->if_flags & IFF_UP)
10793 		bwn_init(sc);
10794 	return (0);
10795 }
10796 
10797 static void
10798 bwn_rfswitch(void *arg)
10799 {
10800 	struct bwn_softc *sc = arg;
10801 	struct bwn_mac *mac = sc->sc_curmac;
10802 	int cur = 0, prev = 0;
10803 
10804 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10805 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10806 
10807 	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10808 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10809 			& BWN_RF_HWENABLED_HI_MASK))
10810 			cur = 1;
10811 	} else {
10812 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10813 		    & BWN_RF_HWENABLED_LO_MASK)
10814 			cur = 1;
10815 	}
10816 
10817 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10818 		prev = 1;
10819 
10820 	if (cur != prev) {
10821 		if (cur)
10822 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10823 		else
10824 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10825 
10826 		device_printf(sc->sc_dev,
10827 		    "status of RF switch is changed to %s\n",
10828 		    cur ? "ON" : "OFF");
10829 		if (cur != mac->mac_phy.rf_on) {
10830 			if (cur)
10831 				bwn_rf_turnon(mac);
10832 			else
10833 				bwn_rf_turnoff(mac);
10834 		}
10835 	}
10836 
10837 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10838 }
10839 
10840 static void
10841 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10842 {
10843 	struct bwn_phy *phy = &mac->mac_phy;
10844 	struct bwn_phy_lp *plp = &phy->phy_lp;
10845 
10846 	plp->plp_antenna = BWN_ANT_DEFAULT;
10847 }
10848 
10849 static int
10850 bwn_phy_lp_init(struct bwn_mac *mac)
10851 {
10852 	static const struct bwn_stxtable tables[] = {
10853 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10854 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10855 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10856 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10857 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10858 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10859 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10860 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10861 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10862 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10863 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10864 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10865 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10866 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10867 		{ 2, 11, 0x40, 0, 0x0f }
10868 	};
10869 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10870 	struct bwn_softc *sc = mac->mac_sc;
10871 	const struct bwn_stxtable *st;
10872 	struct ifnet *ifp = sc->sc_ifp;
10873 	struct ieee80211com *ic = ifp->if_l2com;
10874 	int i, error;
10875 	uint16_t tmp;
10876 
10877 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10878 	bwn_phy_lp_bbinit(mac);
10879 
10880 	/* initialize RF */
10881 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10882 	DELAY(1);
10883 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10884 	DELAY(1);
10885 
10886 	if (mac->mac_phy.rf_ver == 0x2062)
10887 		bwn_phy_lp_b2062_init(mac);
10888 	else {
10889 		bwn_phy_lp_b2063_init(mac);
10890 
10891 		/* synchronize stx table. */
10892 		for (i = 0; i < N(tables); i++) {
10893 			st = &tables[i];
10894 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10895 			tmp >>= st->st_rfshift;
10896 			tmp <<= st->st_physhift;
10897 			BWN_PHY_SETMASK(mac,
10898 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10899 			    ~(st->st_mask << st->st_physhift), tmp);
10900 		}
10901 
10902 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10903 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10904 	}
10905 
10906 	/* calibrate RC */
10907 	if (mac->mac_phy.rev >= 2)
10908 		bwn_phy_lp_rxcal_r2(mac);
10909 	else if (!plp->plp_rccap) {
10910 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10911 			bwn_phy_lp_rccal_r12(mac);
10912 	} else
10913 		bwn_phy_lp_set_rccap(mac);
10914 
10915 	error = bwn_phy_lp_switch_channel(mac, 7);
10916 	if (error)
10917 		device_printf(sc->sc_dev,
10918 		    "failed to change channel 7 (%d)\n", error);
10919 	bwn_phy_lp_txpctl_init(mac);
10920 	bwn_phy_lp_calib(mac);
10921 	return (0);
10922 }
10923 
10924 static uint16_t
10925 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10926 {
10927 
10928 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10929 	return (BWN_READ_2(mac, BWN_PHYDATA));
10930 }
10931 
10932 static void
10933 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10934 {
10935 
10936 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10937 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10938 }
10939 
10940 static void
10941 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10942     uint16_t set)
10943 {
10944 
10945 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10946 	BWN_WRITE_2(mac, BWN_PHYDATA,
10947 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10948 }
10949 
10950 static uint16_t
10951 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10952 {
10953 
10954 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10955 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10956 		reg |= 0x100;
10957 	if (mac->mac_phy.rev >= 2)
10958 		reg |= 0x200;
10959 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10960 	return BWN_READ_2(mac, BWN_RFDATALO);
10961 }
10962 
10963 static void
10964 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10965 {
10966 
10967 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10968 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10969 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10970 }
10971 
10972 static void
10973 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10974 {
10975 
10976 	if (on) {
10977 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10978 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10979 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10980 		return;
10981 	}
10982 
10983 	if (mac->mac_phy.rev >= 2) {
10984 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10985 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10986 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10987 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10988 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10989 		return;
10990 	}
10991 
10992 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10993 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10994 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10995 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10996 }
10997 
10998 static int
10999 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
11000 {
11001 	struct bwn_phy *phy = &mac->mac_phy;
11002 	struct bwn_phy_lp *plp = &phy->phy_lp;
11003 	int error;
11004 
11005 	if (phy->rf_ver == 0x2063) {
11006 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11007 		if (error)
11008 			return (error);
11009 	} else {
11010 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11011 		if (error)
11012 			return (error);
11013 		bwn_phy_lp_set_anafilter(mac, chan);
11014 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11015 	}
11016 
11017 	plp->plp_chan = chan;
11018 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11019 	return (0);
11020 }
11021 
11022 static uint32_t
11023 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11024 {
11025 	struct bwn_softc *sc = mac->mac_sc;
11026 	struct ifnet *ifp = sc->sc_ifp;
11027 	struct ieee80211com *ic = ifp->if_l2com;
11028 
11029 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11030 }
11031 
11032 static void
11033 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11034 {
11035 	struct bwn_phy *phy = &mac->mac_phy;
11036 	struct bwn_phy_lp *plp = &phy->phy_lp;
11037 
11038 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11039 		return;
11040 
11041 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11042 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11043 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11044 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11045 	plp->plp_antenna = antenna;
11046 }
11047 
11048 static void
11049 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11050 {
11051 
11052 	bwn_phy_lp_calib(mac);
11053 }
11054 
11055 static void
11056 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11057 {
11058 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11059 	struct bwn_softc *sc = mac->mac_sc;
11060 	struct ifnet *ifp = sc->sc_ifp;
11061 	struct ieee80211com *ic = ifp->if_l2com;
11062 
11063 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11064 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11065 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11066 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11067 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11068 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11069 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11070 		return;
11071 	}
11072 
11073 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11074 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11075 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11076 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11077 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11078 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11079 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11080 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11081 }
11082 
11083 static void
11084 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11085 {
11086 
11087 	bwn_phy_lp_tblinit(mac);
11088 	if (mac->mac_phy.rev >= 2)
11089 		bwn_phy_lp_bbinit_r2(mac);
11090 	else
11091 		bwn_phy_lp_bbinit_r01(mac);
11092 }
11093 
11094 static void
11095 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11096 {
11097 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11098 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11099 	struct bwn_softc *sc = mac->mac_sc;
11100 	struct ifnet *ifp = sc->sc_ifp;
11101 	struct ieee80211com *ic = ifp->if_l2com;
11102 
11103 	bwn_phy_lp_set_txgain(mac,
11104 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11105 	bwn_phy_lp_set_bbmult(mac, 150);
11106 }
11107 
11108 static void
11109 bwn_phy_lp_calib(struct bwn_mac *mac)
11110 {
11111 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11112 	struct bwn_softc *sc = mac->mac_sc;
11113 	struct ifnet *ifp = sc->sc_ifp;
11114 	struct ieee80211com *ic = ifp->if_l2com;
11115 	const struct bwn_rxcompco *rc = NULL;
11116 	struct bwn_txgain ogain;
11117 	int i, omode, oafeovr, orf, obbmult;
11118 	uint8_t mode, fc = 0;
11119 
11120 	if (plp->plp_chanfullcal != plp->plp_chan) {
11121 		plp->plp_chanfullcal = plp->plp_chan;
11122 		fc = 1;
11123 	}
11124 
11125 	bwn_mac_suspend(mac);
11126 
11127 	/* BlueTooth Coexistance Override */
11128 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11129 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11130 
11131 	if (mac->mac_phy.rev >= 2)
11132 		bwn_phy_lp_digflt_save(mac);
11133 	bwn_phy_lp_get_txpctlmode(mac);
11134 	mode = plp->plp_txpctlmode;
11135 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11136 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11137 		bwn_phy_lp_bugfix(mac);
11138 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11139 		bwn_phy_lp_get_txpctlmode(mac);
11140 		omode = plp->plp_txpctlmode;
11141 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11142 		if (oafeovr)
11143 			ogain = bwn_phy_lp_get_txgain(mac);
11144 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11145 		obbmult = bwn_phy_lp_get_bbmult(mac);
11146 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11147 		if (oafeovr)
11148 			bwn_phy_lp_set_txgain(mac, &ogain);
11149 		bwn_phy_lp_set_bbmult(mac, obbmult);
11150 		bwn_phy_lp_set_txpctlmode(mac, omode);
11151 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11152 	}
11153 	bwn_phy_lp_set_txpctlmode(mac, mode);
11154 	if (mac->mac_phy.rev >= 2)
11155 		bwn_phy_lp_digflt_restore(mac);
11156 
11157 	/* do RX IQ Calculation; assumes that noise is true. */
11158 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11159 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11160 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11161 				rc = &bwn_rxcompco_5354[i];
11162 		}
11163 	} else if (mac->mac_phy.rev >= 2)
11164 		rc = &bwn_rxcompco_r2;
11165 	else {
11166 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11167 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11168 				rc = &bwn_rxcompco_r12[i];
11169 		}
11170 	}
11171 	if (rc == NULL)
11172 		goto fail;
11173 
11174 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11175 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11176 
11177 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11178 
11179 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11180 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11181 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11182 	} else {
11183 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11184 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11185 	}
11186 
11187 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11188 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11189 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11190 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11191 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11192 	bwn_phy_lp_set_deaf(mac, 0);
11193 	/* XXX no checking return value? */
11194 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11195 	bwn_phy_lp_clear_deaf(mac, 0);
11196 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11197 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11198 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11199 
11200 	/* disable RX GAIN override. */
11201 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11202 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11203 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11204 	if (mac->mac_phy.rev >= 2) {
11205 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11206 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11207 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11208 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11209 		}
11210 	} else {
11211 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11212 	}
11213 
11214 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11215 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11216 fail:
11217 	bwn_mac_enable(mac);
11218 }
11219 
11220 static void
11221 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11222 {
11223 
11224 	if (on) {
11225 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11226 		return;
11227 	}
11228 
11229 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11230 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11231 }
11232 
11233 static int
11234 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11235 {
11236 	static const struct bwn_b206x_chan *bc = NULL;
11237 	struct bwn_softc *sc = mac->mac_sc;
11238 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11239 	    tmp[6];
11240 	uint16_t old, scale, tmp16;
11241 	int i, div;
11242 
11243 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11244 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11245 			bc = &bwn_b2063_chantable[i];
11246 			break;
11247 		}
11248 	}
11249 	if (bc == NULL)
11250 		return (EINVAL);
11251 
11252 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11253 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11254 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11255 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11256 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11257 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11258 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11259 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11260 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11261 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11262 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11263 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11264 
11265 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11266 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11267 
11268 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11269 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11270 	freqref = freqxtal * 3;
11271 	div = (freqxtal <= 26000000 ? 1 : 2);
11272 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11273 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11274 		999999) / 1000000) + 1;
11275 
11276 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11277 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11278 	    0xfff8, timeout >> 2);
11279 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11280 	    0xff9f,timeout << 5);
11281 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11282 
11283 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11284 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11285 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11286 
11287 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11288 	    (timeoutref + 1)) - 1;
11289 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11290 	    0xf0, count >> 8);
11291 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11292 
11293 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11294 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11295 	while (tmp[1] >= freqref) {
11296 		tmp[0]++;
11297 		tmp[1] -= freqref;
11298 	}
11299 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11300 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11301 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11302 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11303 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11304 
11305 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11306 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11307 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11308 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11309 
11310 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11311 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11312 
11313 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11314 		scale = 1;
11315 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11316 	} else {
11317 		scale = 0;
11318 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11319 	}
11320 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11321 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11322 
11323 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11324 	    (scale + 1);
11325 	if (tmp[5] > 150)
11326 		tmp[5] = 0;
11327 
11328 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11329 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11330 
11331 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11332 	if (freqxtal > 26000000)
11333 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11334 	else
11335 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11336 
11337 	if (val[0] == 45)
11338 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11339 	else
11340 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11341 
11342 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11343 	DELAY(1);
11344 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11345 
11346 	/* VCO Calibration */
11347 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11348 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11349 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11350 	DELAY(1);
11351 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11352 	DELAY(1);
11353 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11354 	DELAY(1);
11355 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11356 	DELAY(300);
11357 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11358 
11359 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11360 	return (0);
11361 }
11362 
11363 static int
11364 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11365 {
11366 	struct bwn_softc *sc = mac->mac_sc;
11367 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11368 	const struct bwn_b206x_chan *bc = NULL;
11369 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11370 	uint32_t tmp[9];
11371 	int i;
11372 
11373 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11374 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11375 			bc = &bwn_b2062_chantable[i];
11376 			break;
11377 		}
11378 	}
11379 
11380 	if (bc == NULL)
11381 		return (EINVAL);
11382 
11383 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11384 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11385 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11386 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11387 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11388 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11389 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11390 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11391 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11392 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11393 
11394 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11395 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11396 	bwn_phy_lp_b2062_reset_pllbias(mac);
11397 	tmp[0] = freqxtal / 1000;
11398 	tmp[1] = plp->plp_div * 1000;
11399 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11400 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11401 		tmp[2] *= 2;
11402 	tmp[3] = 48 * tmp[0];
11403 	tmp[5] = tmp[2] / tmp[3];
11404 	tmp[6] = tmp[2] % tmp[3];
11405 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11406 	tmp[4] = tmp[6] * 0x100;
11407 	tmp[5] = tmp[4] / tmp[3];
11408 	tmp[6] = tmp[4] % tmp[3];
11409 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11410 	tmp[4] = tmp[6] * 0x100;
11411 	tmp[5] = tmp[4] / tmp[3];
11412 	tmp[6] = tmp[4] % tmp[3];
11413 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11414 	tmp[4] = tmp[6] * 0x100;
11415 	tmp[5] = tmp[4] / tmp[3];
11416 	tmp[6] = tmp[4] % tmp[3];
11417 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11418 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11419 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11420 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11421 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11422 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11423 
11424 	bwn_phy_lp_b2062_vco_calib(mac);
11425 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11426 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11427 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11428 		bwn_phy_lp_b2062_reset_pllbias(mac);
11429 		bwn_phy_lp_b2062_vco_calib(mac);
11430 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11431 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11432 			return (EIO);
11433 		}
11434 	}
11435 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11436 	return (0);
11437 }
11438 
11439 static void
11440 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11441 {
11442 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11443 	uint16_t tmp = (channel == 14);
11444 
11445 	if (mac->mac_phy.rev < 2) {
11446 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11447 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11448 			bwn_phy_lp_set_rccap(mac);
11449 		return;
11450 	}
11451 
11452 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11453 }
11454 
11455 static void
11456 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11457 {
11458 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11459 	struct bwn_softc *sc = mac->mac_sc;
11460 	struct ifnet *ifp = sc->sc_ifp;
11461 	struct ieee80211com *ic = ifp->if_l2com;
11462 	uint16_t iso, tmp[3];
11463 
11464 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11465 
11466 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11467 		iso = plp->plp_txisoband_m;
11468 	else if (freq <= 5320)
11469 		iso = plp->plp_txisoband_l;
11470 	else if (freq <= 5700)
11471 		iso = plp->plp_txisoband_m;
11472 	else
11473 		iso = plp->plp_txisoband_h;
11474 
11475 	tmp[0] = ((iso - 26) / 12) << 12;
11476 	tmp[1] = tmp[0] + 0x1000;
11477 	tmp[2] = tmp[0] + 0x2000;
11478 
11479 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11480 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11481 }
11482 
11483 static void
11484 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11485 {
11486 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11487 	int i;
11488 	static const uint16_t addr[] = {
11489 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11490 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11491 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11492 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11493 		BWN_PHY_OFDM(0xcf),
11494 	};
11495 	static const uint16_t val[] = {
11496 		0xde5e, 0xe832, 0xe331, 0x4d26,
11497 		0x0026, 0x1420, 0x0020, 0xfe08,
11498 		0x0008,
11499 	};
11500 
11501 	for (i = 0; i < N(addr); i++) {
11502 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11503 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11504 	}
11505 }
11506 
11507 static void
11508 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11509 {
11510 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11511 	struct bwn_softc *sc = mac->mac_sc;
11512 	uint16_t ctl;
11513 
11514 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11515 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11516 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11517 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11518 		break;
11519 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11520 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11521 		break;
11522 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11523 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11524 		break;
11525 	default:
11526 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11527 		device_printf(sc->sc_dev, "unknown command mode\n");
11528 		break;
11529 	}
11530 }
11531 
11532 static void
11533 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11534 {
11535 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11536 	uint16_t ctl;
11537 	uint8_t old;
11538 
11539 	bwn_phy_lp_get_txpctlmode(mac);
11540 	old = plp->plp_txpctlmode;
11541 	if (old == mode)
11542 		return;
11543 	plp->plp_txpctlmode = mode;
11544 
11545 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11546 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11547 		    plp->plp_tssiidx);
11548 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11549 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11550 
11551 		/* disable TX GAIN override */
11552 		if (mac->mac_phy.rev < 2)
11553 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11554 		else {
11555 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11556 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11557 		}
11558 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11559 
11560 		plp->plp_txpwridx = -1;
11561 	}
11562 	if (mac->mac_phy.rev >= 2) {
11563 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11564 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11565 		else
11566 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11567 	}
11568 
11569 	/* writes TX Power Control mode */
11570 	switch (plp->plp_txpctlmode) {
11571 	case BWN_PHYLP_TXPCTL_OFF:
11572 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11573 		break;
11574 	case BWN_PHYLP_TXPCTL_ON_HW:
11575 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11576 		break;
11577 	case BWN_PHYLP_TXPCTL_ON_SW:
11578 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11579 		break;
11580 	default:
11581 		ctl = 0;
11582 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11583 	}
11584 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11585 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11586 }
11587 
11588 static void
11589 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11590 {
11591 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11592 	struct bwn_softc *sc = mac->mac_sc;
11593 	const unsigned int size = 256;
11594 	struct bwn_txgain tg;
11595 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11596 	uint16_t tssinpt, tssiidx, value[2];
11597 	uint8_t mode;
11598 	int8_t txpwridx;
11599 
11600 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11601 	    M_NOWAIT | M_ZERO);
11602 	if (tabs == NULL) {
11603 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11604 		return;
11605 	}
11606 
11607 	bwn_phy_lp_get_txpctlmode(mac);
11608 	mode = plp->plp_txpctlmode;
11609 	txpwridx = plp->plp_txpwridx;
11610 	tssinpt = plp->plp_tssinpt;
11611 	tssiidx = plp->plp_tssiidx;
11612 
11613 	bwn_tab_read_multi(mac,
11614 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11615 	    BWN_TAB_4(7, 0x140), size, tabs);
11616 
11617 	bwn_phy_lp_tblinit(mac);
11618 	bwn_phy_lp_bbinit(mac);
11619 	bwn_phy_lp_txpctl_init(mac);
11620 	bwn_phy_lp_rf_onoff(mac, 1);
11621 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11622 
11623 	bwn_tab_write_multi(mac,
11624 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11625 	    BWN_TAB_4(7, 0x140), size, tabs);
11626 
11627 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11628 	plp->plp_tssinpt = tssinpt;
11629 	plp->plp_tssiidx = tssiidx;
11630 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11631 	if (txpwridx != -1) {
11632 		/* set TX power by index */
11633 		plp->plp_txpwridx = txpwridx;
11634 		bwn_phy_lp_get_txpctlmode(mac);
11635 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11636 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11637 		if (mac->mac_phy.rev >= 2) {
11638 			rxcomp = bwn_tab_read(mac,
11639 			    BWN_TAB_4(7, txpwridx + 320));
11640 			txgain = bwn_tab_read(mac,
11641 			    BWN_TAB_4(7, txpwridx + 192));
11642 			tg.tg_pad = (txgain >> 16) & 0xff;
11643 			tg.tg_gm = txgain & 0xff;
11644 			tg.tg_pga = (txgain >> 8) & 0xff;
11645 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11646 			bwn_phy_lp_set_txgain(mac, &tg);
11647 		} else {
11648 			rxcomp = bwn_tab_read(mac,
11649 			    BWN_TAB_4(10, txpwridx + 320));
11650 			txgain = bwn_tab_read(mac,
11651 			    BWN_TAB_4(10, txpwridx + 192));
11652 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11653 			    0xf800, (txgain >> 4) & 0x7fff);
11654 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11655 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11656 		}
11657 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11658 
11659 		/* set TX IQCC */
11660 		value[0] = (rxcomp >> 10) & 0x3ff;
11661 		value[1] = rxcomp & 0x3ff;
11662 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11663 
11664 		coeff = bwn_tab_read(mac,
11665 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11666 		    BWN_TAB_4(10, txpwridx + 448));
11667 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11668 		if (mac->mac_phy.rev >= 2) {
11669 			rfpwr = bwn_tab_read(mac,
11670 			    BWN_TAB_4(7, txpwridx + 576));
11671 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11672 			    rfpwr & 0xffff);
11673 		}
11674 		bwn_phy_lp_set_txgain_override(mac);
11675 	}
11676 	if (plp->plp_rccap)
11677 		bwn_phy_lp_set_rccap(mac);
11678 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11679 	bwn_phy_lp_set_txpctlmode(mac, mode);
11680 	free(tabs, M_DEVBUF);
11681 }
11682 
11683 static void
11684 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11685 {
11686 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11687 	int i;
11688 	static const uint16_t addr[] = {
11689 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11690 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11691 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11692 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11693 		BWN_PHY_OFDM(0xcf),
11694 	};
11695 
11696 	for (i = 0; i < N(addr); i++)
11697 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11698 }
11699 
11700 static void
11701 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11702 {
11703 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11704 
11705 	if (mac->mac_phy.rev < 2) {
11706 		bwn_phy_lp_tblinit_r01(mac);
11707 		bwn_phy_lp_tblinit_txgain(mac);
11708 		bwn_phy_lp_set_gaintbl(mac, freq);
11709 		return;
11710 	}
11711 
11712 	bwn_phy_lp_tblinit_r2(mac);
11713 	bwn_phy_lp_tblinit_txgain(mac);
11714 }
11715 
11716 struct bwn_wpair {
11717 	uint16_t		reg;
11718 	uint16_t		value;
11719 };
11720 
11721 struct bwn_smpair {
11722 	uint16_t		offset;
11723 	uint16_t		mask;
11724 	uint16_t		set;
11725 };
11726 
11727 static void
11728 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11729 {
11730 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11731 	struct bwn_softc *sc = mac->mac_sc;
11732 	struct ifnet *ifp = sc->sc_ifp;
11733 	struct ieee80211com *ic = ifp->if_l2com;
11734 	static const struct bwn_wpair v1[] = {
11735 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11736 		{ BWN_PHY_AFE_CTL, 0x8800 },
11737 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11738 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11739 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11740 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11741 		{ BWN_PHY_OFDM(0xf9), 0 },
11742 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11743 	};
11744 	static const struct bwn_smpair v2[] = {
11745 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11746 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11747 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11748 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11749 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11750 	};
11751 	static const struct bwn_smpair v3[] = {
11752 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11753 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11754 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11755 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11756 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11757 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11758 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11759 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11760 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11761 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11762 
11763 	};
11764 	int i;
11765 
11766 	for (i = 0; i < N(v1); i++)
11767 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11768 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11769 	for (i = 0; i < N(v2); i++)
11770 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11771 
11772 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11773 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11774 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11775 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11776 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11777 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11778 	} else {
11779 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11780 	}
11781 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11782 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11783 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11784 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11785 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11786 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11787 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11788 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11789 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11790 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11791 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11792 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11793 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11794 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11795 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11796 	} else {
11797 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11798 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11799 	}
11800 	for (i = 0; i < N(v3); i++)
11801 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11802 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11803 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11804 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11805 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11806 	}
11807 
11808 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11809 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11810 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11811 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11812 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11813 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11814 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11815 	} else
11816 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11817 
11818 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11819 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11820 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11821 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11822 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11823 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11824 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11825 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11826 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11827 
11828 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11829 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11830 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11831 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11832 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11833 	}
11834 
11835 	bwn_phy_lp_digflt_save(mac);
11836 }
11837 
11838 static void
11839 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11840 {
11841 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11842 	struct bwn_softc *sc = mac->mac_sc;
11843 	struct ifnet *ifp = sc->sc_ifp;
11844 	struct ieee80211com *ic = ifp->if_l2com;
11845 	static const struct bwn_smpair v1[] = {
11846 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11847 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11848 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11849 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11850 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11851 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11852 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11853 	};
11854 	static const struct bwn_smpair v2[] = {
11855 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11856 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11857 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11858 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11859 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11860 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11861 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11862 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11863 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11864 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11865 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11866 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11867 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11868 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11869 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11870 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11871 	};
11872 	static const struct bwn_smpair v3[] = {
11873 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11874 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11875 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11876 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11877 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11878 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11879 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11880 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11881 	};
11882 	static const struct bwn_smpair v4[] = {
11883 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11884 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11885 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11886 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11887 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11888 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11889 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11890 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11891 	};
11892 	static const struct bwn_smpair v5[] = {
11893 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11894 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11895 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11896 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11897 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11898 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11899 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11900 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11901 	};
11902 	int i;
11903 	uint16_t tmp, tmp2;
11904 
11905 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11906 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11907 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11908 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11909 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11910 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11911 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11912 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11913 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11914 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11915 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11916 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11917 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11918 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11919 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11920 	for (i = 0; i < N(v1); i++)
11921 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11922 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11923 	    0xff00, plp->plp_rxpwroffset);
11924 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11925 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11926 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11927 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11928 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11929 		if (mac->mac_phy.rev == 0)
11930 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11931 			    0xffcf, 0x0010);
11932 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11933 	} else {
11934 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11935 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11936 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11937 	}
11938 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11939 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11940 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11941 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11942 	else
11943 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11944 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11945 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11946 	    0xfff9, (plp->plp_bxarch << 1));
11947 	if (mac->mac_phy.rev == 1 &&
11948 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11949 		for (i = 0; i < N(v2); i++)
11950 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11951 			    v2[i].set);
11952 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11953 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11954 	    ((mac->mac_phy.rev == 0) &&
11955 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11956 		for (i = 0; i < N(v3); i++)
11957 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11958 			    v3[i].set);
11959 	} else if (mac->mac_phy.rev == 1 ||
11960 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11961 		for (i = 0; i < N(v4); i++)
11962 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11963 			    v4[i].set);
11964 	} else {
11965 		for (i = 0; i < N(v5); i++)
11966 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11967 			    v5[i].set);
11968 	}
11969 	if (mac->mac_phy.rev == 1 &&
11970 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11971 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11972 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11973 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11974 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11975 	}
11976 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11977 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11978 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11979 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11980 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11981 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11982 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11983 	}
11984 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11985 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11986 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11987 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11988 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11989 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11990 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11991 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11992 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11993 	} else {
11994 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11995 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11996 	}
11997 	if (mac->mac_phy.rev == 1) {
11998 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11999 		tmp2 = (tmp & 0x03e0) >> 5;
12000 		tmp2 |= tmp2 << 5;
12001 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12002 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12003 		tmp2 = (tmp & 0x1f00) >> 8;
12004 		tmp2 |= tmp2 << 5;
12005 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12006 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12007 		tmp2 = tmp & 0x00ff;
12008 		tmp2 |= tmp << 8;
12009 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12010 	}
12011 }
12012 
12013 struct bwn_b2062_freq {
12014 	uint16_t		freq;
12015 	uint8_t			value[6];
12016 };
12017 
12018 static void
12019 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12020 {
12021 #define	CALC_CTL7(freq, div)						\
12022 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12023 #define	CALC_CTL18(freq, div)						\
12024 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12025 #define	CALC_CTL19(freq, div)						\
12026 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12027 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12028 	struct bwn_softc *sc = mac->mac_sc;
12029 	struct ifnet *ifp = sc->sc_ifp;
12030 	struct ieee80211com *ic = ifp->if_l2com;
12031 	static const struct bwn_b2062_freq freqdata_tab[] = {
12032 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12033 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12034 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12035 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12036 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12037 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12038 	};
12039 	static const struct bwn_wpair v1[] = {
12040 		{ BWN_B2062_N_TXCTL3, 0 },
12041 		{ BWN_B2062_N_TXCTL4, 0 },
12042 		{ BWN_B2062_N_TXCTL5, 0 },
12043 		{ BWN_B2062_N_TXCTL6, 0 },
12044 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12045 		{ BWN_B2062_N_PDNCTL0, 0 },
12046 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12047 		{ BWN_B2062_N_CALIB_TS, 0 }
12048 	};
12049 	const struct bwn_b2062_freq *f = NULL;
12050 	uint32_t xtalfreq, ref;
12051 	unsigned int i;
12052 
12053 	bwn_phy_lp_b2062_tblinit(mac);
12054 
12055 	for (i = 0; i < N(v1); i++)
12056 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12057 	if (mac->mac_phy.rev > 0)
12058 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12059 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12060 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12061 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12062 	else
12063 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12064 
12065 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12066 	    ("%s:%d: fail", __func__, __LINE__));
12067 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12068 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12069 
12070 	if (xtalfreq <= 30000000) {
12071 		plp->plp_div = 1;
12072 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12073 	} else {
12074 		plp->plp_div = 2;
12075 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12076 	}
12077 
12078 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12079 	    CALC_CTL7(xtalfreq, plp->plp_div));
12080 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12081 	    CALC_CTL18(xtalfreq, plp->plp_div));
12082 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12083 	    CALC_CTL19(xtalfreq, plp->plp_div));
12084 
12085 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12086 	ref &= 0xffff;
12087 	for (i = 0; i < N(freqdata_tab); i++) {
12088 		if (ref < freqdata_tab[i].freq) {
12089 			f = &freqdata_tab[i];
12090 			break;
12091 		}
12092 	}
12093 	if (f == NULL)
12094 		f = &freqdata_tab[N(freqdata_tab) - 1];
12095 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12096 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12097 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12098 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12099 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12100 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12101 #undef CALC_CTL7
12102 #undef CALC_CTL18
12103 #undef CALC_CTL19
12104 }
12105 
12106 static void
12107 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12108 {
12109 
12110 	bwn_phy_lp_b2063_tblinit(mac);
12111 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12112 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12113 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12114 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12115 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12116 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12117 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12118 	if (mac->mac_phy.rev == 2) {
12119 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12120 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12121 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12122 	} else {
12123 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12124 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12125 	}
12126 }
12127 
12128 static void
12129 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12130 {
12131 	struct bwn_softc *sc = mac->mac_sc;
12132 	static const struct bwn_wpair v1[] = {
12133 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12134 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12135 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12136 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12137 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12138 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12139 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12140 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12141 	};
12142 	static const struct bwn_wpair v2[] = {
12143 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12144 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12145 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12146 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12147 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12148 	};
12149 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12150 	int i;
12151 	uint8_t tmp;
12152 
12153 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12154 
12155 	for (i = 0; i < 2; i++)
12156 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12157 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12158 	for (i = 2; i < N(v1); i++)
12159 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12160 	for (i = 0; i < 10000; i++) {
12161 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12162 			break;
12163 		DELAY(1000);
12164 	}
12165 
12166 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12167 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12168 
12169 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12170 
12171 	for (i = 0; i < N(v2); i++)
12172 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12173 	if (freqxtal == 24000000) {
12174 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12175 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12176 	} else {
12177 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12178 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12179 	}
12180 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12181 	for (i = 0; i < 10000; i++) {
12182 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12183 			break;
12184 		DELAY(1000);
12185 	}
12186 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12187 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12188 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12189 }
12190 
12191 static void
12192 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12193 {
12194 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12195 	struct bwn_softc *sc = mac->mac_sc;
12196 	struct bwn_phy_lp_iq_est ie;
12197 	struct bwn_txgain tx_gains;
12198 	static const uint32_t pwrtbl[21] = {
12199 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12200 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12201 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12202 		0x0004c, 0x0002c, 0x0001a,
12203 	};
12204 	uint32_t npwr, ipwr, sqpwr, tmp;
12205 	int loopback, i, j, sum, error;
12206 	uint16_t save[7];
12207 	uint8_t txo, bbmult, txpctlmode;
12208 
12209 	error = bwn_phy_lp_switch_channel(mac, 7);
12210 	if (error)
12211 		device_printf(sc->sc_dev,
12212 		    "failed to change channel to 7 (%d)\n", error);
12213 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12214 	bbmult = bwn_phy_lp_get_bbmult(mac);
12215 	if (txo)
12216 		tx_gains = bwn_phy_lp_get_txgain(mac);
12217 
12218 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12219 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12220 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12221 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12222 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12223 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12224 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12225 
12226 	bwn_phy_lp_get_txpctlmode(mac);
12227 	txpctlmode = plp->plp_txpctlmode;
12228 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12229 
12230 	/* disable CRS */
12231 	bwn_phy_lp_set_deaf(mac, 1);
12232 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12233 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12234 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12235 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12236 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12237 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12238 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12239 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12240 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12241 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12242 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12243 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12244 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12245 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12246 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12247 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12248 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12249 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12250 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12251 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12252 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12253 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12254 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12255 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12256 
12257 	loopback = bwn_phy_lp_loopback(mac);
12258 	if (loopback == -1)
12259 		goto done;
12260 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12261 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12262 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12263 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12264 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12265 
12266 	tmp = 0;
12267 	memset(&ie, 0, sizeof(ie));
12268 	for (i = 128; i <= 159; i++) {
12269 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12270 		sum = 0;
12271 		for (j = 5; j <= 25; j++) {
12272 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12273 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12274 				goto done;
12275 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12276 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12277 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12278 			    12);
12279 			sum += ((ipwr - npwr) * (ipwr - npwr));
12280 			if ((i == 128) || (sum < tmp)) {
12281 				plp->plp_rccap = i;
12282 				tmp = sum;
12283 			}
12284 		}
12285 	}
12286 	bwn_phy_lp_ddfs_turnoff(mac);
12287 done:
12288 	/* restore CRS */
12289 	bwn_phy_lp_clear_deaf(mac, 1);
12290 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12291 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12292 
12293 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12294 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12295 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12296 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12297 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12298 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12299 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12300 
12301 	bwn_phy_lp_set_bbmult(mac, bbmult);
12302 	if (txo)
12303 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12304 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12305 	if (plp->plp_rccap)
12306 		bwn_phy_lp_set_rccap(mac);
12307 }
12308 
12309 static void
12310 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12311 {
12312 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12313 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12314 
12315 	if (mac->mac_phy.rev == 1)
12316 		rc_cap = MIN(rc_cap + 5, 15);
12317 
12318 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12319 	    MAX(plp->plp_rccap - 4, 0x80));
12320 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12321 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12322 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12323 }
12324 
12325 static uint32_t
12326 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12327 {
12328 	uint32_t i, q, r;
12329 
12330 	if (div == 0)
12331 		return (0);
12332 
12333 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12334 		q <<= 1;
12335 		if (r << 1 >= div) {
12336 			q++;
12337 			r = (r << 1) - div;
12338 		}
12339 	}
12340 	if (r << 1 >= div)
12341 		q++;
12342 	return (q);
12343 }
12344 
12345 static void
12346 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12347 {
12348 	struct bwn_softc *sc = mac->mac_sc;
12349 
12350 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12351 	DELAY(20);
12352 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12353 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12354 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12355 	} else {
12356 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12357 	}
12358 	DELAY(5);
12359 }
12360 
12361 static void
12362 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12363 {
12364 
12365 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12366 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12367 	DELAY(200);
12368 }
12369 
12370 static void
12371 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12372 {
12373 #define	FLAG_A	0x01
12374 #define	FLAG_G	0x02
12375 	struct bwn_softc *sc = mac->mac_sc;
12376 	struct ifnet *ifp = sc->sc_ifp;
12377 	struct ieee80211com *ic = ifp->if_l2com;
12378 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12379 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12380 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12381 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12382 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12383 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12384 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12385 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12386 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12387 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12388 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12389 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12390 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12391 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12392 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12393 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12394 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12395 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12396 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12397 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12398 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12399 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12400 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12401 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12402 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12403 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12404 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12405 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12406 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12407 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12408 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12409 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12410 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12411 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12412 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12413 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12414 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12415 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12416 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12417 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12418 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12419 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12420 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12421 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12422 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12423 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12424 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12425 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12426 	};
12427 	const struct bwn_b206x_rfinit_entry *br;
12428 	unsigned int i;
12429 
12430 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12431 		br = &bwn_b2062_init_tab[i];
12432 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12433 			if (br->br_flags & FLAG_G)
12434 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12435 		} else {
12436 			if (br->br_flags & FLAG_A)
12437 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12438 		}
12439 	}
12440 #undef FLAG_A
12441 #undef FLAG_B
12442 }
12443 
12444 static void
12445 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12446 {
12447 #define	FLAG_A	0x01
12448 #define	FLAG_G	0x02
12449 	struct bwn_softc *sc = mac->mac_sc;
12450 	struct ifnet *ifp = sc->sc_ifp;
12451 	struct ieee80211com *ic = ifp->if_l2com;
12452 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12453 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12454 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12455 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12456 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12457 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12458 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12459 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12460 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12461 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12462 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12463 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12464 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12465 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12466 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12467 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12468 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12469 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12470 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12471 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12472 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12473 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12474 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12475 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12476 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12477 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12478 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12479 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12480 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12481 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12482 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12483 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12484 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12485 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12486 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12487 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12488 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12489 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12490 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12491 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12492 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12493 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12494 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12495 	};
12496 	const struct bwn_b206x_rfinit_entry *br;
12497 	unsigned int i;
12498 
12499 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12500 		br = &bwn_b2063_init_tab[i];
12501 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12502 			if (br->br_flags & FLAG_G)
12503 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12504 		} else {
12505 			if (br->br_flags & FLAG_A)
12506 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12507 		}
12508 	}
12509 #undef FLAG_A
12510 #undef FLAG_B
12511 }
12512 
12513 static void
12514 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12515     int count, void *_data)
12516 {
12517 	unsigned int i;
12518 	uint32_t offset, type;
12519 	uint8_t *data = _data;
12520 
12521 	type = BWN_TAB_GETTYPE(typenoffset);
12522 	offset = BWN_TAB_GETOFFSET(typenoffset);
12523 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12524 
12525 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12526 
12527 	for (i = 0; i < count; i++) {
12528 		switch (type) {
12529 		case BWN_TAB_8BIT:
12530 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12531 			data++;
12532 			break;
12533 		case BWN_TAB_16BIT:
12534 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12535 			    BWN_PHY_TABLEDATALO);
12536 			data += 2;
12537 			break;
12538 		case BWN_TAB_32BIT:
12539 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12540 			    BWN_PHY_TABLEDATAHI);
12541 			*((uint32_t *)data) <<= 16;
12542 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12543 			    BWN_PHY_TABLEDATALO);
12544 			data += 4;
12545 			break;
12546 		default:
12547 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12548 		}
12549 	}
12550 }
12551 
12552 static void
12553 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12554     int count, const void *_data)
12555 {
12556 	uint32_t offset, type, value;
12557 	const uint8_t *data = _data;
12558 	unsigned int i;
12559 
12560 	type = BWN_TAB_GETTYPE(typenoffset);
12561 	offset = BWN_TAB_GETOFFSET(typenoffset);
12562 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12563 
12564 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12565 
12566 	for (i = 0; i < count; i++) {
12567 		switch (type) {
12568 		case BWN_TAB_8BIT:
12569 			value = *data;
12570 			data++;
12571 			KASSERT(!(value & ~0xff),
12572 			    ("%s:%d: fail", __func__, __LINE__));
12573 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12574 			break;
12575 		case BWN_TAB_16BIT:
12576 			value = *((const uint16_t *)data);
12577 			data += 2;
12578 			KASSERT(!(value & ~0xffff),
12579 			    ("%s:%d: fail", __func__, __LINE__));
12580 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12581 			break;
12582 		case BWN_TAB_32BIT:
12583 			value = *((const uint32_t *)data);
12584 			data += 4;
12585 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12586 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12587 			break;
12588 		default:
12589 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12590 		}
12591 	}
12592 }
12593 
12594 static struct bwn_txgain
12595 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12596 {
12597 	struct bwn_txgain tg;
12598 	uint16_t tmp;
12599 
12600 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12601 	if (mac->mac_phy.rev < 2) {
12602 		tmp = BWN_PHY_READ(mac,
12603 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12604 		tg.tg_gm = tmp & 0x0007;
12605 		tg.tg_pga = (tmp & 0x0078) >> 3;
12606 		tg.tg_pad = (tmp & 0x780) >> 7;
12607 		return (tg);
12608 	}
12609 
12610 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12611 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12612 	tg.tg_gm = tmp & 0xff;
12613 	tg.tg_pga = (tmp >> 8) & 0xff;
12614 	return (tg);
12615 }
12616 
12617 static uint8_t
12618 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12619 {
12620 
12621 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12622 }
12623 
12624 static void
12625 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12626 {
12627 	uint16_t pa;
12628 
12629 	if (mac->mac_phy.rev < 2) {
12630 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12631 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12632 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12633 		bwn_phy_lp_set_txgain_override(mac);
12634 		return;
12635 	}
12636 
12637 	pa = bwn_phy_lp_get_pa_gain(mac);
12638 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12639 	    (tg->tg_pga << 8) | tg->tg_gm);
12640 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12641 	    tg->tg_pad | (pa << 6));
12642 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12643 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12644 	    tg->tg_pad | (pa << 8));
12645 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12646 	bwn_phy_lp_set_txgain_override(mac);
12647 }
12648 
12649 static void
12650 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12651 {
12652 
12653 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12654 }
12655 
12656 static void
12657 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12658 {
12659 	uint16_t trsw = (tx << 1) | rx;
12660 
12661 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12662 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12663 }
12664 
12665 static void
12666 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12667 {
12668 	struct bwn_softc *sc = mac->mac_sc;
12669 	struct ifnet *ifp = sc->sc_ifp;
12670 	struct ieee80211com *ic = ifp->if_l2com;
12671 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12672 
12673 	if (mac->mac_phy.rev < 2) {
12674 		trsw = gain & 0x1;
12675 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12676 		ext_lna = (gain & 2) >> 1;
12677 
12678 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12679 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12680 		    0xfbff, ext_lna << 10);
12681 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12682 		    0xf7ff, ext_lna << 11);
12683 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12684 	} else {
12685 		low_gain = gain & 0xffff;
12686 		high_gain = (gain >> 16) & 0xf;
12687 		ext_lna = (gain >> 21) & 0x1;
12688 		trsw = ~(gain >> 20) & 0x1;
12689 
12690 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12691 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12692 		    0xfdff, ext_lna << 9);
12693 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12694 		    0xfbff, ext_lna << 10);
12695 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12696 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12697 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12698 			tmp = (gain >> 2) & 0x3;
12699 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12700 			    0xe7ff, tmp<<11);
12701 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12702 			    tmp << 3);
12703 		}
12704 	}
12705 
12706 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12707 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12708 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12709 	if (mac->mac_phy.rev >= 2) {
12710 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12711 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12712 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12713 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12714 		}
12715 		return;
12716 	}
12717 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12718 }
12719 
12720 static void
12721 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12722 {
12723 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12724 
12725 	if (user)
12726 		plp->plp_crsusr_off = 1;
12727 	else
12728 		plp->plp_crssys_off = 1;
12729 
12730 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12731 }
12732 
12733 static void
12734 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12735 {
12736 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12737 	struct bwn_softc *sc = mac->mac_sc;
12738 	struct ifnet *ifp = sc->sc_ifp;
12739 	struct ieee80211com *ic = ifp->if_l2com;
12740 
12741 	if (user)
12742 		plp->plp_crsusr_off = 0;
12743 	else
12744 		plp->plp_crssys_off = 0;
12745 
12746 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12747 		return;
12748 
12749 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12750 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12751 	else
12752 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12753 }
12754 
12755 static unsigned int
12756 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12757 {
12758 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12759 	static uint8_t sqrt_table[256] = {
12760 		10, 14, 17, 20, 22, 24, 26, 28,
12761 		30, 31, 33, 34, 36, 37, 38, 40,
12762 		41, 42, 43, 44, 45, 46, 47, 48,
12763 		50, 50, 51, 52, 53, 54, 55, 56,
12764 		57, 58, 59, 60, 60, 61, 62, 63,
12765 		64, 64, 65, 66, 67, 67, 68, 69,
12766 		70, 70, 71, 72, 72, 73, 74, 74,
12767 		75, 76, 76, 77, 78, 78, 79, 80,
12768 		80, 81, 81, 82, 83, 83, 84, 84,
12769 		85, 86, 86, 87, 87, 88, 88, 89,
12770 		90, 90, 91, 91, 92, 92, 93, 93,
12771 		94, 94, 95, 95, 96, 96, 97, 97,
12772 		98, 98, 99, 100, 100, 100, 101, 101,
12773 		102, 102, 103, 103, 104, 104, 105, 105,
12774 		106, 106, 107, 107, 108, 108, 109, 109,
12775 		110, 110, 110, 111, 111, 112, 112, 113,
12776 		113, 114, 114, 114, 115, 115, 116, 116,
12777 		117, 117, 117, 118, 118, 119, 119, 120,
12778 		120, 120, 121, 121, 122, 122, 122, 123,
12779 		123, 124, 124, 124, 125, 125, 126, 126,
12780 		126, 127, 127, 128, 128, 128, 129, 129,
12781 		130, 130, 130, 131, 131, 131, 132, 132,
12782 		133, 133, 133, 134, 134, 134, 135, 135,
12783 		136, 136, 136, 137, 137, 137, 138, 138,
12784 		138, 139, 139, 140, 140, 140, 141, 141,
12785 		141, 142, 142, 142, 143, 143, 143, 144,
12786 		144, 144, 145, 145, 145, 146, 146, 146,
12787 		147, 147, 147, 148, 148, 148, 149, 149,
12788 		150, 150, 150, 150, 151, 151, 151, 152,
12789 		152, 152, 153, 153, 153, 154, 154, 154,
12790 		155, 155, 155, 156, 156, 156, 157, 157,
12791 		157, 158, 158, 158, 159, 159, 159, 160
12792 	};
12793 
12794 	if (x == 0)
12795 		return (0);
12796 	if (x >= 256) {
12797 		unsigned int tmp;
12798 
12799 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12800 			/* do nothing */ ;
12801 		return (tmp);
12802 	}
12803 	return (sqrt_table[x - 1] / 10);
12804 }
12805 
12806 static int
12807 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12808 {
12809 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12810 	int _t;								\
12811 	_t = _x - 20;							\
12812 	if (_t >= 0) {							\
12813 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12814 	} else {							\
12815 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12816 	}								\
12817 } while (0)
12818 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12819 	int _t;								\
12820 	_t = _x - 11;							\
12821 	if (_t >= 0)							\
12822 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12823 	else								\
12824 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12825 } while (0)
12826 	struct bwn_phy_lp_iq_est ie;
12827 	uint16_t v0, v1;
12828 	int tmp[2], ret;
12829 
12830 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12831 	v0 = v1 >> 8;
12832 	v1 |= 0xff;
12833 
12834 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12835 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12836 
12837 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12838 	if (ret == 0)
12839 		goto done;
12840 
12841 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12842 		ret = 0;
12843 		goto done;
12844 	}
12845 
12846 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12847 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12848 
12849 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12850 	v0 = tmp[0] >> 3;
12851 	v1 = tmp[1] >> 4;
12852 done:
12853 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12854 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12855 	return ret;
12856 #undef CALC_COEFF
12857 #undef CALC_COEFF2
12858 }
12859 
12860 static void
12861 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12862 {
12863 	static const uint16_t noisescale[] = {
12864 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12865 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12866 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12867 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12868 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12869 	};
12870 	static const uint16_t crsgainnft[] = {
12871 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12872 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12873 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12874 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12875 		0x013d,
12876 	};
12877 	static const uint16_t filterctl[] = {
12878 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12879 		0xff53, 0x0127,
12880 	};
12881 	static const uint32_t psctl[] = {
12882 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12883 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12884 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12885 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12886 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12887 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12888 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12889 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12890 	};
12891 	static const uint16_t ofdmcckgain_r0[] = {
12892 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12893 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12894 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12895 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12896 		0x755d,
12897 	};
12898 	static const uint16_t ofdmcckgain_r1[] = {
12899 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12900 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12901 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12902 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12903 		0x755d,
12904 	};
12905 	static const uint16_t gaindelta[] = {
12906 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12907 		0x0000,
12908 	};
12909 	static const uint32_t txpwrctl[] = {
12910 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12911 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12912 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12913 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12914 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12915 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12916 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12917 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12918 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12919 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12920 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12921 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12922 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12923 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12924 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12948 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12949 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12950 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12951 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12952 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12953 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12954 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12955 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12956 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12957 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12958 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12959 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12960 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12961 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12962 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12963 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12964 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12965 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12966 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12967 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12968 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12969 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12970 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12971 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12972 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12973 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12974 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12975 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12976 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12977 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12978 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12979 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12980 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12981 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12982 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12983 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12984 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12985 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12986 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12987 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12988 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12989 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12990 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12991 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12992 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12993 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12994 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12995 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12996 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12997 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12998 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12999 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
13000 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13001 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13002 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13003 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13004 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13005 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13006 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13007 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13008 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13009 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13010 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13011 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13012 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13013 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13014 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13015 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13016 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13017 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13018 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13019 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13020 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13021 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13022 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13023 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13024 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13025 		0x00000702,
13026 	};
13027 
13028 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13029 
13030 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13031 	    bwn_tab_sigsq_tbl);
13032 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13033 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13034 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13035 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13036 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13037 	    bwn_tab_pllfrac_tbl);
13038 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13039 	    bwn_tabl_iqlocal_tbl);
13040 	if (mac->mac_phy.rev == 0) {
13041 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13042 		    ofdmcckgain_r0);
13043 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13044 		    ofdmcckgain_r0);
13045 	} else {
13046 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13047 		    ofdmcckgain_r1);
13048 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13049 		    ofdmcckgain_r1);
13050 	}
13051 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13052 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13053 }
13054 
13055 static void
13056 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13057 {
13058 	struct bwn_softc *sc = mac->mac_sc;
13059 	int i;
13060 	static const uint16_t noisescale[] = {
13061 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13067 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13068 	};
13069 	static const uint32_t filterctl[] = {
13070 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13071 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13072 	};
13073 	static const uint32_t psctl[] = {
13074 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13075 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13076 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13077 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13078 	};
13079 	static const uint32_t gainidx[] = {
13080 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13081 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13083 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13084 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13085 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13086 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13087 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13088 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13089 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13090 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13091 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13092 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13093 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13094 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13095 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13096 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13098 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13099 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13100 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13101 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13102 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13103 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13104 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13105 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13106 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13107 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13108 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13109 		0x0000001a, 0x64ca55ad, 0x0000001a
13110 	};
13111 	static const uint16_t auxgainidx[] = {
13112 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13113 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13114 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13115 		0x0004, 0x0016
13116 	};
13117 	static const uint16_t swctl[] = {
13118 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13119 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13120 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13121 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13122 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13123 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13124 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13125 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13126 	};
13127 	static const uint8_t hf[] = {
13128 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13129 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13130 	};
13131 	static const uint32_t gainval[] = {
13132 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13133 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13134 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13135 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13136 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13137 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13138 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13140 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13141 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13142 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13143 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13144 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13145 		0x000000f1, 0x00000000, 0x00000000
13146 	};
13147 	static const uint16_t gain[] = {
13148 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13149 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13150 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13151 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13152 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13153 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13154 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13159 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13160 	};
13161 	static const uint32_t papdeps[] = {
13162 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13163 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13164 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13165 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13166 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13167 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13168 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13169 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13170 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13171 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13172 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13173 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13174 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13175 	};
13176 	static const uint32_t papdmult[] = {
13177 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13178 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13179 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13180 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13181 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13182 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13183 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13184 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13185 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13186 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13187 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13188 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13189 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13190 	};
13191 	static const uint32_t gainidx_a0[] = {
13192 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13193 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13194 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13195 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13196 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13197 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13198 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13199 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13200 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13201 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13202 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13203 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13204 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13205 	};
13206 	static const uint16_t auxgainidx_a0[] = {
13207 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13208 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13209 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13210 		0x0002, 0x0014
13211 	};
13212 	static const uint32_t gainval_a0[] = {
13213 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13214 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13215 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13216 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13217 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13218 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13219 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13220 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13221 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13222 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13223 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13224 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13225 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13226 		0x000000f7, 0x00000000, 0x00000000
13227 	};
13228 	static const uint16_t gain_a0[] = {
13229 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13230 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13231 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13232 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13233 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13234 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13235 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13240 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13241 	};
13242 
13243 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13244 
13245 	for (i = 0; i < 704; i++)
13246 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13247 
13248 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13249 	    bwn_tab_sigsq_tbl);
13250 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13251 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13252 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13253 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13254 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13255 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13256 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13257 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13258 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13259 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13260 	    bwn_tab_pllfrac_tbl);
13261 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13262 	    bwn_tabl_iqlocal_tbl);
13263 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13264 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13265 
13266 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13267 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13268 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13269 		    gainidx_a0);
13270 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13271 		    auxgainidx_a0);
13272 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13273 		    gainval_a0);
13274 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13275 	}
13276 }
13277 
13278 static void
13279 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13280 {
13281 	struct bwn_softc *sc = mac->mac_sc;
13282 	struct ifnet *ifp = sc->sc_ifp;
13283 	struct ieee80211com *ic = ifp->if_l2com;
13284 	static struct bwn_txgain_entry txgain_r2[] = {
13285 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13286 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13287 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13288 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13289 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13290 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13291 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13292 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13293 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13294 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13295 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13296 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13297 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13298 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13299 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13300 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13301 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13302 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13303 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13304 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13305 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13306 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13307 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13308 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13309 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13310 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13311 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13312 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13313 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13314 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13315 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13316 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13317 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13318 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13319 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13320 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13321 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13322 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13323 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13324 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13325 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13326 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13327 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13328 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13329 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13330 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13331 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13332 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13333 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13334 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13335 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13336 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13337 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13338 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13339 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13340 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13341 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13342 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13343 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13344 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13345 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13346 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13347 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13348 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13349 	};
13350 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13351 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13352 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13353 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13354 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13355 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13356 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13357 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13358 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13359 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13360 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13361 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13362 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13363 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13364 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13365 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13366 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13367 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13368 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13369 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13370 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13371 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13372 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13373 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13374 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13375 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13376 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13377 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13378 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13379 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13380 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13381 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13382 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13383 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13384 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13385 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13386 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13387 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13388 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13389 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13390 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13391 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13392 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13393 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13394 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13395 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13396 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13397 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13398 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13399 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13400 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13401 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13402 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13403 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13404 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13405 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13406 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13407 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13408 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13409 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13410 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13411 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13412 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13413 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13414 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13415 	};
13416 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13417 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13418 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13419 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13420 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13421 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13422 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13423 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13424 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13425 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13426 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13427 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13428 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13429 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13430 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13431 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13432 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13433 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13434 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13435 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13436 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13437 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13438 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13439 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13440 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13441 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13442 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13443 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13444 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13445 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13446 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13447 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13448 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13449 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13450 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13451 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13452 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13453 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13454 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13455 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13456 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13457 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13458 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13459 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13460 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13461 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13462 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13463 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13464 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13465 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13466 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13467 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13468 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13469 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13470 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13471 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13472 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13473 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13474 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13475 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13476 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13477 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13478 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13479 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13480 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13481 	};
13482 	static struct bwn_txgain_entry txgain_r0[] = {
13483 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13484 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13485 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13486 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13487 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13488 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13489 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13490 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13491 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13492 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13493 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13494 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13495 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13496 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13497 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13498 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13499 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13500 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13501 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13502 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13503 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13504 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13505 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13506 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13507 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13508 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13509 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13510 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13511 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13512 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13513 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13514 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13515 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13516 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13517 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13518 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13519 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13520 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13521 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13522 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13523 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13524 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13525 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13526 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13527 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13528 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13529 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13530 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13531 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13532 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13533 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13534 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13535 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13536 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13537 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13538 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13539 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13540 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13541 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13542 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13543 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13544 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13545 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13546 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13547 	};
13548 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13549 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13550 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13551 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13552 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13553 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13554 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13555 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13556 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13557 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13558 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13559 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13560 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13561 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13562 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13563 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13564 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13565 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13566 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13567 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13568 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13569 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13570 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13571 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13572 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13573 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13574 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13575 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13576 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13577 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13578 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13579 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13580 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13581 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13582 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13583 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13584 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13585 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13586 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13587 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13588 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13589 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13590 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13591 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13592 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13593 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13594 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13595 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13596 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13597 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13598 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13599 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13600 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13601 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13602 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13603 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13604 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13605 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13606 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13607 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13608 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13609 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13610 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13611 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13612 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13613 	};
13614 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13615 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13616 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13617 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13618 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13619 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13620 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13621 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13622 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13623 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13624 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13625 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13626 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13627 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13628 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13629 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13630 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13631 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13632 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13633 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13634 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13635 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13636 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13637 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13638 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13639 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13640 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13641 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13642 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13643 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13644 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13645 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13646 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13647 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13648 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13649 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13650 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13651 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13652 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13653 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13654 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13655 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13656 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13657 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13658 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13659 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13660 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13661 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13662 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13663 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13664 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13665 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13666 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13667 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13668 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13669 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13670 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13671 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13672 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13673 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13674 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13675 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13676 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13677 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13678 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13679 	};
13680 	static struct bwn_txgain_entry txgain_r1[] = {
13681 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13682 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13683 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13684 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13685 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13686 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13687 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13688 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13689 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13690 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13691 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13692 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13693 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13694 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13695 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13696 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13697 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13698 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13699 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13700 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13701 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13702 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13703 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13704 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13705 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13706 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13707 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13708 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13709 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13710 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13711 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13712 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13713 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13714 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13715 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13716 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13717 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13718 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13719 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13720 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13721 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13722 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13723 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13724 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13725 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13726 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13727 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13728 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13729 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13730 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13731 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13732 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13733 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13734 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13735 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13736 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13737 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13738 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13739 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13740 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13741 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13742 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13743 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13744 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13745 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13746 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13747 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13748 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13749 		{ 7, 11, 6, 0, 71 }
13750 	};
13751 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13752 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13753 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13754 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13755 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13756 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13757 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13758 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13759 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13760 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13761 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13762 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13763 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13764 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13765 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13766 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13767 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13768 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13769 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13770 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13771 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13772 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13773 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13774 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13775 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13776 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13777 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13778 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13779 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13780 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13781 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13782 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13783 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13784 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13785 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13786 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13787 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13788 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13789 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13790 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13791 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13792 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13793 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13794 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13795 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13796 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13797 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13798 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13799 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13800 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13801 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13802 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13803 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13804 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13805 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13806 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13807 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13808 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13809 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13810 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13811 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13812 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13813 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13814 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13815 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13816 	};
13817 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13818 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13819 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13820 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13821 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13822 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13823 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13824 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13825 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13826 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13827 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13828 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13829 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13830 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13831 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13832 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13833 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13834 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13835 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13836 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13837 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13838 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13839 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13840 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13841 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13842 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13843 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13844 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13845 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13846 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13847 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13848 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13849 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13850 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13851 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13852 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13853 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13854 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13855 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13856 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13857 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13858 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13859 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13860 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13861 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13862 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13863 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13864 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13865 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13866 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13867 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13868 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13869 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13870 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13871 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13872 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13873 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13874 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13875 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13876 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13877 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13878 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13879 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13880 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13881 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13882 	};
13883 
13884 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13885 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13886 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13887 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13888 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13889 			    txgain_2ghz_r2);
13890 		else
13891 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13892 			    txgain_5ghz_r2);
13893 		return;
13894 	}
13895 
13896 	if (mac->mac_phy.rev == 0) {
13897 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13898 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13899 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13900 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13901 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13902 			    txgain_2ghz_r0);
13903 		else
13904 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13905 			    txgain_5ghz_r0);
13906 		return;
13907 	}
13908 
13909 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13910 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13911 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13912 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13913 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13914 	else
13915 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13916 }
13917 
13918 static void
13919 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13920 {
13921 	uint32_t offset, type;
13922 
13923 	type = BWN_TAB_GETTYPE(typeoffset);
13924 	offset = BWN_TAB_GETOFFSET(typeoffset);
13925 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13926 
13927 	switch (type) {
13928 	case BWN_TAB_8BIT:
13929 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13930 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13931 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13932 		break;
13933 	case BWN_TAB_16BIT:
13934 		KASSERT(!(value & ~0xffff),
13935 		    ("%s:%d: fail", __func__, __LINE__));
13936 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13937 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13938 		break;
13939 	case BWN_TAB_32BIT:
13940 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13941 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13942 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13943 		break;
13944 	default:
13945 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13946 	}
13947 }
13948 
13949 static int
13950 bwn_phy_lp_loopback(struct bwn_mac *mac)
13951 {
13952 	struct bwn_phy_lp_iq_est ie;
13953 	int i, index = -1;
13954 	uint32_t tmp;
13955 
13956 	memset(&ie, 0, sizeof(ie));
13957 
13958 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13959 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13960 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13961 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13962 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13963 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13964 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13965 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13966 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13967 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13968 	for (i = 0; i < 32; i++) {
13969 		bwn_phy_lp_set_rxgain_idx(mac, i);
13970 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13971 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13972 			continue;
13973 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13974 		if ((tmp > 4000) && (tmp < 10000)) {
13975 			index = i;
13976 			break;
13977 		}
13978 	}
13979 	bwn_phy_lp_ddfs_turnoff(mac);
13980 	return (index);
13981 }
13982 
13983 static void
13984 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13985 {
13986 
13987 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13988 }
13989 
13990 static void
13991 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13992     int incr1, int incr2, int scale_idx)
13993 {
13994 
13995 	bwn_phy_lp_ddfs_turnoff(mac);
13996 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13997 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13998 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13999 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
14000 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14001 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14002 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14003 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14004 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14005 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14006 }
14007 
14008 static uint8_t
14009 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14010     struct bwn_phy_lp_iq_est *ie)
14011 {
14012 	int i;
14013 
14014 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14015 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14016 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14017 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14018 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14019 
14020 	for (i = 0; i < 500; i++) {
14021 		if (!(BWN_PHY_READ(mac,
14022 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14023 			break;
14024 		DELAY(1000);
14025 	}
14026 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14027 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14028 		return 0;
14029 	}
14030 
14031 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14032 	ie->ie_iqprod <<= 16;
14033 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14034 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14035 	ie->ie_ipwr <<= 16;
14036 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14037 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14038 	ie->ie_qpwr <<= 16;
14039 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14040 
14041 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14042 	return 1;
14043 }
14044 
14045 static uint32_t
14046 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14047 {
14048 	uint32_t offset, type, value;
14049 
14050 	type = BWN_TAB_GETTYPE(typeoffset);
14051 	offset = BWN_TAB_GETOFFSET(typeoffset);
14052 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14053 
14054 	switch (type) {
14055 	case BWN_TAB_8BIT:
14056 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14057 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14058 		break;
14059 	case BWN_TAB_16BIT:
14060 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14061 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14062 		break;
14063 	case BWN_TAB_32BIT:
14064 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14065 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14066 		value <<= 16;
14067 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14068 		break;
14069 	default:
14070 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14071 		value = 0;
14072 	}
14073 
14074 	return (value);
14075 }
14076 
14077 static void
14078 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14079 {
14080 
14081 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14082 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14083 }
14084 
14085 static void
14086 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14087 {
14088 	uint16_t ctl;
14089 
14090 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14091 	ctl |= dac << 7;
14092 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14093 }
14094 
14095 static void
14096 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14097 {
14098 
14099 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14100 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14101 }
14102 
14103 static void
14104 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14105 {
14106 
14107 	if (mac->mac_phy.rev < 2)
14108 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14109 	else {
14110 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14111 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14112 	}
14113 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14114 }
14115 
14116 static uint16_t
14117 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14118 {
14119 
14120 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14121 }
14122 
14123 static uint8_t
14124 bwn_nbits(int32_t val)
14125 {
14126 	uint32_t tmp;
14127 	uint8_t nbits = 0;
14128 
14129 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14130 		nbits++;
14131 	return (nbits);
14132 }
14133 
14134 static void
14135 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14136     struct bwn_txgain_entry *table)
14137 {
14138 	int i;
14139 
14140 	for (i = offset; i < count; i++)
14141 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14142 }
14143 
14144 static void
14145 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14146     struct bwn_txgain_entry data)
14147 {
14148 
14149 	if (mac->mac_phy.rev >= 2)
14150 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14151 	else
14152 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14153 }
14154 
14155 static void
14156 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14157     struct bwn_txgain_entry te)
14158 {
14159 	struct bwn_softc *sc = mac->mac_sc;
14160 	struct ifnet *ifp = sc->sc_ifp;
14161 	struct ieee80211com *ic = ifp->if_l2com;
14162 	uint32_t tmp;
14163 
14164 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14165 
14166 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14167 	if (mac->mac_phy.rev >= 3) {
14168 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14169 		    (0x10 << 24) : (0x70 << 24));
14170 	} else {
14171 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14172 		    (0x14 << 24) : (0x7f << 24));
14173 	}
14174 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14175 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14176 	    te.te_bbmult << 20 | te.te_dac << 28);
14177 }
14178 
14179 static void
14180 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14181     struct bwn_txgain_entry te)
14182 {
14183 
14184 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14185 
14186 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14187 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14188 	    te.te_dac);
14189 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14190 }
14191 
14192 static void
14193 bwn_sysctl_node(struct bwn_softc *sc)
14194 {
14195 	device_t dev = sc->sc_dev;
14196 	struct bwn_mac *mac;
14197 	struct bwn_stats *stats;
14198 
14199 	/* XXX assume that count of MAC is only 1. */
14200 
14201 	if ((mac = sc->sc_curmac) == NULL)
14202 		return;
14203 	stats = &mac->mac_stats;
14204 
14205 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14206 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14207 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14208 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14209 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14210 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14211 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14212 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14213 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14214 
14215 #ifdef BWN_DEBUG
14216 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14217 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14218 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14219 #endif
14220 }
14221 
14222 static device_method_t bwn_methods[] = {
14223 	/* Device interface */
14224 	DEVMETHOD(device_probe,		bwn_probe),
14225 	DEVMETHOD(device_attach,	bwn_attach),
14226 	DEVMETHOD(device_detach,	bwn_detach),
14227 	DEVMETHOD(device_suspend,	bwn_suspend),
14228 	DEVMETHOD(device_resume,	bwn_resume),
14229 	DEVMETHOD_END
14230 };
14231 static driver_t bwn_driver = {
14232 	"bwn",
14233 	bwn_methods,
14234 	sizeof(struct bwn_softc)
14235 };
14236 static devclass_t bwn_devclass;
14237 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14238 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14239 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14240 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14241 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14242