xref: /freebsd/sys/dev/bwn/if_bwn.c (revision 69c5bce6ee1ec42997757e7f1334767d217c5d7d)
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 SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, "Broadcom driver parameters");
77 
78 /*
79  * Tunable & sysctl variables.
80  */
81 
82 #ifdef BWN_DEBUG
83 static	int bwn_debug = 0;
84 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RW, &bwn_debug, 0,
85     "Broadcom debugging printfs");
86 TUNABLE_INT("hw.bwn.debug", &bwn_debug);
87 enum {
88 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
89 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
90 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
91 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
92 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
93 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
94 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
95 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
96 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
97 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
98 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
99 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
100 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
101 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
102 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
103 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
104 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
105 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
106 	BWN_DEBUG_ANY		= 0xffffffff
107 };
108 #define	DPRINTF(sc, m, fmt, ...) do {			\
109 	if (sc->sc_debug & (m))				\
110 		printf(fmt, __VA_ARGS__);		\
111 } while (0)
112 #else
113 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
114 #endif
115 
116 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
117 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
118     "uses Bad Frames Preemption");
119 static int	bwn_bluetooth = 1;
120 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
121     "turns on Bluetooth Coexistence");
122 static int	bwn_hwpctl = 0;
123 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
124     "uses H/W power control");
125 static int	bwn_msi_disable = 0;		/* MSI disabled  */
126 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
127 static int	bwn_usedma = 1;
128 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
129     "uses DMA");
130 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
131 static int	bwn_wme = 1;
132 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
133     "uses WME support");
134 
135 static int	bwn_attach_pre(struct bwn_softc *);
136 static int	bwn_attach_post(struct bwn_softc *);
137 static void	bwn_sprom_bugfixes(device_t);
138 static void	bwn_init(void *);
139 static int	bwn_init_locked(struct bwn_softc *);
140 static int	bwn_ioctl(struct ifnet *, u_long, caddr_t);
141 static void	bwn_start(struct ifnet *);
142 static int	bwn_attach_core(struct bwn_mac *);
143 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
144 static int	bwn_phy_getinfo(struct bwn_mac *, int);
145 static int	bwn_chiptest(struct bwn_mac *);
146 static int	bwn_setup_channels(struct bwn_mac *, int, int);
147 static int	bwn_phy_g_attach(struct bwn_mac *);
148 static void	bwn_phy_g_detach(struct bwn_mac *);
149 static void	bwn_phy_g_init_pre(struct bwn_mac *);
150 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
151 static int	bwn_phy_g_init(struct bwn_mac *);
152 static void	bwn_phy_g_exit(struct bwn_mac *);
153 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
154 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
155 		    uint16_t);
156 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
157 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
158 		    uint16_t);
159 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
160 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
161 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
162 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
163 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
164 static int	bwn_phy_g_im(struct bwn_mac *, int);
165 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
166 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
167 static void	bwn_phy_g_task_15s(struct bwn_mac *);
168 static void	bwn_phy_g_task_60s(struct bwn_mac *);
169 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
170 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
171 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
172 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
173 		    uint16_t);
174 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
175 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
176 		    uint32_t);
177 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
178 		    uint16_t);
179 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
180 		    const struct bwn_channelinfo *, int);
181 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
182 		    const struct ieee80211_bpf_params *);
183 static void	bwn_updateslot(struct ifnet *);
184 static void	bwn_update_promisc(struct ifnet *);
185 static void	bwn_wme_init(struct bwn_mac *);
186 static int	bwn_wme_update(struct ieee80211com *);
187 static void	bwn_wme_clear(struct bwn_softc *);
188 static void	bwn_wme_load(struct bwn_mac *);
189 static void	bwn_wme_loadparams(struct bwn_mac *,
190 		    const struct wmeParams *, uint16_t);
191 static void	bwn_scan_start(struct ieee80211com *);
192 static void	bwn_scan_end(struct ieee80211com *);
193 static void	bwn_set_channel(struct ieee80211com *);
194 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
195 		    const char [IFNAMSIZ], int, int,
196 		    int, const uint8_t [IEEE80211_ADDR_LEN],
197 		    const uint8_t [IEEE80211_ADDR_LEN]);
198 static void	bwn_vap_delete(struct ieee80211vap *);
199 static void	bwn_stop(struct bwn_softc *, int);
200 static void	bwn_stop_locked(struct bwn_softc *, int);
201 static int	bwn_core_init(struct bwn_mac *);
202 static void	bwn_core_start(struct bwn_mac *);
203 static void	bwn_core_exit(struct bwn_mac *);
204 static void	bwn_bt_disable(struct bwn_mac *);
205 static int	bwn_chip_init(struct bwn_mac *);
206 static uint64_t	bwn_hf_read(struct bwn_mac *);
207 static void	bwn_hf_write(struct bwn_mac *, uint64_t);
208 static void	bwn_set_txretry(struct bwn_mac *, int, int);
209 static void	bwn_rate_init(struct bwn_mac *);
210 static void	bwn_set_phytxctl(struct bwn_mac *);
211 static void	bwn_spu_setdelay(struct bwn_mac *, int);
212 static void	bwn_bt_enable(struct bwn_mac *);
213 static void	bwn_set_macaddr(struct bwn_mac *);
214 static void	bwn_crypt_init(struct bwn_mac *);
215 static void	bwn_chip_exit(struct bwn_mac *);
216 static int	bwn_fw_fillinfo(struct bwn_mac *);
217 static int	bwn_fw_loaducode(struct bwn_mac *);
218 static int	bwn_gpio_init(struct bwn_mac *);
219 static int	bwn_fw_loadinitvals(struct bwn_mac *);
220 static int	bwn_phy_init(struct bwn_mac *);
221 static void	bwn_set_txantenna(struct bwn_mac *, int);
222 static void	bwn_set_opmode(struct bwn_mac *);
223 static void	bwn_rate_write(struct bwn_mac *, uint16_t, int);
224 static uint8_t	bwn_plcp_getcck(const uint8_t);
225 static uint8_t	bwn_plcp_getofdm(const uint8_t);
226 static void	bwn_pio_init(struct bwn_mac *);
227 static uint16_t	bwn_pio_idx2base(struct bwn_mac *, int);
228 static void	bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *,
229 		    int);
230 static void	bwn_pio_setupqueue_rx(struct bwn_mac *,
231 		    struct bwn_pio_rxqueue *, int);
232 static void	bwn_destroy_queue_tx(struct bwn_pio_txqueue *);
233 static uint16_t	bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *,
234 		    uint16_t);
235 static void	bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *);
236 static int	bwn_pio_rx(struct bwn_pio_rxqueue *);
237 static uint8_t	bwn_pio_rxeof(struct bwn_pio_rxqueue *);
238 static void	bwn_pio_handle_txeof(struct bwn_mac *,
239 		    const struct bwn_txstatus *);
240 static uint16_t	bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t);
241 static uint32_t	bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t);
242 static void	bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t,
243 		    uint16_t);
244 static void	bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t,
245 		    uint32_t);
246 static int	bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *,
247 		    struct mbuf *);
248 static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t);
249 static uint32_t	bwn_pio_write_multi_4(struct bwn_mac *,
250 		    struct bwn_pio_txqueue *, uint32_t, const void *, int);
251 static void	bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *,
252 		    uint16_t, uint32_t);
253 static uint16_t	bwn_pio_write_multi_2(struct bwn_mac *,
254 		    struct bwn_pio_txqueue *, uint16_t, const void *, int);
255 static uint16_t	bwn_pio_write_mbuf_2(struct bwn_mac *,
256 		    struct bwn_pio_txqueue *, uint16_t, struct mbuf *);
257 static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *,
258 		    uint16_t, struct bwn_pio_txpkt **);
259 static void	bwn_dma_init(struct bwn_mac *);
260 static void	bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t);
261 static int	bwn_dma_mask2type(uint64_t);
262 static uint64_t	bwn_dma_mask(struct bwn_mac *);
263 static uint16_t	bwn_dma_base(int, int);
264 static void	bwn_dma_ringfree(struct bwn_dma_ring **);
265 static void	bwn_dma_32_getdesc(struct bwn_dma_ring *,
266 		    int, struct bwn_dmadesc_generic **,
267 		    struct bwn_dmadesc_meta **);
268 static void	bwn_dma_32_setdesc(struct bwn_dma_ring *,
269 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
270 		    int, int);
271 static void	bwn_dma_32_start_transfer(struct bwn_dma_ring *, int);
272 static void	bwn_dma_32_suspend(struct bwn_dma_ring *);
273 static void	bwn_dma_32_resume(struct bwn_dma_ring *);
274 static int	bwn_dma_32_get_curslot(struct bwn_dma_ring *);
275 static void	bwn_dma_32_set_curslot(struct bwn_dma_ring *, int);
276 static void	bwn_dma_64_getdesc(struct bwn_dma_ring *,
277 		    int, struct bwn_dmadesc_generic **,
278 		    struct bwn_dmadesc_meta **);
279 static void	bwn_dma_64_setdesc(struct bwn_dma_ring *,
280 		    struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int,
281 		    int, int);
282 static void	bwn_dma_64_start_transfer(struct bwn_dma_ring *, int);
283 static void	bwn_dma_64_suspend(struct bwn_dma_ring *);
284 static void	bwn_dma_64_resume(struct bwn_dma_ring *);
285 static int	bwn_dma_64_get_curslot(struct bwn_dma_ring *);
286 static void	bwn_dma_64_set_curslot(struct bwn_dma_ring *, int);
287 static int	bwn_dma_allocringmemory(struct bwn_dma_ring *);
288 static void	bwn_dma_setup(struct bwn_dma_ring *);
289 static void	bwn_dma_free_ringmemory(struct bwn_dma_ring *);
290 static void	bwn_dma_cleanup(struct bwn_dma_ring *);
291 static void	bwn_dma_free_descbufs(struct bwn_dma_ring *);
292 static int	bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int);
293 static void	bwn_dma_rx(struct bwn_dma_ring *);
294 static int	bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int);
295 static void	bwn_dma_free_descbuf(struct bwn_dma_ring *,
296 		    struct bwn_dmadesc_meta *);
297 static void	bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *);
298 static int	bwn_dma_gettype(struct bwn_mac *);
299 static void	bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int);
300 static int	bwn_dma_freeslot(struct bwn_dma_ring *);
301 static int	bwn_dma_nextslot(struct bwn_dma_ring *, int);
302 static void	bwn_dma_rxeof(struct bwn_dma_ring *, int *);
303 static int	bwn_dma_newbuf(struct bwn_dma_ring *,
304 		    struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *,
305 		    int);
306 static void	bwn_dma_buf_addr(void *, bus_dma_segment_t *, int,
307 		    bus_size_t, int);
308 static uint8_t	bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *);
309 static void	bwn_dma_handle_txeof(struct bwn_mac *,
310 		    const struct bwn_txstatus *);
311 static int	bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *,
312 		    struct mbuf *);
313 static int	bwn_dma_getslot(struct bwn_dma_ring *);
314 static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *,
315 		    uint8_t);
316 static int	bwn_dma_attach(struct bwn_mac *);
317 static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *,
318 		    int, int, int);
319 static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *,
320 		    const struct bwn_txstatus *, uint16_t, int *);
321 static void	bwn_dma_free(struct bwn_mac *);
322 static void	bwn_phy_g_init_sub(struct bwn_mac *);
323 static uint8_t	bwn_has_hwpctl(struct bwn_mac *);
324 static void	bwn_phy_init_b5(struct bwn_mac *);
325 static void	bwn_phy_init_b6(struct bwn_mac *);
326 static void	bwn_phy_init_a(struct bwn_mac *);
327 static void	bwn_loopback_calcgain(struct bwn_mac *);
328 static uint16_t	bwn_rf_init_bcm2050(struct bwn_mac *);
329 static void	bwn_lo_g_init(struct bwn_mac *);
330 static void	bwn_lo_g_adjust(struct bwn_mac *);
331 static void	bwn_lo_get_powervector(struct bwn_mac *);
332 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
333 		    const struct bwn_bbatt *, const struct bwn_rfatt *);
334 static void	bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
335 static void	bwn_phy_hwpctl_init(struct bwn_mac *);
336 static void	bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
337 static void	bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
338 		    const struct bwn_bbatt *, const struct bwn_rfatt *,
339 		    uint8_t);
340 static void	bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
341 static uint16_t	bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
342 static void	bwn_spu_workaround(struct bwn_mac *, uint8_t);
343 static void	bwn_wa_init(struct bwn_mac *);
344 static void	bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
345 		    uint16_t);
346 static void	bwn_dummy_transmission(struct bwn_mac *, int, int);
347 static void	bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
348 		    uint32_t);
349 static void	bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
350 		    uint16_t);
351 static void	bwn_ram_write(struct bwn_mac *, uint16_t, uint32_t);
352 static void	bwn_mac_suspend(struct bwn_mac *);
353 static void	bwn_mac_enable(struct bwn_mac *);
354 static void	bwn_psctl(struct bwn_mac *, uint32_t);
355 static int16_t	bwn_nrssi_read(struct bwn_mac *, uint16_t);
356 static void	bwn_nrssi_offset(struct bwn_mac *);
357 static void	bwn_nrssi_threshold(struct bwn_mac *);
358 static void	bwn_nrssi_slope_11g(struct bwn_mac *);
359 static void	bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
360 		    int16_t);
361 static void	bwn_set_original_gains(struct bwn_mac *);
362 static void	bwn_hwpctl_early_init(struct bwn_mac *);
363 static void	bwn_hwpctl_init_gphy(struct bwn_mac *);
364 static uint16_t	bwn_phy_g_chan2freq(uint8_t);
365 static int	bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype);
366 static int	bwn_fw_get(struct bwn_mac *, enum bwn_fwtype,
367 		    const char *, struct bwn_fwfile *);
368 static void	bwn_release_firmware(struct bwn_mac *);
369 static void	bwn_do_release_fw(struct bwn_fwfile *);
370 static uint16_t	bwn_fwcaps_read(struct bwn_mac *);
371 static int	bwn_fwinitvals_write(struct bwn_mac *,
372 		    const struct bwn_fwinitvals *, size_t, size_t);
373 static int	bwn_switch_channel(struct bwn_mac *, int);
374 static uint16_t	bwn_ant2phy(int);
375 static void	bwn_mac_write_bssid(struct bwn_mac *);
376 static void	bwn_mac_setfilter(struct bwn_mac *, uint16_t,
377 		    const uint8_t *);
378 static void	bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t,
379 		    const uint8_t *, size_t, const uint8_t *);
380 static void	bwn_key_macwrite(struct bwn_mac *, uint8_t,
381 		    const uint8_t *);
382 static void	bwn_key_write(struct bwn_mac *, uint8_t, uint8_t,
383 		    const uint8_t *);
384 static void	bwn_phy_exit(struct bwn_mac *);
385 static void	bwn_core_stop(struct bwn_mac *);
386 static int	bwn_switch_band(struct bwn_softc *,
387 		    struct ieee80211_channel *);
388 static void	bwn_phy_reset(struct bwn_mac *);
389 static int	bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
390 static void	bwn_set_pretbtt(struct bwn_mac *);
391 static int	bwn_intr(void *);
392 static void	bwn_intrtask(void *, int);
393 static void	bwn_restart(struct bwn_mac *, const char *);
394 static void	bwn_intr_ucode_debug(struct bwn_mac *);
395 static void	bwn_intr_tbtt_indication(struct bwn_mac *);
396 static void	bwn_intr_atim_end(struct bwn_mac *);
397 static void	bwn_intr_beacon(struct bwn_mac *);
398 static void	bwn_intr_pmq(struct bwn_mac *);
399 static void	bwn_intr_noise(struct bwn_mac *);
400 static void	bwn_intr_txeof(struct bwn_mac *);
401 static void	bwn_hwreset(void *, int);
402 static void	bwn_handle_fwpanic(struct bwn_mac *);
403 static void	bwn_load_beacon0(struct bwn_mac *);
404 static void	bwn_load_beacon1(struct bwn_mac *);
405 static uint32_t	bwn_jssi_read(struct bwn_mac *);
406 static void	bwn_noise_gensample(struct bwn_mac *);
407 static void	bwn_handle_txeof(struct bwn_mac *,
408 		    const struct bwn_txstatus *);
409 static void	bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
410 static void	bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
411 static void	bwn_start_locked(struct ifnet *);
412 static int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
413 		    struct mbuf *);
414 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
415 static int	bwn_set_txhdr(struct bwn_mac *,
416 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
417 		    uint16_t);
418 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
419 		    const uint8_t);
420 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
421 static uint8_t	bwn_get_fbrate(uint8_t);
422 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
423 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
424 static void	bwn_phy_lock(struct bwn_mac *);
425 static void	bwn_phy_unlock(struct bwn_mac *);
426 static void	bwn_rf_lock(struct bwn_mac *);
427 static void	bwn_rf_unlock(struct bwn_mac *);
428 static void	bwn_txpwr(void *, int);
429 static void	bwn_tasks(void *);
430 static void	bwn_task_15s(struct bwn_mac *);
431 static void	bwn_task_30s(struct bwn_mac *);
432 static void	bwn_task_60s(struct bwn_mac *);
433 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
434 		    uint8_t);
435 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
436 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
437 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
438 		    int, int);
439 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
440 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
441 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
442 static void	bwn_watchdog(void *);
443 static void	bwn_dma_stop(struct bwn_mac *);
444 static void	bwn_pio_stop(struct bwn_mac *);
445 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
446 static void	bwn_led_attach(struct bwn_mac *);
447 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
448 static void	bwn_led_event(struct bwn_mac *, int);
449 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
450 static void	bwn_led_blink_next(void *);
451 static void	bwn_led_blink_end(void *);
452 static void	bwn_rfswitch(void *);
453 static void	bwn_rf_turnon(struct bwn_mac *);
454 static void	bwn_rf_turnoff(struct bwn_mac *);
455 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
456 static int	bwn_phy_lp_init(struct bwn_mac *);
457 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
458 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
459 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
460 		    uint16_t);
461 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
462 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
463 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
464 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
465 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
466 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
467 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
468 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
469 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
470 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
471 static void	bwn_phy_lp_calib(struct bwn_mac *);
472 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
473 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
474 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
475 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
476 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
477 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
478 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
479 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
480 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
481 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
482 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
483 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
484 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
485 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
486 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
487 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
488 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
489 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
490 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
491 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
492 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
493 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
494 		    const void *);
495 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
496 static struct bwn_txgain
497 		bwn_phy_lp_get_txgain(struct bwn_mac *);
498 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
499 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
500 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
501 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
502 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
503 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
504 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
505 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
506 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
507 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
508 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
509 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
510 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
511 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
512 static int	bwn_phy_lp_loopback(struct bwn_mac *);
513 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
514 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
515 		    int);
516 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
517 		    struct bwn_phy_lp_iq_est *);
518 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
519 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
520 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
521 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
522 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
523 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
524 static uint8_t	bwn_nbits(int32_t);
525 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
526 		    struct bwn_txgain_entry *);
527 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
528 		    struct bwn_txgain_entry);
529 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
530 		    struct bwn_txgain_entry);
531 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
532 		    struct bwn_txgain_entry);
533 static void	bwn_sysctl_node(struct bwn_softc *);
534 
535 static struct resource_spec bwn_res_spec_legacy[] = {
536 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
537 	{ -1,			0,		0 }
538 };
539 
540 static struct resource_spec bwn_res_spec_msi[] = {
541 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
542 	{ -1,			0,		0 }
543 };
544 
545 static const struct bwn_channelinfo bwn_chantable_bg = {
546 	.channels = {
547 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
548 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
549 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
550 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
551 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
552 	.nchannels = 14
553 };
554 
555 static const struct bwn_channelinfo bwn_chantable_a = {
556 	.channels = {
557 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
558 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
559 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
560 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
561 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
562 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
563 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
564 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
565 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
566 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
567 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
568 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
569 		{ 6080, 216, 30 } },
570 	.nchannels = 37
571 };
572 
573 static const struct bwn_channelinfo bwn_chantable_n = {
574 	.channels = {
575 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
576 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
577 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
578 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
579 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
580 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
581 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
582 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
583 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
584 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
585 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
586 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
587 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
588 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
589 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
590 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
591 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
592 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
593 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
594 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
595 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
596 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
597 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
598 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
599 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
600 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
601 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
602 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
603 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
604 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
605 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
606 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
607 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
608 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
609 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
610 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
611 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
612 	.nchannels = 110
613 };
614 
615 static const uint8_t bwn_b2063_chantable_data[33][12] = {
616 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
617 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
621 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
622 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
623 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
624 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
625 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
626 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
627 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
628 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
629 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
630 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
631 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
632 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
633 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
634 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
635 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
636 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
637 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
638 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
640 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
641 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
642 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
643 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
644 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
646 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
647 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
648 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
649 };
650 
651 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
652 	{ 1, 2412, bwn_b2063_chantable_data[0] },
653 	{ 2, 2417, bwn_b2063_chantable_data[0] },
654 	{ 3, 2422, bwn_b2063_chantable_data[0] },
655 	{ 4, 2427, bwn_b2063_chantable_data[1] },
656 	{ 5, 2432, bwn_b2063_chantable_data[1] },
657 	{ 6, 2437, bwn_b2063_chantable_data[1] },
658 	{ 7, 2442, bwn_b2063_chantable_data[1] },
659 	{ 8, 2447, bwn_b2063_chantable_data[1] },
660 	{ 9, 2452, bwn_b2063_chantable_data[2] },
661 	{ 10, 2457, bwn_b2063_chantable_data[2] },
662 	{ 11, 2462, bwn_b2063_chantable_data[3] },
663 	{ 12, 2467, bwn_b2063_chantable_data[3] },
664 	{ 13, 2472, bwn_b2063_chantable_data[3] },
665 	{ 14, 2484, bwn_b2063_chantable_data[4] },
666 	{ 34, 5170, bwn_b2063_chantable_data[5] },
667 	{ 36, 5180, bwn_b2063_chantable_data[6] },
668 	{ 38, 5190, bwn_b2063_chantable_data[7] },
669 	{ 40, 5200, bwn_b2063_chantable_data[8] },
670 	{ 42, 5210, bwn_b2063_chantable_data[9] },
671 	{ 44, 5220, bwn_b2063_chantable_data[10] },
672 	{ 46, 5230, bwn_b2063_chantable_data[11] },
673 	{ 48, 5240, bwn_b2063_chantable_data[12] },
674 	{ 52, 5260, bwn_b2063_chantable_data[13] },
675 	{ 56, 5280, bwn_b2063_chantable_data[14] },
676 	{ 60, 5300, bwn_b2063_chantable_data[14] },
677 	{ 64, 5320, bwn_b2063_chantable_data[15] },
678 	{ 100, 5500, bwn_b2063_chantable_data[16] },
679 	{ 104, 5520, bwn_b2063_chantable_data[17] },
680 	{ 108, 5540, bwn_b2063_chantable_data[18] },
681 	{ 112, 5560, bwn_b2063_chantable_data[19] },
682 	{ 116, 5580, bwn_b2063_chantable_data[20] },
683 	{ 120, 5600, bwn_b2063_chantable_data[21] },
684 	{ 124, 5620, bwn_b2063_chantable_data[21] },
685 	{ 128, 5640, bwn_b2063_chantable_data[22] },
686 	{ 132, 5660, bwn_b2063_chantable_data[22] },
687 	{ 136, 5680, bwn_b2063_chantable_data[22] },
688 	{ 140, 5700, bwn_b2063_chantable_data[23] },
689 	{ 149, 5745, bwn_b2063_chantable_data[23] },
690 	{ 153, 5765, bwn_b2063_chantable_data[23] },
691 	{ 157, 5785, bwn_b2063_chantable_data[23] },
692 	{ 161, 5805, bwn_b2063_chantable_data[23] },
693 	{ 165, 5825, bwn_b2063_chantable_data[23] },
694 	{ 184, 4920, bwn_b2063_chantable_data[24] },
695 	{ 188, 4940, bwn_b2063_chantable_data[25] },
696 	{ 192, 4960, bwn_b2063_chantable_data[26] },
697 	{ 196, 4980, bwn_b2063_chantable_data[27] },
698 	{ 200, 5000, bwn_b2063_chantable_data[28] },
699 	{ 204, 5020, bwn_b2063_chantable_data[29] },
700 	{ 208, 5040, bwn_b2063_chantable_data[30] },
701 	{ 212, 5060, bwn_b2063_chantable_data[31] },
702 	{ 216, 5080, bwn_b2063_chantable_data[32] }
703 };
704 
705 static const uint8_t bwn_b2062_chantable_data[22][12] = {
706 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
707 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
715 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
716 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
719 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
726 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
727 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
728 };
729 
730 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
731 	{ 1, 2412, bwn_b2062_chantable_data[0] },
732 	{ 2, 2417, bwn_b2062_chantable_data[0] },
733 	{ 3, 2422, bwn_b2062_chantable_data[0] },
734 	{ 4, 2427, bwn_b2062_chantable_data[0] },
735 	{ 5, 2432, bwn_b2062_chantable_data[0] },
736 	{ 6, 2437, bwn_b2062_chantable_data[0] },
737 	{ 7, 2442, bwn_b2062_chantable_data[0] },
738 	{ 8, 2447, bwn_b2062_chantable_data[0] },
739 	{ 9, 2452, bwn_b2062_chantable_data[0] },
740 	{ 10, 2457, bwn_b2062_chantable_data[0] },
741 	{ 11, 2462, bwn_b2062_chantable_data[0] },
742 	{ 12, 2467, bwn_b2062_chantable_data[0] },
743 	{ 13, 2472, bwn_b2062_chantable_data[0] },
744 	{ 14, 2484, bwn_b2062_chantable_data[0] },
745 	{ 34, 5170, bwn_b2062_chantable_data[1] },
746 	{ 38, 5190, bwn_b2062_chantable_data[2] },
747 	{ 42, 5210, bwn_b2062_chantable_data[2] },
748 	{ 46, 5230, bwn_b2062_chantable_data[3] },
749 	{ 36, 5180, bwn_b2062_chantable_data[4] },
750 	{ 40, 5200, bwn_b2062_chantable_data[5] },
751 	{ 44, 5220, bwn_b2062_chantable_data[6] },
752 	{ 48, 5240, bwn_b2062_chantable_data[3] },
753 	{ 52, 5260, bwn_b2062_chantable_data[3] },
754 	{ 56, 5280, bwn_b2062_chantable_data[3] },
755 	{ 60, 5300, bwn_b2062_chantable_data[7] },
756 	{ 64, 5320, bwn_b2062_chantable_data[8] },
757 	{ 100, 5500, bwn_b2062_chantable_data[9] },
758 	{ 104, 5520, bwn_b2062_chantable_data[10] },
759 	{ 108, 5540, bwn_b2062_chantable_data[10] },
760 	{ 112, 5560, bwn_b2062_chantable_data[10] },
761 	{ 116, 5580, bwn_b2062_chantable_data[11] },
762 	{ 120, 5600, bwn_b2062_chantable_data[12] },
763 	{ 124, 5620, bwn_b2062_chantable_data[12] },
764 	{ 128, 5640, bwn_b2062_chantable_data[12] },
765 	{ 132, 5660, bwn_b2062_chantable_data[12] },
766 	{ 136, 5680, bwn_b2062_chantable_data[12] },
767 	{ 140, 5700, bwn_b2062_chantable_data[12] },
768 	{ 149, 5745, bwn_b2062_chantable_data[12] },
769 	{ 153, 5765, bwn_b2062_chantable_data[12] },
770 	{ 157, 5785, bwn_b2062_chantable_data[12] },
771 	{ 161, 5805, bwn_b2062_chantable_data[12] },
772 	{ 165, 5825, bwn_b2062_chantable_data[12] },
773 	{ 184, 4920, bwn_b2062_chantable_data[13] },
774 	{ 188, 4940, bwn_b2062_chantable_data[14] },
775 	{ 192, 4960, bwn_b2062_chantable_data[15] },
776 	{ 196, 4980, bwn_b2062_chantable_data[16] },
777 	{ 200, 5000, bwn_b2062_chantable_data[17] },
778 	{ 204, 5020, bwn_b2062_chantable_data[18] },
779 	{ 208, 5040, bwn_b2062_chantable_data[19] },
780 	{ 212, 5060, bwn_b2062_chantable_data[20] },
781 	{ 216, 5080, bwn_b2062_chantable_data[21] }
782 };
783 
784 /* for LP PHY */
785 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
786 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
787 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
788 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
789 	{ 13, -66, 13 }, { 14, -66, 13 },
790 };
791 
792 /* for LP PHY */
793 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
794 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
795 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
796 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
797 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
798 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
799 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
800 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
801 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
802 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
803 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
804 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
805 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
806 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
807 };
808 
809 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
810 
811 static const uint8_t bwn_tab_sigsq_tbl[] = {
812 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
813 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
814 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
815 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
816 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
817 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
818 };
819 
820 static const uint8_t bwn_tab_pllfrac_tbl[] = {
821 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
822 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
823 };
824 
825 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
826 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
827 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
828 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
829 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
830 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
831 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
832 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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, 0x4000, 0x0000, 0x0000,
836 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
838 };
839 
840 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
841 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
842 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
843 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
844 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
845 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
846 
847 #define	VENDOR_LED_ACT(vendor)				\
848 {							\
849 	.vid = PCI_VENDOR_##vendor,			\
850 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
851 }
852 
853 static const struct {
854 	uint16_t	vid;
855 	uint8_t		led_act[BWN_LED_MAX];
856 } bwn_vendor_led_act[] = {
857 	VENDOR_LED_ACT(COMPAQ),
858 	VENDOR_LED_ACT(ASUSTEK)
859 };
860 
861 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
862 	{ BWN_VENDOR_LED_ACT_DEFAULT };
863 
864 #undef VENDOR_LED_ACT
865 
866 static const struct {
867 	int		on_dur;
868 	int		off_dur;
869 } bwn_led_duration[109] = {
870 	[0]	= { 400, 100 },
871 	[2]	= { 150, 75 },
872 	[4]	= { 90, 45 },
873 	[11]	= { 66, 34 },
874 	[12]	= { 53, 26 },
875 	[18]	= { 42, 21 },
876 	[22]	= { 35, 17 },
877 	[24]	= { 32, 16 },
878 	[36]	= { 21, 10 },
879 	[48]	= { 16, 8 },
880 	[72]	= { 11, 5 },
881 	[96]	= { 9, 4 },
882 	[108]	= { 7, 3 }
883 };
884 
885 static const uint16_t bwn_wme_shm_offsets[] = {
886 	[0] = BWN_WME_BESTEFFORT,
887 	[1] = BWN_WME_BACKGROUND,
888 	[2] = BWN_WME_VOICE,
889 	[3] = BWN_WME_VIDEO,
890 };
891 
892 static const struct siba_devid bwn_devs[] = {
893 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
894 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
895 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
896 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
897 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
898 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
899 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
900 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
901 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
902 };
903 
904 static int
905 bwn_probe(device_t dev)
906 {
907 	int i;
908 
909 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
910 		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
911 		    siba_get_device(dev) == bwn_devs[i].sd_device &&
912 		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
913 			return (BUS_PROBE_DEFAULT);
914 	}
915 
916 	return (ENXIO);
917 }
918 
919 static int
920 bwn_attach(device_t dev)
921 {
922 	struct bwn_mac *mac;
923 	struct bwn_softc *sc = device_get_softc(dev);
924 	int error, i, msic, reg;
925 
926 	sc->sc_dev = dev;
927 #ifdef BWN_DEBUG
928 	sc->sc_debug = bwn_debug;
929 #endif
930 
931 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
932 		error = bwn_attach_pre(sc);
933 		if (error != 0)
934 			return (error);
935 		bwn_sprom_bugfixes(dev);
936 		sc->sc_flags |= BWN_FLAG_ATTACHED;
937 	}
938 
939 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
940 		if (siba_get_pci_device(dev) != 0x4313 &&
941 		    siba_get_pci_device(dev) != 0x431a &&
942 		    siba_get_pci_device(dev) != 0x4321) {
943 			device_printf(sc->sc_dev,
944 			    "skip 802.11 cores\n");
945 			return (ENODEV);
946 		}
947 	}
948 
949 	mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
950 	    M_NOWAIT | M_ZERO);
951 	if (mac == NULL)
952 		return (ENOMEM);
953 	mac->mac_sc = sc;
954 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
955 	if (bwn_bfp != 0)
956 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
957 
958 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
959 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
960 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
961 
962 	error = bwn_attach_core(mac);
963 	if (error)
964 		goto fail0;
965 	bwn_led_attach(mac);
966 
967 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
968 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
969 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
970 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
971 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
972 	    mac->mac_phy.rf_rev);
973 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
974 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
975 		    mac->mac_method.dma.dmatype);
976 	else
977 		device_printf(sc->sc_dev, "PIO\n");
978 
979 	/*
980 	 * setup PCI resources and interrupt.
981 	 */
982 	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
983 		msic = pci_msi_count(dev);
984 		if (bootverbose)
985 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
986 	} else
987 		msic = 0;
988 
989 	mac->mac_intr_spec = bwn_res_spec_legacy;
990 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
991 		if (pci_alloc_msi(dev, &msic) == 0) {
992 			device_printf(sc->sc_dev,
993 			    "Using %d MSI messages\n", msic);
994 			mac->mac_intr_spec = bwn_res_spec_msi;
995 			mac->mac_msi = 1;
996 		}
997 	}
998 
999 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
1000 	    mac->mac_res_irq);
1001 	if (error) {
1002 		device_printf(sc->sc_dev,
1003 		    "couldn't allocate IRQ resources (%d)\n", error);
1004 		goto fail1;
1005 	}
1006 
1007 	if (mac->mac_msi == 0)
1008 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1009 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1010 		    &mac->mac_intrhand[0]);
1011 	else {
1012 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1013 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1014 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1015 			    &mac->mac_intrhand[i]);
1016 			if (error != 0) {
1017 				device_printf(sc->sc_dev,
1018 				    "couldn't setup interrupt (%d)\n", error);
1019 				break;
1020 			}
1021 		}
1022 	}
1023 
1024 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1025 
1026 	/*
1027 	 * calls attach-post routine
1028 	 */
1029 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1030 		bwn_attach_post(sc);
1031 
1032 	return (0);
1033 fail1:
1034 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1035 		pci_release_msi(dev);
1036 fail0:
1037 	free(mac, M_DEVBUF);
1038 	return (error);
1039 }
1040 
1041 static int
1042 bwn_is_valid_ether_addr(uint8_t *addr)
1043 {
1044 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1045 
1046 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1047 		return (FALSE);
1048 
1049 	return (TRUE);
1050 }
1051 
1052 static int
1053 bwn_attach_post(struct bwn_softc *sc)
1054 {
1055 	struct ieee80211com *ic;
1056 	struct ifnet *ifp = sc->sc_ifp;
1057 
1058 	ic = ifp->if_l2com;
1059 	ic->ic_ifp = ifp;
1060 	/* XXX not right but it's not used anywhere important */
1061 	ic->ic_phytype = IEEE80211_T_OFDM;
1062 	ic->ic_opmode = IEEE80211_M_STA;
1063 	ic->ic_caps =
1064 		  IEEE80211_C_STA		/* station mode supported */
1065 		| IEEE80211_C_MONITOR		/* monitor mode */
1066 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1067 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1068 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1069 		| IEEE80211_C_WME		/* WME/WMM supported */
1070 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1071 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1072 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1073 		;
1074 
1075 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1076 
1077 	/* call MI attach routine. */
1078 	ieee80211_ifattach(ic,
1079 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1080 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1081 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1082 
1083 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1084 
1085 	/* override default methods */
1086 	ic->ic_raw_xmit = bwn_raw_xmit;
1087 	ic->ic_updateslot = bwn_updateslot;
1088 	ic->ic_update_promisc = bwn_update_promisc;
1089 	ic->ic_wme.wme_update = bwn_wme_update;
1090 
1091 	ic->ic_scan_start = bwn_scan_start;
1092 	ic->ic_scan_end = bwn_scan_end;
1093 	ic->ic_set_channel = bwn_set_channel;
1094 
1095 	ic->ic_vap_create = bwn_vap_create;
1096 	ic->ic_vap_delete = bwn_vap_delete;
1097 
1098 	ieee80211_radiotap_attach(ic,
1099 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1100 	    BWN_TX_RADIOTAP_PRESENT,
1101 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1102 	    BWN_RX_RADIOTAP_PRESENT);
1103 
1104 	bwn_sysctl_node(sc);
1105 
1106 	if (bootverbose)
1107 		ieee80211_announce(ic);
1108 	return (0);
1109 }
1110 
1111 static void
1112 bwn_phy_detach(struct bwn_mac *mac)
1113 {
1114 
1115 	if (mac->mac_phy.detach != NULL)
1116 		mac->mac_phy.detach(mac);
1117 }
1118 
1119 static int
1120 bwn_detach(device_t dev)
1121 {
1122 	struct bwn_softc *sc = device_get_softc(dev);
1123 	struct bwn_mac *mac = sc->sc_curmac;
1124 	struct ifnet *ifp = sc->sc_ifp;
1125 	struct ieee80211com *ic = ifp->if_l2com;
1126 	int i;
1127 
1128 	sc->sc_flags |= BWN_FLAG_INVALID;
1129 
1130 	if (device_is_attached(sc->sc_dev)) {
1131 		bwn_stop(sc, 1);
1132 		bwn_dma_free(mac);
1133 		callout_drain(&sc->sc_led_blink_ch);
1134 		callout_drain(&sc->sc_rfswitch_ch);
1135 		callout_drain(&sc->sc_task_ch);
1136 		callout_drain(&sc->sc_watchdog_ch);
1137 		bwn_phy_detach(mac);
1138 		if (ifp != NULL) {
1139 			ieee80211_draintask(ic, &mac->mac_hwreset);
1140 			ieee80211_draintask(ic, &mac->mac_txpower);
1141 			ieee80211_ifdetach(ic);
1142 			if_free(ifp);
1143 		}
1144 	}
1145 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1146 	taskqueue_free(sc->sc_tq);
1147 
1148 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1149 		if (mac->mac_intrhand[i] != NULL) {
1150 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1151 			    mac->mac_intrhand[i]);
1152 			mac->mac_intrhand[i] = NULL;
1153 		}
1154 	}
1155 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1156 	if (mac->mac_msi != 0)
1157 		pci_release_msi(dev);
1158 
1159 	BWN_LOCK_DESTROY(sc);
1160 	return (0);
1161 }
1162 
1163 static int
1164 bwn_attach_pre(struct bwn_softc *sc)
1165 {
1166 	struct ifnet *ifp;
1167 	int error = 0;
1168 
1169 	BWN_LOCK_INIT(sc);
1170 	TAILQ_INIT(&sc->sc_maclist);
1171 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1172 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1173 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1174 
1175 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1176 		taskqueue_thread_enqueue, &sc->sc_tq);
1177 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1178 		"%s taskq", device_get_nameunit(sc->sc_dev));
1179 
1180 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
1181 	if (ifp == NULL) {
1182 		device_printf(sc->sc_dev, "can not if_alloc()\n");
1183 		error = ENOSPC;
1184 		goto fail;
1185 	}
1186 
1187 	/* set these up early for if_printf use */
1188 	if_initname(ifp, device_get_name(sc->sc_dev),
1189 	    device_get_unit(sc->sc_dev));
1190 
1191 	ifp->if_softc = sc;
1192 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1193 	ifp->if_init = bwn_init;
1194 	ifp->if_ioctl = bwn_ioctl;
1195 	ifp->if_start = bwn_start;
1196 	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1197 	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1198 	IFQ_SET_READY(&ifp->if_snd);
1199 
1200 	return (0);
1201 
1202 fail:	BWN_LOCK_DESTROY(sc);
1203 	return (error);
1204 }
1205 
1206 static void
1207 bwn_sprom_bugfixes(device_t dev)
1208 {
1209 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1210 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1211 	 (siba_get_pci_device(dev) == _device) &&			\
1212 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1213 	 (siba_get_pci_subdevice(dev) == _subdevice))
1214 
1215 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1216 	    siba_get_pci_subdevice(dev) == 0x4e &&
1217 	    siba_get_pci_revid(dev) > 0x40)
1218 		siba_sprom_set_bf_lo(dev,
1219 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1220 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1221 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1222 		siba_sprom_set_bf_lo(dev,
1223 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1224 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1225 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1226 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1227 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1228 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1229 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1230 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1231 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1232 			siba_sprom_set_bf_lo(dev,
1233 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1234 	}
1235 #undef	BWN_ISDEV
1236 }
1237 
1238 static int
1239 bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1240 {
1241 #define	IS_RUNNING(ifp) \
1242 	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
1243 	struct bwn_softc *sc = ifp->if_softc;
1244 	struct ieee80211com *ic = ifp->if_l2com;
1245 	struct ifreq *ifr = (struct ifreq *)data;
1246 	int error = 0, startall;
1247 
1248 	switch (cmd) {
1249 	case SIOCSIFFLAGS:
1250 		startall = 0;
1251 		if (IS_RUNNING(ifp)) {
1252 			bwn_update_promisc(ifp);
1253 		} else if (ifp->if_flags & IFF_UP) {
1254 			if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
1255 				bwn_init(sc);
1256 				startall = 1;
1257 			}
1258 		} else
1259 			bwn_stop(sc, 1);
1260 		if (startall)
1261 			ieee80211_start_all(ic);
1262 		break;
1263 	case SIOCGIFMEDIA:
1264 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
1265 		break;
1266 	case SIOCGIFADDR:
1267 		error = ether_ioctl(ifp, cmd, data);
1268 		break;
1269 	default:
1270 		error = EINVAL;
1271 		break;
1272 	}
1273 	return (error);
1274 }
1275 
1276 static void
1277 bwn_start(struct ifnet *ifp)
1278 {
1279 	struct bwn_softc *sc = ifp->if_softc;
1280 
1281 	BWN_LOCK(sc);
1282 	bwn_start_locked(ifp);
1283 	BWN_UNLOCK(sc);
1284 }
1285 
1286 static void
1287 bwn_start_locked(struct ifnet *ifp)
1288 {
1289 	struct bwn_softc *sc = ifp->if_softc;
1290 	struct bwn_mac *mac = sc->sc_curmac;
1291 	struct ieee80211_frame *wh;
1292 	struct ieee80211_node *ni;
1293 	struct ieee80211_key *k;
1294 	struct mbuf *m;
1295 
1296 	BWN_ASSERT_LOCKED(sc);
1297 
1298 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
1299 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1300 		return;
1301 
1302 	for (;;) {
1303 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);	/* XXX: LOCK */
1304 		if (m == NULL)
1305 			break;
1306 
1307 		if (bwn_tx_isfull(sc, m))
1308 			break;
1309 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1310 		if (ni == NULL) {
1311 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1312 			m_freem(m);
1313 			ifp->if_oerrors++;
1314 			continue;
1315 		}
1316 		KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
1317 		wh = mtod(m, struct ieee80211_frame *);
1318 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1319 			k = ieee80211_crypto_encap(ni, m);
1320 			if (k == NULL) {
1321 				ieee80211_free_node(ni);
1322 				m_freem(m);
1323 				ifp->if_oerrors++;
1324 				continue;
1325 			}
1326 		}
1327 		wh = NULL;	/* Catch any invalid use */
1328 
1329 		if (bwn_tx_start(sc, ni, m) != 0) {
1330 			if (ni != NULL)
1331 				ieee80211_free_node(ni);
1332 			ifp->if_oerrors++;
1333 			continue;
1334 		}
1335 
1336 		sc->sc_watchdog_timer = 5;
1337 	}
1338 }
1339 
1340 static int
1341 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1342 {
1343 	struct bwn_dma_ring *dr;
1344 	struct bwn_mac *mac = sc->sc_curmac;
1345 	struct bwn_pio_txqueue *tq;
1346 	struct ifnet *ifp = sc->sc_ifp;
1347 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1348 
1349 	BWN_ASSERT_LOCKED(sc);
1350 
1351 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1352 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1353 		if (dr->dr_stop == 1 ||
1354 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1355 			dr->dr_stop = 1;
1356 			goto full;
1357 		}
1358 	} else {
1359 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1360 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1361 		    pktlen > (tq->tq_size - tq->tq_used)) {
1362 			tq->tq_stop = 1;
1363 			goto full;
1364 		}
1365 	}
1366 	return (0);
1367 full:
1368 	IFQ_DRV_PREPEND(&ifp->if_snd, m);
1369 	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1370 	return (1);
1371 }
1372 
1373 static int
1374 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1375 {
1376 	struct bwn_mac *mac = sc->sc_curmac;
1377 	int error;
1378 
1379 	BWN_ASSERT_LOCKED(sc);
1380 
1381 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1382 		m_freem(m);
1383 		return (ENXIO);
1384 	}
1385 
1386 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1387 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1388 	if (error) {
1389 		m_freem(m);
1390 		return (error);
1391 	}
1392 	return (0);
1393 }
1394 
1395 static int
1396 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1397 {
1398 	struct bwn_pio_txpkt *tp;
1399 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1400 	struct bwn_softc *sc = mac->mac_sc;
1401 	struct bwn_txhdr txhdr;
1402 	struct mbuf *m_new;
1403 	uint32_t ctl32;
1404 	int error;
1405 	uint16_t ctl16;
1406 
1407 	BWN_ASSERT_LOCKED(sc);
1408 
1409 	/* XXX TODO send packets after DTIM */
1410 
1411 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1412 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1413 	tp->tp_ni = ni;
1414 	tp->tp_m = m;
1415 
1416 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1417 	if (error) {
1418 		device_printf(sc->sc_dev, "tx fail\n");
1419 		return (error);
1420 	}
1421 
1422 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1423 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1424 	tq->tq_free--;
1425 
1426 	if (siba_get_revid(sc->sc_dev) >= 8) {
1427 		/*
1428 		 * XXX please removes m_defrag(9)
1429 		 */
1430 		m_new = m_defrag(m, M_DONTWAIT);
1431 		if (m_new == NULL) {
1432 			device_printf(sc->sc_dev,
1433 			    "%s: can't defrag TX buffer\n",
1434 			    __func__);
1435 			return (ENOBUFS);
1436 		}
1437 		if (m_new->m_next != NULL)
1438 			device_printf(sc->sc_dev,
1439 			    "TODO: fragmented packets for PIO\n");
1440 		tp->tp_m = m_new;
1441 
1442 		/* send HEADER */
1443 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1444 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1445 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1446 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1447 		/* send BODY */
1448 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1449 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1450 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1451 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1452 	} else {
1453 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1454 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1455 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1456 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1457 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1458 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1459 		    ctl16 | BWN_PIO_TXCTL_EOF);
1460 	}
1461 
1462 	return (0);
1463 }
1464 
1465 static struct bwn_pio_txqueue *
1466 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1467 {
1468 
1469 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1470 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1471 
1472 	switch (prio) {
1473 	case 0:
1474 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1475 	case 1:
1476 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1477 	case 2:
1478 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1479 	case 3:
1480 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1481 	}
1482 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1483 	return (NULL);
1484 }
1485 
1486 static int
1487 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1488 {
1489 #define	BWN_GET_TXHDRCACHE(slot)					\
1490 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1491 	struct bwn_dma *dma = &mac->mac_method.dma;
1492 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1493 	struct bwn_dmadesc_generic *desc;
1494 	struct bwn_dmadesc_meta *mt;
1495 	struct bwn_softc *sc = mac->mac_sc;
1496 	struct ifnet *ifp = sc->sc_ifp;
1497 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1498 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1499 
1500 	BWN_ASSERT_LOCKED(sc);
1501 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1502 
1503 	/* XXX send after DTIM */
1504 
1505 	slot = bwn_dma_getslot(dr);
1506 	dr->getdesc(dr, slot, &desc, &mt);
1507 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1508 	    ("%s:%d: fail", __func__, __LINE__));
1509 
1510 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1511 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1512 	    BWN_DMA_COOKIE(dr, slot));
1513 	if (error)
1514 		goto fail;
1515 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1516 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1517 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1518 	if (error) {
1519 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1520 		    __func__, error);
1521 		goto fail;
1522 	}
1523 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1524 	    BUS_DMASYNC_PREWRITE);
1525 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1526 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1527 	    BUS_DMASYNC_PREWRITE);
1528 
1529 	slot = bwn_dma_getslot(dr);
1530 	dr->getdesc(dr, slot, &desc, &mt);
1531 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1532 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1533 	mt->mt_m = m;
1534 	mt->mt_ni = ni;
1535 
1536 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1537 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1538 	if (error && error != EFBIG) {
1539 		if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
1540 		    __func__, error);
1541 		goto fail;
1542 	}
1543 	if (error) {    /* error == EFBIG */
1544 		struct mbuf *m_new;
1545 
1546 		m_new = m_defrag(m, M_DONTWAIT);
1547 		if (m_new == NULL) {
1548 			if_printf(ifp, "%s: can't defrag TX buffer\n",
1549 			    __func__);
1550 			error = ENOBUFS;
1551 			goto fail;
1552 		} else {
1553 			m = m_new;
1554 		}
1555 
1556 		mt->mt_m = m;
1557 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1558 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1559 		if (error) {
1560 			if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
1561 			    __func__, error);
1562 			goto fail;
1563 		}
1564 	}
1565 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1566 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1567 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1568 	    BUS_DMASYNC_PREWRITE);
1569 
1570 	/* XXX send after DTIM */
1571 
1572 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1573 	return (0);
1574 fail:
1575 	dr->dr_curslot = backup[0];
1576 	dr->dr_usedslot = backup[1];
1577 	return (error);
1578 #undef BWN_GET_TXHDRCACHE
1579 }
1580 
1581 static void
1582 bwn_watchdog(void *arg)
1583 {
1584 	struct bwn_softc *sc = arg;
1585 	struct ifnet *ifp = sc->sc_ifp;
1586 
1587 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1588 		if_printf(ifp, "device timeout\n");
1589 		ifp->if_oerrors++;
1590 	}
1591 	callout_schedule(&sc->sc_watchdog_ch, hz);
1592 }
1593 
1594 static int
1595 bwn_attach_core(struct bwn_mac *mac)
1596 {
1597 	struct bwn_softc *sc = mac->mac_sc;
1598 	int error, have_bg = 0, have_a = 0;
1599 	uint32_t high;
1600 
1601 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1602 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1603 
1604 	siba_powerup(sc->sc_dev, 0);
1605 
1606 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1607 	bwn_reset_core(mac,
1608 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1609 	error = bwn_phy_getinfo(mac, high);
1610 	if (error)
1611 		goto fail;
1612 
1613 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1614 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1615 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1616 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1617 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1618 		have_a = have_bg = 0;
1619 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1620 			have_a = 1;
1621 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1622 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1623 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1624 			have_bg = 1;
1625 		else
1626 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1627 			    mac->mac_phy.type));
1628 	}
1629 	/* XXX turns off PHY A because it's not supported */
1630 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1631 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1632 		have_a = 0;
1633 		have_bg = 1;
1634 	}
1635 
1636 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1637 		mac->mac_phy.attach = bwn_phy_g_attach;
1638 		mac->mac_phy.detach = bwn_phy_g_detach;
1639 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1640 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1641 		mac->mac_phy.init = bwn_phy_g_init;
1642 		mac->mac_phy.exit = bwn_phy_g_exit;
1643 		mac->mac_phy.phy_read = bwn_phy_g_read;
1644 		mac->mac_phy.phy_write = bwn_phy_g_write;
1645 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1646 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1647 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1648 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1649 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1650 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1651 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1652 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1653 		mac->mac_phy.set_im = bwn_phy_g_im;
1654 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1655 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1656 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1657 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1658 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1659 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1660 		mac->mac_phy.init = bwn_phy_lp_init;
1661 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1662 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1663 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1664 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1665 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1666 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1667 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1668 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1669 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1670 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1671 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1672 	} else {
1673 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1674 		    mac->mac_phy.type);
1675 		error = ENXIO;
1676 		goto fail;
1677 	}
1678 
1679 	mac->mac_phy.gmode = have_bg;
1680 	if (mac->mac_phy.attach != NULL) {
1681 		error = mac->mac_phy.attach(mac);
1682 		if (error) {
1683 			device_printf(sc->sc_dev, "failed\n");
1684 			goto fail;
1685 		}
1686 	}
1687 
1688 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1689 
1690 	error = bwn_chiptest(mac);
1691 	if (error)
1692 		goto fail;
1693 	error = bwn_setup_channels(mac, have_bg, have_a);
1694 	if (error) {
1695 		device_printf(sc->sc_dev, "failed to setup channels\n");
1696 		goto fail;
1697 	}
1698 
1699 	if (sc->sc_curmac == NULL)
1700 		sc->sc_curmac = mac;
1701 
1702 	error = bwn_dma_attach(mac);
1703 	if (error != 0) {
1704 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1705 		goto fail;
1706 	}
1707 
1708 	mac->mac_phy.switch_analog(mac, 0);
1709 
1710 	siba_dev_down(sc->sc_dev, 0);
1711 fail:
1712 	siba_powerdown(sc->sc_dev);
1713 	return (error);
1714 }
1715 
1716 static void
1717 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1718 {
1719 	struct bwn_softc *sc = mac->mac_sc;
1720 	uint32_t low, ctl;
1721 
1722 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1723 
1724 	siba_dev_up(sc->sc_dev, flags);
1725 	DELAY(2000);
1726 
1727 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1728 	    ~BWN_TGSLOW_PHYRESET;
1729 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1730 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1731 	DELAY(1000);
1732 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1733 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1734 	DELAY(1000);
1735 
1736 	if (mac->mac_phy.switch_analog != NULL)
1737 		mac->mac_phy.switch_analog(mac, 1);
1738 
1739 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1740 	if (flags & BWN_TGSLOW_SUPPORT_G)
1741 		ctl |= BWN_MACCTL_GMODE;
1742 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1743 }
1744 
1745 static int
1746 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1747 {
1748 	struct bwn_phy *phy = &mac->mac_phy;
1749 	struct bwn_softc *sc = mac->mac_sc;
1750 	uint32_t tmp;
1751 
1752 	/* PHY */
1753 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1754 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1755 	phy->rf_on = 1;
1756 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1757 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1758 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1759 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1760 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1761 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1762 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1763 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1764 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1765 		goto unsupphy;
1766 
1767 	/* RADIO */
1768 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1769 		if (siba_get_chiprev(sc->sc_dev) == 0)
1770 			tmp = 0x3205017f;
1771 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1772 			tmp = 0x4205017f;
1773 		else
1774 			tmp = 0x5205017f;
1775 	} else {
1776 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1777 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1778 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1779 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1780 	}
1781 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1782 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1783 	phy->rf_manuf = (tmp & 0x00000fff);
1784 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1785 		goto unsupradio;
1786 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1787 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1788 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1789 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1790 	    (phy->type == BWN_PHYTYPE_N &&
1791 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1792 	    (phy->type == BWN_PHYTYPE_LP &&
1793 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1794 		goto unsupradio;
1795 
1796 	return (0);
1797 unsupphy:
1798 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1799 	    "analog %#x)\n",
1800 	    phy->type, phy->rev, phy->analog);
1801 	return (ENXIO);
1802 unsupradio:
1803 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1804 	    "rev %#x)\n",
1805 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1806 	return (ENXIO);
1807 }
1808 
1809 static int
1810 bwn_chiptest(struct bwn_mac *mac)
1811 {
1812 #define	TESTVAL0	0x55aaaa55
1813 #define	TESTVAL1	0xaa5555aa
1814 	struct bwn_softc *sc = mac->mac_sc;
1815 	uint32_t v, backup;
1816 
1817 	BWN_LOCK(sc);
1818 
1819 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1820 
1821 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1822 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1823 		goto error;
1824 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1825 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1826 		goto error;
1827 
1828 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1829 
1830 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1831 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1832 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1833 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1834 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1835 			goto error;
1836 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1837 			goto error;
1838 	}
1839 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1840 
1841 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1842 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1843 		goto error;
1844 
1845 	BWN_UNLOCK(sc);
1846 	return (0);
1847 error:
1848 	BWN_UNLOCK(sc);
1849 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1850 	return (ENODEV);
1851 }
1852 
1853 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1854 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1855 
1856 static int
1857 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1858 {
1859 	struct bwn_softc *sc = mac->mac_sc;
1860 	struct ifnet *ifp = sc->sc_ifp;
1861 	struct ieee80211com *ic = ifp->if_l2com;
1862 
1863 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1864 	ic->ic_nchans = 0;
1865 
1866 	if (have_bg)
1867 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1868 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1869 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1870 		if (have_a)
1871 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1872 			    &ic->ic_nchans, &bwn_chantable_n,
1873 			    IEEE80211_CHAN_HTA);
1874 	} else {
1875 		if (have_a)
1876 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1877 			    &ic->ic_nchans, &bwn_chantable_a,
1878 			    IEEE80211_CHAN_A);
1879 	}
1880 
1881 	mac->mac_phy.supports_2ghz = have_bg;
1882 	mac->mac_phy.supports_5ghz = have_a;
1883 
1884 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1885 }
1886 
1887 static uint32_t
1888 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1889 {
1890 	uint32_t ret;
1891 
1892 	BWN_ASSERT_LOCKED(mac->mac_sc);
1893 
1894 	if (way == BWN_SHARED) {
1895 		KASSERT((offset & 0x0001) == 0,
1896 		    ("%s:%d warn", __func__, __LINE__));
1897 		if (offset & 0x0003) {
1898 			bwn_shm_ctlword(mac, way, offset >> 2);
1899 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1900 			ret <<= 16;
1901 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1902 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1903 			goto out;
1904 		}
1905 		offset >>= 2;
1906 	}
1907 	bwn_shm_ctlword(mac, way, offset);
1908 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1909 out:
1910 	return (ret);
1911 }
1912 
1913 static uint16_t
1914 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1915 {
1916 	uint16_t ret;
1917 
1918 	BWN_ASSERT_LOCKED(mac->mac_sc);
1919 
1920 	if (way == BWN_SHARED) {
1921 		KASSERT((offset & 0x0001) == 0,
1922 		    ("%s:%d warn", __func__, __LINE__));
1923 		if (offset & 0x0003) {
1924 			bwn_shm_ctlword(mac, way, offset >> 2);
1925 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1926 			goto out;
1927 		}
1928 		offset >>= 2;
1929 	}
1930 	bwn_shm_ctlword(mac, way, offset);
1931 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1932 out:
1933 
1934 	return (ret);
1935 }
1936 
1937 static void
1938 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1939     uint16_t offset)
1940 {
1941 	uint32_t control;
1942 
1943 	control = way;
1944 	control <<= 16;
1945 	control |= offset;
1946 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1947 }
1948 
1949 static void
1950 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1951     uint32_t value)
1952 {
1953 	BWN_ASSERT_LOCKED(mac->mac_sc);
1954 
1955 	if (way == BWN_SHARED) {
1956 		KASSERT((offset & 0x0001) == 0,
1957 		    ("%s:%d warn", __func__, __LINE__));
1958 		if (offset & 0x0003) {
1959 			bwn_shm_ctlword(mac, way, offset >> 2);
1960 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1961 				    (value >> 16) & 0xffff);
1962 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1963 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1964 			return;
1965 		}
1966 		offset >>= 2;
1967 	}
1968 	bwn_shm_ctlword(mac, way, offset);
1969 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1970 }
1971 
1972 static void
1973 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1974     uint16_t value)
1975 {
1976 	BWN_ASSERT_LOCKED(mac->mac_sc);
1977 
1978 	if (way == BWN_SHARED) {
1979 		KASSERT((offset & 0x0001) == 0,
1980 		    ("%s:%d warn", __func__, __LINE__));
1981 		if (offset & 0x0003) {
1982 			bwn_shm_ctlword(mac, way, offset >> 2);
1983 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1984 			return;
1985 		}
1986 		offset >>= 2;
1987 	}
1988 	bwn_shm_ctlword(mac, way, offset);
1989 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1990 }
1991 
1992 static void
1993 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1994     int txpow)
1995 {
1996 
1997 	c->ic_freq = freq;
1998 	c->ic_flags = flags;
1999 	c->ic_ieee = ieee;
2000 	c->ic_minpower = 0;
2001 	c->ic_maxpower = 2 * txpow;
2002 	c->ic_maxregpower = txpow;
2003 }
2004 
2005 static void
2006 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
2007     const struct bwn_channelinfo *ci, int flags)
2008 {
2009 	struct ieee80211_channel *c;
2010 	int i;
2011 
2012 	c = &chans[*nchans];
2013 
2014 	for (i = 0; i < ci->nchannels; i++) {
2015 		const struct bwn_channel *hc;
2016 
2017 		hc = &ci->channels[i];
2018 		if (*nchans >= maxchans)
2019 			break;
2020 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
2021 		c++, (*nchans)++;
2022 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
2023 			/* g channel have a separate b-only entry */
2024 			if (*nchans >= maxchans)
2025 				break;
2026 			c[0] = c[-1];
2027 			c[-1].ic_flags = IEEE80211_CHAN_B;
2028 			c++, (*nchans)++;
2029 		}
2030 		if (flags == IEEE80211_CHAN_HTG) {
2031 			/* HT g channel have a separate g-only entry */
2032 			if (*nchans >= maxchans)
2033 				break;
2034 			c[-1].ic_flags = IEEE80211_CHAN_G;
2035 			c[0] = c[-1];
2036 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2037 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2038 			c++, (*nchans)++;
2039 		}
2040 		if (flags == IEEE80211_CHAN_HTA) {
2041 			/* HT a channel have a separate a-only entry */
2042 			if (*nchans >= maxchans)
2043 				break;
2044 			c[-1].ic_flags = IEEE80211_CHAN_A;
2045 			c[0] = c[-1];
2046 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
2047 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
2048 			c++, (*nchans)++;
2049 		}
2050 	}
2051 }
2052 
2053 static int
2054 bwn_phy_g_attach(struct bwn_mac *mac)
2055 {
2056 	struct bwn_softc *sc = mac->mac_sc;
2057 	struct bwn_phy *phy = &mac->mac_phy;
2058 	struct bwn_phy_g *pg = &phy->phy_g;
2059 	unsigned int i;
2060 	int16_t pab0, pab1, pab2;
2061 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2062 	int8_t bg;
2063 
2064 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2065 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2066 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2067 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2068 
2069 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2070 		device_printf(sc->sc_dev, "not supported anymore\n");
2071 
2072 	pg->pg_flags = 0;
2073 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2074 	    pab2 == -1) {
2075 		pg->pg_idletssi = 52;
2076 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2077 		return (0);
2078 	}
2079 
2080 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2081 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2082 	if (pg->pg_tssi2dbm == NULL) {
2083 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2084 		return (ENOMEM);
2085 	}
2086 	for (i = 0; i < 64; i++) {
2087 		int32_t m1, m2, f, q, delta;
2088 		int8_t j = 0;
2089 
2090 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2091 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2092 		f = 256;
2093 
2094 		do {
2095 			if (j > 15) {
2096 				device_printf(sc->sc_dev,
2097 				    "failed to generate tssi2dBm\n");
2098 				free(pg->pg_tssi2dbm, M_DEVBUF);
2099 				return (ENOMEM);
2100 			}
2101 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2102 			    f, 2048);
2103 			delta = abs(q - f);
2104 			f = q;
2105 			j++;
2106 		} while (delta >= 2);
2107 
2108 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2109 		    128);
2110 	}
2111 
2112 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2113 	return (0);
2114 }
2115 
2116 static void
2117 bwn_phy_g_detach(struct bwn_mac *mac)
2118 {
2119 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2120 
2121 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2122 		free(pg->pg_tssi2dbm, M_DEVBUF);
2123 		pg->pg_tssi2dbm = NULL;
2124 	}
2125 	pg->pg_flags = 0;
2126 }
2127 
2128 static void
2129 bwn_phy_g_init_pre(struct bwn_mac *mac)
2130 {
2131 	struct bwn_phy *phy = &mac->mac_phy;
2132 	struct bwn_phy_g *pg = &phy->phy_g;
2133 	void *tssi2dbm;
2134 	int idletssi;
2135 	unsigned int i;
2136 
2137 	tssi2dbm = pg->pg_tssi2dbm;
2138 	idletssi = pg->pg_idletssi;
2139 
2140 	memset(pg, 0, sizeof(*pg));
2141 
2142 	pg->pg_tssi2dbm = tssi2dbm;
2143 	pg->pg_idletssi = idletssi;
2144 
2145 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2146 
2147 	for (i = 0; i < N(pg->pg_nrssi); i++)
2148 		pg->pg_nrssi[i] = -1000;
2149 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2150 		pg->pg_nrssi_lt[i] = i;
2151 	pg->pg_lofcal = 0xffff;
2152 	pg->pg_initval = 0xffff;
2153 	pg->pg_immode = BWN_IMMODE_NONE;
2154 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2155 	pg->pg_avgtssi = 0xff;
2156 
2157 	pg->pg_loctl.tx_bias = 0xff;
2158 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2159 }
2160 
2161 static int
2162 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2163 {
2164 	struct bwn_phy *phy = &mac->mac_phy;
2165 	struct bwn_phy_g *pg = &phy->phy_g;
2166 	struct bwn_softc *sc = mac->mac_sc;
2167 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2168 	static const struct bwn_rfatt rfatt0[] = {
2169 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2170 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2171 		{ 3, 1 }, { 4, 1 }
2172 	};
2173 	static const struct bwn_rfatt rfatt1[] = {
2174 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2175 		{ 14, 1 }
2176 	};
2177 	static const struct bwn_rfatt rfatt2[] = {
2178 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2179 		{ 9, 1 }
2180 	};
2181 	static const struct bwn_bbatt bbatt_0[] = {
2182 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2183 	};
2184 
2185 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2186 
2187 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2188 		pg->pg_bbatt.att = 0;
2189 	else
2190 		pg->pg_bbatt.att = 2;
2191 
2192 	/* prepare Radio Attenuation */
2193 	pg->pg_rfatt.padmix = 0;
2194 
2195 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2196 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2197 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2198 			pg->pg_rfatt.att = 2;
2199 			goto done;
2200 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2201 			pg->pg_rfatt.att = 3;
2202 			goto done;
2203 		}
2204 	}
2205 
2206 	if (phy->type == BWN_PHYTYPE_A) {
2207 		pg->pg_rfatt.att = 0x60;
2208 		goto done;
2209 	}
2210 
2211 	switch (phy->rf_ver) {
2212 	case 0x2050:
2213 		switch (phy->rf_rev) {
2214 		case 0:
2215 			pg->pg_rfatt.att = 5;
2216 			goto done;
2217 		case 1:
2218 			if (phy->type == BWN_PHYTYPE_G) {
2219 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2220 				    SIBA_BOARDVENDOR_BCM &&
2221 				    siba_get_pci_subdevice(sc->sc_dev) ==
2222 				    SIBA_BOARD_BCM4309G &&
2223 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2224 					pg->pg_rfatt.att = 3;
2225 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2226 				    SIBA_BOARDVENDOR_BCM &&
2227 				    siba_get_pci_subdevice(sc->sc_dev) ==
2228 				    SIBA_BOARD_BU4306)
2229 					pg->pg_rfatt.att = 3;
2230 				else
2231 					pg->pg_rfatt.att = 1;
2232 			} else {
2233 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2234 				    SIBA_BOARDVENDOR_BCM &&
2235 				    siba_get_pci_subdevice(sc->sc_dev) ==
2236 				    SIBA_BOARD_BCM4309G &&
2237 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2238 					pg->pg_rfatt.att = 7;
2239 				else
2240 					pg->pg_rfatt.att = 6;
2241 			}
2242 			goto done;
2243 		case 2:
2244 			if (phy->type == BWN_PHYTYPE_G) {
2245 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2246 				    SIBA_BOARDVENDOR_BCM &&
2247 				    siba_get_pci_subdevice(sc->sc_dev) ==
2248 				    SIBA_BOARD_BCM4309G &&
2249 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2250 					pg->pg_rfatt.att = 3;
2251 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2252 				    SIBA_BOARDVENDOR_BCM &&
2253 				    siba_get_pci_subdevice(sc->sc_dev) ==
2254 				    SIBA_BOARD_BU4306)
2255 					pg->pg_rfatt.att = 5;
2256 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2257 					pg->pg_rfatt.att = 4;
2258 				else
2259 					pg->pg_rfatt.att = 3;
2260 			} else
2261 				pg->pg_rfatt.att = 6;
2262 			goto done;
2263 		case 3:
2264 			pg->pg_rfatt.att = 5;
2265 			goto done;
2266 		case 4:
2267 		case 5:
2268 			pg->pg_rfatt.att = 1;
2269 			goto done;
2270 		case 6:
2271 		case 7:
2272 			pg->pg_rfatt.att = 5;
2273 			goto done;
2274 		case 8:
2275 			pg->pg_rfatt.att = 0xa;
2276 			pg->pg_rfatt.padmix = 1;
2277 			goto done;
2278 		case 9:
2279 		default:
2280 			pg->pg_rfatt.att = 5;
2281 			goto done;
2282 		}
2283 		break;
2284 	case 0x2053:
2285 		switch (phy->rf_rev) {
2286 		case 1:
2287 			pg->pg_rfatt.att = 6;
2288 			goto done;
2289 		}
2290 		break;
2291 	}
2292 	pg->pg_rfatt.att = 5;
2293 done:
2294 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2295 
2296 	if (!bwn_has_hwpctl(mac)) {
2297 		lo->rfatt.array = rfatt0;
2298 		lo->rfatt.len = N(rfatt0);
2299 		lo->rfatt.min = 0;
2300 		lo->rfatt.max = 9;
2301 		goto genbbatt;
2302 	}
2303 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2304 		lo->rfatt.array = rfatt1;
2305 		lo->rfatt.len = N(rfatt1);
2306 		lo->rfatt.min = 0;
2307 		lo->rfatt.max = 14;
2308 		goto genbbatt;
2309 	}
2310 	lo->rfatt.array = rfatt2;
2311 	lo->rfatt.len = N(rfatt2);
2312 	lo->rfatt.min = 0;
2313 	lo->rfatt.max = 9;
2314 genbbatt:
2315 	lo->bbatt.array = bbatt_0;
2316 	lo->bbatt.len = N(bbatt_0);
2317 	lo->bbatt.min = 0;
2318 	lo->bbatt.max = 8;
2319 
2320 	BWN_READ_4(mac, BWN_MACCTL);
2321 	if (phy->rev == 1) {
2322 		phy->gmode = 0;
2323 		bwn_reset_core(mac, 0);
2324 		bwn_phy_g_init_sub(mac);
2325 		phy->gmode = 1;
2326 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2327 	}
2328 	return (0);
2329 }
2330 
2331 static uint16_t
2332 bwn_phy_g_txctl(struct bwn_mac *mac)
2333 {
2334 	struct bwn_phy *phy = &mac->mac_phy;
2335 
2336 	if (phy->rf_ver != 0x2050)
2337 		return (0);
2338 	if (phy->rf_rev == 1)
2339 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2340 	if (phy->rf_rev < 6)
2341 		return (BWN_TXCTL_PA2DB);
2342 	if (phy->rf_rev == 8)
2343 		return (BWN_TXCTL_TXMIX);
2344 	return (0);
2345 }
2346 
2347 static int
2348 bwn_phy_g_init(struct bwn_mac *mac)
2349 {
2350 
2351 	bwn_phy_g_init_sub(mac);
2352 	return (0);
2353 }
2354 
2355 static void
2356 bwn_phy_g_exit(struct bwn_mac *mac)
2357 {
2358 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2359 	struct bwn_lo_calib *cal, *tmp;
2360 
2361 	if (lo == NULL)
2362 		return;
2363 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2364 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2365 		free(cal, M_DEVBUF);
2366 	}
2367 }
2368 
2369 static uint16_t
2370 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2371 {
2372 
2373 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2374 	return (BWN_READ_2(mac, BWN_PHYDATA));
2375 }
2376 
2377 static void
2378 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2379 {
2380 
2381 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2382 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2383 }
2384 
2385 static uint16_t
2386 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2387 {
2388 
2389 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2390 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2391 	return (BWN_READ_2(mac, BWN_RFDATALO));
2392 }
2393 
2394 static void
2395 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2396 {
2397 
2398 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2399 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2400 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2401 }
2402 
2403 static int
2404 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2405 {
2406 
2407 	return (mac->mac_phy.rev >= 6);
2408 }
2409 
2410 static void
2411 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2412 {
2413 	struct bwn_phy *phy = &mac->mac_phy;
2414 	struct bwn_phy_g *pg = &phy->phy_g;
2415 	unsigned int channel;
2416 	uint16_t rfover, rfoverval;
2417 
2418 	if (on) {
2419 		if (phy->rf_on)
2420 			return;
2421 
2422 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2423 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2424 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2425 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2426 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2427 			    pg->pg_radioctx_over);
2428 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2429 			    pg->pg_radioctx_overval);
2430 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2431 		}
2432 		channel = phy->chan;
2433 		bwn_phy_g_switch_chan(mac, 6, 1);
2434 		bwn_phy_g_switch_chan(mac, channel, 0);
2435 		return;
2436 	}
2437 
2438 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2439 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2440 	pg->pg_radioctx_over = rfover;
2441 	pg->pg_radioctx_overval = rfoverval;
2442 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2443 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2444 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2445 }
2446 
2447 static int
2448 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2449 {
2450 
2451 	if ((newchan < 1) || (newchan > 14))
2452 		return (EINVAL);
2453 	bwn_phy_g_switch_chan(mac, newchan, 0);
2454 
2455 	return (0);
2456 }
2457 
2458 static uint32_t
2459 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2460 {
2461 
2462 	return (1);
2463 }
2464 
2465 static void
2466 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2467 {
2468 	struct bwn_phy *phy = &mac->mac_phy;
2469 	uint64_t hf;
2470 	int autodiv = 0;
2471 	uint16_t tmp;
2472 
2473 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2474 		autodiv = 1;
2475 
2476 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2477 	bwn_hf_write(mac, hf);
2478 
2479 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2480 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2481 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2482 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2483 
2484 	if (autodiv) {
2485 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2486 		if (antenna == BWN_ANTAUTO1)
2487 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2488 		else
2489 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2490 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2491 	}
2492 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2493 	if (autodiv)
2494 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2495 	else
2496 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2497 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2498 	if (phy->rev >= 2) {
2499 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2500 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2501 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2502 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2503 		    0x15);
2504 		if (phy->rev == 2)
2505 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2506 		else
2507 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2508 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2509 			    8);
2510 	}
2511 	if (phy->rev >= 6)
2512 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2513 
2514 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2515 	bwn_hf_write(mac, hf);
2516 }
2517 
2518 static int
2519 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2520 {
2521 	struct bwn_phy *phy = &mac->mac_phy;
2522 	struct bwn_phy_g *pg = &phy->phy_g;
2523 
2524 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2525 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2526 
2527 	if (phy->rev == 0 || !phy->gmode)
2528 		return (ENODEV);
2529 
2530 	pg->pg_aci_wlan_automatic = 0;
2531 	return (0);
2532 }
2533 
2534 static int
2535 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2536 {
2537 	struct bwn_phy *phy = &mac->mac_phy;
2538 	struct bwn_phy_g *pg = &phy->phy_g;
2539 	struct bwn_softc *sc = mac->mac_sc;
2540 	unsigned int tssi;
2541 	int cck, ofdm;
2542 	int power;
2543 	int rfatt, bbatt;
2544 	unsigned int max;
2545 
2546 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2547 
2548 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2549 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2550 	if (cck < 0 && ofdm < 0) {
2551 		if (ignore_tssi == 0)
2552 			return (BWN_TXPWR_RES_DONE);
2553 		cck = 0;
2554 		ofdm = 0;
2555 	}
2556 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2557 	if (pg->pg_avgtssi != 0xff)
2558 		tssi = (tssi + pg->pg_avgtssi) / 2;
2559 	pg->pg_avgtssi = tssi;
2560 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2561 
2562 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2563 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2564 		max -= 3;
2565 	if (max >= 120) {
2566 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2567 		max = 80;
2568 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2569 	}
2570 
2571 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2572 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2573 	     tssi, 0x00), 0x3f)]);
2574 	if (power == 0)
2575 		return (BWN_TXPWR_RES_DONE);
2576 
2577 	rfatt = -((power + 7) / 8);
2578 	bbatt = (-(power / 2)) - (4 * rfatt);
2579 	if ((rfatt == 0) && (bbatt == 0))
2580 		return (BWN_TXPWR_RES_DONE);
2581 	pg->pg_bbatt_delta = bbatt;
2582 	pg->pg_rfatt_delta = rfatt;
2583 	return (BWN_TXPWR_RES_NEED_ADJUST);
2584 }
2585 
2586 static void
2587 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2588 {
2589 	struct bwn_phy *phy = &mac->mac_phy;
2590 	struct bwn_phy_g *pg = &phy->phy_g;
2591 	struct bwn_softc *sc = mac->mac_sc;
2592 	int rfatt, bbatt;
2593 	uint8_t txctl;
2594 
2595 	bwn_mac_suspend(mac);
2596 
2597 	BWN_ASSERT_LOCKED(sc);
2598 
2599 	bbatt = pg->pg_bbatt.att;
2600 	bbatt += pg->pg_bbatt_delta;
2601 	rfatt = pg->pg_rfatt.att;
2602 	rfatt += pg->pg_rfatt_delta;
2603 
2604 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2605 	txctl = pg->pg_txctl;
2606 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2607 		if (rfatt <= 1) {
2608 			if (txctl == 0) {
2609 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2610 				rfatt += 2;
2611 				bbatt += 2;
2612 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2613 			    BWN_BFL_PACTRL) {
2614 				bbatt += 4 * (rfatt - 2);
2615 				rfatt = 2;
2616 			}
2617 		} else if (rfatt > 4 && txctl) {
2618 			txctl = 0;
2619 			if (bbatt < 3) {
2620 				rfatt -= 3;
2621 				bbatt += 2;
2622 			} else {
2623 				rfatt -= 2;
2624 				bbatt -= 2;
2625 			}
2626 		}
2627 	}
2628 	pg->pg_txctl = txctl;
2629 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2630 	pg->pg_rfatt.att = rfatt;
2631 	pg->pg_bbatt.att = bbatt;
2632 
2633 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2634 
2635 	bwn_phy_lock(mac);
2636 	bwn_rf_lock(mac);
2637 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2638 	    pg->pg_txctl);
2639 	bwn_rf_unlock(mac);
2640 	bwn_phy_unlock(mac);
2641 
2642 	bwn_mac_enable(mac);
2643 }
2644 
2645 static void
2646 bwn_phy_g_task_15s(struct bwn_mac *mac)
2647 {
2648 	struct bwn_phy *phy = &mac->mac_phy;
2649 	struct bwn_phy_g *pg = &phy->phy_g;
2650 	struct bwn_softc *sc = mac->mac_sc;
2651 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2652 	unsigned long expire, now;
2653 	struct bwn_lo_calib *cal, *tmp;
2654 	uint8_t expired = 0;
2655 
2656 	bwn_mac_suspend(mac);
2657 
2658 	if (lo == NULL)
2659 		goto fail;
2660 
2661 	BWN_GETTIME(now);
2662 	if (bwn_has_hwpctl(mac)) {
2663 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2664 		if (time_before(lo->pwr_vec_read_time, expire)) {
2665 			bwn_lo_get_powervector(mac);
2666 			bwn_phy_g_dc_lookup_init(mac, 0);
2667 		}
2668 		goto fail;
2669 	}
2670 
2671 	expire = now - BWN_LO_CALIB_EXPIRE;
2672 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2673 		if (!time_before(cal->calib_time, expire))
2674 			continue;
2675 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2676 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2677 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2678 			expired = 1;
2679 		}
2680 
2681 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2682 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2683 		    cal->ctl.i, cal->ctl.q);
2684 
2685 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2686 		free(cal, M_DEVBUF);
2687 	}
2688 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2689 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2690 		    &pg->pg_rfatt);
2691 		if (cal == NULL) {
2692 			device_printf(sc->sc_dev,
2693 			    "failed to recalibrate LO\n");
2694 			goto fail;
2695 		}
2696 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2697 		bwn_lo_write(mac, &cal->ctl);
2698 	}
2699 
2700 fail:
2701 	bwn_mac_enable(mac);
2702 }
2703 
2704 static void
2705 bwn_phy_g_task_60s(struct bwn_mac *mac)
2706 {
2707 	struct bwn_phy *phy = &mac->mac_phy;
2708 	struct bwn_softc *sc = mac->mac_sc;
2709 	uint8_t old = phy->chan;
2710 
2711 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2712 		return;
2713 
2714 	bwn_mac_suspend(mac);
2715 	bwn_nrssi_slope_11g(mac);
2716 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2717 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2718 		bwn_switch_channel(mac, old);
2719 	}
2720 	bwn_mac_enable(mac);
2721 }
2722 
2723 static void
2724 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2725 {
2726 
2727 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2728 }
2729 
2730 static int
2731 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2732 	const struct ieee80211_bpf_params *params)
2733 {
2734 	struct ieee80211com *ic = ni->ni_ic;
2735 	struct ifnet *ifp = ic->ic_ifp;
2736 	struct bwn_softc *sc = ifp->if_softc;
2737 	struct bwn_mac *mac = sc->sc_curmac;
2738 
2739 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
2740 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2741 		ieee80211_free_node(ni);
2742 		m_freem(m);
2743 		return (ENETDOWN);
2744 	}
2745 
2746 	BWN_LOCK(sc);
2747 	if (bwn_tx_isfull(sc, m)) {
2748 		ieee80211_free_node(ni);
2749 		m_freem(m);
2750 		ifp->if_oerrors++;
2751 		BWN_UNLOCK(sc);
2752 		return (ENOBUFS);
2753 	}
2754 
2755 	if (bwn_tx_start(sc, ni, m) != 0) {
2756 		if (ni != NULL)
2757 			ieee80211_free_node(ni);
2758 		ifp->if_oerrors++;
2759 	}
2760 	sc->sc_watchdog_timer = 5;
2761 	BWN_UNLOCK(sc);
2762 	return (0);
2763 }
2764 
2765 /*
2766  * Callback from the 802.11 layer to update the slot time
2767  * based on the current setting.  We use it to notify the
2768  * firmware of ERP changes and the f/w takes care of things
2769  * like slot time and preamble.
2770  */
2771 static void
2772 bwn_updateslot(struct ifnet *ifp)
2773 {
2774 	struct bwn_softc *sc = ifp->if_softc;
2775 	struct ieee80211com *ic = ifp->if_l2com;
2776 	struct bwn_mac *mac;
2777 
2778 	BWN_LOCK(sc);
2779 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2780 		mac = (struct bwn_mac *)sc->sc_curmac;
2781 		bwn_set_slot_time(mac,
2782 		    (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
2783 	}
2784 	BWN_UNLOCK(sc);
2785 }
2786 
2787 /*
2788  * Callback from the 802.11 layer after a promiscuous mode change.
2789  * Note this interface does not check the operating mode as this
2790  * is an internal callback and we are expected to honor the current
2791  * state (e.g. this is used for setting the interface in promiscuous
2792  * mode when operating in hostap mode to do ACS).
2793  */
2794 static void
2795 bwn_update_promisc(struct ifnet *ifp)
2796 {
2797 	struct bwn_softc *sc = ifp->if_softc;
2798 	struct bwn_mac *mac = sc->sc_curmac;
2799 
2800 	BWN_LOCK(sc);
2801 	mac = sc->sc_curmac;
2802 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2803 		if (ifp->if_flags & IFF_PROMISC)
2804 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2805 		else
2806 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2807 		bwn_set_opmode(mac);
2808 	}
2809 	BWN_UNLOCK(sc);
2810 }
2811 
2812 /*
2813  * Callback from the 802.11 layer to update WME parameters.
2814  */
2815 static int
2816 bwn_wme_update(struct ieee80211com *ic)
2817 {
2818 	struct bwn_softc *sc = ic->ic_ifp->if_softc;
2819 	struct bwn_mac *mac = sc->sc_curmac;
2820 	struct wmeParams *wmep;
2821 	int i;
2822 
2823 	BWN_LOCK(sc);
2824 	mac = sc->sc_curmac;
2825 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2826 		bwn_mac_suspend(mac);
2827 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2828 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2829 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2830 		}
2831 		bwn_mac_enable(mac);
2832 	}
2833 	BWN_UNLOCK(sc);
2834 	return (0);
2835 }
2836 
2837 static void
2838 bwn_scan_start(struct ieee80211com *ic)
2839 {
2840 	struct ifnet *ifp = ic->ic_ifp;
2841 	struct bwn_softc *sc = ifp->if_softc;
2842 	struct bwn_mac *mac;
2843 
2844 	BWN_LOCK(sc);
2845 	mac = sc->sc_curmac;
2846 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2847 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2848 		bwn_set_opmode(mac);
2849 		/* disable CFP update during scan */
2850 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2851 	}
2852 	BWN_UNLOCK(sc);
2853 }
2854 
2855 static void
2856 bwn_scan_end(struct ieee80211com *ic)
2857 {
2858 	struct ifnet *ifp = ic->ic_ifp;
2859 	struct bwn_softc *sc = ifp->if_softc;
2860 	struct bwn_mac *mac;
2861 
2862 	BWN_LOCK(sc);
2863 	mac = sc->sc_curmac;
2864 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2865 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2866 		bwn_set_opmode(mac);
2867 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2868 	}
2869 	BWN_UNLOCK(sc);
2870 }
2871 
2872 static void
2873 bwn_set_channel(struct ieee80211com *ic)
2874 {
2875 	struct ifnet *ifp = ic->ic_ifp;
2876 	struct bwn_softc *sc = ifp->if_softc;
2877 	struct bwn_mac *mac = sc->sc_curmac;
2878 	struct bwn_phy *phy = &mac->mac_phy;
2879 	int chan, error;
2880 
2881 	BWN_LOCK(sc);
2882 
2883 	error = bwn_switch_band(sc, ic->ic_curchan);
2884 	if (error)
2885 		goto fail;
2886 	bwn_mac_suspend(mac);
2887 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2888 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2889 	if (chan != phy->chan)
2890 		bwn_switch_channel(mac, chan);
2891 
2892 	/* TX power level */
2893 	if (ic->ic_curchan->ic_maxpower != 0 &&
2894 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2895 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2896 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2897 		    BWN_TXPWR_IGNORE_TSSI);
2898 	}
2899 
2900 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2901 	if (phy->set_antenna)
2902 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2903 
2904 	if (sc->sc_rf_enabled != phy->rf_on) {
2905 		if (sc->sc_rf_enabled) {
2906 			bwn_rf_turnon(mac);
2907 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2908 				device_printf(sc->sc_dev,
2909 				    "please turn on the RF switch\n");
2910 		} else
2911 			bwn_rf_turnoff(mac);
2912 	}
2913 
2914 	bwn_mac_enable(mac);
2915 
2916 fail:
2917 	/*
2918 	 * Setup radio tap channel freq and flags
2919 	 */
2920 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2921 		htole16(ic->ic_curchan->ic_freq);
2922 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2923 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2924 
2925 	BWN_UNLOCK(sc);
2926 }
2927 
2928 static struct ieee80211vap *
2929 bwn_vap_create(struct ieee80211com *ic,
2930 	const char name[IFNAMSIZ], int unit, int opmode, int flags,
2931 	const uint8_t bssid[IEEE80211_ADDR_LEN],
2932 	const uint8_t mac0[IEEE80211_ADDR_LEN])
2933 {
2934 	struct ifnet *ifp = ic->ic_ifp;
2935 	struct bwn_softc *sc = ifp->if_softc;
2936 	struct ieee80211vap *vap;
2937 	struct bwn_vap *bvp;
2938 	uint8_t mac[IEEE80211_ADDR_LEN];
2939 
2940 	IEEE80211_ADDR_COPY(mac, mac0);
2941 	switch (opmode) {
2942 	case IEEE80211_M_HOSTAP:
2943 	case IEEE80211_M_MBSS:
2944 	case IEEE80211_M_STA:
2945 	case IEEE80211_M_WDS:
2946 	case IEEE80211_M_MONITOR:
2947 	case IEEE80211_M_IBSS:
2948 	case IEEE80211_M_AHDEMO:
2949 		break;
2950 	default:
2951 		return (NULL);
2952 	}
2953 
2954 	IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
2955 
2956 	bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
2957 	    M_80211_VAP, M_NOWAIT | M_ZERO);
2958 	if (bvp == NULL) {
2959 		device_printf(sc->sc_dev, "failed to allocate a buffer\n");
2960 		return (NULL);
2961 	}
2962 	vap = &bvp->bv_vap;
2963 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
2964 	IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
2965 	/* override with driver methods */
2966 	bvp->bv_newstate = vap->iv_newstate;
2967 	vap->iv_newstate = bwn_newstate;
2968 
2969 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2970 	vap->iv_max_aid = BWN_STAID_MAX;
2971 
2972 	ieee80211_ratectl_init(vap);
2973 
2974 	/* complete setup */
2975 	ieee80211_vap_attach(vap, ieee80211_media_change,
2976 	    ieee80211_media_status);
2977 	return (vap);
2978 }
2979 
2980 static void
2981 bwn_vap_delete(struct ieee80211vap *vap)
2982 {
2983 	struct bwn_vap *bvp = BWN_VAP(vap);
2984 
2985 	ieee80211_ratectl_deinit(vap);
2986 	ieee80211_vap_detach(vap);
2987 	free(bvp, M_80211_VAP);
2988 }
2989 
2990 static void
2991 bwn_init(void *arg)
2992 {
2993 	struct bwn_softc *sc = arg;
2994 	struct ifnet *ifp = sc->sc_ifp;
2995 	struct ieee80211com *ic = ifp->if_l2com;
2996 	int error = 0;
2997 
2998 	DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
2999 		__func__, ifp->if_flags);
3000 
3001 	BWN_LOCK(sc);
3002 	error = bwn_init_locked(sc);
3003 	BWN_UNLOCK(sc);
3004 
3005 	if (error == 0)
3006 		ieee80211_start_all(ic);	/* start all vap's */
3007 }
3008 
3009 static int
3010 bwn_init_locked(struct bwn_softc *sc)
3011 {
3012 	struct bwn_mac *mac;
3013 	struct ifnet *ifp = sc->sc_ifp;
3014 	int error;
3015 
3016 	BWN_ASSERT_LOCKED(sc);
3017 
3018 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
3019 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
3020 	sc->sc_filters = 0;
3021 	bwn_wme_clear(sc);
3022 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
3023 	sc->sc_rf_enabled = 1;
3024 
3025 	mac = sc->sc_curmac;
3026 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
3027 		error = bwn_core_init(mac);
3028 		if (error != 0)
3029 			return (error);
3030 	}
3031 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
3032 		bwn_core_start(mac);
3033 
3034 	bwn_set_opmode(mac);
3035 	bwn_set_pretbtt(mac);
3036 	bwn_spu_setdelay(mac, 0);
3037 	bwn_set_macaddr(mac);
3038 
3039 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3040 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
3041 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
3042 
3043 	return (0);
3044 }
3045 
3046 static void
3047 bwn_stop(struct bwn_softc *sc, int statechg)
3048 {
3049 
3050 	BWN_LOCK(sc);
3051 	bwn_stop_locked(sc, statechg);
3052 	BWN_UNLOCK(sc);
3053 }
3054 
3055 static void
3056 bwn_stop_locked(struct bwn_softc *sc, int statechg)
3057 {
3058 	struct bwn_mac *mac = sc->sc_curmac;
3059 	struct ifnet *ifp = sc->sc_ifp;
3060 
3061 	BWN_ASSERT_LOCKED(sc);
3062 
3063 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
3064 		/* XXX FIXME opmode not based on VAP */
3065 		bwn_set_opmode(mac);
3066 		bwn_set_macaddr(mac);
3067 	}
3068 
3069 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
3070 		bwn_core_stop(mac);
3071 
3072 	callout_stop(&sc->sc_led_blink_ch);
3073 	sc->sc_led_blinking = 0;
3074 
3075 	bwn_core_exit(mac);
3076 	sc->sc_rf_enabled = 0;
3077 
3078 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3079 }
3080 
3081 static void
3082 bwn_wme_clear(struct bwn_softc *sc)
3083 {
3084 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
3085 	struct wmeParams *p;
3086 	unsigned int i;
3087 
3088 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
3089 	    ("%s:%d: fail", __func__, __LINE__));
3090 
3091 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
3092 		p = &(sc->sc_wmeParams[i]);
3093 
3094 		switch (bwn_wme_shm_offsets[i]) {
3095 		case BWN_WME_VOICE:
3096 			p->wmep_txopLimit = 0;
3097 			p->wmep_aifsn = 2;
3098 			/* XXX FIXME: log2(cwmin) */
3099 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3100 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3101 			break;
3102 		case BWN_WME_VIDEO:
3103 			p->wmep_txopLimit = 0;
3104 			p->wmep_aifsn = 2;
3105 			/* XXX FIXME: log2(cwmin) */
3106 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3107 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3108 			break;
3109 		case BWN_WME_BESTEFFORT:
3110 			p->wmep_txopLimit = 0;
3111 			p->wmep_aifsn = 3;
3112 			/* XXX FIXME: log2(cwmin) */
3113 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3114 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3115 			break;
3116 		case BWN_WME_BACKGROUND:
3117 			p->wmep_txopLimit = 0;
3118 			p->wmep_aifsn = 7;
3119 			/* XXX FIXME: log2(cwmin) */
3120 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3121 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3122 			break;
3123 		default:
3124 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3125 		}
3126 	}
3127 }
3128 
3129 static int
3130 bwn_core_init(struct bwn_mac *mac)
3131 {
3132 	struct bwn_softc *sc = mac->mac_sc;
3133 	uint64_t hf;
3134 	int error;
3135 
3136 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3137 	    ("%s:%d: fail", __func__, __LINE__));
3138 
3139 	siba_powerup(sc->sc_dev, 0);
3140 	if (!siba_dev_isup(sc->sc_dev))
3141 		bwn_reset_core(mac,
3142 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3143 
3144 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3145 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3146 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3147 	BWN_GETTIME(mac->mac_phy.nexttime);
3148 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3149 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3150 	mac->mac_stats.link_noise = -95;
3151 	mac->mac_reason_intr = 0;
3152 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3153 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3154 #ifdef BWN_DEBUG
3155 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3156 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3157 #endif
3158 	mac->mac_suspended = 1;
3159 	mac->mac_task_state = 0;
3160 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3161 
3162 	mac->mac_phy.init_pre(mac);
3163 
3164 	siba_pcicore_intr(sc->sc_dev);
3165 
3166 	siba_fix_imcfglobug(sc->sc_dev);
3167 	bwn_bt_disable(mac);
3168 	if (mac->mac_phy.prepare_hw) {
3169 		error = mac->mac_phy.prepare_hw(mac);
3170 		if (error)
3171 			goto fail0;
3172 	}
3173 	error = bwn_chip_init(mac);
3174 	if (error)
3175 		goto fail0;
3176 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3177 	    siba_get_revid(sc->sc_dev));
3178 	hf = bwn_hf_read(mac);
3179 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3180 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3181 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3182 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3183 		if (mac->mac_phy.rev == 1)
3184 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3185 	}
3186 	if (mac->mac_phy.rf_ver == 0x2050) {
3187 		if (mac->mac_phy.rf_rev < 6)
3188 			hf |= BWN_HF_FORCE_VCO_RECALC;
3189 		if (mac->mac_phy.rf_rev == 6)
3190 			hf |= BWN_HF_4318_TSSI;
3191 	}
3192 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3193 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3194 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3195 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3196 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3197 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3198 	bwn_hf_write(mac, hf);
3199 
3200 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3201 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3202 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3203 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3204 
3205 	bwn_rate_init(mac);
3206 	bwn_set_phytxctl(mac);
3207 
3208 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3209 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3210 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3211 
3212 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3213 		bwn_pio_init(mac);
3214 	else
3215 		bwn_dma_init(mac);
3216 	bwn_wme_init(mac);
3217 	bwn_spu_setdelay(mac, 1);
3218 	bwn_bt_enable(mac);
3219 
3220 	siba_powerup(sc->sc_dev,
3221 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3222 	bwn_set_macaddr(mac);
3223 	bwn_crypt_init(mac);
3224 
3225 	/* XXX LED initializatin */
3226 
3227 	mac->mac_status = BWN_MAC_STATUS_INITED;
3228 
3229 	return (error);
3230 
3231 fail0:
3232 	siba_powerdown(sc->sc_dev);
3233 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3234 	    ("%s:%d: fail", __func__, __LINE__));
3235 	return (error);
3236 }
3237 
3238 static void
3239 bwn_core_start(struct bwn_mac *mac)
3240 {
3241 	struct bwn_softc *sc = mac->mac_sc;
3242 	uint32_t tmp;
3243 
3244 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3245 	    ("%s:%d: fail", __func__, __LINE__));
3246 
3247 	if (siba_get_revid(sc->sc_dev) < 5)
3248 		return;
3249 
3250 	while (1) {
3251 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3252 		if (!(tmp & 0x00000001))
3253 			break;
3254 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3255 	}
3256 
3257 	bwn_mac_enable(mac);
3258 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3259 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3260 
3261 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3262 }
3263 
3264 static void
3265 bwn_core_exit(struct bwn_mac *mac)
3266 {
3267 	struct bwn_softc *sc = mac->mac_sc;
3268 	uint32_t macctl;
3269 
3270 	BWN_ASSERT_LOCKED(mac->mac_sc);
3271 
3272 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3273 	    ("%s:%d: fail", __func__, __LINE__));
3274 
3275 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3276 		return;
3277 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3278 
3279 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3280 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3281 	macctl |= BWN_MACCTL_MCODE_JMP0;
3282 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3283 
3284 	bwn_dma_stop(mac);
3285 	bwn_pio_stop(mac);
3286 	bwn_chip_exit(mac);
3287 	mac->mac_phy.switch_analog(mac, 0);
3288 	siba_dev_down(sc->sc_dev, 0);
3289 	siba_powerdown(sc->sc_dev);
3290 }
3291 
3292 static void
3293 bwn_bt_disable(struct bwn_mac *mac)
3294 {
3295 	struct bwn_softc *sc = mac->mac_sc;
3296 
3297 	(void)sc;
3298 	/* XXX do nothing yet */
3299 }
3300 
3301 static int
3302 bwn_chip_init(struct bwn_mac *mac)
3303 {
3304 	struct bwn_softc *sc = mac->mac_sc;
3305 	struct bwn_phy *phy = &mac->mac_phy;
3306 	uint32_t macctl;
3307 	int error;
3308 
3309 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3310 	if (phy->gmode)
3311 		macctl |= BWN_MACCTL_GMODE;
3312 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3313 
3314 	error = bwn_fw_fillinfo(mac);
3315 	if (error)
3316 		return (error);
3317 	error = bwn_fw_loaducode(mac);
3318 	if (error)
3319 		return (error);
3320 
3321 	error = bwn_gpio_init(mac);
3322 	if (error)
3323 		return (error);
3324 
3325 	error = bwn_fw_loadinitvals(mac);
3326 	if (error) {
3327 		siba_gpio_set(sc->sc_dev, 0);
3328 		return (error);
3329 	}
3330 	phy->switch_analog(mac, 1);
3331 	error = bwn_phy_init(mac);
3332 	if (error) {
3333 		siba_gpio_set(sc->sc_dev, 0);
3334 		return (error);
3335 	}
3336 	if (phy->set_im)
3337 		phy->set_im(mac, BWN_IMMODE_NONE);
3338 	if (phy->set_antenna)
3339 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3340 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3341 
3342 	if (phy->type == BWN_PHYTYPE_B)
3343 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3344 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3345 	if (siba_get_revid(sc->sc_dev) < 5)
3346 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3347 
3348 	BWN_WRITE_4(mac, BWN_MACCTL,
3349 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3350 	BWN_WRITE_4(mac, BWN_MACCTL,
3351 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3352 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3353 
3354 	bwn_set_opmode(mac);
3355 	if (siba_get_revid(sc->sc_dev) < 3) {
3356 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3357 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3358 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3359 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3360 	} else {
3361 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3362 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3363 	}
3364 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3365 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3366 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3367 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3368 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3369 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3370 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3371 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3372 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3373 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3374 	return (error);
3375 }
3376 
3377 /* read hostflags */
3378 static uint64_t
3379 bwn_hf_read(struct bwn_mac *mac)
3380 {
3381 	uint64_t ret;
3382 
3383 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3384 	ret <<= 16;
3385 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3386 	ret <<= 16;
3387 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3388 	return (ret);
3389 }
3390 
3391 static void
3392 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3393 {
3394 
3395 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3396 	    (value & 0x00000000ffffull));
3397 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3398 	    (value & 0x0000ffff0000ull) >> 16);
3399 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3400 	    (value & 0xffff00000000ULL) >> 32);
3401 }
3402 
3403 static void
3404 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3405 {
3406 
3407 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3408 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3409 }
3410 
3411 static void
3412 bwn_rate_init(struct bwn_mac *mac)
3413 {
3414 
3415 	switch (mac->mac_phy.type) {
3416 	case BWN_PHYTYPE_A:
3417 	case BWN_PHYTYPE_G:
3418 	case BWN_PHYTYPE_LP:
3419 	case BWN_PHYTYPE_N:
3420 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3421 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3422 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3423 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3424 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3425 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3426 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3427 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3428 			break;
3429 		/* FALLTHROUGH */
3430 	case BWN_PHYTYPE_B:
3431 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3432 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3433 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3434 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3435 		break;
3436 	default:
3437 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3438 	}
3439 }
3440 
3441 static void
3442 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3443 {
3444 	uint16_t offset;
3445 
3446 	if (ofdm) {
3447 		offset = 0x480;
3448 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3449 	} else {
3450 		offset = 0x4c0;
3451 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3452 	}
3453 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3454 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3455 }
3456 
3457 static uint8_t
3458 bwn_plcp_getcck(const uint8_t bitrate)
3459 {
3460 
3461 	switch (bitrate) {
3462 	case BWN_CCK_RATE_1MB:
3463 		return (0x0a);
3464 	case BWN_CCK_RATE_2MB:
3465 		return (0x14);
3466 	case BWN_CCK_RATE_5MB:
3467 		return (0x37);
3468 	case BWN_CCK_RATE_11MB:
3469 		return (0x6e);
3470 	}
3471 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3472 	return (0);
3473 }
3474 
3475 static uint8_t
3476 bwn_plcp_getofdm(const uint8_t bitrate)
3477 {
3478 
3479 	switch (bitrate) {
3480 	case BWN_OFDM_RATE_6MB:
3481 		return (0xb);
3482 	case BWN_OFDM_RATE_9MB:
3483 		return (0xf);
3484 	case BWN_OFDM_RATE_12MB:
3485 		return (0xa);
3486 	case BWN_OFDM_RATE_18MB:
3487 		return (0xe);
3488 	case BWN_OFDM_RATE_24MB:
3489 		return (0x9);
3490 	case BWN_OFDM_RATE_36MB:
3491 		return (0xd);
3492 	case BWN_OFDM_RATE_48MB:
3493 		return (0x8);
3494 	case BWN_OFDM_RATE_54MB:
3495 		return (0xc);
3496 	}
3497 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3498 	return (0);
3499 }
3500 
3501 static void
3502 bwn_set_phytxctl(struct bwn_mac *mac)
3503 {
3504 	uint16_t ctl;
3505 
3506 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3507 	    BWN_TX_PHY_TXPWR);
3508 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3509 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3510 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3511 }
3512 
3513 static void
3514 bwn_pio_init(struct bwn_mac *mac)
3515 {
3516 	struct bwn_pio *pio = &mac->mac_method.pio;
3517 
3518 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3519 	    & ~BWN_MACCTL_BIGENDIAN);
3520 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3521 
3522 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3523 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3524 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3525 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3526 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3527 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3528 }
3529 
3530 static void
3531 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3532     int index)
3533 {
3534 	struct bwn_pio_txpkt *tp;
3535 	struct bwn_softc *sc = mac->mac_sc;
3536 	unsigned int i;
3537 
3538 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3539 	tq->tq_index = index;
3540 
3541 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3542 	if (siba_get_revid(sc->sc_dev) >= 8)
3543 		tq->tq_size = 1920;
3544 	else {
3545 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3546 		tq->tq_size -= 80;
3547 	}
3548 
3549 	TAILQ_INIT(&tq->tq_pktlist);
3550 	for (i = 0; i < N(tq->tq_pkts); i++) {
3551 		tp = &(tq->tq_pkts[i]);
3552 		tp->tp_index = i;
3553 		tp->tp_queue = tq;
3554 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3555 	}
3556 }
3557 
3558 static uint16_t
3559 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3560 {
3561 	struct bwn_softc *sc = mac->mac_sc;
3562 	static const uint16_t bases[] = {
3563 		BWN_PIO_BASE0,
3564 		BWN_PIO_BASE1,
3565 		BWN_PIO_BASE2,
3566 		BWN_PIO_BASE3,
3567 		BWN_PIO_BASE4,
3568 		BWN_PIO_BASE5,
3569 		BWN_PIO_BASE6,
3570 		BWN_PIO_BASE7,
3571 	};
3572 	static const uint16_t bases_rev11[] = {
3573 		BWN_PIO11_BASE0,
3574 		BWN_PIO11_BASE1,
3575 		BWN_PIO11_BASE2,
3576 		BWN_PIO11_BASE3,
3577 		BWN_PIO11_BASE4,
3578 		BWN_PIO11_BASE5,
3579 	};
3580 
3581 	if (siba_get_revid(sc->sc_dev) >= 11) {
3582 		if (index >= N(bases_rev11))
3583 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3584 		return (bases_rev11[index]);
3585 	}
3586 	if (index >= N(bases))
3587 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3588 	return (bases[index]);
3589 }
3590 
3591 static void
3592 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3593     int index)
3594 {
3595 	struct bwn_softc *sc = mac->mac_sc;
3596 
3597 	prq->prq_mac = mac;
3598 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3599 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3600 	bwn_dma_rxdirectfifo(mac, index, 1);
3601 }
3602 
3603 static void
3604 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3605 {
3606 	if (tq == NULL)
3607 		return;
3608 	bwn_pio_cancel_tx_packets(tq);
3609 }
3610 
3611 static void
3612 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3613 {
3614 
3615 	bwn_destroy_pioqueue_tx(pio);
3616 }
3617 
3618 static uint16_t
3619 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3620     uint16_t offset)
3621 {
3622 
3623 	return (BWN_READ_2(mac, tq->tq_base + offset));
3624 }
3625 
3626 static void
3627 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3628 {
3629 	uint32_t ctl;
3630 	int type;
3631 	uint16_t base;
3632 
3633 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3634 	base = bwn_dma_base(type, idx);
3635 	if (type == BWN_DMA_64BIT) {
3636 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3637 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3638 		if (enable)
3639 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3640 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3641 	} else {
3642 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3643 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3644 		if (enable)
3645 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3646 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3647 	}
3648 }
3649 
3650 static uint64_t
3651 bwn_dma_mask(struct bwn_mac *mac)
3652 {
3653 	uint32_t tmp;
3654 	uint16_t base;
3655 
3656 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3657 	if (tmp & SIBA_TGSHIGH_DMA64)
3658 		return (BWN_DMA_BIT_MASK(64));
3659 	base = bwn_dma_base(0, 0);
3660 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3661 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3662 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3663 		return (BWN_DMA_BIT_MASK(32));
3664 
3665 	return (BWN_DMA_BIT_MASK(30));
3666 }
3667 
3668 static int
3669 bwn_dma_mask2type(uint64_t dmamask)
3670 {
3671 
3672 	if (dmamask == BWN_DMA_BIT_MASK(30))
3673 		return (BWN_DMA_30BIT);
3674 	if (dmamask == BWN_DMA_BIT_MASK(32))
3675 		return (BWN_DMA_32BIT);
3676 	if (dmamask == BWN_DMA_BIT_MASK(64))
3677 		return (BWN_DMA_64BIT);
3678 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3679 	return (BWN_DMA_30BIT);
3680 }
3681 
3682 static void
3683 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3684 {
3685 	struct bwn_pio_txpkt *tp;
3686 	unsigned int i;
3687 
3688 	for (i = 0; i < N(tq->tq_pkts); i++) {
3689 		tp = &(tq->tq_pkts[i]);
3690 		if (tp->tp_m) {
3691 			m_freem(tp->tp_m);
3692 			tp->tp_m = NULL;
3693 		}
3694 	}
3695 }
3696 
3697 static uint16_t
3698 bwn_dma_base(int type, int controller_idx)
3699 {
3700 	static const uint16_t map64[] = {
3701 		BWN_DMA64_BASE0,
3702 		BWN_DMA64_BASE1,
3703 		BWN_DMA64_BASE2,
3704 		BWN_DMA64_BASE3,
3705 		BWN_DMA64_BASE4,
3706 		BWN_DMA64_BASE5,
3707 	};
3708 	static const uint16_t map32[] = {
3709 		BWN_DMA32_BASE0,
3710 		BWN_DMA32_BASE1,
3711 		BWN_DMA32_BASE2,
3712 		BWN_DMA32_BASE3,
3713 		BWN_DMA32_BASE4,
3714 		BWN_DMA32_BASE5,
3715 	};
3716 
3717 	if (type == BWN_DMA_64BIT) {
3718 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3719 		    ("%s:%d: fail", __func__, __LINE__));
3720 		return (map64[controller_idx]);
3721 	}
3722 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3723 	    ("%s:%d: fail", __func__, __LINE__));
3724 	return (map32[controller_idx]);
3725 }
3726 
3727 static void
3728 bwn_dma_init(struct bwn_mac *mac)
3729 {
3730 	struct bwn_dma *dma = &mac->mac_method.dma;
3731 
3732 	/* setup TX DMA channels. */
3733 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3734 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3735 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3736 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3737 	bwn_dma_setup(dma->mcast);
3738 	/* setup RX DMA channel. */
3739 	bwn_dma_setup(dma->rx);
3740 }
3741 
3742 static struct bwn_dma_ring *
3743 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3744     int for_tx, int type)
3745 {
3746 	struct bwn_dma *dma = &mac->mac_method.dma;
3747 	struct bwn_dma_ring *dr;
3748 	struct bwn_dmadesc_generic *desc;
3749 	struct bwn_dmadesc_meta *mt;
3750 	struct bwn_softc *sc = mac->mac_sc;
3751 	int error, i;
3752 
3753 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3754 	if (dr == NULL)
3755 		goto out;
3756 	dr->dr_numslots = BWN_RXRING_SLOTS;
3757 	if (for_tx)
3758 		dr->dr_numslots = BWN_TXRING_SLOTS;
3759 
3760 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3761 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3762 	if (dr->dr_meta == NULL)
3763 		goto fail0;
3764 
3765 	dr->dr_type = type;
3766 	dr->dr_mac = mac;
3767 	dr->dr_base = bwn_dma_base(type, controller_index);
3768 	dr->dr_index = controller_index;
3769 	if (type == BWN_DMA_64BIT) {
3770 		dr->getdesc = bwn_dma_64_getdesc;
3771 		dr->setdesc = bwn_dma_64_setdesc;
3772 		dr->start_transfer = bwn_dma_64_start_transfer;
3773 		dr->suspend = bwn_dma_64_suspend;
3774 		dr->resume = bwn_dma_64_resume;
3775 		dr->get_curslot = bwn_dma_64_get_curslot;
3776 		dr->set_curslot = bwn_dma_64_set_curslot;
3777 	} else {
3778 		dr->getdesc = bwn_dma_32_getdesc;
3779 		dr->setdesc = bwn_dma_32_setdesc;
3780 		dr->start_transfer = bwn_dma_32_start_transfer;
3781 		dr->suspend = bwn_dma_32_suspend;
3782 		dr->resume = bwn_dma_32_resume;
3783 		dr->get_curslot = bwn_dma_32_get_curslot;
3784 		dr->set_curslot = bwn_dma_32_set_curslot;
3785 	}
3786 	if (for_tx) {
3787 		dr->dr_tx = 1;
3788 		dr->dr_curslot = -1;
3789 	} else {
3790 		if (dr->dr_index == 0) {
3791 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3792 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3793 		} else
3794 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3795 	}
3796 
3797 	error = bwn_dma_allocringmemory(dr);
3798 	if (error)
3799 		goto fail2;
3800 
3801 	if (for_tx) {
3802 		/*
3803 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3804 		 * BWN_TX_SLOTS_PER_FRAME
3805 		 */
3806 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3807 		    ("%s:%d: fail", __func__, __LINE__));
3808 
3809 		dr->dr_txhdr_cache =
3810 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3811 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3812 		KASSERT(dr->dr_txhdr_cache != NULL,
3813 		    ("%s:%d: fail", __func__, __LINE__));
3814 
3815 		/*
3816 		 * Create TX ring DMA stuffs
3817 		 */
3818 		error = bus_dma_tag_create(dma->parent_dtag,
3819 				    BWN_ALIGN, 0,
3820 				    BUS_SPACE_MAXADDR,
3821 				    BUS_SPACE_MAXADDR,
3822 				    NULL, NULL,
3823 				    BWN_HDRSIZE(mac),
3824 				    1,
3825 				    BUS_SPACE_MAXSIZE_32BIT,
3826 				    0,
3827 				    NULL, NULL,
3828 				    &dr->dr_txring_dtag);
3829 		if (error) {
3830 			device_printf(sc->sc_dev,
3831 			    "can't create TX ring DMA tag: TODO frees\n");
3832 			goto fail1;
3833 		}
3834 
3835 		for (i = 0; i < dr->dr_numslots; i += 2) {
3836 			dr->getdesc(dr, i, &desc, &mt);
3837 
3838 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3839 			mt->mt_m = NULL;
3840 			mt->mt_ni = NULL;
3841 			mt->mt_islast = 0;
3842 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3843 			    &mt->mt_dmap);
3844 			if (error) {
3845 				device_printf(sc->sc_dev,
3846 				     "can't create RX buf DMA map\n");
3847 				goto fail1;
3848 			}
3849 
3850 			dr->getdesc(dr, i + 1, &desc, &mt);
3851 
3852 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3853 			mt->mt_m = NULL;
3854 			mt->mt_ni = NULL;
3855 			mt->mt_islast = 1;
3856 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3857 			    &mt->mt_dmap);
3858 			if (error) {
3859 				device_printf(sc->sc_dev,
3860 				     "can't create RX buf DMA map\n");
3861 				goto fail1;
3862 			}
3863 		}
3864 	} else {
3865 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3866 		    &dr->dr_spare_dmap);
3867 		if (error) {
3868 			device_printf(sc->sc_dev,
3869 			    "can't create RX buf DMA map\n");
3870 			goto out;		/* XXX wrong! */
3871 		}
3872 
3873 		for (i = 0; i < dr->dr_numslots; i++) {
3874 			dr->getdesc(dr, i, &desc, &mt);
3875 
3876 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3877 			    &mt->mt_dmap);
3878 			if (error) {
3879 				device_printf(sc->sc_dev,
3880 				    "can't create RX buf DMA map\n");
3881 				goto out;	/* XXX wrong! */
3882 			}
3883 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3884 			if (error) {
3885 				device_printf(sc->sc_dev,
3886 				    "failed to allocate RX buf\n");
3887 				goto out;	/* XXX wrong! */
3888 			}
3889 		}
3890 
3891 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3892 		    BUS_DMASYNC_PREWRITE);
3893 
3894 		dr->dr_usedslot = dr->dr_numslots;
3895 	}
3896 
3897       out:
3898 	return (dr);
3899 
3900 fail2:
3901 	free(dr->dr_txhdr_cache, M_DEVBUF);
3902 fail1:
3903 	free(dr->dr_meta, M_DEVBUF);
3904 fail0:
3905 	free(dr, M_DEVBUF);
3906 	return (NULL);
3907 }
3908 
3909 static void
3910 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3911 {
3912 
3913 	if (dr == NULL)
3914 		return;
3915 
3916 	bwn_dma_free_descbufs(*dr);
3917 	bwn_dma_free_ringmemory(*dr);
3918 
3919 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3920 	free((*dr)->dr_meta, M_DEVBUF);
3921 	free(*dr, M_DEVBUF);
3922 
3923 	*dr = NULL;
3924 }
3925 
3926 static void
3927 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3928     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3929 {
3930 	struct bwn_dmadesc32 *desc;
3931 
3932 	*meta = &(dr->dr_meta[slot]);
3933 	desc = dr->dr_ring_descbase;
3934 	desc = &(desc[slot]);
3935 
3936 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3937 }
3938 
3939 static void
3940 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3941     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3942     int start, int end, int irq)
3943 {
3944 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3945 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3946 	uint32_t addr, addrext, ctl;
3947 	int slot;
3948 
3949 	slot = (int)(&(desc->dma.dma32) - descbase);
3950 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3951 	    ("%s:%d: fail", __func__, __LINE__));
3952 
3953 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3954 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3955 	addr |= siba_dma_translation(sc->sc_dev);
3956 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3957 	if (slot == dr->dr_numslots - 1)
3958 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3959 	if (start)
3960 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3961 	if (end)
3962 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3963 	if (irq)
3964 		ctl |= BWN_DMA32_DCTL_IRQ;
3965 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3966 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3967 
3968 	desc->dma.dma32.control = htole32(ctl);
3969 	desc->dma.dma32.address = htole32(addr);
3970 }
3971 
3972 static void
3973 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3974 {
3975 
3976 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3977 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3978 }
3979 
3980 static void
3981 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3982 {
3983 
3984 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3985 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3986 }
3987 
3988 static void
3989 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3990 {
3991 
3992 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3993 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3994 }
3995 
3996 static int
3997 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3998 {
3999 	uint32_t val;
4000 
4001 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
4002 	val &= BWN_DMA32_RXDPTR;
4003 
4004 	return (val / sizeof(struct bwn_dmadesc32));
4005 }
4006 
4007 static void
4008 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
4009 {
4010 
4011 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
4012 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
4013 }
4014 
4015 static void
4016 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
4017     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
4018 {
4019 	struct bwn_dmadesc64 *desc;
4020 
4021 	*meta = &(dr->dr_meta[slot]);
4022 	desc = dr->dr_ring_descbase;
4023 	desc = &(desc[slot]);
4024 
4025 	*gdesc = (struct bwn_dmadesc_generic *)desc;
4026 }
4027 
4028 static void
4029 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
4030     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
4031     int start, int end, int irq)
4032 {
4033 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
4034 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4035 	int slot;
4036 	uint32_t ctl0 = 0, ctl1 = 0;
4037 	uint32_t addrlo, addrhi;
4038 	uint32_t addrext;
4039 
4040 	slot = (int)(&(desc->dma.dma64) - descbase);
4041 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
4042 	    ("%s:%d: fail", __func__, __LINE__));
4043 
4044 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
4045 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
4046 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
4047 	    30;
4048 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
4049 	if (slot == dr->dr_numslots - 1)
4050 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
4051 	if (start)
4052 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
4053 	if (end)
4054 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
4055 	if (irq)
4056 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
4057 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
4058 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
4059 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
4060 
4061 	desc->dma.dma64.control0 = htole32(ctl0);
4062 	desc->dma.dma64.control1 = htole32(ctl1);
4063 	desc->dma.dma64.address_low = htole32(addrlo);
4064 	desc->dma.dma64.address_high = htole32(addrhi);
4065 }
4066 
4067 static void
4068 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
4069 {
4070 
4071 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
4072 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4073 }
4074 
4075 static void
4076 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
4077 {
4078 
4079 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4080 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
4081 }
4082 
4083 static void
4084 bwn_dma_64_resume(struct bwn_dma_ring *dr)
4085 {
4086 
4087 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
4088 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
4089 }
4090 
4091 static int
4092 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
4093 {
4094 	uint32_t val;
4095 
4096 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
4097 	val &= BWN_DMA64_RXSTATDPTR;
4098 
4099 	return (val / sizeof(struct bwn_dmadesc64));
4100 }
4101 
4102 static void
4103 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4104 {
4105 
4106 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4107 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4108 }
4109 
4110 static int
4111 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4112 {
4113 	struct bwn_mac *mac = dr->dr_mac;
4114 	struct bwn_dma *dma = &mac->mac_method.dma;
4115 	struct bwn_softc *sc = mac->mac_sc;
4116 	int error;
4117 
4118 	error = bus_dma_tag_create(dma->parent_dtag,
4119 			    BWN_ALIGN, 0,
4120 			    BUS_SPACE_MAXADDR,
4121 			    BUS_SPACE_MAXADDR,
4122 			    NULL, NULL,
4123 			    BWN_DMA_RINGMEMSIZE,
4124 			    1,
4125 			    BUS_SPACE_MAXSIZE_32BIT,
4126 			    0,
4127 			    NULL, NULL,
4128 			    &dr->dr_ring_dtag);
4129 	if (error) {
4130 		device_printf(sc->sc_dev,
4131 		    "can't create TX ring DMA tag: TODO frees\n");
4132 		return (-1);
4133 	}
4134 
4135 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4136 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4137 	    &dr->dr_ring_dmap);
4138 	if (error) {
4139 		device_printf(sc->sc_dev,
4140 		    "can't allocate DMA mem: TODO frees\n");
4141 		return (-1);
4142 	}
4143 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4144 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4145 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4146 	if (error) {
4147 		device_printf(sc->sc_dev,
4148 		    "can't load DMA mem: TODO free\n");
4149 		return (-1);
4150 	}
4151 
4152 	return (0);
4153 }
4154 
4155 static void
4156 bwn_dma_setup(struct bwn_dma_ring *dr)
4157 {
4158 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4159 	uint64_t ring64;
4160 	uint32_t addrext, ring32, value;
4161 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4162 
4163 	if (dr->dr_tx) {
4164 		dr->dr_curslot = -1;
4165 
4166 		if (dr->dr_type == BWN_DMA_64BIT) {
4167 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4168 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4169 			    >> 30;
4170 			value = BWN_DMA64_TXENABLE;
4171 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4172 			    & BWN_DMA64_TXADDREXT_MASK;
4173 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4174 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4175 			    (ring64 & 0xffffffff));
4176 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4177 			    ((ring64 >> 32) &
4178 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4179 		} else {
4180 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4181 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4182 			value = BWN_DMA32_TXENABLE;
4183 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4184 			    & BWN_DMA32_TXADDREXT_MASK;
4185 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4186 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4187 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4188 		}
4189 		return;
4190 	}
4191 
4192 	/*
4193 	 * set for RX
4194 	 */
4195 	dr->dr_usedslot = dr->dr_numslots;
4196 
4197 	if (dr->dr_type == BWN_DMA_64BIT) {
4198 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4199 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4200 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4201 		value |= BWN_DMA64_RXENABLE;
4202 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4203 		    & BWN_DMA64_RXADDREXT_MASK;
4204 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4205 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4206 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4207 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4208 		    | (trans << 1));
4209 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4210 		    sizeof(struct bwn_dmadesc64));
4211 	} else {
4212 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4213 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4214 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4215 		value |= BWN_DMA32_RXENABLE;
4216 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4217 		    & BWN_DMA32_RXADDREXT_MASK;
4218 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4219 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4220 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4221 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4222 		    sizeof(struct bwn_dmadesc32));
4223 	}
4224 }
4225 
4226 static void
4227 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4228 {
4229 
4230 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4231 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4232 	    dr->dr_ring_dmap);
4233 }
4234 
4235 static void
4236 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4237 {
4238 
4239 	if (dr->dr_tx) {
4240 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4241 		if (dr->dr_type == BWN_DMA_64BIT) {
4242 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4243 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4244 		} else
4245 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4246 	} else {
4247 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4248 		if (dr->dr_type == BWN_DMA_64BIT) {
4249 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4250 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4251 		} else
4252 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4253 	}
4254 }
4255 
4256 static void
4257 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4258 {
4259 	struct bwn_dmadesc_generic *desc;
4260 	struct bwn_dmadesc_meta *meta;
4261 	struct bwn_mac *mac = dr->dr_mac;
4262 	struct bwn_dma *dma = &mac->mac_method.dma;
4263 	struct bwn_softc *sc = mac->mac_sc;
4264 	int i;
4265 
4266 	if (!dr->dr_usedslot)
4267 		return;
4268 	for (i = 0; i < dr->dr_numslots; i++) {
4269 		dr->getdesc(dr, i, &desc, &meta);
4270 
4271 		if (meta->mt_m == NULL) {
4272 			if (!dr->dr_tx)
4273 				device_printf(sc->sc_dev, "%s: not TX?\n",
4274 				    __func__);
4275 			continue;
4276 		}
4277 		if (dr->dr_tx) {
4278 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4279 				bus_dmamap_unload(dr->dr_txring_dtag,
4280 				    meta->mt_dmap);
4281 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4282 				bus_dmamap_unload(dma->txbuf_dtag,
4283 				    meta->mt_dmap);
4284 		} else
4285 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4286 		bwn_dma_free_descbuf(dr, meta);
4287 	}
4288 }
4289 
4290 static int
4291 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4292     int type)
4293 {
4294 	struct bwn_softc *sc = mac->mac_sc;
4295 	uint32_t value;
4296 	int i;
4297 	uint16_t offset;
4298 
4299 	for (i = 0; i < 10; i++) {
4300 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4301 		    BWN_DMA32_TXSTATUS;
4302 		value = BWN_READ_4(mac, base + offset);
4303 		if (type == BWN_DMA_64BIT) {
4304 			value &= BWN_DMA64_TXSTAT;
4305 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4306 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4307 			    value == BWN_DMA64_TXSTAT_STOPPED)
4308 				break;
4309 		} else {
4310 			value &= BWN_DMA32_TXSTATE;
4311 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4312 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4313 			    value == BWN_DMA32_TXSTAT_STOPPED)
4314 				break;
4315 		}
4316 		DELAY(1000);
4317 	}
4318 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4319 	BWN_WRITE_4(mac, base + offset, 0);
4320 	for (i = 0; i < 10; i++) {
4321 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4322 						   BWN_DMA32_TXSTATUS;
4323 		value = BWN_READ_4(mac, base + offset);
4324 		if (type == BWN_DMA_64BIT) {
4325 			value &= BWN_DMA64_TXSTAT;
4326 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4327 				i = -1;
4328 				break;
4329 			}
4330 		} else {
4331 			value &= BWN_DMA32_TXSTATE;
4332 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4333 				i = -1;
4334 				break;
4335 			}
4336 		}
4337 		DELAY(1000);
4338 	}
4339 	if (i != -1) {
4340 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4341 		return (ENODEV);
4342 	}
4343 	DELAY(1000);
4344 
4345 	return (0);
4346 }
4347 
4348 static int
4349 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4350     int type)
4351 {
4352 	struct bwn_softc *sc = mac->mac_sc;
4353 	uint32_t value;
4354 	int i;
4355 	uint16_t offset;
4356 
4357 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4358 	BWN_WRITE_4(mac, base + offset, 0);
4359 	for (i = 0; i < 10; i++) {
4360 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4361 		    BWN_DMA32_RXSTATUS;
4362 		value = BWN_READ_4(mac, base + offset);
4363 		if (type == BWN_DMA_64BIT) {
4364 			value &= BWN_DMA64_RXSTAT;
4365 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4366 				i = -1;
4367 				break;
4368 			}
4369 		} else {
4370 			value &= BWN_DMA32_RXSTATE;
4371 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4372 				i = -1;
4373 				break;
4374 			}
4375 		}
4376 		DELAY(1000);
4377 	}
4378 	if (i != -1) {
4379 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4380 		return (ENODEV);
4381 	}
4382 
4383 	return (0);
4384 }
4385 
4386 static void
4387 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4388     struct bwn_dmadesc_meta *meta)
4389 {
4390 
4391 	if (meta->mt_m != NULL) {
4392 		m_freem(meta->mt_m);
4393 		meta->mt_m = NULL;
4394 	}
4395 	if (meta->mt_ni != NULL) {
4396 		ieee80211_free_node(meta->mt_ni);
4397 		meta->mt_ni = NULL;
4398 	}
4399 }
4400 
4401 static void
4402 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4403 {
4404 	struct bwn_rxhdr4 *rxhdr;
4405 	unsigned char *frame;
4406 
4407 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4408 	rxhdr->frame_len = 0;
4409 
4410 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4411 	    sizeof(struct bwn_plcp6) + 2,
4412 	    ("%s:%d: fail", __func__, __LINE__));
4413 	frame = mtod(m, char *) + dr->dr_frameoffset;
4414 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4415 }
4416 
4417 static uint8_t
4418 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4419 {
4420 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4421 
4422 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4423 	    == 0xff);
4424 }
4425 
4426 static void
4427 bwn_wme_init(struct bwn_mac *mac)
4428 {
4429 
4430 	bwn_wme_load(mac);
4431 
4432 	/* enable WME support. */
4433 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4434 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4435 	    BWN_IFSCTL_USE_EDCF);
4436 }
4437 
4438 static void
4439 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4440 {
4441 	struct bwn_softc *sc = mac->mac_sc;
4442 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4443 	uint16_t delay;	/* microsec */
4444 
4445 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4446 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4447 		delay = 500;
4448 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4449 		delay = max(delay, (uint16_t)2400);
4450 
4451 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4452 }
4453 
4454 static void
4455 bwn_bt_enable(struct bwn_mac *mac)
4456 {
4457 	struct bwn_softc *sc = mac->mac_sc;
4458 	uint64_t hf;
4459 
4460 	if (bwn_bluetooth == 0)
4461 		return;
4462 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4463 		return;
4464 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4465 		return;
4466 
4467 	hf = bwn_hf_read(mac);
4468 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4469 		hf |= BWN_HF_BT_COEXISTALT;
4470 	else
4471 		hf |= BWN_HF_BT_COEXIST;
4472 	bwn_hf_write(mac, hf);
4473 }
4474 
4475 static void
4476 bwn_set_macaddr(struct bwn_mac *mac)
4477 {
4478 
4479 	bwn_mac_write_bssid(mac);
4480 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
4481 }
4482 
4483 static void
4484 bwn_clear_keys(struct bwn_mac *mac)
4485 {
4486 	int i;
4487 
4488 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4489 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4490 		    ("%s:%d: fail", __func__, __LINE__));
4491 
4492 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4493 		    NULL, BWN_SEC_KEYSIZE, NULL);
4494 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4495 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4496 			    NULL, BWN_SEC_KEYSIZE, NULL);
4497 		}
4498 		mac->mac_key[i].keyconf = NULL;
4499 	}
4500 }
4501 
4502 static void
4503 bwn_crypt_init(struct bwn_mac *mac)
4504 {
4505 	struct bwn_softc *sc = mac->mac_sc;
4506 
4507 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4508 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4509 	    ("%s:%d: fail", __func__, __LINE__));
4510 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4511 	mac->mac_ktp *= 2;
4512 	if (siba_get_revid(sc->sc_dev) >= 5)
4513 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4514 	bwn_clear_keys(mac);
4515 }
4516 
4517 static void
4518 bwn_chip_exit(struct bwn_mac *mac)
4519 {
4520 	struct bwn_softc *sc = mac->mac_sc;
4521 
4522 	bwn_phy_exit(mac);
4523 	siba_gpio_set(sc->sc_dev, 0);
4524 }
4525 
4526 static int
4527 bwn_fw_fillinfo(struct bwn_mac *mac)
4528 {
4529 	int error;
4530 
4531 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4532 	if (error == 0)
4533 		return (0);
4534 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4535 	if (error == 0)
4536 		return (0);
4537 	return (error);
4538 }
4539 
4540 static int
4541 bwn_gpio_init(struct bwn_mac *mac)
4542 {
4543 	struct bwn_softc *sc = mac->mac_sc;
4544 	uint32_t mask = 0x1f, set = 0xf, value;
4545 
4546 	BWN_WRITE_4(mac, BWN_MACCTL,
4547 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4548 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4549 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4550 
4551 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4552 		mask |= 0x0060;
4553 		set |= 0x0060;
4554 	}
4555 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4556 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4557 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4558 		mask |= 0x0200;
4559 		set |= 0x0200;
4560 	}
4561 	if (siba_get_revid(sc->sc_dev) >= 2)
4562 		mask |= 0x0010;
4563 
4564 	value = siba_gpio_get(sc->sc_dev);
4565 	if (value == -1)
4566 		return (0);
4567 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4568 
4569 	return (0);
4570 }
4571 
4572 static int
4573 bwn_fw_loadinitvals(struct bwn_mac *mac)
4574 {
4575 #define	GETFWOFFSET(fwp, offset)				\
4576 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4577 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4578 	const struct bwn_fwhdr *hdr;
4579 	struct bwn_fw *fw = &mac->mac_fw;
4580 	int error;
4581 
4582 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4583 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4584 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4585 	if (error)
4586 		return (error);
4587 	if (fw->initvals_band.fw) {
4588 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4589 		error = bwn_fwinitvals_write(mac,
4590 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4591 		    be32toh(hdr->size),
4592 		    fw->initvals_band.fw->datasize - hdr_len);
4593 	}
4594 	return (error);
4595 #undef GETFWOFFSET
4596 }
4597 
4598 static int
4599 bwn_phy_init(struct bwn_mac *mac)
4600 {
4601 	struct bwn_softc *sc = mac->mac_sc;
4602 	int error;
4603 
4604 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4605 	mac->mac_phy.rf_onoff(mac, 1);
4606 	error = mac->mac_phy.init(mac);
4607 	if (error) {
4608 		device_printf(sc->sc_dev, "PHY init failed\n");
4609 		goto fail0;
4610 	}
4611 	error = bwn_switch_channel(mac,
4612 	    mac->mac_phy.get_default_chan(mac));
4613 	if (error) {
4614 		device_printf(sc->sc_dev,
4615 		    "failed to switch default channel\n");
4616 		goto fail1;
4617 	}
4618 	return (0);
4619 fail1:
4620 	if (mac->mac_phy.exit)
4621 		mac->mac_phy.exit(mac);
4622 fail0:
4623 	mac->mac_phy.rf_onoff(mac, 0);
4624 
4625 	return (error);
4626 }
4627 
4628 static void
4629 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4630 {
4631 	uint16_t ant;
4632 	uint16_t tmp;
4633 
4634 	ant = bwn_ant2phy(antenna);
4635 
4636 	/* For ACK/CTS */
4637 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4638 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4639 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4640 	/* For Probe Resposes */
4641 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4642 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4643 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4644 }
4645 
4646 static void
4647 bwn_set_opmode(struct bwn_mac *mac)
4648 {
4649 	struct bwn_softc *sc = mac->mac_sc;
4650 	struct ifnet *ifp = sc->sc_ifp;
4651 	struct ieee80211com *ic = ifp->if_l2com;
4652 	uint32_t ctl;
4653 	uint16_t cfp_pretbtt;
4654 
4655 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4656 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4657 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4658 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4659 	ctl |= BWN_MACCTL_STA;
4660 
4661 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4662 	    ic->ic_opmode == IEEE80211_M_MBSS)
4663 		ctl |= BWN_MACCTL_HOSTAP;
4664 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4665 		ctl &= ~BWN_MACCTL_STA;
4666 	ctl |= sc->sc_filters;
4667 
4668 	if (siba_get_revid(sc->sc_dev) <= 4)
4669 		ctl |= BWN_MACCTL_PROMISC;
4670 
4671 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4672 
4673 	cfp_pretbtt = 2;
4674 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4675 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4676 		    siba_get_chiprev(sc->sc_dev) == 3)
4677 			cfp_pretbtt = 100;
4678 		else
4679 			cfp_pretbtt = 50;
4680 	}
4681 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4682 }
4683 
4684 static int
4685 bwn_dma_gettype(struct bwn_mac *mac)
4686 {
4687 	uint32_t tmp;
4688 	uint16_t base;
4689 
4690 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4691 	if (tmp & SIBA_TGSHIGH_DMA64)
4692 		return (BWN_DMA_64BIT);
4693 	base = bwn_dma_base(0, 0);
4694 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4695 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4696 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4697 		return (BWN_DMA_32BIT);
4698 
4699 	return (BWN_DMA_30BIT);
4700 }
4701 
4702 static void
4703 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4704 {
4705 	if (!error) {
4706 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4707 		*((bus_addr_t *)arg) = seg->ds_addr;
4708 	}
4709 }
4710 
4711 static void
4712 bwn_phy_g_init_sub(struct bwn_mac *mac)
4713 {
4714 	struct bwn_phy *phy = &mac->mac_phy;
4715 	struct bwn_phy_g *pg = &phy->phy_g;
4716 	struct bwn_softc *sc = mac->mac_sc;
4717 	uint16_t i, tmp;
4718 
4719 	if (phy->rev == 1)
4720 		bwn_phy_init_b5(mac);
4721 	else
4722 		bwn_phy_init_b6(mac);
4723 
4724 	if (phy->rev >= 2 || phy->gmode)
4725 		bwn_phy_init_a(mac);
4726 
4727 	if (phy->rev >= 2) {
4728 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4729 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4730 	}
4731 	if (phy->rev == 2) {
4732 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4733 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4734 	}
4735 	if (phy->rev > 5) {
4736 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4737 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4738 	}
4739 	if (phy->gmode || phy->rev >= 2) {
4740 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4741 		tmp &= BWN_PHYVER_VERSION;
4742 		if (tmp == 3 || tmp == 5) {
4743 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4744 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4745 		}
4746 		if (tmp == 5) {
4747 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4748 			    0x1f00);
4749 		}
4750 	}
4751 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4752 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4753 	if (phy->rf_rev == 8) {
4754 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4755 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4756 	}
4757 	if (BWN_HAS_LOOPBACK(phy))
4758 		bwn_loopback_calcgain(mac);
4759 
4760 	if (phy->rf_rev != 8) {
4761 		if (pg->pg_initval == 0xffff)
4762 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4763 		else
4764 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4765 	}
4766 	bwn_lo_g_init(mac);
4767 	if (BWN_HAS_TXMAG(phy)) {
4768 		BWN_RF_WRITE(mac, 0x52,
4769 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4770 		    | pg->pg_loctl.tx_bias |
4771 		    pg->pg_loctl.tx_magn);
4772 	} else {
4773 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4774 	}
4775 	if (phy->rev >= 6) {
4776 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4777 		    (pg->pg_loctl.tx_bias << 12));
4778 	}
4779 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4780 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4781 	else
4782 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4783 	if (phy->rev < 2)
4784 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4785 	else
4786 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4787 	if (phy->gmode || phy->rev >= 2) {
4788 		bwn_lo_g_adjust(mac);
4789 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4790 	}
4791 
4792 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4793 		for (i = 0; i < 64; i++) {
4794 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4795 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4796 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4797 			    -32), 31));
4798 		}
4799 		bwn_nrssi_threshold(mac);
4800 	} else if (phy->gmode || phy->rev >= 2) {
4801 		if (pg->pg_nrssi[0] == -1000) {
4802 			KASSERT(pg->pg_nrssi[1] == -1000,
4803 			    ("%s:%d: fail", __func__, __LINE__));
4804 			bwn_nrssi_slope_11g(mac);
4805 		} else
4806 			bwn_nrssi_threshold(mac);
4807 	}
4808 	if (phy->rf_rev == 8)
4809 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4810 	bwn_phy_hwpctl_init(mac);
4811 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4812 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4813 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4814 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4815 	}
4816 }
4817 
4818 static uint8_t
4819 bwn_has_hwpctl(struct bwn_mac *mac)
4820 {
4821 
4822 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4823 		return (0);
4824 	return (mac->mac_phy.use_hwpctl(mac));
4825 }
4826 
4827 static void
4828 bwn_phy_init_b5(struct bwn_mac *mac)
4829 {
4830 	struct bwn_phy *phy = &mac->mac_phy;
4831 	struct bwn_phy_g *pg = &phy->phy_g;
4832 	struct bwn_softc *sc = mac->mac_sc;
4833 	uint16_t offset, value;
4834 	uint8_t old_channel;
4835 
4836 	if (phy->analog == 1)
4837 		BWN_RF_SET(mac, 0x007a, 0x0050);
4838 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4839 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4840 		value = 0x2120;
4841 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4842 			BWN_PHY_WRITE(mac, offset, value);
4843 			value += 0x202;
4844 		}
4845 	}
4846 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4847 	if (phy->rf_ver == 0x2050)
4848 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4849 
4850 	if (phy->gmode || phy->rev >= 2) {
4851 		if (phy->rf_ver == 0x2050) {
4852 			BWN_RF_SET(mac, 0x007a, 0x0020);
4853 			BWN_RF_SET(mac, 0x0051, 0x0004);
4854 		}
4855 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4856 
4857 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4858 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4859 
4860 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4861 
4862 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4863 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4864 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4865 	}
4866 
4867 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4868 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4869 
4870 	if (phy->analog == 1) {
4871 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4872 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4873 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4874 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4875 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4876 	} else
4877 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4878 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4879 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4880 
4881 	if (phy->analog == 1)
4882 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4883 	else
4884 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4885 
4886 	if (phy->analog == 0)
4887 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4888 
4889 	old_channel = phy->chan;
4890 	bwn_phy_g_switch_chan(mac, 7, 0);
4891 
4892 	if (phy->rf_ver != 0x2050) {
4893 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4894 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4895 	}
4896 
4897 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4898 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4899 
4900 	if (phy->rf_ver == 0x2050) {
4901 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4902 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4903 	}
4904 
4905 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4906 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4907 	BWN_RF_SET(mac, 0x007a, 0x0007);
4908 
4909 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4910 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4911 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4912 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4913 
4914 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4915 	    pg->pg_txctl);
4916 
4917 	if (phy->rf_ver == 0x2050)
4918 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4919 
4920 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4921 }
4922 
4923 static void
4924 bwn_loopback_calcgain(struct bwn_mac *mac)
4925 {
4926 	struct bwn_phy *phy = &mac->mac_phy;
4927 	struct bwn_phy_g *pg = &phy->phy_g;
4928 	struct bwn_softc *sc = mac->mac_sc;
4929 	uint16_t backup_phy[16] = { 0 };
4930 	uint16_t backup_radio[3];
4931 	uint16_t backup_bband;
4932 	uint16_t i, j, loop_i_max;
4933 	uint16_t trsw_rx;
4934 	uint16_t loop1_outer_done, loop1_inner_done;
4935 
4936 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4937 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4938 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4939 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4940 	if (phy->rev != 1) {
4941 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4942 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4943 	}
4944 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4945 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4946 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4947 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4948 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4949 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4950 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4951 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4952 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4953 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4954 	backup_bband = pg->pg_bbatt.att;
4955 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4956 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4957 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4958 
4959 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4960 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4961 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4962 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4963 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4964 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4965 	if (phy->rev != 1) {
4966 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4967 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4968 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4969 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4970 	}
4971 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4972 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4973 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4974 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4975 
4976 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4977 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4978 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4979 
4980 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4981 	if (phy->rev != 1) {
4982 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4983 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4984 	}
4985 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4986 
4987 	if (phy->rf_rev == 8)
4988 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4989 	else {
4990 		BWN_RF_WRITE(mac, 0x52, 0);
4991 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4992 	}
4993 	bwn_phy_g_set_bbatt(mac, 11);
4994 
4995 	if (phy->rev >= 3)
4996 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4997 	else
4998 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4999 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5000 
5001 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
5002 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
5003 
5004 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
5005 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
5006 
5007 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
5008 		if (phy->rev >= 7) {
5009 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
5010 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
5011 		}
5012 	}
5013 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
5014 
5015 	j = 0;
5016 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
5017 	for (i = 0; i < loop_i_max; i++) {
5018 		for (j = 0; j < 16; j++) {
5019 			BWN_RF_WRITE(mac, 0x43, i);
5020 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
5021 			    (j << 8));
5022 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5023 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5024 			DELAY(20);
5025 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5026 				goto done0;
5027 		}
5028 	}
5029 done0:
5030 	loop1_outer_done = i;
5031 	loop1_inner_done = j;
5032 	if (j >= 8) {
5033 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
5034 		trsw_rx = 0x1b;
5035 		for (j = j - 8; j < 16; j++) {
5036 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
5037 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
5038 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
5039 			DELAY(20);
5040 			trsw_rx -= 3;
5041 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
5042 				goto done1;
5043 		}
5044 	} else
5045 		trsw_rx = 0x18;
5046 done1:
5047 
5048 	if (phy->rev != 1) {
5049 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
5050 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
5051 	}
5052 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
5053 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
5054 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
5055 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
5056 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
5057 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
5058 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
5059 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
5060 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
5061 
5062 	bwn_phy_g_set_bbatt(mac, backup_bband);
5063 
5064 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
5065 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
5066 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
5067 
5068 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
5069 	DELAY(10);
5070 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
5071 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
5072 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
5073 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
5074 
5075 	pg->pg_max_lb_gain =
5076 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
5077 	pg->pg_trsw_rx_gain = trsw_rx * 2;
5078 }
5079 
5080 static uint16_t
5081 bwn_rf_init_bcm2050(struct bwn_mac *mac)
5082 {
5083 	struct bwn_phy *phy = &mac->mac_phy;
5084 	uint32_t tmp1 = 0, tmp2 = 0;
5085 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
5086 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
5087 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
5088 	static const uint8_t rcc_table[] = {
5089 		0x02, 0x03, 0x01, 0x0f,
5090 		0x06, 0x07, 0x05, 0x0f,
5091 		0x0a, 0x0b, 0x09, 0x0f,
5092 		0x0e, 0x0f, 0x0d, 0x0f,
5093 	};
5094 
5095 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
5096 	    rfoverval = rfover = cck3 = 0;
5097 	radio0 = BWN_RF_READ(mac, 0x43);
5098 	radio1 = BWN_RF_READ(mac, 0x51);
5099 	radio2 = BWN_RF_READ(mac, 0x52);
5100 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
5101 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
5102 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5103 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5104 
5105 	if (phy->type == BWN_PHYTYPE_B) {
5106 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5107 		reg0 = BWN_READ_2(mac, 0x3ec);
5108 
5109 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5110 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5111 	} else if (phy->gmode || phy->rev >= 2) {
5112 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5113 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5114 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5115 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5116 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5117 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5118 
5119 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5120 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5121 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5122 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5123 		if (BWN_HAS_LOOPBACK(phy)) {
5124 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5125 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5126 			if (phy->rev >= 3)
5127 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5128 			else
5129 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5130 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5131 		}
5132 
5133 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5134 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5135 			BWN_LPD(0, 1, 1)));
5136 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5137 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5138 	}
5139 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5140 
5141 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5142 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5143 	reg1 = BWN_READ_2(mac, 0x3e6);
5144 	reg2 = BWN_READ_2(mac, 0x3f4);
5145 
5146 	if (phy->analog == 0)
5147 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5148 	else {
5149 		if (phy->analog >= 2)
5150 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5151 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5152 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5153 	}
5154 
5155 	reg = BWN_RF_READ(mac, 0x60);
5156 	index = (reg & 0x001e) >> 1;
5157 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5158 
5159 	if (phy->type == BWN_PHYTYPE_B)
5160 		BWN_RF_WRITE(mac, 0x78, 0x26);
5161 	if (phy->gmode || phy->rev >= 2) {
5162 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5163 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5164 			BWN_LPD(0, 1, 1)));
5165 	}
5166 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5167 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5168 	if (phy->gmode || phy->rev >= 2) {
5169 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5170 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5171 			BWN_LPD(0, 0, 1)));
5172 	}
5173 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5174 	BWN_RF_SET(mac, 0x51, 0x0004);
5175 	if (phy->rf_rev == 8)
5176 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5177 	else {
5178 		BWN_RF_WRITE(mac, 0x52, 0);
5179 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5180 	}
5181 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5182 
5183 	for (i = 0; i < 16; i++) {
5184 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5185 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5186 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5187 		if (phy->gmode || phy->rev >= 2) {
5188 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5189 			    bwn_rf_2050_rfoverval(mac,
5190 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5191 		}
5192 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5193 		DELAY(10);
5194 		if (phy->gmode || phy->rev >= 2) {
5195 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5196 			    bwn_rf_2050_rfoverval(mac,
5197 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5198 		}
5199 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5200 		DELAY(10);
5201 		if (phy->gmode || phy->rev >= 2) {
5202 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5203 			    bwn_rf_2050_rfoverval(mac,
5204 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5205 		}
5206 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5207 		DELAY(20);
5208 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5209 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5210 		if (phy->gmode || phy->rev >= 2) {
5211 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5212 			    bwn_rf_2050_rfoverval(mac,
5213 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5214 		}
5215 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5216 	}
5217 	DELAY(10);
5218 
5219 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5220 	tmp1++;
5221 	tmp1 >>= 9;
5222 
5223 	for (i = 0; i < 16; i++) {
5224 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5225 		BWN_RF_WRITE(mac, 0x78, radio78);
5226 		DELAY(10);
5227 		for (j = 0; j < 16; j++) {
5228 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5229 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5230 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5231 			if (phy->gmode || phy->rev >= 2) {
5232 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5233 				    bwn_rf_2050_rfoverval(mac,
5234 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5235 			}
5236 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5237 			DELAY(10);
5238 			if (phy->gmode || phy->rev >= 2) {
5239 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5240 				    bwn_rf_2050_rfoverval(mac,
5241 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5242 			}
5243 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5244 			DELAY(10);
5245 			if (phy->gmode || phy->rev >= 2) {
5246 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5247 				    bwn_rf_2050_rfoverval(mac,
5248 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5249 			}
5250 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5251 			DELAY(10);
5252 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5253 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5254 			if (phy->gmode || phy->rev >= 2) {
5255 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5256 				    bwn_rf_2050_rfoverval(mac,
5257 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5258 			}
5259 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5260 		}
5261 		tmp2++;
5262 		tmp2 >>= 8;
5263 		if (tmp1 < tmp2)
5264 			break;
5265 	}
5266 
5267 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5268 	BWN_RF_WRITE(mac, 0x51, radio1);
5269 	BWN_RF_WRITE(mac, 0x52, radio2);
5270 	BWN_RF_WRITE(mac, 0x43, radio0);
5271 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5272 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5273 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5274 	BWN_WRITE_2(mac, 0x3e6, reg1);
5275 	if (phy->analog != 0)
5276 		BWN_WRITE_2(mac, 0x3f4, reg2);
5277 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5278 	bwn_spu_workaround(mac, phy->chan);
5279 	if (phy->type == BWN_PHYTYPE_B) {
5280 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5281 		BWN_WRITE_2(mac, 0x3ec, reg0);
5282 	} else if (phy->gmode) {
5283 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5284 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5285 			    & 0x7fff);
5286 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5287 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5288 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5289 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5290 			      analogoverval);
5291 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5292 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5293 		if (BWN_HAS_LOOPBACK(phy)) {
5294 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5295 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5296 		}
5297 	}
5298 
5299 	return ((i > 15) ? radio78 : rcc);
5300 }
5301 
5302 static void
5303 bwn_phy_init_b6(struct bwn_mac *mac)
5304 {
5305 	struct bwn_phy *phy = &mac->mac_phy;
5306 	struct bwn_phy_g *pg = &phy->phy_g;
5307 	struct bwn_softc *sc = mac->mac_sc;
5308 	uint16_t offset, val;
5309 	uint8_t old_channel;
5310 
5311 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5312 	    ("%s:%d: fail", __func__, __LINE__));
5313 
5314 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5315 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5316 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5317 		BWN_RF_WRITE(mac, 0x51, 0x37);
5318 		BWN_RF_WRITE(mac, 0x52, 0x70);
5319 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5320 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5321 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5322 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5323 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5324 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5325 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5326 		bwn_hf_write(mac,
5327 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5328 	}
5329 	if (phy->rf_rev == 8) {
5330 		BWN_RF_WRITE(mac, 0x51, 0);
5331 		BWN_RF_WRITE(mac, 0x52, 0x40);
5332 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5333 		BWN_RF_WRITE(mac, 0x54, 0x98);
5334 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5335 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5336 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5337 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5338 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5339 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5340 		} else {
5341 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5342 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5343 		}
5344 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5345 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5346 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5347 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5348 	}
5349 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5350 		BWN_PHY_WRITE(mac, offset, val);
5351 		val -= 0x0202;
5352 	}
5353 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5354 		BWN_PHY_WRITE(mac, offset, val);
5355 		val -= 0x0202;
5356 	}
5357 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5358 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5359 		val += 0x0202;
5360 	}
5361 	if (phy->type == BWN_PHYTYPE_G) {
5362 		BWN_RF_SET(mac, 0x007a, 0x0020);
5363 		BWN_RF_SET(mac, 0x0051, 0x0004);
5364 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5365 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5366 		BWN_PHY_WRITE(mac, 0x5b, 0);
5367 		BWN_PHY_WRITE(mac, 0x5c, 0);
5368 	}
5369 
5370 	old_channel = phy->chan;
5371 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5372 
5373 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5374 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5375 	DELAY(40);
5376 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5377 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5378 		BWN_RF_WRITE(mac, 0x50, 0x20);
5379 	}
5380 	if (phy->rf_rev <= 2) {
5381 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5382 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5383 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5384 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5385 	}
5386 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5387 
5388 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5389 
5390 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5391 	if (phy->rf_rev >= 6)
5392 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5393 	else
5394 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5395 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5396 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5397 	    pg->pg_txctl);
5398 	if (phy->rf_rev <= 5)
5399 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5400 	if (phy->rf_rev <= 2)
5401 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5402 
5403 	if (phy->analog == 4) {
5404 		BWN_WRITE_2(mac, 0x3e4, 9);
5405 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5406 	} else
5407 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5408 	if (phy->type == BWN_PHYTYPE_B)
5409 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5410 	else if (phy->type == BWN_PHYTYPE_G)
5411 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5412 }
5413 
5414 static void
5415 bwn_phy_init_a(struct bwn_mac *mac)
5416 {
5417 	struct bwn_phy *phy = &mac->mac_phy;
5418 	struct bwn_softc *sc = mac->mac_sc;
5419 
5420 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5421 	    ("%s:%d: fail", __func__, __LINE__));
5422 
5423 	if (phy->rev >= 6) {
5424 		if (phy->type == BWN_PHYTYPE_A)
5425 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5426 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5427 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5428 		else
5429 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5430 	}
5431 
5432 	bwn_wa_init(mac);
5433 
5434 	if (phy->type == BWN_PHYTYPE_G &&
5435 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5436 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5437 }
5438 
5439 static void
5440 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5441 {
5442 	int i;
5443 
5444 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5445 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5446 }
5447 
5448 static void
5449 bwn_wa_agc(struct bwn_mac *mac)
5450 {
5451 	struct bwn_phy *phy = &mac->mac_phy;
5452 
5453 	if (phy->rev == 1) {
5454 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5455 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5456 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5457 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5458 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5459 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5460 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5461 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5462 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5463 	} else {
5464 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5465 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5466 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5467 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5468 	}
5469 
5470 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5471 	    0x5700);
5472 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5473 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5474 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5475 	BWN_RF_SET(mac, 0x7a, 0x0008);
5476 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5477 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5478 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5479 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5480 	if (phy->rev == 1)
5481 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5482 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5483 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5484 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5485 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5486 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5487 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5488 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5489 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5490 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5491 	if (phy->rev == 1) {
5492 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5493 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5494 	} else {
5495 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5496 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5497 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5498 		if (phy->rev >= 6) {
5499 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5500 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5501 			    (uint16_t)~0xf000, 0x3000);
5502 		}
5503 	}
5504 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5505 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5506 	if (phy->rev == 1) {
5507 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5508 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5509 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5510 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5511 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5512 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5513 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5514 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5515 	} else {
5516 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5517 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5518 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5519 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5520 	}
5521 	if (phy->rev >= 6) {
5522 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5523 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5524 	}
5525 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5526 }
5527 
5528 static void
5529 bwn_wa_grev1(struct bwn_mac *mac)
5530 {
5531 	struct bwn_phy *phy = &mac->mac_phy;
5532 	int i;
5533 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5534 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5535 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5536 
5537 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5538 
5539 	/* init CRSTHRES and ANTDWELL */
5540 	if (phy->rev == 1) {
5541 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5542 	} else if (phy->rev == 2) {
5543 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5544 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5545 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5546 	} else {
5547 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5548 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5549 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5550 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5551 	}
5552 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5553 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5554 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5555 
5556 	/* XXX support PHY-A??? */
5557 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5558 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5559 		    bwn_tab_finefreqg[i]);
5560 
5561 	/* XXX support PHY-A??? */
5562 	if (phy->rev == 1)
5563 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5564 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5565 			    bwn_tab_noise_g1[i]);
5566 	else
5567 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5568 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5569 			    bwn_tab_noise_g2[i]);
5570 
5571 
5572 	for (i = 0; i < N(bwn_tab_rotor); i++)
5573 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5574 		    bwn_tab_rotor[i]);
5575 
5576 	/* XXX support PHY-A??? */
5577 	if (phy->rev >= 6) {
5578 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5579 		    BWN_PHY_ENCORE_EN)
5580 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5581 		else
5582 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5583 	} else
5584 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5585 
5586 	for (i = 0; i < N(bwn_tab_retard); i++)
5587 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5588 		    bwn_tab_retard[i]);
5589 
5590 	if (phy->rev == 1) {
5591 		for (i = 0; i < 16; i++)
5592 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5593 			    i, 0x0020);
5594 	} else {
5595 		for (i = 0; i < 32; i++)
5596 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5597 	}
5598 
5599 	bwn_wa_agc(mac);
5600 }
5601 
5602 static void
5603 bwn_wa_grev26789(struct bwn_mac *mac)
5604 {
5605 	struct bwn_phy *phy = &mac->mac_phy;
5606 	int i;
5607 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5608 	uint16_t ofdmrev;
5609 
5610 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5611 
5612 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5613 
5614 	/* init CRSTHRES and ANTDWELL */
5615 	if (phy->rev == 1)
5616 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5617 	else if (phy->rev == 2) {
5618 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5619 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5620 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5621 	} else {
5622 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5623 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5624 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5625 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5626 	}
5627 
5628 	for (i = 0; i < 64; i++)
5629 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5630 
5631 	/* XXX support PHY-A??? */
5632 	if (phy->rev == 1)
5633 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5634 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5635 			    bwn_tab_noise_g1[i]);
5636 	else
5637 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5638 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5639 			    bwn_tab_noise_g2[i]);
5640 
5641 	/* XXX support PHY-A??? */
5642 	if (phy->rev >= 6) {
5643 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5644 		    BWN_PHY_ENCORE_EN)
5645 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5646 		else
5647 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5648 	} else
5649 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5650 
5651 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5652 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5653 		    bwn_tab_sigmasqr2[i]);
5654 
5655 	if (phy->rev == 1) {
5656 		for (i = 0; i < 16; i++)
5657 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5658 			    0x0020);
5659 	} else {
5660 		for (i = 0; i < 32; i++)
5661 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5662 	}
5663 
5664 	bwn_wa_agc(mac);
5665 
5666 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5667 	if (ofdmrev > 2) {
5668 		if (phy->type == BWN_PHYTYPE_A)
5669 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5670 		else
5671 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5672 	} else {
5673 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5674 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5675 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5676 	}
5677 
5678 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5679 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5680 }
5681 
5682 static void
5683 bwn_wa_init(struct bwn_mac *mac)
5684 {
5685 	struct bwn_phy *phy = &mac->mac_phy;
5686 	struct bwn_softc *sc = mac->mac_sc;
5687 
5688 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5689 
5690 	switch (phy->rev) {
5691 	case 1:
5692 		bwn_wa_grev1(mac);
5693 		break;
5694 	case 2:
5695 	case 6:
5696 	case 7:
5697 	case 8:
5698 	case 9:
5699 		bwn_wa_grev26789(mac);
5700 		break;
5701 	default:
5702 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5703 	}
5704 
5705 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5706 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5707 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5708 		if (phy->rev < 2) {
5709 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5710 			    0x0002);
5711 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5712 			    0x0001);
5713 		} else {
5714 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5715 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5716 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5717 			     BWN_BFL_EXTLNA) &&
5718 			    (phy->rev >= 7)) {
5719 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5720 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5721 				    0x0020, 0x0001);
5722 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5723 				    0x0021, 0x0001);
5724 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5725 				    0x0022, 0x0001);
5726 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5727 				    0x0023, 0x0000);
5728 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5729 				    0x0000, 0x0000);
5730 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5731 				    0x0003, 0x0002);
5732 			}
5733 		}
5734 	}
5735 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5736 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5737 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5738 	}
5739 
5740 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5741 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5742 }
5743 
5744 static void
5745 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5746     uint16_t value)
5747 {
5748 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5749 	uint16_t addr;
5750 
5751 	addr = table + offset;
5752 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5753 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5754 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5755 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5756 	}
5757 	pg->pg_ofdmtab_addr = addr;
5758 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5759 }
5760 
5761 static void
5762 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5763     uint32_t value)
5764 {
5765 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5766 	uint16_t addr;
5767 
5768 	addr = table + offset;
5769 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5770 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5771 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5772 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5773 	}
5774 	pg->pg_ofdmtab_addr = addr;
5775 
5776 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5777 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5778 }
5779 
5780 static void
5781 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5782     uint16_t value)
5783 {
5784 
5785 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5786 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5787 }
5788 
5789 static void
5790 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5791 {
5792 	struct bwn_phy *phy = &mac->mac_phy;
5793 	struct bwn_softc *sc = mac->mac_sc;
5794 	unsigned int i, max_loop;
5795 	uint16_t value;
5796 	uint32_t buffer[5] = {
5797 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5798 	};
5799 
5800 	if (ofdm) {
5801 		max_loop = 0x1e;
5802 		buffer[0] = 0x000201cc;
5803 	} else {
5804 		max_loop = 0xfa;
5805 		buffer[0] = 0x000b846e;
5806 	}
5807 
5808 	BWN_ASSERT_LOCKED(mac->mac_sc);
5809 
5810 	for (i = 0; i < 5; i++)
5811 		bwn_ram_write(mac, i * 4, buffer[i]);
5812 
5813 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5814 	BWN_WRITE_2(mac, 0x07c0,
5815 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5816 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5817 	BWN_WRITE_2(mac, 0x050c, value);
5818 	if (phy->type == BWN_PHYTYPE_LP)
5819 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5820 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5821 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5822 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5823 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5824 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5825 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5826 	if (phy->type == BWN_PHYTYPE_LP)
5827 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5828 	else
5829 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5830 
5831 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5832 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5833 	for (i = 0x00; i < max_loop; i++) {
5834 		value = BWN_READ_2(mac, 0x050e);
5835 		if (value & 0x0080)
5836 			break;
5837 		DELAY(10);
5838 	}
5839 	for (i = 0x00; i < 0x0a; i++) {
5840 		value = BWN_READ_2(mac, 0x050e);
5841 		if (value & 0x0400)
5842 			break;
5843 		DELAY(10);
5844 	}
5845 	for (i = 0x00; i < 0x19; i++) {
5846 		value = BWN_READ_2(mac, 0x0690);
5847 		if (!(value & 0x0100))
5848 			break;
5849 		DELAY(10);
5850 	}
5851 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5852 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5853 }
5854 
5855 static void
5856 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5857 {
5858 	uint32_t macctl;
5859 
5860 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5861 
5862 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5863 	if (macctl & BWN_MACCTL_BIGENDIAN)
5864 		printf("TODO: need swap\n");
5865 
5866 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5867 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5868 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5869 }
5870 
5871 static void
5872 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5873 {
5874 	uint16_t value;
5875 
5876 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5877 	    ("%s:%d: fail", __func__, __LINE__));
5878 
5879 	value = (uint8_t) (ctl->q);
5880 	value |= ((uint8_t) (ctl->i)) << 8;
5881 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5882 }
5883 
5884 static uint16_t
5885 bwn_lo_calcfeed(struct bwn_mac *mac,
5886     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5887 {
5888 	struct bwn_phy *phy = &mac->mac_phy;
5889 	struct bwn_softc *sc = mac->mac_sc;
5890 	uint16_t rfover;
5891 	uint16_t feedthrough;
5892 
5893 	if (phy->gmode) {
5894 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5895 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5896 
5897 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5898 		    ("%s:%d: fail", __func__, __LINE__));
5899 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5900 		    ("%s:%d: fail", __func__, __LINE__));
5901 
5902 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5903 
5904 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5905 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5906 		    phy->rev > 6)
5907 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5908 
5909 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5910 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5911 		DELAY(10);
5912 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5913 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5914 		DELAY(10);
5915 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5916 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5917 		DELAY(10);
5918 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5919 	} else {
5920 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5921 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5922 		DELAY(10);
5923 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5924 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5925 		DELAY(10);
5926 		pga |= BWN_PHY_PGACTL_LPF;
5927 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5928 	}
5929 	DELAY(21);
5930 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5931 
5932 	return (feedthrough);
5933 }
5934 
5935 static uint16_t
5936 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5937     uint16_t *value, uint16_t *pad_mix_gain)
5938 {
5939 	struct bwn_phy *phy = &mac->mac_phy;
5940 	uint16_t reg, v, padmix;
5941 
5942 	if (phy->type == BWN_PHYTYPE_B) {
5943 		v = 0x30;
5944 		if (phy->rf_rev <= 5) {
5945 			reg = 0x43;
5946 			padmix = 0;
5947 		} else {
5948 			reg = 0x52;
5949 			padmix = 5;
5950 		}
5951 	} else {
5952 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5953 			reg = 0x43;
5954 			v = 0x10;
5955 			padmix = 2;
5956 		} else {
5957 			reg = 0x52;
5958 			v = 0x30;
5959 			padmix = 5;
5960 		}
5961 	}
5962 	if (value)
5963 		*value = v;
5964 	if (pad_mix_gain)
5965 		*pad_mix_gain = padmix;
5966 
5967 	return (reg);
5968 }
5969 
5970 static void
5971 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5972 {
5973 	struct bwn_phy *phy = &mac->mac_phy;
5974 	struct bwn_phy_g *pg = &phy->phy_g;
5975 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5976 	uint16_t reg, mask;
5977 	uint16_t trsw_rx, pga;
5978 	uint16_t rf_pctl_reg;
5979 
5980 	static const uint8_t tx_bias_values[] = {
5981 		0x09, 0x08, 0x0a, 0x01, 0x00,
5982 		0x02, 0x05, 0x04, 0x06,
5983 	};
5984 	static const uint8_t tx_magn_values[] = {
5985 		0x70, 0x40,
5986 	};
5987 
5988 	if (!BWN_HAS_LOOPBACK(phy)) {
5989 		rf_pctl_reg = 6;
5990 		trsw_rx = 2;
5991 		pga = 0;
5992 	} else {
5993 		int lb_gain;
5994 
5995 		trsw_rx = 0;
5996 		lb_gain = pg->pg_max_lb_gain / 2;
5997 		if (lb_gain > 10) {
5998 			rf_pctl_reg = 0;
5999 			pga = abs(10 - lb_gain) / 6;
6000 			pga = MIN(MAX(pga, 0), 15);
6001 		} else {
6002 			int cmp_val;
6003 			int tmp;
6004 
6005 			pga = 0;
6006 			cmp_val = 0x24;
6007 			if ((phy->rev >= 2) &&
6008 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
6009 				cmp_val = 0x3c;
6010 			tmp = lb_gain;
6011 			if ((10 - lb_gain) < cmp_val)
6012 				tmp = (10 - lb_gain);
6013 			if (tmp < 0)
6014 				tmp += 6;
6015 			else
6016 				tmp += 3;
6017 			cmp_val /= 4;
6018 			tmp /= 4;
6019 			if (tmp >= cmp_val)
6020 				rf_pctl_reg = cmp_val;
6021 			else
6022 				rf_pctl_reg = tmp;
6023 		}
6024 	}
6025 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
6026 	bwn_phy_g_set_bbatt(mac, 2);
6027 
6028 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
6029 	mask = ~mask;
6030 	BWN_RF_MASK(mac, reg, mask);
6031 
6032 	if (BWN_HAS_TXMAG(phy)) {
6033 		int i, j;
6034 		int feedthrough;
6035 		int min_feedth = 0xffff;
6036 		uint8_t tx_magn, tx_bias;
6037 
6038 		for (i = 0; i < N(tx_magn_values); i++) {
6039 			tx_magn = tx_magn_values[i];
6040 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
6041 			for (j = 0; j < N(tx_bias_values); j++) {
6042 				tx_bias = tx_bias_values[j];
6043 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
6044 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
6045 				    trsw_rx);
6046 				if (feedthrough < min_feedth) {
6047 					lo->tx_bias = tx_bias;
6048 					lo->tx_magn = tx_magn;
6049 					min_feedth = feedthrough;
6050 				}
6051 				if (lo->tx_bias == 0)
6052 					break;
6053 			}
6054 			BWN_RF_WRITE(mac, 0x52,
6055 					  (BWN_RF_READ(mac, 0x52)
6056 					   & 0xff00) | lo->tx_bias | lo->
6057 					  tx_magn);
6058 		}
6059 	} else {
6060 		lo->tx_magn = 0;
6061 		lo->tx_bias = 0;
6062 		BWN_RF_MASK(mac, 0x52, 0xfff0);
6063 	}
6064 
6065 	BWN_GETTIME(lo->txctl_measured_time);
6066 }
6067 
6068 static void
6069 bwn_lo_get_powervector(struct bwn_mac *mac)
6070 {
6071 	struct bwn_phy *phy = &mac->mac_phy;
6072 	struct bwn_phy_g *pg = &phy->phy_g;
6073 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6074 	int i;
6075 	uint64_t tmp;
6076 	uint64_t power_vector = 0;
6077 
6078 	for (i = 0; i < 8; i += 2) {
6079 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
6080 		power_vector |= (tmp << (i * 8));
6081 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
6082 	}
6083 	if (power_vector)
6084 		lo->power_vector = power_vector;
6085 
6086 	BWN_GETTIME(lo->pwr_vec_read_time);
6087 }
6088 
6089 static void
6090 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
6091     int use_trsw_rx)
6092 {
6093 	struct bwn_phy *phy = &mac->mac_phy;
6094 	struct bwn_phy_g *pg = &phy->phy_g;
6095 	uint16_t tmp;
6096 
6097 	if (max_rx_gain < 0)
6098 		max_rx_gain = 0;
6099 
6100 	if (BWN_HAS_LOOPBACK(phy)) {
6101 		int trsw_rx = 0;
6102 		int trsw_rx_gain;
6103 
6104 		if (use_trsw_rx) {
6105 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6106 			if (max_rx_gain >= trsw_rx_gain) {
6107 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6108 				trsw_rx = 0x20;
6109 			}
6110 		} else
6111 			trsw_rx_gain = max_rx_gain;
6112 		if (trsw_rx_gain < 9) {
6113 			pg->pg_lna_lod_gain = 0;
6114 		} else {
6115 			pg->pg_lna_lod_gain = 1;
6116 			trsw_rx_gain -= 8;
6117 		}
6118 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6119 		pg->pg_pga_gain = trsw_rx_gain / 3;
6120 		if (pg->pg_pga_gain >= 5) {
6121 			pg->pg_pga_gain -= 5;
6122 			pg->pg_lna_gain = 2;
6123 		} else
6124 			pg->pg_lna_gain = 0;
6125 	} else {
6126 		pg->pg_lna_gain = 0;
6127 		pg->pg_trsw_rx_gain = 0x20;
6128 		if (max_rx_gain >= 0x14) {
6129 			pg->pg_lna_lod_gain = 1;
6130 			pg->pg_pga_gain = 2;
6131 		} else if (max_rx_gain >= 0x12) {
6132 			pg->pg_lna_lod_gain = 1;
6133 			pg->pg_pga_gain = 1;
6134 		} else if (max_rx_gain >= 0xf) {
6135 			pg->pg_lna_lod_gain = 1;
6136 			pg->pg_pga_gain = 0;
6137 		} else {
6138 			pg->pg_lna_lod_gain = 0;
6139 			pg->pg_pga_gain = 0;
6140 		}
6141 	}
6142 
6143 	tmp = BWN_RF_READ(mac, 0x7a);
6144 	if (pg->pg_lna_lod_gain == 0)
6145 		tmp &= ~0x0008;
6146 	else
6147 		tmp |= 0x0008;
6148 	BWN_RF_WRITE(mac, 0x7a, tmp);
6149 }
6150 
6151 static void
6152 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6153 {
6154 	struct bwn_phy *phy = &mac->mac_phy;
6155 	struct bwn_phy_g *pg = &phy->phy_g;
6156 	struct bwn_softc *sc = mac->mac_sc;
6157 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6158 	struct timespec ts;
6159 	uint16_t tmp;
6160 
6161 	if (bwn_has_hwpctl(mac)) {
6162 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6163 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6164 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6165 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6166 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6167 
6168 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6169 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6170 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6171 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6172 	}
6173 	if (phy->type == BWN_PHYTYPE_B &&
6174 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6175 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6176 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6177 	}
6178 	if (phy->rev >= 2) {
6179 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6180 		sav->phy_analogoverval =
6181 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6182 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6183 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6184 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6185 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6186 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6187 
6188 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6189 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6190 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6191 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6192 		if (phy->type == BWN_PHYTYPE_G) {
6193 			if ((phy->rev >= 7) &&
6194 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6195 			     BWN_BFL_EXTLNA)) {
6196 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6197 			} else {
6198 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6199 			}
6200 		} else {
6201 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6202 		}
6203 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6204 	}
6205 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6206 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6207 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6208 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6209 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6210 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6211 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6212 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6213 
6214 	if (!BWN_HAS_TXMAG(phy)) {
6215 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6216 		sav->rf2 &= 0x00f0;
6217 	}
6218 	if (phy->type == BWN_PHYTYPE_B) {
6219 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6220 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6221 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6222 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6223 	} else {
6224 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6225 			    | 0x8000);
6226 	}
6227 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6228 		    & 0xf000);
6229 
6230 	tmp =
6231 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6232 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6233 
6234 	tmp = sav->phy_syncctl;
6235 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6236 	tmp = sav->rf1;
6237 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6238 
6239 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6240 	if (phy->type == BWN_PHYTYPE_G ||
6241 	    (phy->type == BWN_PHYTYPE_B &&
6242 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6243 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6244 	} else
6245 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6246 	if (phy->rev >= 2)
6247 		bwn_dummy_transmission(mac, 0, 1);
6248 	bwn_phy_g_switch_chan(mac, 6, 0);
6249 	BWN_RF_READ(mac, 0x51);
6250 	if (phy->type == BWN_PHYTYPE_G)
6251 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6252 
6253 	nanouptime(&ts);
6254 	if (time_before(lo->txctl_measured_time,
6255 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6256 		bwn_lo_measure_txctl_values(mac);
6257 
6258 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6259 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6260 	else {
6261 		if (phy->type == BWN_PHYTYPE_B)
6262 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6263 		else
6264 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6265 	}
6266 }
6267 
6268 static void
6269 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6270 {
6271 	struct bwn_phy *phy = &mac->mac_phy;
6272 	struct bwn_phy_g *pg = &phy->phy_g;
6273 	uint16_t tmp;
6274 
6275 	if (phy->rev >= 2) {
6276 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6277 		tmp = (pg->pg_pga_gain << 8);
6278 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6279 		DELAY(5);
6280 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6281 		DELAY(2);
6282 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6283 	} else {
6284 		tmp = (pg->pg_pga_gain | 0xefa0);
6285 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6286 	}
6287 	if (phy->type == BWN_PHYTYPE_G) {
6288 		if (phy->rev >= 3)
6289 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6290 		else
6291 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6292 		if (phy->rev >= 2)
6293 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6294 		else
6295 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6296 	}
6297 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6298 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6299 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6300 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6301 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6302 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6303 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6304 	if (!BWN_HAS_TXMAG(phy)) {
6305 		tmp = sav->rf2;
6306 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6307 	}
6308 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6309 	if (phy->type == BWN_PHYTYPE_B &&
6310 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6311 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6312 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6313 	}
6314 	if (phy->rev >= 2) {
6315 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6316 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6317 			      sav->phy_analogoverval);
6318 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6319 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6320 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6321 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6322 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6323 	}
6324 	if (bwn_has_hwpctl(mac)) {
6325 		tmp = (sav->phy_lomask & 0xbfff);
6326 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6327 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6328 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6329 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6330 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6331 	}
6332 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6333 }
6334 
6335 static int
6336 bwn_lo_probe_loctl(struct bwn_mac *mac,
6337     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6338 {
6339 	struct bwn_phy *phy = &mac->mac_phy;
6340 	struct bwn_phy_g *pg = &phy->phy_g;
6341 	struct bwn_loctl orig, test;
6342 	struct bwn_loctl prev = { -100, -100 };
6343 	static const struct bwn_loctl modifiers[] = {
6344 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6345 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6346 	};
6347 	int begin, end, lower = 0, i;
6348 	uint16_t feedth;
6349 
6350 	if (d->curstate == 0) {
6351 		begin = 1;
6352 		end = 8;
6353 	} else if (d->curstate % 2 == 0) {
6354 		begin = d->curstate - 1;
6355 		end = d->curstate + 1;
6356 	} else {
6357 		begin = d->curstate - 2;
6358 		end = d->curstate + 2;
6359 	}
6360 	if (begin < 1)
6361 		begin += 8;
6362 	if (end > 8)
6363 		end -= 8;
6364 
6365 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6366 	i = begin;
6367 	d->curstate = i;
6368 	while (1) {
6369 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6370 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6371 		test.i += modifiers[i - 1].i * d->multipler;
6372 		test.q += modifiers[i - 1].q * d->multipler;
6373 		if ((test.i != prev.i || test.q != prev.q) &&
6374 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6375 			bwn_lo_write(mac, &test);
6376 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6377 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6378 			if (feedth < d->feedth) {
6379 				memcpy(probe, &test,
6380 				    sizeof(struct bwn_loctl));
6381 				lower = 1;
6382 				d->feedth = feedth;
6383 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6384 					break;
6385 			}
6386 		}
6387 		memcpy(&prev, &test, sizeof(prev));
6388 		if (i == end)
6389 			break;
6390 		if (i == 8)
6391 			i = 1;
6392 		else
6393 			i++;
6394 		d->curstate = i;
6395 	}
6396 
6397 	return (lower);
6398 }
6399 
6400 static void
6401 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6402 {
6403 	struct bwn_phy *phy = &mac->mac_phy;
6404 	struct bwn_phy_g *pg = &phy->phy_g;
6405 	struct bwn_lo_g_sm d;
6406 	struct bwn_loctl probe;
6407 	int lower, repeat, cnt = 0;
6408 	uint16_t feedth;
6409 
6410 	d.nmeasure = 0;
6411 	d.multipler = 1;
6412 	if (BWN_HAS_LOOPBACK(phy))
6413 		d.multipler = 3;
6414 
6415 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6416 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6417 
6418 	do {
6419 		bwn_lo_write(mac, &d.loctl);
6420 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6421 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6422 		if (feedth < 0x258) {
6423 			if (feedth >= 0x12c)
6424 				*rxgain += 6;
6425 			else
6426 				*rxgain += 3;
6427 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6428 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6429 		}
6430 		d.feedth = feedth;
6431 		d.curstate = 0;
6432 		do {
6433 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6434 			    ("%s:%d: fail", __func__, __LINE__));
6435 			memcpy(&probe, &d.loctl,
6436 			       sizeof(struct bwn_loctl));
6437 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6438 			if (!lower)
6439 				break;
6440 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6441 				break;
6442 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6443 			d.nmeasure++;
6444 		} while (d.nmeasure < 24);
6445 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6446 
6447 		if (BWN_HAS_LOOPBACK(phy)) {
6448 			if (d.feedth > 0x1194)
6449 				*rxgain -= 6;
6450 			else if (d.feedth < 0x5dc)
6451 				*rxgain += 3;
6452 			if (cnt == 0) {
6453 				if (d.feedth <= 0x5dc) {
6454 					d.multipler = 1;
6455 					cnt++;
6456 				} else
6457 					d.multipler = 2;
6458 			} else if (cnt == 2)
6459 				d.multipler = 1;
6460 		}
6461 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6462 	} while (++cnt < repeat);
6463 }
6464 
6465 static struct bwn_lo_calib *
6466 bwn_lo_calibset(struct bwn_mac *mac,
6467     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6468 {
6469 	struct bwn_phy *phy = &mac->mac_phy;
6470 	struct bwn_phy_g *pg = &phy->phy_g;
6471 	struct bwn_loctl loctl = { 0, 0 };
6472 	struct bwn_lo_calib *cal;
6473 	struct bwn_lo_g_value sval = { 0 };
6474 	int rxgain;
6475 	uint16_t pad, reg, value;
6476 
6477 	sval.old_channel = phy->chan;
6478 	bwn_mac_suspend(mac);
6479 	bwn_lo_save(mac, &sval);
6480 
6481 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6482 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6483 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6484 
6485 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6486 	if (rfatt->padmix)
6487 		rxgain -= pad;
6488 	if (BWN_HAS_LOOPBACK(phy))
6489 		rxgain += pg->pg_max_lb_gain;
6490 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6491 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6492 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6493 
6494 	bwn_lo_restore(mac, &sval);
6495 	bwn_mac_enable(mac);
6496 
6497 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6498 	if (!cal) {
6499 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6500 		return (NULL);
6501 	}
6502 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6503 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6504 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6505 
6506 	BWN_GETTIME(cal->calib_time);
6507 
6508 	return (cal);
6509 }
6510 
6511 static struct bwn_lo_calib *
6512 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6513     const struct bwn_rfatt *rfatt)
6514 {
6515 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6516 	struct bwn_lo_calib *c;
6517 
6518 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6519 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6520 			continue;
6521 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6522 			continue;
6523 		return (c);
6524 	}
6525 
6526 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6527 	if (!c)
6528 		return (NULL);
6529 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6530 
6531 	return (c);
6532 }
6533 
6534 static void
6535 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6536 {
6537 	struct bwn_phy *phy = &mac->mac_phy;
6538 	struct bwn_phy_g *pg = &phy->phy_g;
6539 	struct bwn_softc *sc = mac->mac_sc;
6540 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6541 	const struct bwn_rfatt *rfatt;
6542 	const struct bwn_bbatt *bbatt;
6543 	uint64_t pvector;
6544 	int i;
6545 	int rf_offset, bb_offset;
6546 	uint8_t changed = 0;
6547 
6548 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6549 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6550 	    ("%s:%d: fail", __func__, __LINE__));
6551 
6552 	pvector = lo->power_vector;
6553 	if (!update && !pvector)
6554 		return;
6555 
6556 	bwn_mac_suspend(mac);
6557 
6558 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6559 		struct bwn_lo_calib *cal;
6560 		int idx;
6561 		uint16_t val;
6562 
6563 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6564 			continue;
6565 		bb_offset = i / lo->rfatt.len;
6566 		rf_offset = i % lo->rfatt.len;
6567 		bbatt = &(lo->bbatt.array[bb_offset]);
6568 		rfatt = &(lo->rfatt.array[rf_offset]);
6569 
6570 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6571 		if (!cal) {
6572 			device_printf(sc->sc_dev, "LO: Could not "
6573 			    "calibrate DC table entry\n");
6574 			continue;
6575 		}
6576 		val = (uint8_t)(cal->ctl.q);
6577 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6578 		free(cal, M_DEVBUF);
6579 
6580 		idx = i / 2;
6581 		if (i % 2)
6582 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6583 			    | ((val & 0x00ff) << 8);
6584 		else
6585 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6586 			    | (val & 0x00ff);
6587 		changed = 1;
6588 	}
6589 	if (changed) {
6590 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6591 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6592 	}
6593 	bwn_mac_enable(mac);
6594 }
6595 
6596 static void
6597 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6598 {
6599 
6600 	if (!rf->padmix)
6601 		return;
6602 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6603 		rf->att = 4;
6604 }
6605 
6606 static void
6607 bwn_lo_g_adjust(struct bwn_mac *mac)
6608 {
6609 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6610 	struct bwn_lo_calib *cal;
6611 	struct bwn_rfatt rf;
6612 
6613 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6614 	bwn_lo_fixup_rfatt(&rf);
6615 
6616 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6617 	if (!cal)
6618 		return;
6619 	bwn_lo_write(mac, &cal->ctl);
6620 }
6621 
6622 static void
6623 bwn_lo_g_init(struct bwn_mac *mac)
6624 {
6625 
6626 	if (!bwn_has_hwpctl(mac))
6627 		return;
6628 
6629 	bwn_lo_get_powervector(mac);
6630 	bwn_phy_g_dc_lookup_init(mac, 1);
6631 }
6632 
6633 static void
6634 bwn_mac_suspend(struct bwn_mac *mac)
6635 {
6636 	struct bwn_softc *sc = mac->mac_sc;
6637 	int i;
6638 	uint32_t tmp;
6639 
6640 	KASSERT(mac->mac_suspended >= 0,
6641 	    ("%s:%d: fail", __func__, __LINE__));
6642 
6643 	if (mac->mac_suspended == 0) {
6644 		bwn_psctl(mac, BWN_PS_AWAKE);
6645 		BWN_WRITE_4(mac, BWN_MACCTL,
6646 			    BWN_READ_4(mac, BWN_MACCTL)
6647 			    & ~BWN_MACCTL_ON);
6648 		BWN_READ_4(mac, BWN_MACCTL);
6649 		for (i = 35; i; i--) {
6650 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6651 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6652 				goto out;
6653 			DELAY(10);
6654 		}
6655 		for (i = 40; i; i--) {
6656 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6657 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6658 				goto out;
6659 			DELAY(1000);
6660 		}
6661 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6662 	}
6663 out:
6664 	mac->mac_suspended++;
6665 }
6666 
6667 static void
6668 bwn_mac_enable(struct bwn_mac *mac)
6669 {
6670 	struct bwn_softc *sc = mac->mac_sc;
6671 	uint16_t state;
6672 
6673 	state = bwn_shm_read_2(mac, BWN_SHARED,
6674 	    BWN_SHARED_UCODESTAT);
6675 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6676 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6677 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6678 
6679 	mac->mac_suspended--;
6680 	KASSERT(mac->mac_suspended >= 0,
6681 	    ("%s:%d: fail", __func__, __LINE__));
6682 	if (mac->mac_suspended == 0) {
6683 		BWN_WRITE_4(mac, BWN_MACCTL,
6684 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6685 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6686 		BWN_READ_4(mac, BWN_MACCTL);
6687 		BWN_READ_4(mac, BWN_INTR_REASON);
6688 		bwn_psctl(mac, 0);
6689 	}
6690 }
6691 
6692 static void
6693 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6694 {
6695 	struct bwn_softc *sc = mac->mac_sc;
6696 	int i;
6697 	uint16_t ucstat;
6698 
6699 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6700 	    ("%s:%d: fail", __func__, __LINE__));
6701 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6702 	    ("%s:%d: fail", __func__, __LINE__));
6703 
6704 	/* XXX forcibly awake and hwps-off */
6705 
6706 	BWN_WRITE_4(mac, BWN_MACCTL,
6707 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6708 	    ~BWN_MACCTL_HWPS);
6709 	BWN_READ_4(mac, BWN_MACCTL);
6710 	if (siba_get_revid(sc->sc_dev) >= 5) {
6711 		for (i = 0; i < 100; i++) {
6712 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6713 			    BWN_SHARED_UCODESTAT);
6714 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6715 				break;
6716 			DELAY(10);
6717 		}
6718 	}
6719 }
6720 
6721 static int16_t
6722 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6723 {
6724 
6725 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6726 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6727 }
6728 
6729 static void
6730 bwn_nrssi_threshold(struct bwn_mac *mac)
6731 {
6732 	struct bwn_phy *phy = &mac->mac_phy;
6733 	struct bwn_phy_g *pg = &phy->phy_g;
6734 	struct bwn_softc *sc = mac->mac_sc;
6735 	int32_t a, b;
6736 	int16_t tmp16;
6737 	uint16_t tmpu16;
6738 
6739 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6740 
6741 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6742 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6743 			a = 0x13;
6744 			b = 0x12;
6745 		} else {
6746 			a = 0xe;
6747 			b = 0x11;
6748 		}
6749 
6750 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6751 		a += (pg->pg_nrssi[0] << 6);
6752 		a += (a < 32) ? 31 : 32;
6753 		a = a >> 6;
6754 		a = MIN(MAX(a, -31), 31);
6755 
6756 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6757 		b += (pg->pg_nrssi[0] << 6);
6758 		if (b < 32)
6759 			b += 31;
6760 		else
6761 			b += 32;
6762 		b = b >> 6;
6763 		b = MIN(MAX(b, -31), 31);
6764 
6765 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6766 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6767 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6768 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6769 		return;
6770 	}
6771 
6772 	tmp16 = bwn_nrssi_read(mac, 0x20);
6773 	if (tmp16 >= 0x20)
6774 		tmp16 -= 0x40;
6775 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6776 }
6777 
6778 static void
6779 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6780 {
6781 #define	SAVE_RF_MAX		3
6782 #define	SAVE_PHY_COMM_MAX	4
6783 #define	SAVE_PHY3_MAX		8
6784 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6785 		{ 0x7a, 0x52, 0x43 };
6786 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6787 		{ 0x15, 0x5a, 0x59, 0x58 };
6788 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6789 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6790 		0x0801, 0x0060, 0x0014, 0x0478
6791 	};
6792 	struct bwn_phy *phy = &mac->mac_phy;
6793 	struct bwn_phy_g *pg = &phy->phy_g;
6794 	int32_t i, tmp32, phy3_idx = 0;
6795 	uint16_t delta, tmp;
6796 	uint16_t save_rf[SAVE_RF_MAX];
6797 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6798 	uint16_t save_phy3[SAVE_PHY3_MAX];
6799 	uint16_t ant_div, phy0, chan_ex;
6800 	int16_t nrssi0, nrssi1;
6801 
6802 	KASSERT(phy->type == BWN_PHYTYPE_G,
6803 	    ("%s:%d: fail", __func__, __LINE__));
6804 
6805 	if (phy->rf_rev >= 9)
6806 		return;
6807 	if (phy->rf_rev == 8)
6808 		bwn_nrssi_offset(mac);
6809 
6810 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6811 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6812 
6813 	/*
6814 	 * Save RF/PHY registers for later restoration
6815 	 */
6816 	ant_div = BWN_READ_2(mac, 0x03e2);
6817 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6818 	for (i = 0; i < SAVE_RF_MAX; ++i)
6819 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6820 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6821 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6822 
6823 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6824 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6825 	if (phy->rev >= 3) {
6826 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6827 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6828 		BWN_PHY_WRITE(mac, 0x002e, 0);
6829 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6830 		switch (phy->rev) {
6831 		case 4:
6832 		case 6:
6833 		case 7:
6834 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6835 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6836 			break;
6837 		case 3:
6838 		case 5:
6839 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6840 			break;
6841 		}
6842 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6843 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6844 	}
6845 	/*
6846 	 * Calculate nrssi0
6847 	 */
6848 	BWN_RF_SET(mac, 0x007a, 0x0070);
6849 	bwn_set_all_gains(mac, 0, 8, 0);
6850 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6851 	if (phy->rev >= 2) {
6852 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6853 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6854 	}
6855 	BWN_RF_SET(mac, 0x007a, 0x0080);
6856 	DELAY(20);
6857 
6858 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6859 	if (nrssi0 >= 0x0020)
6860 		nrssi0 -= 0x0040;
6861 
6862 	/*
6863 	 * Calculate nrssi1
6864 	 */
6865 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6866 	if (phy->rev >= 2)
6867 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6868 
6869 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6870 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6871 	BWN_RF_SET(mac, 0x007a, 0x000f);
6872 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6873 	if (phy->rev >= 2) {
6874 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6875 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6876 	}
6877 
6878 	bwn_set_all_gains(mac, 3, 0, 1);
6879 	if (phy->rf_rev == 8) {
6880 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6881 	} else {
6882 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6883 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6884 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6885 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6886 	}
6887 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6888 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6889 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6890 	DELAY(20);
6891 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6892 
6893 	/*
6894 	 * Install calculated narrow RSSI values
6895 	 */
6896 	if (nrssi1 >= 0x0020)
6897 		nrssi1 -= 0x0040;
6898 	if (nrssi0 == nrssi1)
6899 		pg->pg_nrssi_slope = 0x00010000;
6900 	else
6901 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6902 	if (nrssi0 >= -4) {
6903 		pg->pg_nrssi[0] = nrssi1;
6904 		pg->pg_nrssi[1] = nrssi0;
6905 	}
6906 
6907 	/*
6908 	 * Restore saved RF/PHY registers
6909 	 */
6910 	if (phy->rev >= 3) {
6911 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6912 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6913 			    save_phy3[phy3_idx]);
6914 		}
6915 	}
6916 	if (phy->rev >= 2) {
6917 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6918 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6919 	}
6920 
6921 	for (i = 0; i < SAVE_RF_MAX; ++i)
6922 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6923 
6924 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6925 	BWN_WRITE_2(mac, 0x03e6, phy0);
6926 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6927 
6928 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6929 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6930 
6931 	bwn_spu_workaround(mac, phy->chan);
6932 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6933 	bwn_set_original_gains(mac);
6934 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6935 	if (phy->rev >= 3) {
6936 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6937 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6938 			    save_phy3[phy3_idx]);
6939 		}
6940 	}
6941 
6942 	delta = 0x1f - pg->pg_nrssi[0];
6943 	for (i = 0; i < 64; i++) {
6944 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6945 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6946 		pg->pg_nrssi_lt[i] = tmp32;
6947 	}
6948 
6949 	bwn_nrssi_threshold(mac);
6950 #undef SAVE_RF_MAX
6951 #undef SAVE_PHY_COMM_MAX
6952 #undef SAVE_PHY3_MAX
6953 }
6954 
6955 static void
6956 bwn_nrssi_offset(struct bwn_mac *mac)
6957 {
6958 #define	SAVE_RF_MAX		2
6959 #define	SAVE_PHY_COMM_MAX	10
6960 #define	SAVE_PHY6_MAX		8
6961 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6962 		{ 0x7a, 0x43 };
6963 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6964 		0x0001, 0x0811, 0x0812, 0x0814,
6965 		0x0815, 0x005a, 0x0059, 0x0058,
6966 		0x000a, 0x0003
6967 	};
6968 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6969 		0x002e, 0x002f, 0x080f, 0x0810,
6970 		0x0801, 0x0060, 0x0014, 0x0478
6971 	};
6972 	struct bwn_phy *phy = &mac->mac_phy;
6973 	int i, phy6_idx = 0;
6974 	uint16_t save_rf[SAVE_RF_MAX];
6975 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6976 	uint16_t save_phy6[SAVE_PHY6_MAX];
6977 	int16_t nrssi;
6978 	uint16_t saved = 0xffff;
6979 
6980 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6981 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6982 	for (i = 0; i < SAVE_RF_MAX; ++i)
6983 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6984 
6985 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6986 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6987 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6988 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6989 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6990 	if (phy->rev >= 6) {
6991 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6992 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6993 
6994 		BWN_PHY_WRITE(mac, 0x002e, 0);
6995 		BWN_PHY_WRITE(mac, 0x002f, 0);
6996 		BWN_PHY_WRITE(mac, 0x080f, 0);
6997 		BWN_PHY_WRITE(mac, 0x0810, 0);
6998 		BWN_PHY_SET(mac, 0x0478, 0x0100);
6999 		BWN_PHY_SET(mac, 0x0801, 0x0040);
7000 		BWN_PHY_SET(mac, 0x0060, 0x0040);
7001 		BWN_PHY_SET(mac, 0x0014, 0x0200);
7002 	}
7003 	BWN_RF_SET(mac, 0x007a, 0x0070);
7004 	BWN_RF_SET(mac, 0x007a, 0x0080);
7005 	DELAY(30);
7006 
7007 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7008 	if (nrssi >= 0x20)
7009 		nrssi -= 0x40;
7010 	if (nrssi == 31) {
7011 		for (i = 7; i >= 4; i--) {
7012 			BWN_RF_WRITE(mac, 0x007b, i);
7013 			DELAY(20);
7014 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
7015 			    0x003f);
7016 			if (nrssi >= 0x20)
7017 				nrssi -= 0x40;
7018 			if (nrssi < 31 && saved == 0xffff)
7019 				saved = i;
7020 		}
7021 		if (saved == 0xffff)
7022 			saved = 4;
7023 	} else {
7024 		BWN_RF_MASK(mac, 0x007a, 0x007f);
7025 		if (phy->rev != 1) {
7026 			BWN_PHY_SET(mac, 0x0814, 0x0001);
7027 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
7028 		}
7029 		BWN_PHY_SET(mac, 0x0811, 0x000c);
7030 		BWN_PHY_SET(mac, 0x0812, 0x000c);
7031 		BWN_PHY_SET(mac, 0x0811, 0x0030);
7032 		BWN_PHY_SET(mac, 0x0812, 0x0030);
7033 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
7034 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
7035 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
7036 		if (phy->rev == 0)
7037 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
7038 		else
7039 			BWN_PHY_SET(mac, 0x000a, 0x2000);
7040 		if (phy->rev != 1) {
7041 			BWN_PHY_SET(mac, 0x0814, 0x0004);
7042 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
7043 		}
7044 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
7045 		BWN_RF_SET(mac, 0x007a, 0x000f);
7046 		bwn_set_all_gains(mac, 3, 0, 1);
7047 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
7048 		DELAY(30);
7049 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
7050 		if (nrssi >= 0x20)
7051 			nrssi -= 0x40;
7052 		if (nrssi == -32) {
7053 			for (i = 0; i < 4; i++) {
7054 				BWN_RF_WRITE(mac, 0x007b, i);
7055 				DELAY(20);
7056 				nrssi = (int16_t)((BWN_PHY_READ(mac,
7057 				    0x047f) >> 8) & 0x003f);
7058 				if (nrssi >= 0x20)
7059 					nrssi -= 0x40;
7060 				if (nrssi > -31 && saved == 0xffff)
7061 					saved = i;
7062 			}
7063 			if (saved == 0xffff)
7064 				saved = 3;
7065 		} else
7066 			saved = 0;
7067 	}
7068 	BWN_RF_WRITE(mac, 0x007b, saved);
7069 
7070 	/*
7071 	 * Restore saved RF/PHY registers
7072 	 */
7073 	if (phy->rev >= 6) {
7074 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
7075 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7076 			    save_phy6[phy6_idx]);
7077 		}
7078 	}
7079 	if (phy->rev != 1) {
7080 		for (i = 3; i < 5; i++)
7081 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
7082 			    save_phy_comm[i]);
7083 	}
7084 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
7085 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
7086 
7087 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
7088 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
7089 
7090 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
7091 	BWN_PHY_SET(mac, 0x0429, 0x8000);
7092 	bwn_set_original_gains(mac);
7093 	if (phy->rev >= 6) {
7094 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
7095 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
7096 			    save_phy6[phy6_idx]);
7097 		}
7098 	}
7099 
7100 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
7101 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
7102 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7103 }
7104 
7105 static void
7106 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7107     int16_t third)
7108 {
7109 	struct bwn_phy *phy = &mac->mac_phy;
7110 	uint16_t i;
7111 	uint16_t start = 0x08, end = 0x18;
7112 	uint16_t tmp;
7113 	uint16_t table;
7114 
7115 	if (phy->rev <= 1) {
7116 		start = 0x10;
7117 		end = 0x20;
7118 	}
7119 
7120 	table = BWN_OFDMTAB_GAINX;
7121 	if (phy->rev <= 1)
7122 		table = BWN_OFDMTAB_GAINX_R1;
7123 	for (i = 0; i < 4; i++)
7124 		bwn_ofdmtab_write_2(mac, table, i, first);
7125 
7126 	for (i = start; i < end; i++)
7127 		bwn_ofdmtab_write_2(mac, table, i, second);
7128 
7129 	if (third != -1) {
7130 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7131 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7132 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7133 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7134 	}
7135 	bwn_dummy_transmission(mac, 0, 1);
7136 }
7137 
7138 static void
7139 bwn_set_original_gains(struct bwn_mac *mac)
7140 {
7141 	struct bwn_phy *phy = &mac->mac_phy;
7142 	uint16_t i, tmp;
7143 	uint16_t table;
7144 	uint16_t start = 0x0008, end = 0x0018;
7145 
7146 	if (phy->rev <= 1) {
7147 		start = 0x0010;
7148 		end = 0x0020;
7149 	}
7150 
7151 	table = BWN_OFDMTAB_GAINX;
7152 	if (phy->rev <= 1)
7153 		table = BWN_OFDMTAB_GAINX_R1;
7154 	for (i = 0; i < 4; i++) {
7155 		tmp = (i & 0xfffc);
7156 		tmp |= (i & 0x0001) << 1;
7157 		tmp |= (i & 0x0002) >> 1;
7158 
7159 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7160 	}
7161 
7162 	for (i = start; i < end; i++)
7163 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7164 
7165 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7166 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7167 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7168 	bwn_dummy_transmission(mac, 0, 1);
7169 }
7170 
7171 static void
7172 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7173 {
7174 	struct bwn_phy *phy = &mac->mac_phy;
7175 	struct bwn_phy_g *pg = &phy->phy_g;
7176 	struct bwn_rfatt old_rfatt, rfatt;
7177 	struct bwn_bbatt old_bbatt, bbatt;
7178 	struct bwn_softc *sc = mac->mac_sc;
7179 	uint8_t old_txctl = 0;
7180 
7181 	KASSERT(phy->type == BWN_PHYTYPE_G,
7182 	    ("%s:%d: fail", __func__, __LINE__));
7183 
7184 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7185 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7186 		return;
7187 
7188 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7189 
7190 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7191 
7192 	if (!phy->gmode)
7193 		return;
7194 	bwn_hwpctl_early_init(mac);
7195 	if (pg->pg_curtssi == 0) {
7196 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7197 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7198 		} else {
7199 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7200 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7201 			old_txctl = pg->pg_txctl;
7202 
7203 			bbatt.att = 11;
7204 			if (phy->rf_rev == 8) {
7205 				rfatt.att = 15;
7206 				rfatt.padmix = 1;
7207 			} else {
7208 				rfatt.att = 9;
7209 				rfatt.padmix = 0;
7210 			}
7211 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7212 		}
7213 		bwn_dummy_transmission(mac, 0, 1);
7214 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7215 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7216 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7217 		else
7218 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7219 			    &old_rfatt, old_txctl);
7220 	}
7221 	bwn_hwpctl_init_gphy(mac);
7222 
7223 	/* clear TSSI */
7224 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7225 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7226 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7227 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7228 }
7229 
7230 static void
7231 bwn_hwpctl_early_init(struct bwn_mac *mac)
7232 {
7233 	struct bwn_phy *phy = &mac->mac_phy;
7234 
7235 	if (!bwn_has_hwpctl(mac)) {
7236 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7237 		return;
7238 	}
7239 
7240 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7241 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7242 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7243 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7244 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7245 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7246 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7247 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7248 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7249 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7250 	} else {
7251 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7252 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7253 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7254 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7255 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7256 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7257 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7258 	}
7259 }
7260 
7261 static void
7262 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7263 {
7264 	struct bwn_phy *phy = &mac->mac_phy;
7265 	struct bwn_phy_g *pg = &phy->phy_g;
7266 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7267 	int i;
7268 	uint16_t nr_written = 0, tmp, value;
7269 	uint8_t rf, bb;
7270 
7271 	if (!bwn_has_hwpctl(mac)) {
7272 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7273 		return;
7274 	}
7275 
7276 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7277 	    (pg->pg_idletssi - pg->pg_curtssi));
7278 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7279 	    (pg->pg_idletssi - pg->pg_curtssi));
7280 
7281 	for (i = 0; i < 32; i++)
7282 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7283 	for (i = 32; i < 64; i++)
7284 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7285 	for (i = 0; i < 64; i += 2) {
7286 		value = (uint16_t) pg->pg_tssi2dbm[i];
7287 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7288 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7289 	}
7290 
7291 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7292 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7293 			if (nr_written >= 0x40)
7294 				return;
7295 			tmp = lo->bbatt.array[bb].att;
7296 			tmp <<= 8;
7297 			if (phy->rf_rev == 8)
7298 				tmp |= 0x50;
7299 			else
7300 				tmp |= 0x40;
7301 			tmp |= lo->rfatt.array[rf].att;
7302 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7303 			nr_written++;
7304 		}
7305 	}
7306 
7307 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7308 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7309 
7310 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7311 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7312 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7313 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7314 
7315 	bwn_phy_g_dc_lookup_init(mac, 1);
7316 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7317 }
7318 
7319 static void
7320 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7321 {
7322 	struct bwn_softc *sc = mac->mac_sc;
7323 
7324 	if (spu != 0)
7325 		bwn_spu_workaround(mac, channel);
7326 
7327 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7328 
7329 	if (channel == 14) {
7330 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7331 			bwn_hf_write(mac,
7332 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7333 		else
7334 			bwn_hf_write(mac,
7335 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7336 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7337 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7338 		return;
7339 	}
7340 
7341 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7342 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7343 }
7344 
7345 static uint16_t
7346 bwn_phy_g_chan2freq(uint8_t channel)
7347 {
7348 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7349 
7350 	KASSERT(channel >= 1 && channel <= 14,
7351 	    ("%s:%d: fail", __func__, __LINE__));
7352 
7353 	return (bwn_phy_g_rf_channels[channel - 1]);
7354 }
7355 
7356 static void
7357 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7358     const struct bwn_rfatt *rfatt, uint8_t txctl)
7359 {
7360 	struct bwn_phy *phy = &mac->mac_phy;
7361 	struct bwn_phy_g *pg = &phy->phy_g;
7362 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7363 	uint16_t bb, rf;
7364 	uint16_t tx_bias, tx_magn;
7365 
7366 	bb = bbatt->att;
7367 	rf = rfatt->att;
7368 	tx_bias = lo->tx_bias;
7369 	tx_magn = lo->tx_magn;
7370 	if (tx_bias == 0xff)
7371 		tx_bias = 0;
7372 
7373 	pg->pg_txctl = txctl;
7374 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7375 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7376 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7377 	bwn_phy_g_set_bbatt(mac, bb);
7378 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7379 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7380 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7381 	else {
7382 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7383 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7384 	}
7385 	if (BWN_HAS_TXMAG(phy))
7386 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7387 	else
7388 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7389 	bwn_lo_g_adjust(mac);
7390 }
7391 
7392 static void
7393 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7394     uint16_t bbatt)
7395 {
7396 	struct bwn_phy *phy = &mac->mac_phy;
7397 
7398 	if (phy->analog == 0) {
7399 		BWN_WRITE_2(mac, BWN_PHY0,
7400 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7401 		return;
7402 	}
7403 	if (phy->analog > 1) {
7404 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7405 		return;
7406 	}
7407 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7408 }
7409 
7410 static uint16_t
7411 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7412 {
7413 	struct bwn_phy *phy = &mac->mac_phy;
7414 	struct bwn_phy_g *pg = &phy->phy_g;
7415 	struct bwn_softc *sc = mac->mac_sc;
7416 	int max_lb_gain;
7417 	uint16_t extlna;
7418 	uint16_t i;
7419 
7420 	if (phy->gmode == 0)
7421 		return (0);
7422 
7423 	if (BWN_HAS_LOOPBACK(phy)) {
7424 		max_lb_gain = pg->pg_max_lb_gain;
7425 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7426 		if (max_lb_gain >= 0x46) {
7427 			extlna = 0x3000;
7428 			max_lb_gain -= 0x46;
7429 		} else if (max_lb_gain >= 0x3a) {
7430 			extlna = 0x1000;
7431 			max_lb_gain -= 0x3a;
7432 		} else if (max_lb_gain >= 0x2e) {
7433 			extlna = 0x2000;
7434 			max_lb_gain -= 0x2e;
7435 		} else {
7436 			extlna = 0;
7437 			max_lb_gain -= 0x10;
7438 		}
7439 
7440 		for (i = 0; i < 16; i++) {
7441 			max_lb_gain -= (i * 6);
7442 			if (max_lb_gain < 6)
7443 				break;
7444 		}
7445 
7446 		if ((phy->rev < 7) ||
7447 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7448 			if (reg == BWN_PHY_RFOVER) {
7449 				return (0x1b3);
7450 			} else if (reg == BWN_PHY_RFOVERVAL) {
7451 				extlna |= (i << 8);
7452 				switch (lpd) {
7453 				case BWN_LPD(0, 1, 1):
7454 					return (0x0f92);
7455 				case BWN_LPD(0, 0, 1):
7456 				case BWN_LPD(1, 0, 1):
7457 					return (0x0092 | extlna);
7458 				case BWN_LPD(1, 0, 0):
7459 					return (0x0093 | extlna);
7460 				}
7461 				KASSERT(0 == 1,
7462 				    ("%s:%d: fail", __func__, __LINE__));
7463 			}
7464 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7465 		} else {
7466 			if (reg == BWN_PHY_RFOVER)
7467 				return (0x9b3);
7468 			if (reg == BWN_PHY_RFOVERVAL) {
7469 				if (extlna)
7470 					extlna |= 0x8000;
7471 				extlna |= (i << 8);
7472 				switch (lpd) {
7473 				case BWN_LPD(0, 1, 1):
7474 					return (0x8f92);
7475 				case BWN_LPD(0, 0, 1):
7476 					return (0x8092 | extlna);
7477 				case BWN_LPD(1, 0, 1):
7478 					return (0x2092 | extlna);
7479 				case BWN_LPD(1, 0, 0):
7480 					return (0x2093 | extlna);
7481 				}
7482 				KASSERT(0 == 1,
7483 				    ("%s:%d: fail", __func__, __LINE__));
7484 			}
7485 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7486 		}
7487 		return (0);
7488 	}
7489 
7490 	if ((phy->rev < 7) ||
7491 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7492 		if (reg == BWN_PHY_RFOVER) {
7493 			return (0x1b3);
7494 		} else if (reg == BWN_PHY_RFOVERVAL) {
7495 			switch (lpd) {
7496 			case BWN_LPD(0, 1, 1):
7497 				return (0x0fb2);
7498 			case BWN_LPD(0, 0, 1):
7499 				return (0x00b2);
7500 			case BWN_LPD(1, 0, 1):
7501 				return (0x30b2);
7502 			case BWN_LPD(1, 0, 0):
7503 				return (0x30b3);
7504 			}
7505 			KASSERT(0 == 1,
7506 			    ("%s:%d: fail", __func__, __LINE__));
7507 		}
7508 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7509 	} else {
7510 		if (reg == BWN_PHY_RFOVER) {
7511 			return (0x9b3);
7512 		} else if (reg == BWN_PHY_RFOVERVAL) {
7513 			switch (lpd) {
7514 			case BWN_LPD(0, 1, 1):
7515 				return (0x8fb2);
7516 			case BWN_LPD(0, 0, 1):
7517 				return (0x80b2);
7518 			case BWN_LPD(1, 0, 1):
7519 				return (0x20b2);
7520 			case BWN_LPD(1, 0, 0):
7521 				return (0x20b3);
7522 			}
7523 			KASSERT(0 == 1,
7524 			    ("%s:%d: fail", __func__, __LINE__));
7525 		}
7526 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7527 	}
7528 	return (0);
7529 }
7530 
7531 static void
7532 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7533 {
7534 
7535 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7536 		return;
7537 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7538 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7539 	DELAY(1000);
7540 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7541 }
7542 
7543 static int
7544 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7545 {
7546 	struct bwn_softc *sc = mac->mac_sc;
7547 	struct bwn_fw *fw = &mac->mac_fw;
7548 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7549 	const char *filename;
7550 	uint32_t high;
7551 	int error;
7552 
7553 	/* microcode */
7554 	if (rev >= 5 && rev <= 10)
7555 		filename = "ucode5";
7556 	else if (rev >= 11 && rev <= 12)
7557 		filename = "ucode11";
7558 	else if (rev == 13)
7559 		filename = "ucode13";
7560 	else if (rev == 14)
7561 		filename = "ucode14";
7562 	else if (rev >= 15)
7563 		filename = "ucode15";
7564 	else {
7565 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7566 		bwn_release_firmware(mac);
7567 		return (EOPNOTSUPP);
7568 	}
7569 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7570 	if (error) {
7571 		bwn_release_firmware(mac);
7572 		return (error);
7573 	}
7574 
7575 	/* PCM */
7576 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7577 	if (rev >= 5 && rev <= 10) {
7578 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7579 		if (error == ENOENT)
7580 			fw->no_pcmfile = 1;
7581 		else if (error) {
7582 			bwn_release_firmware(mac);
7583 			return (error);
7584 		}
7585 	} else if (rev < 11) {
7586 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7587 		return (EOPNOTSUPP);
7588 	}
7589 
7590 	/* initvals */
7591 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7592 	switch (mac->mac_phy.type) {
7593 	case BWN_PHYTYPE_A:
7594 		if (rev < 5 || rev > 10)
7595 			goto fail1;
7596 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7597 			filename = "a0g1initvals5";
7598 		else
7599 			filename = "a0g0initvals5";
7600 		break;
7601 	case BWN_PHYTYPE_G:
7602 		if (rev >= 5 && rev <= 10)
7603 			filename = "b0g0initvals5";
7604 		else if (rev >= 13)
7605 			filename = "b0g0initvals13";
7606 		else
7607 			goto fail1;
7608 		break;
7609 	case BWN_PHYTYPE_LP:
7610 		if (rev == 13)
7611 			filename = "lp0initvals13";
7612 		else if (rev == 14)
7613 			filename = "lp0initvals14";
7614 		else if (rev >= 15)
7615 			filename = "lp0initvals15";
7616 		else
7617 			goto fail1;
7618 		break;
7619 	case BWN_PHYTYPE_N:
7620 		if (rev >= 11 && rev <= 12)
7621 			filename = "n0initvals11";
7622 		else
7623 			goto fail1;
7624 		break;
7625 	default:
7626 		goto fail1;
7627 	}
7628 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7629 	if (error) {
7630 		bwn_release_firmware(mac);
7631 		return (error);
7632 	}
7633 
7634 	/* bandswitch initvals */
7635 	switch (mac->mac_phy.type) {
7636 	case BWN_PHYTYPE_A:
7637 		if (rev >= 5 && rev <= 10) {
7638 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7639 				filename = "a0g1bsinitvals5";
7640 			else
7641 				filename = "a0g0bsinitvals5";
7642 		} else if (rev >= 11)
7643 			filename = NULL;
7644 		else
7645 			goto fail1;
7646 		break;
7647 	case BWN_PHYTYPE_G:
7648 		if (rev >= 5 && rev <= 10)
7649 			filename = "b0g0bsinitvals5";
7650 		else if (rev >= 11)
7651 			filename = NULL;
7652 		else
7653 			goto fail1;
7654 		break;
7655 	case BWN_PHYTYPE_LP:
7656 		if (rev == 13)
7657 			filename = "lp0bsinitvals13";
7658 		else if (rev == 14)
7659 			filename = "lp0bsinitvals14";
7660 		else if (rev >= 15)
7661 			filename = "lp0bsinitvals15";
7662 		else
7663 			goto fail1;
7664 		break;
7665 	case BWN_PHYTYPE_N:
7666 		if (rev >= 11 && rev <= 12)
7667 			filename = "n0bsinitvals11";
7668 		else
7669 			goto fail1;
7670 		break;
7671 	default:
7672 		goto fail1;
7673 	}
7674 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7675 	if (error) {
7676 		bwn_release_firmware(mac);
7677 		return (error);
7678 	}
7679 	return (0);
7680 fail1:
7681 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7682 	bwn_release_firmware(mac);
7683 	return (EOPNOTSUPP);
7684 }
7685 
7686 static int
7687 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7688     const char *name, struct bwn_fwfile *bfw)
7689 {
7690 	const struct bwn_fwhdr *hdr;
7691 	struct bwn_softc *sc = mac->mac_sc;
7692 	const struct firmware *fw;
7693 	char namebuf[64];
7694 
7695 	if (name == NULL) {
7696 		bwn_do_release_fw(bfw);
7697 		return (0);
7698 	}
7699 	if (bfw->filename != NULL) {
7700 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7701 			return (0);
7702 		bwn_do_release_fw(bfw);
7703 	}
7704 
7705 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7706 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7707 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7708 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7709 	fw = firmware_get(namebuf);
7710 	if (fw == NULL) {
7711 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7712 		    namebuf);
7713 		return (ENOENT);
7714 	}
7715 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7716 		goto fail;
7717 	hdr = (const struct bwn_fwhdr *)(fw->data);
7718 	switch (hdr->type) {
7719 	case BWN_FWTYPE_UCODE:
7720 	case BWN_FWTYPE_PCM:
7721 		if (be32toh(hdr->size) !=
7722 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7723 			goto fail;
7724 		/* FALLTHROUGH */
7725 	case BWN_FWTYPE_IV:
7726 		if (hdr->ver != 1)
7727 			goto fail;
7728 		break;
7729 	default:
7730 		goto fail;
7731 	}
7732 	bfw->filename = name;
7733 	bfw->fw = fw;
7734 	bfw->type = type;
7735 	return (0);
7736 fail:
7737 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7738 	if (fw != NULL)
7739 		firmware_put(fw, FIRMWARE_UNLOAD);
7740 	return (EPROTO);
7741 }
7742 
7743 static void
7744 bwn_release_firmware(struct bwn_mac *mac)
7745 {
7746 
7747 	bwn_do_release_fw(&mac->mac_fw.ucode);
7748 	bwn_do_release_fw(&mac->mac_fw.pcm);
7749 	bwn_do_release_fw(&mac->mac_fw.initvals);
7750 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7751 }
7752 
7753 static void
7754 bwn_do_release_fw(struct bwn_fwfile *bfw)
7755 {
7756 
7757 	if (bfw->fw != NULL)
7758 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7759 	bfw->fw = NULL;
7760 	bfw->filename = NULL;
7761 }
7762 
7763 static int
7764 bwn_fw_loaducode(struct bwn_mac *mac)
7765 {
7766 #define	GETFWOFFSET(fwp, offset)	\
7767 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7768 #define	GETFWSIZE(fwp, offset)	\
7769 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7770 	struct bwn_softc *sc = mac->mac_sc;
7771 	const uint32_t *data;
7772 	unsigned int i;
7773 	uint32_t ctl;
7774 	uint16_t date, fwcaps, time;
7775 	int error = 0;
7776 
7777 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7778 	ctl |= BWN_MACCTL_MCODE_JMP0;
7779 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7780 	    __LINE__));
7781 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7782 	for (i = 0; i < 64; i++)
7783 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7784 	for (i = 0; i < 4096; i += 2)
7785 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7786 
7787 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7788 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7789 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7790 	     i++) {
7791 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7792 		DELAY(10);
7793 	}
7794 
7795 	if (mac->mac_fw.pcm.fw) {
7796 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7797 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7798 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7799 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7800 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7801 		    sizeof(struct bwn_fwhdr)); i++) {
7802 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7803 			DELAY(10);
7804 		}
7805 	}
7806 
7807 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7808 	BWN_WRITE_4(mac, BWN_MACCTL,
7809 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7810 	    BWN_MACCTL_MCODE_RUN);
7811 
7812 	for (i = 0; i < 21; i++) {
7813 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7814 			break;
7815 		if (i >= 20) {
7816 			device_printf(sc->sc_dev, "ucode timeout\n");
7817 			error = ENXIO;
7818 			goto error;
7819 		}
7820 		DELAY(50000);
7821 	}
7822 	BWN_READ_4(mac, BWN_INTR_REASON);
7823 
7824 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7825 	if (mac->mac_fw.rev <= 0x128) {
7826 		device_printf(sc->sc_dev, "the firmware is too old\n");
7827 		error = EOPNOTSUPP;
7828 		goto error;
7829 	}
7830 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7831 	    BWN_SHARED_UCODE_PATCH);
7832 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7833 	mac->mac_fw.opensource = (date == 0xffff);
7834 	if (bwn_wme != 0)
7835 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7836 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7837 
7838 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7839 	if (mac->mac_fw.opensource == 0) {
7840 		device_printf(sc->sc_dev,
7841 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7842 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7843 		if (mac->mac_fw.no_pcmfile)
7844 			device_printf(sc->sc_dev,
7845 			    "no HW crypto acceleration due to pcm5\n");
7846 	} else {
7847 		mac->mac_fw.patch = time;
7848 		fwcaps = bwn_fwcaps_read(mac);
7849 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7850 			device_printf(sc->sc_dev,
7851 			    "disabling HW crypto acceleration\n");
7852 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7853 		}
7854 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7855 			device_printf(sc->sc_dev, "disabling WME support\n");
7856 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7857 		}
7858 	}
7859 
7860 	if (BWN_ISOLDFMT(mac))
7861 		device_printf(sc->sc_dev, "using old firmware image\n");
7862 
7863 	return (0);
7864 
7865 error:
7866 	BWN_WRITE_4(mac, BWN_MACCTL,
7867 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7868 	    BWN_MACCTL_MCODE_JMP0);
7869 
7870 	return (error);
7871 #undef GETFWSIZE
7872 #undef GETFWOFFSET
7873 }
7874 
7875 /* OpenFirmware only */
7876 static uint16_t
7877 bwn_fwcaps_read(struct bwn_mac *mac)
7878 {
7879 
7880 	KASSERT(mac->mac_fw.opensource == 1,
7881 	    ("%s:%d: fail", __func__, __LINE__));
7882 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7883 }
7884 
7885 static int
7886 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7887     size_t count, size_t array_size)
7888 {
7889 #define	GET_NEXTIV16(iv)						\
7890 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7891 	    sizeof(uint16_t) + sizeof(uint16_t)))
7892 #define	GET_NEXTIV32(iv)						\
7893 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7894 	    sizeof(uint16_t) + sizeof(uint32_t)))
7895 	struct bwn_softc *sc = mac->mac_sc;
7896 	const struct bwn_fwinitvals *iv;
7897 	uint16_t offset;
7898 	size_t i;
7899 	uint8_t bit32;
7900 
7901 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7902 	    ("%s:%d: fail", __func__, __LINE__));
7903 	iv = ivals;
7904 	for (i = 0; i < count; i++) {
7905 		if (array_size < sizeof(iv->offset_size))
7906 			goto fail;
7907 		array_size -= sizeof(iv->offset_size);
7908 		offset = be16toh(iv->offset_size);
7909 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7910 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7911 		if (offset >= 0x1000)
7912 			goto fail;
7913 		if (bit32) {
7914 			if (array_size < sizeof(iv->data.d32))
7915 				goto fail;
7916 			array_size -= sizeof(iv->data.d32);
7917 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7918 			iv = GET_NEXTIV32(iv);
7919 		} else {
7920 
7921 			if (array_size < sizeof(iv->data.d16))
7922 				goto fail;
7923 			array_size -= sizeof(iv->data.d16);
7924 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7925 
7926 			iv = GET_NEXTIV16(iv);
7927 		}
7928 	}
7929 	if (array_size != 0)
7930 		goto fail;
7931 	return (0);
7932 fail:
7933 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7934 	return (EPROTO);
7935 #undef GET_NEXTIV16
7936 #undef GET_NEXTIV32
7937 }
7938 
7939 static int
7940 bwn_switch_channel(struct bwn_mac *mac, int chan)
7941 {
7942 	struct bwn_phy *phy = &(mac->mac_phy);
7943 	struct bwn_softc *sc = mac->mac_sc;
7944 	struct ifnet *ifp = sc->sc_ifp;
7945 	struct ieee80211com *ic = ifp->if_l2com;
7946 	uint16_t channelcookie, savedcookie;
7947 	int error;
7948 
7949 	if (chan == 0xffff)
7950 		chan = phy->get_default_chan(mac);
7951 
7952 	channelcookie = chan;
7953 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7954 		channelcookie |= 0x100;
7955 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7956 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7957 	error = phy->switch_channel(mac, chan);
7958 	if (error)
7959 		goto fail;
7960 
7961 	mac->mac_phy.chan = chan;
7962 	DELAY(8000);
7963 	return (0);
7964 fail:
7965 	device_printf(sc->sc_dev, "failed to switch channel\n");
7966 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7967 	return (error);
7968 }
7969 
7970 static uint16_t
7971 bwn_ant2phy(int antenna)
7972 {
7973 
7974 	switch (antenna) {
7975 	case BWN_ANT0:
7976 		return (BWN_TX_PHY_ANT0);
7977 	case BWN_ANT1:
7978 		return (BWN_TX_PHY_ANT1);
7979 	case BWN_ANT2:
7980 		return (BWN_TX_PHY_ANT2);
7981 	case BWN_ANT3:
7982 		return (BWN_TX_PHY_ANT3);
7983 	case BWN_ANTAUTO:
7984 		return (BWN_TX_PHY_ANT01AUTO);
7985 	}
7986 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7987 	return (0);
7988 }
7989 
7990 static void
7991 bwn_wme_load(struct bwn_mac *mac)
7992 {
7993 	struct bwn_softc *sc = mac->mac_sc;
7994 	int i;
7995 
7996 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7997 	    ("%s:%d: fail", __func__, __LINE__));
7998 
7999 	bwn_mac_suspend(mac);
8000 	for (i = 0; i < N(sc->sc_wmeParams); i++)
8001 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
8002 		    bwn_wme_shm_offsets[i]);
8003 	bwn_mac_enable(mac);
8004 }
8005 
8006 static void
8007 bwn_wme_loadparams(struct bwn_mac *mac,
8008     const struct wmeParams *p, uint16_t shm_offset)
8009 {
8010 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
8011 	struct bwn_softc *sc = mac->mac_sc;
8012 	uint16_t params[BWN_NR_WMEPARAMS];
8013 	int slot, tmp;
8014 	unsigned int i;
8015 
8016 	slot = BWN_READ_2(mac, BWN_RNG) &
8017 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8018 
8019 	memset(&params, 0, sizeof(params));
8020 
8021 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
8022 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
8023 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
8024 
8025 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
8026 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8027 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
8028 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
8029 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
8030 	params[BWN_WMEPARAM_BSLOTS] = slot;
8031 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
8032 
8033 	for (i = 0; i < N(params); i++) {
8034 		if (i == BWN_WMEPARAM_STATUS) {
8035 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
8036 			    shm_offset + (i * 2));
8037 			tmp |= 0x100;
8038 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8039 			    tmp);
8040 		} else {
8041 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
8042 			    params[i]);
8043 		}
8044 	}
8045 }
8046 
8047 static void
8048 bwn_mac_write_bssid(struct bwn_mac *mac)
8049 {
8050 	struct bwn_softc *sc = mac->mac_sc;
8051 	uint32_t tmp;
8052 	int i;
8053 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
8054 
8055 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
8056 	memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
8057 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
8058 	    IEEE80211_ADDR_LEN);
8059 
8060 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
8061 		tmp = (uint32_t) (mac_bssid[i + 0]);
8062 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
8063 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
8064 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
8065 		bwn_ram_write(mac, 0x20 + i, tmp);
8066 	}
8067 }
8068 
8069 static void
8070 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
8071     const uint8_t *macaddr)
8072 {
8073 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
8074 	uint16_t data;
8075 
8076 	if (!mac)
8077 		macaddr = zero;
8078 
8079 	offset |= 0x0020;
8080 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
8081 
8082 	data = macaddr[0];
8083 	data |= macaddr[1] << 8;
8084 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8085 	data = macaddr[2];
8086 	data |= macaddr[3] << 8;
8087 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8088 	data = macaddr[4];
8089 	data |= macaddr[5] << 8;
8090 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
8091 }
8092 
8093 static void
8094 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8095     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
8096 {
8097 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
8098 	uint8_t per_sta_keys_start = 8;
8099 
8100 	if (BWN_SEC_NEWAPI(mac))
8101 		per_sta_keys_start = 4;
8102 
8103 	KASSERT(index < mac->mac_max_nr_keys,
8104 	    ("%s:%d: fail", __func__, __LINE__));
8105 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8106 	    ("%s:%d: fail", __func__, __LINE__));
8107 
8108 	if (index >= per_sta_keys_start)
8109 		bwn_key_macwrite(mac, index, NULL);
8110 	if (key)
8111 		memcpy(buf, key, key_len);
8112 	bwn_key_write(mac, index, algorithm, buf);
8113 	if (index >= per_sta_keys_start)
8114 		bwn_key_macwrite(mac, index, mac_addr);
8115 
8116 	mac->mac_key[index].algorithm = algorithm;
8117 }
8118 
8119 static void
8120 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8121 {
8122 	struct bwn_softc *sc = mac->mac_sc;
8123 	uint32_t addrtmp[2] = { 0, 0 };
8124 	uint8_t start = 8;
8125 
8126 	if (BWN_SEC_NEWAPI(mac))
8127 		start = 4;
8128 
8129 	KASSERT(index >= start,
8130 	    ("%s:%d: fail", __func__, __LINE__));
8131 	index -= start;
8132 
8133 	if (addr) {
8134 		addrtmp[0] = addr[0];
8135 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8136 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8137 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8138 		addrtmp[1] = addr[4];
8139 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8140 	}
8141 
8142 	if (siba_get_revid(sc->sc_dev) >= 5) {
8143 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8144 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8145 	} else {
8146 		if (index >= 8) {
8147 			bwn_shm_write_4(mac, BWN_SHARED,
8148 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8149 			bwn_shm_write_2(mac, BWN_SHARED,
8150 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8151 		}
8152 	}
8153 }
8154 
8155 static void
8156 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8157     const uint8_t *key)
8158 {
8159 	unsigned int i;
8160 	uint32_t offset;
8161 	uint16_t kidx, value;
8162 
8163 	kidx = BWN_SEC_KEY2FW(mac, index);
8164 	bwn_shm_write_2(mac, BWN_SHARED,
8165 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8166 
8167 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8168 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8169 		value = key[i];
8170 		value |= (uint16_t)(key[i + 1]) << 8;
8171 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8172 	}
8173 }
8174 
8175 static void
8176 bwn_phy_exit(struct bwn_mac *mac)
8177 {
8178 
8179 	mac->mac_phy.rf_onoff(mac, 0);
8180 	if (mac->mac_phy.exit != NULL)
8181 		mac->mac_phy.exit(mac);
8182 }
8183 
8184 static void
8185 bwn_dma_free(struct bwn_mac *mac)
8186 {
8187 	struct bwn_dma *dma;
8188 
8189 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8190 		return;
8191 	dma = &mac->mac_method.dma;
8192 
8193 	bwn_dma_ringfree(&dma->rx);
8194 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8195 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8196 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8197 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8198 	bwn_dma_ringfree(&dma->mcast);
8199 }
8200 
8201 static void
8202 bwn_core_stop(struct bwn_mac *mac)
8203 {
8204 	struct bwn_softc *sc = mac->mac_sc;
8205 
8206 	BWN_ASSERT_LOCKED(sc);
8207 
8208 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8209 		return;
8210 
8211 	callout_stop(&sc->sc_rfswitch_ch);
8212 	callout_stop(&sc->sc_task_ch);
8213 	callout_stop(&sc->sc_watchdog_ch);
8214 	sc->sc_watchdog_timer = 0;
8215 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8216 	BWN_READ_4(mac, BWN_INTR_MASK);
8217 	bwn_mac_suspend(mac);
8218 
8219 	mac->mac_status = BWN_MAC_STATUS_INITED;
8220 }
8221 
8222 static int
8223 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8224 {
8225 	struct bwn_mac *up_dev = NULL;
8226 	struct bwn_mac *down_dev;
8227 	struct bwn_mac *mac;
8228 	int err, status;
8229 	uint8_t gmode;
8230 
8231 	BWN_ASSERT_LOCKED(sc);
8232 
8233 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8234 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8235 		    mac->mac_phy.supports_2ghz) {
8236 			up_dev = mac;
8237 			gmode = 1;
8238 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8239 		    mac->mac_phy.supports_5ghz) {
8240 			up_dev = mac;
8241 			gmode = 0;
8242 		} else {
8243 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8244 			return (EINVAL);
8245 		}
8246 		if (up_dev != NULL)
8247 			break;
8248 	}
8249 	if (up_dev == NULL) {
8250 		device_printf(sc->sc_dev, "Could not find a device\n");
8251 		return (ENODEV);
8252 	}
8253 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8254 		return (0);
8255 
8256 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8257 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8258 
8259 	down_dev = sc->sc_curmac;
8260 	status = down_dev->mac_status;
8261 	if (status >= BWN_MAC_STATUS_STARTED)
8262 		bwn_core_stop(down_dev);
8263 	if (status >= BWN_MAC_STATUS_INITED)
8264 		bwn_core_exit(down_dev);
8265 
8266 	if (down_dev != up_dev)
8267 		bwn_phy_reset(down_dev);
8268 
8269 	up_dev->mac_phy.gmode = gmode;
8270 	if (status >= BWN_MAC_STATUS_INITED) {
8271 		err = bwn_core_init(up_dev);
8272 		if (err) {
8273 			device_printf(sc->sc_dev,
8274 			    "fatal: failed to initialize for %s-GHz\n",
8275 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8276 			goto fail;
8277 		}
8278 	}
8279 	if (status >= BWN_MAC_STATUS_STARTED)
8280 		bwn_core_start(up_dev);
8281 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8282 	sc->sc_curmac = up_dev;
8283 
8284 	return (0);
8285 fail:
8286 	sc->sc_curmac = NULL;
8287 	return (err);
8288 }
8289 
8290 static void
8291 bwn_rf_turnon(struct bwn_mac *mac)
8292 {
8293 
8294 	bwn_mac_suspend(mac);
8295 	mac->mac_phy.rf_onoff(mac, 1);
8296 	mac->mac_phy.rf_on = 1;
8297 	bwn_mac_enable(mac);
8298 }
8299 
8300 static void
8301 bwn_rf_turnoff(struct bwn_mac *mac)
8302 {
8303 
8304 	bwn_mac_suspend(mac);
8305 	mac->mac_phy.rf_onoff(mac, 0);
8306 	mac->mac_phy.rf_on = 0;
8307 	bwn_mac_enable(mac);
8308 }
8309 
8310 static void
8311 bwn_phy_reset(struct bwn_mac *mac)
8312 {
8313 	struct bwn_softc *sc = mac->mac_sc;
8314 
8315 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8316 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8317 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8318 	DELAY(1000);
8319 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8320 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8321 	    BWN_TGSLOW_PHYRESET);
8322 	DELAY(1000);
8323 }
8324 
8325 static int
8326 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8327 {
8328 	struct bwn_vap *bvp = BWN_VAP(vap);
8329 	struct ieee80211com *ic= vap->iv_ic;
8330 	struct ifnet *ifp = ic->ic_ifp;
8331 	enum ieee80211_state ostate = vap->iv_state;
8332 	struct bwn_softc *sc = ifp->if_softc;
8333 	struct bwn_mac *mac = sc->sc_curmac;
8334 	int error;
8335 
8336 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8337 	    ieee80211_state_name[vap->iv_state],
8338 	    ieee80211_state_name[nstate]);
8339 
8340 	error = bvp->bv_newstate(vap, nstate, arg);
8341 	if (error != 0)
8342 		return (error);
8343 
8344 	BWN_LOCK(sc);
8345 
8346 	bwn_led_newstate(mac, nstate);
8347 
8348 	/*
8349 	 * Clear the BSSID when we stop a STA
8350 	 */
8351 	if (vap->iv_opmode == IEEE80211_M_STA) {
8352 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8353 			/*
8354 			 * Clear out the BSSID.  If we reassociate to
8355 			 * the same AP, this will reinialize things
8356 			 * correctly...
8357 			 */
8358 			if (ic->ic_opmode == IEEE80211_M_STA &&
8359 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8360 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8361 				bwn_set_macaddr(mac);
8362 			}
8363 		}
8364 	}
8365 
8366 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8367 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8368 		/* XXX nothing to do? */
8369 	} else if (nstate == IEEE80211_S_RUN) {
8370 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8371 		memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
8372 		bwn_set_opmode(mac);
8373 		bwn_set_pretbtt(mac);
8374 		bwn_spu_setdelay(mac, 0);
8375 		bwn_set_macaddr(mac);
8376 	}
8377 
8378 	BWN_UNLOCK(sc);
8379 
8380 	return (error);
8381 }
8382 
8383 static void
8384 bwn_set_pretbtt(struct bwn_mac *mac)
8385 {
8386 	struct bwn_softc *sc = mac->mac_sc;
8387 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8388 	uint16_t pretbtt;
8389 
8390 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8391 		pretbtt = 2;
8392 	else
8393 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8394 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8395 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8396 }
8397 
8398 static int
8399 bwn_intr(void *arg)
8400 {
8401 	struct bwn_mac *mac = arg;
8402 	struct bwn_softc *sc = mac->mac_sc;
8403 	uint32_t reason;
8404 
8405 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8406 	    (sc->sc_flags & BWN_FLAG_INVALID))
8407 		return (FILTER_STRAY);
8408 
8409 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8410 	if (reason == 0xffffffff)	/* shared IRQ */
8411 		return (FILTER_STRAY);
8412 	reason &= mac->mac_intr_mask;
8413 	if (reason == 0)
8414 		return (FILTER_HANDLED);
8415 
8416 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8417 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8418 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8419 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8420 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8421 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8422 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8423 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8424 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8425 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8426 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8427 
8428 	/* Disable interrupts. */
8429 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8430 
8431 	mac->mac_reason_intr = reason;
8432 
8433 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8434 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8435 
8436 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8437 	return (FILTER_HANDLED);
8438 }
8439 
8440 static void
8441 bwn_intrtask(void *arg, int npending)
8442 {
8443 	struct bwn_mac *mac = arg;
8444 	struct bwn_softc *sc = mac->mac_sc;
8445 	struct ifnet *ifp = sc->sc_ifp;
8446 	uint32_t merged = 0;
8447 	int i, tx = 0, rx = 0;
8448 
8449 	BWN_LOCK(sc);
8450 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8451 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8452 		BWN_UNLOCK(sc);
8453 		return;
8454 	}
8455 
8456 	for (i = 0; i < N(mac->mac_reason); i++)
8457 		merged |= mac->mac_reason[i];
8458 
8459 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8460 		device_printf(sc->sc_dev, "MAC trans error\n");
8461 
8462 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8463 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8464 		mac->mac_phy.txerrors--;
8465 		if (mac->mac_phy.txerrors == 0) {
8466 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8467 			bwn_restart(mac, "PHY TX errors");
8468 		}
8469 	}
8470 
8471 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8472 		if (merged & BWN_DMAINTR_FATALMASK) {
8473 			device_printf(sc->sc_dev,
8474 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8475 			    mac->mac_reason[0], mac->mac_reason[1],
8476 			    mac->mac_reason[2], mac->mac_reason[3],
8477 			    mac->mac_reason[4], mac->mac_reason[5]);
8478 			bwn_restart(mac, "DMA error");
8479 			BWN_UNLOCK(sc);
8480 			return;
8481 		}
8482 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8483 			device_printf(sc->sc_dev,
8484 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8485 			    mac->mac_reason[0], mac->mac_reason[1],
8486 			    mac->mac_reason[2], mac->mac_reason[3],
8487 			    mac->mac_reason[4], mac->mac_reason[5]);
8488 		}
8489 	}
8490 
8491 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8492 		bwn_intr_ucode_debug(mac);
8493 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8494 		bwn_intr_tbtt_indication(mac);
8495 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8496 		bwn_intr_atim_end(mac);
8497 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8498 		bwn_intr_beacon(mac);
8499 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8500 		bwn_intr_pmq(mac);
8501 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8502 		bwn_intr_noise(mac);
8503 
8504 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8505 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8506 			bwn_dma_rx(mac->mac_method.dma.rx);
8507 			rx = 1;
8508 		}
8509 	} else
8510 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8511 
8512 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8513 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8514 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8515 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8516 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8517 
8518 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8519 		bwn_intr_txeof(mac);
8520 		tx = 1;
8521 	}
8522 
8523 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8524 
8525 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8526 		int evt = BWN_LED_EVENT_NONE;
8527 
8528 		if (tx && rx) {
8529 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8530 				evt = BWN_LED_EVENT_RX;
8531 			else
8532 				evt = BWN_LED_EVENT_TX;
8533 		} else if (tx) {
8534 			evt = BWN_LED_EVENT_TX;
8535 		} else if (rx) {
8536 			evt = BWN_LED_EVENT_RX;
8537 		} else if (rx == 0) {
8538 			evt = BWN_LED_EVENT_POLL;
8539 		}
8540 
8541 		if (evt != BWN_LED_EVENT_NONE)
8542 			bwn_led_event(mac, evt);
8543        }
8544 
8545 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
8546 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
8547 			bwn_start_locked(ifp);
8548 	}
8549 
8550 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8551 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8552 
8553 	BWN_UNLOCK(sc);
8554 }
8555 
8556 static void
8557 bwn_restart(struct bwn_mac *mac, const char *msg)
8558 {
8559 	struct bwn_softc *sc = mac->mac_sc;
8560 	struct ifnet *ifp = sc->sc_ifp;
8561 	struct ieee80211com *ic = ifp->if_l2com;
8562 
8563 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8564 		return;
8565 
8566 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8567 	ieee80211_runtask(ic, &mac->mac_hwreset);
8568 }
8569 
8570 static void
8571 bwn_intr_ucode_debug(struct bwn_mac *mac)
8572 {
8573 	struct bwn_softc *sc = mac->mac_sc;
8574 	uint16_t reason;
8575 
8576 	if (mac->mac_fw.opensource == 0)
8577 		return;
8578 
8579 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8580 	switch (reason) {
8581 	case BWN_DEBUGINTR_PANIC:
8582 		bwn_handle_fwpanic(mac);
8583 		break;
8584 	case BWN_DEBUGINTR_DUMP_SHM:
8585 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8586 		break;
8587 	case BWN_DEBUGINTR_DUMP_REGS:
8588 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8589 		break;
8590 	case BWN_DEBUGINTR_MARKER:
8591 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8592 		break;
8593 	default:
8594 		device_printf(sc->sc_dev,
8595 		    "ucode debug unknown reason: %#x\n", reason);
8596 	}
8597 
8598 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8599 	    BWN_DEBUGINTR_ACK);
8600 }
8601 
8602 static void
8603 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8604 {
8605 	struct bwn_softc *sc = mac->mac_sc;
8606 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8607 
8608 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8609 		bwn_psctl(mac, 0);
8610 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8611 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8612 }
8613 
8614 static void
8615 bwn_intr_atim_end(struct bwn_mac *mac)
8616 {
8617 
8618 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8619 		BWN_WRITE_4(mac, BWN_MACCMD,
8620 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8621 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8622 	}
8623 }
8624 
8625 static void
8626 bwn_intr_beacon(struct bwn_mac *mac)
8627 {
8628 	struct bwn_softc *sc = mac->mac_sc;
8629 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
8630 	uint32_t cmd, beacon0, beacon1;
8631 
8632 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8633 	    ic->ic_opmode == IEEE80211_M_MBSS)
8634 		return;
8635 
8636 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8637 
8638 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8639 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8640 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8641 
8642 	if (beacon0 && beacon1) {
8643 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8644 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8645 		return;
8646 	}
8647 
8648 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8649 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8650 		bwn_load_beacon0(mac);
8651 		bwn_load_beacon1(mac);
8652 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8653 		cmd |= BWN_MACCMD_BEACON0_VALID;
8654 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8655 	} else {
8656 		if (!beacon0) {
8657 			bwn_load_beacon0(mac);
8658 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8659 			cmd |= BWN_MACCMD_BEACON0_VALID;
8660 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8661 		} else if (!beacon1) {
8662 			bwn_load_beacon1(mac);
8663 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8664 			cmd |= BWN_MACCMD_BEACON1_VALID;
8665 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8666 		}
8667 	}
8668 }
8669 
8670 static void
8671 bwn_intr_pmq(struct bwn_mac *mac)
8672 {
8673 	uint32_t tmp;
8674 
8675 	while (1) {
8676 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8677 		if (!(tmp & 0x00000008))
8678 			break;
8679 	}
8680 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8681 }
8682 
8683 static void
8684 bwn_intr_noise(struct bwn_mac *mac)
8685 {
8686 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8687 	uint16_t tmp;
8688 	uint8_t noise[4];
8689 	uint8_t i, j;
8690 	int32_t average;
8691 
8692 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8693 		return;
8694 
8695 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8696 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8697 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8698 	    noise[3] == 0x7f)
8699 		goto new;
8700 
8701 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8702 	    ("%s:%d: fail", __func__, __LINE__));
8703 	i = mac->mac_noise.noi_nsamples;
8704 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8705 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8706 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8707 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8708 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8709 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8710 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8711 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8712 	mac->mac_noise.noi_nsamples++;
8713 	if (mac->mac_noise.noi_nsamples == 8) {
8714 		average = 0;
8715 		for (i = 0; i < 8; i++) {
8716 			for (j = 0; j < 4; j++)
8717 				average += mac->mac_noise.noi_samples[i][j];
8718 		}
8719 		average = (((average / 32) * 125) + 64) / 128;
8720 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8721 		if (tmp >= 8)
8722 			average += 2;
8723 		else
8724 			average -= 25;
8725 		average -= (tmp == 8) ? 72 : 48;
8726 
8727 		mac->mac_stats.link_noise = average;
8728 		mac->mac_noise.noi_running = 0;
8729 		return;
8730 	}
8731 new:
8732 	bwn_noise_gensample(mac);
8733 }
8734 
8735 static int
8736 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8737 {
8738 	struct bwn_mac *mac = prq->prq_mac;
8739 	struct bwn_softc *sc = mac->mac_sc;
8740 	unsigned int i;
8741 
8742 	BWN_ASSERT_LOCKED(sc);
8743 
8744 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8745 		return (0);
8746 
8747 	for (i = 0; i < 5000; i++) {
8748 		if (bwn_pio_rxeof(prq) == 0)
8749 			break;
8750 	}
8751 	if (i >= 5000)
8752 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8753 	return ((i > 0) ? 1 : 0);
8754 }
8755 
8756 static void
8757 bwn_dma_rx(struct bwn_dma_ring *dr)
8758 {
8759 	int slot, curslot;
8760 
8761 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8762 	curslot = dr->get_curslot(dr);
8763 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8764 	    ("%s:%d: fail", __func__, __LINE__));
8765 
8766 	slot = dr->dr_curslot;
8767 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8768 		bwn_dma_rxeof(dr, &slot);
8769 
8770 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8771 	    BUS_DMASYNC_PREWRITE);
8772 
8773 	dr->set_curslot(dr, slot);
8774 	dr->dr_curslot = slot;
8775 }
8776 
8777 static void
8778 bwn_intr_txeof(struct bwn_mac *mac)
8779 {
8780 	struct bwn_txstatus stat;
8781 	uint32_t stat0, stat1;
8782 	uint16_t tmp;
8783 
8784 	BWN_ASSERT_LOCKED(mac->mac_sc);
8785 
8786 	while (1) {
8787 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8788 		if (!(stat0 & 0x00000001))
8789 			break;
8790 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8791 
8792 		stat.cookie = (stat0 >> 16);
8793 		stat.seq = (stat1 & 0x0000ffff);
8794 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8795 		tmp = (stat0 & 0x0000ffff);
8796 		stat.framecnt = ((tmp & 0xf000) >> 12);
8797 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8798 		stat.sreason = ((tmp & 0x001c) >> 2);
8799 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8800 		stat.im = (tmp & 0x0040) ? 1 : 0;
8801 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8802 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8803 
8804 		bwn_handle_txeof(mac, &stat);
8805 	}
8806 }
8807 
8808 static void
8809 bwn_hwreset(void *arg, int npending)
8810 {
8811 	struct bwn_mac *mac = arg;
8812 	struct bwn_softc *sc = mac->mac_sc;
8813 	int error = 0;
8814 	int prev_status;
8815 
8816 	BWN_LOCK(sc);
8817 
8818 	prev_status = mac->mac_status;
8819 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8820 		bwn_core_stop(mac);
8821 	if (prev_status >= BWN_MAC_STATUS_INITED)
8822 		bwn_core_exit(mac);
8823 
8824 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8825 		error = bwn_core_init(mac);
8826 		if (error)
8827 			goto out;
8828 	}
8829 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8830 		bwn_core_start(mac);
8831 out:
8832 	if (error) {
8833 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8834 		sc->sc_curmac = NULL;
8835 	}
8836 	BWN_UNLOCK(sc);
8837 }
8838 
8839 static void
8840 bwn_handle_fwpanic(struct bwn_mac *mac)
8841 {
8842 	struct bwn_softc *sc = mac->mac_sc;
8843 	uint16_t reason;
8844 
8845 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8846 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8847 
8848 	if (reason == BWN_FWPANIC_RESTART)
8849 		bwn_restart(mac, "ucode panic");
8850 }
8851 
8852 static void
8853 bwn_load_beacon0(struct bwn_mac *mac)
8854 {
8855 
8856 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8857 }
8858 
8859 static void
8860 bwn_load_beacon1(struct bwn_mac *mac)
8861 {
8862 
8863 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8864 }
8865 
8866 static uint32_t
8867 bwn_jssi_read(struct bwn_mac *mac)
8868 {
8869 	uint32_t val = 0;
8870 
8871 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8872 	val <<= 16;
8873 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8874 
8875 	return (val);
8876 }
8877 
8878 static void
8879 bwn_noise_gensample(struct bwn_mac *mac)
8880 {
8881 	uint32_t jssi = 0x7f7f7f7f;
8882 
8883 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8884 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8885 	BWN_WRITE_4(mac, BWN_MACCMD,
8886 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8887 }
8888 
8889 static int
8890 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8891 {
8892 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8893 
8894 	return (dr->dr_numslots - dr->dr_usedslot);
8895 }
8896 
8897 static int
8898 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8899 {
8900 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8901 
8902 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8903 	    ("%s:%d: fail", __func__, __LINE__));
8904 	if (slot == dr->dr_numslots - 1)
8905 		return (0);
8906 	return (slot + 1);
8907 }
8908 
8909 static void
8910 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8911 {
8912 	struct bwn_mac *mac = dr->dr_mac;
8913 	struct bwn_softc *sc = mac->mac_sc;
8914 	struct bwn_dma *dma = &mac->mac_method.dma;
8915 	struct bwn_dmadesc_generic *desc;
8916 	struct bwn_dmadesc_meta *meta;
8917 	struct bwn_rxhdr4 *rxhdr;
8918 	struct ifnet *ifp = sc->sc_ifp;
8919 	struct mbuf *m;
8920 	uint32_t macstat;
8921 	int32_t tmp;
8922 	int cnt = 0;
8923 	uint16_t len;
8924 
8925 	dr->getdesc(dr, *slot, &desc, &meta);
8926 
8927 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8928 	m = meta->mt_m;
8929 
8930 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8931 		ifp->if_ierrors++;
8932 		return;
8933 	}
8934 
8935 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8936 	len = le16toh(rxhdr->frame_len);
8937 	if (len <= 0) {
8938 		ifp->if_ierrors++;
8939 		return;
8940 	}
8941 	if (bwn_dma_check_redzone(dr, m)) {
8942 		device_printf(sc->sc_dev, "redzone error.\n");
8943 		bwn_dma_set_redzone(dr, m);
8944 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8945 		    BUS_DMASYNC_PREWRITE);
8946 		return;
8947 	}
8948 	if (len > dr->dr_rx_bufsize) {
8949 		tmp = len;
8950 		while (1) {
8951 			dr->getdesc(dr, *slot, &desc, &meta);
8952 			bwn_dma_set_redzone(dr, meta->mt_m);
8953 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8954 			    BUS_DMASYNC_PREWRITE);
8955 			*slot = bwn_dma_nextslot(dr, *slot);
8956 			cnt++;
8957 			tmp -= dr->dr_rx_bufsize;
8958 			if (tmp <= 0)
8959 				break;
8960 		}
8961 		device_printf(sc->sc_dev, "too small buffer "
8962 		       "(len %u buffer %u dropped %d)\n",
8963 		       len, dr->dr_rx_bufsize, cnt);
8964 		return;
8965 	}
8966 	macstat = le32toh(rxhdr->mac_status);
8967 	if (macstat & BWN_RX_MAC_FCSERR) {
8968 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8969 			device_printf(sc->sc_dev, "RX drop\n");
8970 			return;
8971 		}
8972 	}
8973 
8974 	m->m_pkthdr.rcvif = ifp;
8975 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8976 	m_adj(m, dr->dr_frameoffset);
8977 
8978 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8979 }
8980 
8981 static void
8982 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8983 {
8984 	struct bwn_dma_ring *dr;
8985 	struct bwn_dmadesc_generic *desc;
8986 	struct bwn_dmadesc_meta *meta;
8987 	struct bwn_pio_txqueue *tq;
8988 	struct bwn_pio_txpkt *tp = NULL;
8989 	struct bwn_softc *sc = mac->mac_sc;
8990 	struct bwn_stats *stats = &mac->mac_stats;
8991 	struct ieee80211_node *ni;
8992 	struct ieee80211vap *vap;
8993 	int retrycnt = 0, slot;
8994 
8995 	BWN_ASSERT_LOCKED(mac->mac_sc);
8996 
8997 	if (status->im)
8998 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8999 	if (status->ampdu)
9000 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
9001 	if (status->rtscnt) {
9002 		if (status->rtscnt == 0xf)
9003 			stats->rtsfail++;
9004 		else
9005 			stats->rts++;
9006 	}
9007 
9008 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
9009 		if (status->ack) {
9010 			dr = bwn_dma_parse_cookie(mac, status,
9011 			    status->cookie, &slot);
9012 			if (dr == NULL) {
9013 				device_printf(sc->sc_dev,
9014 				    "failed to parse cookie\n");
9015 				return;
9016 			}
9017 			while (1) {
9018 				dr->getdesc(dr, slot, &desc, &meta);
9019 				if (meta->mt_islast) {
9020 					ni = meta->mt_ni;
9021 					vap = ni->ni_vap;
9022 					ieee80211_ratectl_tx_complete(vap, ni,
9023 					    status->ack ?
9024 					      IEEE80211_RATECTL_TX_SUCCESS :
9025 					      IEEE80211_RATECTL_TX_FAILURE,
9026 					    &retrycnt, 0);
9027 					break;
9028 				}
9029 				slot = bwn_dma_nextslot(dr, slot);
9030 			}
9031 		}
9032 		bwn_dma_handle_txeof(mac, status);
9033 	} else {
9034 		if (status->ack) {
9035 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9036 			if (tq == NULL) {
9037 				device_printf(sc->sc_dev,
9038 				    "failed to parse cookie\n");
9039 				return;
9040 			}
9041 			ni = tp->tp_ni;
9042 			vap = ni->ni_vap;
9043 			ieee80211_ratectl_tx_complete(vap, ni,
9044 			    status->ack ?
9045 			      IEEE80211_RATECTL_TX_SUCCESS :
9046 			      IEEE80211_RATECTL_TX_FAILURE,
9047 			    &retrycnt, 0);
9048 		}
9049 		bwn_pio_handle_txeof(mac, status);
9050 	}
9051 
9052 	bwn_phy_txpower_check(mac, 0);
9053 }
9054 
9055 static uint8_t
9056 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
9057 {
9058 	struct bwn_mac *mac = prq->prq_mac;
9059 	struct bwn_softc *sc = mac->mac_sc;
9060 	struct bwn_rxhdr4 rxhdr;
9061 	struct ifnet *ifp = sc->sc_ifp;
9062 	struct mbuf *m;
9063 	uint32_t ctl32, macstat, v32;
9064 	unsigned int i, padding;
9065 	uint16_t ctl16, len, totlen, v16;
9066 	unsigned char *mp;
9067 	char *data;
9068 
9069 	memset(&rxhdr, 0, sizeof(rxhdr));
9070 
9071 	if (prq->prq_rev >= 8) {
9072 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9073 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
9074 			return (0);
9075 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9076 		    BWN_PIO8_RXCTL_FRAMEREADY);
9077 		for (i = 0; i < 10; i++) {
9078 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
9079 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
9080 				goto ready;
9081 			DELAY(10);
9082 		}
9083 	} else {
9084 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9085 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
9086 			return (0);
9087 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
9088 		    BWN_PIO_RXCTL_FRAMEREADY);
9089 		for (i = 0; i < 10; i++) {
9090 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
9091 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
9092 				goto ready;
9093 			DELAY(10);
9094 		}
9095 	}
9096 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
9097 	return (1);
9098 ready:
9099 	if (prq->prq_rev >= 8)
9100 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9101 		    prq->prq_base + BWN_PIO8_RXDATA);
9102 	else
9103 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
9104 		    prq->prq_base + BWN_PIO_RXDATA);
9105 	len = le16toh(rxhdr.frame_len);
9106 	if (len > 0x700) {
9107 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
9108 		goto error;
9109 	}
9110 	if (len == 0) {
9111 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
9112 		goto error;
9113 	}
9114 
9115 	macstat = le32toh(rxhdr.mac_status);
9116 	if (macstat & BWN_RX_MAC_FCSERR) {
9117 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9118 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9119 			goto error;
9120 		}
9121 	}
9122 
9123 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9124 	totlen = len + padding;
9125 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9126 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9127 	if (m == NULL) {
9128 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9129 		goto error;
9130 	}
9131 	mp = mtod(m, unsigned char *);
9132 	if (prq->prq_rev >= 8) {
9133 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9134 		    prq->prq_base + BWN_PIO8_RXDATA);
9135 		if (totlen & 3) {
9136 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9137 			data = &(mp[totlen - 1]);
9138 			switch (totlen & 3) {
9139 			case 3:
9140 				*data = (v32 >> 16);
9141 				data--;
9142 			case 2:
9143 				*data = (v32 >> 8);
9144 				data--;
9145 			case 1:
9146 				*data = v32;
9147 			}
9148 		}
9149 	} else {
9150 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9151 		    prq->prq_base + BWN_PIO_RXDATA);
9152 		if (totlen & 1) {
9153 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9154 			mp[totlen - 1] = v16;
9155 		}
9156 	}
9157 
9158 	m->m_pkthdr.rcvif = ifp;
9159 	m->m_len = m->m_pkthdr.len = totlen;
9160 
9161 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9162 
9163 	return (1);
9164 error:
9165 	if (prq->prq_rev >= 8)
9166 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9167 		    BWN_PIO8_RXCTL_DATAREADY);
9168 	else
9169 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9170 	return (1);
9171 }
9172 
9173 static int
9174 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9175     struct bwn_dmadesc_meta *meta, int init)
9176 {
9177 	struct bwn_mac *mac = dr->dr_mac;
9178 	struct bwn_dma *dma = &mac->mac_method.dma;
9179 	struct bwn_rxhdr4 *hdr;
9180 	bus_dmamap_t map;
9181 	bus_addr_t paddr;
9182 	struct mbuf *m;
9183 	int error;
9184 
9185 	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
9186 	if (m == NULL) {
9187 		error = ENOBUFS;
9188 
9189 		/*
9190 		 * If the NIC is up and running, we need to:
9191 		 * - Clear RX buffer's header.
9192 		 * - Restore RX descriptor settings.
9193 		 */
9194 		if (init)
9195 			return (error);
9196 		else
9197 			goto back;
9198 	}
9199 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9200 
9201 	bwn_dma_set_redzone(dr, m);
9202 
9203 	/*
9204 	 * Try to load RX buf into temporary DMA map
9205 	 */
9206 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9207 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9208 	if (error) {
9209 		m_freem(m);
9210 
9211 		/*
9212 		 * See the comment above
9213 		 */
9214 		if (init)
9215 			return (error);
9216 		else
9217 			goto back;
9218 	}
9219 
9220 	if (!init)
9221 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9222 	meta->mt_m = m;
9223 	meta->mt_paddr = paddr;
9224 
9225 	/*
9226 	 * Swap RX buf's DMA map with the loaded temporary one
9227 	 */
9228 	map = meta->mt_dmap;
9229 	meta->mt_dmap = dr->dr_spare_dmap;
9230 	dr->dr_spare_dmap = map;
9231 
9232 back:
9233 	/*
9234 	 * Clear RX buf header
9235 	 */
9236 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9237 	bzero(hdr, sizeof(*hdr));
9238 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9239 	    BUS_DMASYNC_PREWRITE);
9240 
9241 	/*
9242 	 * Setup RX buf descriptor
9243 	 */
9244 	dr->setdesc(dr, desc, paddr, meta->mt_m->m_len -
9245 	    sizeof(*hdr), 0, 0, 0);
9246 	return (error);
9247 }
9248 
9249 static void
9250 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9251 		 bus_size_t mapsz __unused, int error)
9252 {
9253 
9254 	if (!error) {
9255 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9256 		*((bus_addr_t *)arg) = seg->ds_addr;
9257 	}
9258 }
9259 
9260 static int
9261 bwn_hwrate2ieeerate(int rate)
9262 {
9263 
9264 	switch (rate) {
9265 	case BWN_CCK_RATE_1MB:
9266 		return (2);
9267 	case BWN_CCK_RATE_2MB:
9268 		return (4);
9269 	case BWN_CCK_RATE_5MB:
9270 		return (11);
9271 	case BWN_CCK_RATE_11MB:
9272 		return (22);
9273 	case BWN_OFDM_RATE_6MB:
9274 		return (12);
9275 	case BWN_OFDM_RATE_9MB:
9276 		return (18);
9277 	case BWN_OFDM_RATE_12MB:
9278 		return (24);
9279 	case BWN_OFDM_RATE_18MB:
9280 		return (36);
9281 	case BWN_OFDM_RATE_24MB:
9282 		return (48);
9283 	case BWN_OFDM_RATE_36MB:
9284 		return (72);
9285 	case BWN_OFDM_RATE_48MB:
9286 		return (96);
9287 	case BWN_OFDM_RATE_54MB:
9288 		return (108);
9289 	default:
9290 		printf("Ooops\n");
9291 		return (0);
9292 	}
9293 }
9294 
9295 static void
9296 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9297 {
9298 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9299 	struct bwn_plcp6 *plcp;
9300 	struct bwn_softc *sc = mac->mac_sc;
9301 	struct ieee80211_frame_min *wh;
9302 	struct ieee80211_node *ni;
9303 	struct ifnet *ifp = sc->sc_ifp;
9304 	struct ieee80211com *ic = ifp->if_l2com;
9305 	uint32_t macstat;
9306 	int padding, rate, rssi = 0, noise = 0, type;
9307 	uint16_t phytype, phystat0, phystat3, chanstat;
9308 	unsigned char *mp = mtod(m, unsigned char *);
9309 	static int rx_mac_dec_rpt = 0;
9310 
9311 	BWN_ASSERT_LOCKED(sc);
9312 
9313 	phystat0 = le16toh(rxhdr->phy_status0);
9314 	phystat3 = le16toh(rxhdr->phy_status3);
9315 	macstat = le32toh(rxhdr->mac_status);
9316 	chanstat = le16toh(rxhdr->channel);
9317 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9318 
9319 	if (macstat & BWN_RX_MAC_FCSERR)
9320 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9321 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9322 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9323 	if (macstat & BWN_RX_MAC_DECERR)
9324 		goto drop;
9325 
9326 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9327 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9328 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9329 		    m->m_pkthdr.len);
9330 		goto drop;
9331 	}
9332 	plcp = (struct bwn_plcp6 *)(mp + padding);
9333 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9334 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9335 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9336 		    m->m_pkthdr.len);
9337 		goto drop;
9338 	}
9339 	wh = mtod(m, struct ieee80211_frame_min *);
9340 
9341 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9342 		device_printf(sc->sc_dev,
9343 		    "RX decryption attempted (old %d keyidx %#x)\n",
9344 		    BWN_ISOLDFMT(mac),
9345 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9346 
9347 	/* XXX calculating RSSI & noise & antenna */
9348 
9349 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9350 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9351 		    phytype == BWN_PHYTYPE_A);
9352 	else
9353 		rate = bwn_plcp_get_cckrate(mac, plcp);
9354 	if (rate == -1) {
9355 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9356 			goto drop;
9357 	}
9358 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9359 
9360 	/* RX radio tap */
9361 	if (ieee80211_radiotap_active(ic))
9362 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9363 	m_adj(m, -IEEE80211_CRC_LEN);
9364 
9365 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9366 	noise = mac->mac_stats.link_noise;
9367 
9368 	ifp->if_ipackets++;
9369 
9370 	BWN_UNLOCK(sc);
9371 
9372 	ni = ieee80211_find_rxnode(ic, wh);
9373 	if (ni != NULL) {
9374 		type = ieee80211_input(ni, m, rssi, noise);
9375 		ieee80211_free_node(ni);
9376 	} else
9377 		type = ieee80211_input_all(ic, m, rssi, noise);
9378 
9379 	BWN_LOCK(sc);
9380 	return;
9381 drop:
9382 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9383 }
9384 
9385 static void
9386 bwn_dma_handle_txeof(struct bwn_mac *mac,
9387     const struct bwn_txstatus *status)
9388 {
9389 	struct bwn_dma *dma = &mac->mac_method.dma;
9390 	struct bwn_dma_ring *dr;
9391 	struct bwn_dmadesc_generic *desc;
9392 	struct bwn_dmadesc_meta *meta;
9393 	struct bwn_softc *sc = mac->mac_sc;
9394 	struct ieee80211_node *ni;
9395 	struct ifnet *ifp = sc->sc_ifp;
9396 	struct mbuf *m;
9397 	int slot;
9398 
9399 	BWN_ASSERT_LOCKED(sc);
9400 
9401 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9402 	if (dr == NULL) {
9403 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9404 		return;
9405 	}
9406 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9407 
9408 	while (1) {
9409 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9410 		    ("%s:%d: fail", __func__, __LINE__));
9411 		dr->getdesc(dr, slot, &desc, &meta);
9412 
9413 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9414 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9415 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9416 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9417 
9418 		if (meta->mt_islast) {
9419 			KASSERT(meta->mt_m != NULL,
9420 			    ("%s:%d: fail", __func__, __LINE__));
9421 
9422 			ni = meta->mt_ni;
9423 			m = meta->mt_m;
9424 			if (ni != NULL) {
9425 				/*
9426 				 * Do any tx complete callback. Note this must
9427 				 * be done before releasing the node reference.
9428 				 */
9429 				if (m->m_flags & M_TXCB)
9430 					ieee80211_process_callback(ni, m, 0);
9431 				ieee80211_free_node(ni);
9432 				meta->mt_ni = NULL;
9433 			}
9434 			m_freem(m);
9435 			meta->mt_m = NULL;
9436 		} else {
9437 			KASSERT(meta->mt_m == NULL,
9438 			    ("%s:%d: fail", __func__, __LINE__));
9439 		}
9440 
9441 		dr->dr_usedslot--;
9442 		if (meta->mt_islast) {
9443 			ifp->if_opackets++;
9444 			break;
9445 		}
9446 		slot = bwn_dma_nextslot(dr, slot);
9447 	}
9448 	sc->sc_watchdog_timer = 0;
9449 	if (dr->dr_stop) {
9450 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9451 		    ("%s:%d: fail", __func__, __LINE__));
9452 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9453 		dr->dr_stop = 0;
9454 	}
9455 }
9456 
9457 static void
9458 bwn_pio_handle_txeof(struct bwn_mac *mac,
9459     const struct bwn_txstatus *status)
9460 {
9461 	struct bwn_pio_txqueue *tq;
9462 	struct bwn_pio_txpkt *tp = NULL;
9463 	struct bwn_softc *sc = mac->mac_sc;
9464 	struct ifnet *ifp = sc->sc_ifp;
9465 
9466 	BWN_ASSERT_LOCKED(sc);
9467 
9468 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9469 	if (tq == NULL)
9470 		return;
9471 
9472 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9473 	tq->tq_free++;
9474 
9475 	if (tp->tp_ni != NULL) {
9476 		/*
9477 		 * Do any tx complete callback.  Note this must
9478 		 * be done before releasing the node reference.
9479 		 */
9480 		if (tp->tp_m->m_flags & M_TXCB)
9481 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9482 		ieee80211_free_node(tp->tp_ni);
9483 		tp->tp_ni = NULL;
9484 	}
9485 	m_freem(tp->tp_m);
9486 	tp->tp_m = NULL;
9487 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9488 
9489 	ifp->if_opackets++;
9490 
9491 	sc->sc_watchdog_timer = 0;
9492 	if (tq->tq_stop) {
9493 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
9494 		tq->tq_stop = 0;
9495 	}
9496 }
9497 
9498 static void
9499 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9500 {
9501 	struct bwn_softc *sc = mac->mac_sc;
9502 	struct bwn_phy *phy = &mac->mac_phy;
9503 	struct ifnet *ifp = sc->sc_ifp;
9504 	struct ieee80211com *ic = ifp->if_l2com;
9505 	unsigned long now;
9506 	int result;
9507 
9508 	BWN_GETTIME(now);
9509 
9510 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9511 		return;
9512 	phy->nexttime = now + 2 * 1000;
9513 
9514 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9515 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9516 		return;
9517 
9518 	if (phy->recalc_txpwr != NULL) {
9519 		result = phy->recalc_txpwr(mac,
9520 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9521 		if (result == BWN_TXPWR_RES_DONE)
9522 			return;
9523 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9524 		    ("%s: fail", __func__));
9525 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9526 
9527 		ieee80211_runtask(ic, &mac->mac_txpower);
9528 	}
9529 }
9530 
9531 static uint16_t
9532 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9533 {
9534 
9535 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9536 }
9537 
9538 static uint32_t
9539 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9540 {
9541 
9542 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9543 }
9544 
9545 static void
9546 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9547 {
9548 
9549 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9550 }
9551 
9552 static void
9553 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9554 {
9555 
9556 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9557 }
9558 
9559 static int
9560 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9561 {
9562 
9563 	switch (rate) {
9564 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9565 	case 12:
9566 		return (BWN_OFDM_RATE_6MB);
9567 	case 18:
9568 		return (BWN_OFDM_RATE_9MB);
9569 	case 24:
9570 		return (BWN_OFDM_RATE_12MB);
9571 	case 36:
9572 		return (BWN_OFDM_RATE_18MB);
9573 	case 48:
9574 		return (BWN_OFDM_RATE_24MB);
9575 	case 72:
9576 		return (BWN_OFDM_RATE_36MB);
9577 	case 96:
9578 		return (BWN_OFDM_RATE_48MB);
9579 	case 108:
9580 		return (BWN_OFDM_RATE_54MB);
9581 	/* CCK rates (NB: not IEEE std, device-specific) */
9582 	case 2:
9583 		return (BWN_CCK_RATE_1MB);
9584 	case 4:
9585 		return (BWN_CCK_RATE_2MB);
9586 	case 11:
9587 		return (BWN_CCK_RATE_5MB);
9588 	case 22:
9589 		return (BWN_CCK_RATE_11MB);
9590 	}
9591 
9592 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9593 	return (BWN_CCK_RATE_1MB);
9594 }
9595 
9596 static int
9597 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9598     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9599 {
9600 	const struct bwn_phy *phy = &mac->mac_phy;
9601 	struct bwn_softc *sc = mac->mac_sc;
9602 	struct ieee80211_frame *wh;
9603 	struct ieee80211_frame *protwh;
9604 	struct ieee80211_frame_cts *cts;
9605 	struct ieee80211_frame_rts *rts;
9606 	const struct ieee80211_txparam *tp;
9607 	struct ieee80211vap *vap = ni->ni_vap;
9608 	struct ifnet *ifp = sc->sc_ifp;
9609 	struct ieee80211com *ic = ifp->if_l2com;
9610 	struct mbuf *mprot;
9611 	unsigned int len;
9612 	uint32_t macctl = 0;
9613 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9614 	uint16_t phyctl = 0;
9615 	uint8_t rate, rate_fb;
9616 
9617 	wh = mtod(m, struct ieee80211_frame *);
9618 	memset(txhdr, 0, sizeof(*txhdr));
9619 
9620 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9621 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9622 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9623 
9624 	/*
9625 	 * Find TX rate
9626 	 */
9627 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9628 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9629 		rate = rate_fb = tp->mgmtrate;
9630 	else if (ismcast)
9631 		rate = rate_fb = tp->mcastrate;
9632 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9633 		rate = rate_fb = tp->ucastrate;
9634 	else {
9635 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9636 		rate = ni->ni_txrate;
9637 
9638 		if (rix > 0)
9639 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9640 			    IEEE80211_RATE_VAL;
9641 		else
9642 			rate_fb = rate;
9643 	}
9644 
9645 	sc->sc_tx_rate = rate;
9646 
9647 	rate = bwn_ieeerate2hwrate(sc, rate);
9648 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9649 
9650 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9651 	    bwn_plcp_getcck(rate);
9652 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9653 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9654 
9655 	if ((rate_fb == rate) ||
9656 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9657 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9658 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9659 	else
9660 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9661 		    m->m_pkthdr.len, rate, isshort);
9662 
9663 	/* XXX TX encryption */
9664 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9665 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9666 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9667 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9668 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9669 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9670 
9671 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9672 	    BWN_TX_EFT_FB_CCK;
9673 	txhdr->chan = phy->chan;
9674 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9675 	    BWN_TX_PHY_ENC_CCK;
9676 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9677 	     rate == BWN_CCK_RATE_11MB))
9678 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9679 
9680 	/* XXX TX antenna selection */
9681 
9682 	switch (bwn_antenna_sanitize(mac, 0)) {
9683 	case 0:
9684 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9685 		break;
9686 	case 1:
9687 		phyctl |= BWN_TX_PHY_ANT0;
9688 		break;
9689 	case 2:
9690 		phyctl |= BWN_TX_PHY_ANT1;
9691 		break;
9692 	case 3:
9693 		phyctl |= BWN_TX_PHY_ANT2;
9694 		break;
9695 	case 4:
9696 		phyctl |= BWN_TX_PHY_ANT3;
9697 		break;
9698 	default:
9699 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9700 	}
9701 
9702 	if (!ismcast)
9703 		macctl |= BWN_TX_MAC_ACK;
9704 
9705 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9706 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9707 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9708 		macctl |= BWN_TX_MAC_LONGFRAME;
9709 
9710 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9711 		/* XXX RTS rate is always 1MB??? */
9712 		rts_rate = BWN_CCK_RATE_1MB;
9713 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9714 
9715 		protdur = ieee80211_compute_duration(ic->ic_rt,
9716 		    m->m_pkthdr.len, rate, isshort) +
9717 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9718 
9719 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9720 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9721 			    (txhdr->body.old.rts_frame) :
9722 			    (txhdr->body.new.rts_frame));
9723 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9724 			    protdur);
9725 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9726 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9727 			    mprot->m_pkthdr.len);
9728 			m_freem(mprot);
9729 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9730 			len = sizeof(struct ieee80211_frame_cts);
9731 		} else {
9732 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9733 			    (txhdr->body.old.rts_frame) :
9734 			    (txhdr->body.new.rts_frame));
9735 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9736 			    isshort);
9737 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9738 			    wh->i_addr2, protdur);
9739 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9740 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9741 			    mprot->m_pkthdr.len);
9742 			m_freem(mprot);
9743 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9744 			len = sizeof(struct ieee80211_frame_rts);
9745 		}
9746 		len += IEEE80211_CRC_LEN;
9747 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9748 		    &txhdr->body.old.rts_plcp :
9749 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9750 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9751 		    rts_rate_fb);
9752 
9753 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9754 		    (&txhdr->body.old.rts_frame) :
9755 		    (&txhdr->body.new.rts_frame));
9756 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9757 
9758 		if (BWN_ISOFDMRATE(rts_rate)) {
9759 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9760 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9761 		} else {
9762 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9763 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9764 		}
9765 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9766 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9767 	}
9768 
9769 	if (BWN_ISOLDFMT(mac))
9770 		txhdr->body.old.cookie = htole16(cookie);
9771 	else
9772 		txhdr->body.new.cookie = htole16(cookie);
9773 
9774 	txhdr->macctl = htole32(macctl);
9775 	txhdr->phyctl = htole16(phyctl);
9776 
9777 	/*
9778 	 * TX radio tap
9779 	 */
9780 	if (ieee80211_radiotap_active_vap(vap)) {
9781 		sc->sc_tx_th.wt_flags = 0;
9782 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
9783 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9784 		if (isshort &&
9785 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9786 		     rate == BWN_CCK_RATE_11MB))
9787 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9788 		sc->sc_tx_th.wt_rate = rate;
9789 
9790 		ieee80211_radiotap_tx(vap, m);
9791 	}
9792 
9793 	return (0);
9794 }
9795 
9796 static void
9797 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9798     const uint8_t rate)
9799 {
9800 	uint32_t d, plen;
9801 	uint8_t *raw = plcp->o.raw;
9802 
9803 	if (BWN_ISOFDMRATE(rate)) {
9804 		d = bwn_plcp_getofdm(rate);
9805 		KASSERT(!(octets & 0xf000),
9806 		    ("%s:%d: fail", __func__, __LINE__));
9807 		d |= (octets << 5);
9808 		plcp->o.data = htole32(d);
9809 	} else {
9810 		plen = octets * 16 / rate;
9811 		if ((octets * 16 % rate) > 0) {
9812 			plen++;
9813 			if ((rate == BWN_CCK_RATE_11MB)
9814 			    && ((octets * 8 % 11) < 4)) {
9815 				raw[1] = 0x84;
9816 			} else
9817 				raw[1] = 0x04;
9818 		} else
9819 			raw[1] = 0x04;
9820 		plcp->o.data |= htole32(plen << 16);
9821 		raw[0] = bwn_plcp_getcck(rate);
9822 	}
9823 }
9824 
9825 static uint8_t
9826 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9827 {
9828 	struct bwn_softc *sc = mac->mac_sc;
9829 	uint8_t mask;
9830 
9831 	if (n == 0)
9832 		return (0);
9833 	if (mac->mac_phy.gmode)
9834 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9835 	else
9836 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9837 	if (!(mask & (1 << (n - 1))))
9838 		return (0);
9839 	return (n);
9840 }
9841 
9842 static uint8_t
9843 bwn_get_fbrate(uint8_t bitrate)
9844 {
9845 	switch (bitrate) {
9846 	case BWN_CCK_RATE_1MB:
9847 		return (BWN_CCK_RATE_1MB);
9848 	case BWN_CCK_RATE_2MB:
9849 		return (BWN_CCK_RATE_1MB);
9850 	case BWN_CCK_RATE_5MB:
9851 		return (BWN_CCK_RATE_2MB);
9852 	case BWN_CCK_RATE_11MB:
9853 		return (BWN_CCK_RATE_5MB);
9854 	case BWN_OFDM_RATE_6MB:
9855 		return (BWN_CCK_RATE_5MB);
9856 	case BWN_OFDM_RATE_9MB:
9857 		return (BWN_OFDM_RATE_6MB);
9858 	case BWN_OFDM_RATE_12MB:
9859 		return (BWN_OFDM_RATE_9MB);
9860 	case BWN_OFDM_RATE_18MB:
9861 		return (BWN_OFDM_RATE_12MB);
9862 	case BWN_OFDM_RATE_24MB:
9863 		return (BWN_OFDM_RATE_18MB);
9864 	case BWN_OFDM_RATE_36MB:
9865 		return (BWN_OFDM_RATE_24MB);
9866 	case BWN_OFDM_RATE_48MB:
9867 		return (BWN_OFDM_RATE_36MB);
9868 	case BWN_OFDM_RATE_54MB:
9869 		return (BWN_OFDM_RATE_48MB);
9870 	}
9871 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9872 	return (0);
9873 }
9874 
9875 static uint32_t
9876 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9877     uint32_t ctl, const void *_data, int len)
9878 {
9879 	struct bwn_softc *sc = mac->mac_sc;
9880 	uint32_t value = 0;
9881 	const uint8_t *data = _data;
9882 
9883 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9884 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9885 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9886 
9887 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9888 	    tq->tq_base + BWN_PIO8_TXDATA);
9889 	if (len & 3) {
9890 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9891 		    BWN_PIO8_TXCTL_24_31);
9892 		data = &(data[len - 1]);
9893 		switch (len & 3) {
9894 		case 3:
9895 			ctl |= BWN_PIO8_TXCTL_16_23;
9896 			value |= (uint32_t)(*data) << 16;
9897 			data--;
9898 		case 2:
9899 			ctl |= BWN_PIO8_TXCTL_8_15;
9900 			value |= (uint32_t)(*data) << 8;
9901 			data--;
9902 		case 1:
9903 			value |= (uint32_t)(*data);
9904 		}
9905 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9906 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9907 	}
9908 
9909 	return (ctl);
9910 }
9911 
9912 static void
9913 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9914     uint16_t offset, uint32_t value)
9915 {
9916 
9917 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9918 }
9919 
9920 static uint16_t
9921 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9922     uint16_t ctl, const void *_data, int len)
9923 {
9924 	struct bwn_softc *sc = mac->mac_sc;
9925 	const uint8_t *data = _data;
9926 
9927 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9928 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9929 
9930 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9931 	    tq->tq_base + BWN_PIO_TXDATA);
9932 	if (len & 1) {
9933 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9934 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9935 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9936 	}
9937 
9938 	return (ctl);
9939 }
9940 
9941 static uint16_t
9942 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9943     uint16_t ctl, struct mbuf *m0)
9944 {
9945 	int i, j = 0;
9946 	uint16_t data = 0;
9947 	const uint8_t *buf;
9948 	struct mbuf *m = m0;
9949 
9950 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9951 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9952 
9953 	for (; m != NULL; m = m->m_next) {
9954 		buf = mtod(m, const uint8_t *);
9955 		for (i = 0; i < m->m_len; i++) {
9956 			if (!((j++) % 2))
9957 				data |= buf[i];
9958 			else {
9959 				data |= (buf[i] << 8);
9960 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9961 				data = 0;
9962 			}
9963 		}
9964 	}
9965 	if (m0->m_pkthdr.len % 2) {
9966 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9967 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9968 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9969 	}
9970 
9971 	return (ctl);
9972 }
9973 
9974 static void
9975 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9976 {
9977 
9978 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9979 		return;
9980 	BWN_WRITE_2(mac, 0x684, 510 + time);
9981 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9982 }
9983 
9984 static struct bwn_dma_ring *
9985 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9986 {
9987 
9988 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9989 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9990 
9991 	switch (prio) {
9992 	case 3:
9993 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9994 	case 2:
9995 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9996 	case 0:
9997 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9998 	case 1:
9999 		return (mac->mac_method.dma.wme[WME_AC_BK]);
10000 	}
10001 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
10002 	return (NULL);
10003 }
10004 
10005 static int
10006 bwn_dma_getslot(struct bwn_dma_ring *dr)
10007 {
10008 	int slot;
10009 
10010 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
10011 
10012 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
10013 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
10014 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
10015 
10016 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
10017 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
10018 	dr->dr_curslot = slot;
10019 	dr->dr_usedslot++;
10020 
10021 	return (slot);
10022 }
10023 
10024 static int
10025 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
10026 {
10027 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
10028 	unsigned int a, b, c, d;
10029 	unsigned int avg;
10030 	uint32_t tmp;
10031 
10032 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
10033 	a = tmp & 0xff;
10034 	b = (tmp >> 8) & 0xff;
10035 	c = (tmp >> 16) & 0xff;
10036 	d = (tmp >> 24) & 0xff;
10037 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
10038 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
10039 		return (ENOENT);
10040 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
10041 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
10042 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
10043 
10044 	if (ofdm) {
10045 		a = (a + 32) & 0x3f;
10046 		b = (b + 32) & 0x3f;
10047 		c = (c + 32) & 0x3f;
10048 		d = (d + 32) & 0x3f;
10049 	}
10050 
10051 	avg = (a + b + c + d + 2) / 4;
10052 	if (ofdm) {
10053 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
10054 		    & BWN_HF_4DB_CCK_POWERBOOST)
10055 			avg = (avg >= 13) ? (avg - 13) : 0;
10056 	}
10057 	return (avg);
10058 }
10059 
10060 static void
10061 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
10062 {
10063 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
10064 	int rfatt = *rfattp;
10065 	int bbatt = *bbattp;
10066 
10067 	while (1) {
10068 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
10069 			break;
10070 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
10071 			break;
10072 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
10073 			break;
10074 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
10075 			break;
10076 		if (bbatt > lo->bbatt.max) {
10077 			bbatt -= 4;
10078 			rfatt += 1;
10079 			continue;
10080 		}
10081 		if (bbatt < lo->bbatt.min) {
10082 			bbatt += 4;
10083 			rfatt -= 1;
10084 			continue;
10085 		}
10086 		if (rfatt > lo->rfatt.max) {
10087 			rfatt -= 1;
10088 			bbatt += 4;
10089 			continue;
10090 		}
10091 		if (rfatt < lo->rfatt.min) {
10092 			rfatt += 1;
10093 			bbatt -= 4;
10094 			continue;
10095 		}
10096 		break;
10097 	}
10098 
10099 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
10100 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
10101 }
10102 
10103 static void
10104 bwn_phy_lock(struct bwn_mac *mac)
10105 {
10106 	struct bwn_softc *sc = mac->mac_sc;
10107 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10108 
10109 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10110 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10111 
10112 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10113 		bwn_psctl(mac, BWN_PS_AWAKE);
10114 }
10115 
10116 static void
10117 bwn_phy_unlock(struct bwn_mac *mac)
10118 {
10119 	struct bwn_softc *sc = mac->mac_sc;
10120 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
10121 
10122 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
10123 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
10124 
10125 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
10126 		bwn_psctl(mac, 0);
10127 }
10128 
10129 static void
10130 bwn_rf_lock(struct bwn_mac *mac)
10131 {
10132 
10133 	BWN_WRITE_4(mac, BWN_MACCTL,
10134 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
10135 	BWN_READ_4(mac, BWN_MACCTL);
10136 	DELAY(10);
10137 }
10138 
10139 static void
10140 bwn_rf_unlock(struct bwn_mac *mac)
10141 {
10142 
10143 	BWN_READ_2(mac, BWN_PHYVER);
10144 	BWN_WRITE_4(mac, BWN_MACCTL,
10145 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10146 }
10147 
10148 static struct bwn_pio_txqueue *
10149 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10150     struct bwn_pio_txpkt **pack)
10151 {
10152 	struct bwn_pio *pio = &mac->mac_method.pio;
10153 	struct bwn_pio_txqueue *tq = NULL;
10154 	unsigned int index;
10155 
10156 	switch (cookie & 0xf000) {
10157 	case 0x1000:
10158 		tq = &pio->wme[WME_AC_BK];
10159 		break;
10160 	case 0x2000:
10161 		tq = &pio->wme[WME_AC_BE];
10162 		break;
10163 	case 0x3000:
10164 		tq = &pio->wme[WME_AC_VI];
10165 		break;
10166 	case 0x4000:
10167 		tq = &pio->wme[WME_AC_VO];
10168 		break;
10169 	case 0x5000:
10170 		tq = &pio->mcast;
10171 		break;
10172 	}
10173 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10174 	if (tq == NULL)
10175 		return (NULL);
10176 	index = (cookie & 0x0fff);
10177 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10178 	if (index >= N(tq->tq_pkts))
10179 		return (NULL);
10180 	*pack = &tq->tq_pkts[index];
10181 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10182 	return (tq);
10183 }
10184 
10185 static void
10186 bwn_txpwr(void *arg, int npending)
10187 {
10188 	struct bwn_mac *mac = arg;
10189 	struct bwn_softc *sc = mac->mac_sc;
10190 
10191 	BWN_LOCK(sc);
10192 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10193 	    mac->mac_phy.set_txpwr != NULL)
10194 		mac->mac_phy.set_txpwr(mac);
10195 	BWN_UNLOCK(sc);
10196 }
10197 
10198 static void
10199 bwn_task_15s(struct bwn_mac *mac)
10200 {
10201 	uint16_t reg;
10202 
10203 	if (mac->mac_fw.opensource) {
10204 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10205 		if (reg) {
10206 			bwn_restart(mac, "fw watchdog");
10207 			return;
10208 		}
10209 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10210 	}
10211 	if (mac->mac_phy.task_15s)
10212 		mac->mac_phy.task_15s(mac);
10213 
10214 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10215 }
10216 
10217 static void
10218 bwn_task_30s(struct bwn_mac *mac)
10219 {
10220 
10221 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10222 		return;
10223 	mac->mac_noise.noi_running = 1;
10224 	mac->mac_noise.noi_nsamples = 0;
10225 
10226 	bwn_noise_gensample(mac);
10227 }
10228 
10229 static void
10230 bwn_task_60s(struct bwn_mac *mac)
10231 {
10232 
10233 	if (mac->mac_phy.task_60s)
10234 		mac->mac_phy.task_60s(mac);
10235 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10236 }
10237 
10238 static void
10239 bwn_tasks(void *arg)
10240 {
10241 	struct bwn_mac *mac = arg;
10242 	struct bwn_softc *sc = mac->mac_sc;
10243 
10244 	BWN_ASSERT_LOCKED(sc);
10245 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10246 		return;
10247 
10248 	if (mac->mac_task_state % 4 == 0)
10249 		bwn_task_60s(mac);
10250 	if (mac->mac_task_state % 2 == 0)
10251 		bwn_task_30s(mac);
10252 	bwn_task_15s(mac);
10253 
10254 	mac->mac_task_state++;
10255 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10256 }
10257 
10258 static int
10259 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10260 {
10261 	struct bwn_softc *sc = mac->mac_sc;
10262 
10263 	KASSERT(a == 0, ("not support APHY\n"));
10264 
10265 	switch (plcp->o.raw[0] & 0xf) {
10266 	case 0xb:
10267 		return (BWN_OFDM_RATE_6MB);
10268 	case 0xf:
10269 		return (BWN_OFDM_RATE_9MB);
10270 	case 0xa:
10271 		return (BWN_OFDM_RATE_12MB);
10272 	case 0xe:
10273 		return (BWN_OFDM_RATE_18MB);
10274 	case 0x9:
10275 		return (BWN_OFDM_RATE_24MB);
10276 	case 0xd:
10277 		return (BWN_OFDM_RATE_36MB);
10278 	case 0x8:
10279 		return (BWN_OFDM_RATE_48MB);
10280 	case 0xc:
10281 		return (BWN_OFDM_RATE_54MB);
10282 	}
10283 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10284 	    plcp->o.raw[0] & 0xf);
10285 	return (-1);
10286 }
10287 
10288 static int
10289 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10290 {
10291 	struct bwn_softc *sc = mac->mac_sc;
10292 
10293 	switch (plcp->o.raw[0]) {
10294 	case 0x0a:
10295 		return (BWN_CCK_RATE_1MB);
10296 	case 0x14:
10297 		return (BWN_CCK_RATE_2MB);
10298 	case 0x37:
10299 		return (BWN_CCK_RATE_5MB);
10300 	case 0x6e:
10301 		return (BWN_CCK_RATE_11MB);
10302 	}
10303 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10304 	return (-1);
10305 }
10306 
10307 static void
10308 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10309     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10310     int rssi, int noise)
10311 {
10312 	struct bwn_softc *sc = mac->mac_sc;
10313 	const struct ieee80211_frame_min *wh;
10314 	uint64_t tsf;
10315 	uint16_t low_mactime_now;
10316 
10317 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10318 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10319 
10320 	wh = mtod(m, const struct ieee80211_frame_min *);
10321 	if (wh->i_fc[1] & IEEE80211_FC1_WEP)
10322 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10323 
10324 	bwn_tsf_read(mac, &tsf);
10325 	low_mactime_now = tsf;
10326 	tsf = tsf & ~0xffffULL;
10327 	tsf += le16toh(rxhdr->mac_time);
10328 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10329 		tsf -= 0x10000;
10330 
10331 	sc->sc_rx_th.wr_tsf = tsf;
10332 	sc->sc_rx_th.wr_rate = rate;
10333 	sc->sc_rx_th.wr_antsignal = rssi;
10334 	sc->sc_rx_th.wr_antnoise = noise;
10335 }
10336 
10337 static void
10338 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10339 {
10340 	uint32_t low, high;
10341 
10342 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10343 	    ("%s:%d: fail", __func__, __LINE__));
10344 
10345 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10346 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10347 	*tsf = high;
10348 	*tsf <<= 32;
10349 	*tsf |= low;
10350 }
10351 
10352 static int
10353 bwn_dma_attach(struct bwn_mac *mac)
10354 {
10355 	struct bwn_dma *dma = &mac->mac_method.dma;
10356 	struct bwn_softc *sc = mac->mac_sc;
10357 	bus_addr_t lowaddr = 0;
10358 	int error;
10359 
10360 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10361 		return (0);
10362 
10363 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10364 
10365 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10366 
10367 	dma->dmatype = bwn_dma_gettype(mac);
10368 	if (dma->dmatype == BWN_DMA_30BIT)
10369 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10370 	else if (dma->dmatype == BWN_DMA_32BIT)
10371 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10372 	else
10373 		lowaddr = BUS_SPACE_MAXADDR;
10374 
10375 	/*
10376 	 * Create top level DMA tag
10377 	 */
10378 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10379 			       BWN_ALIGN, 0,		/* alignment, bounds */
10380 			       lowaddr,			/* lowaddr */
10381 			       BUS_SPACE_MAXADDR,	/* highaddr */
10382 			       NULL, NULL,		/* filter, filterarg */
10383 			       MAXBSIZE,		/* maxsize */
10384 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10385 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10386 			       0,			/* flags */
10387 			       NULL, NULL,		/* lockfunc, lockarg */
10388 			       &dma->parent_dtag);
10389 	if (error) {
10390 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10391 		return (error);
10392 	}
10393 
10394 	/*
10395 	 * Create TX/RX mbuf DMA tag
10396 	 */
10397 	error = bus_dma_tag_create(dma->parent_dtag,
10398 				1,
10399 				0,
10400 				BUS_SPACE_MAXADDR,
10401 				BUS_SPACE_MAXADDR,
10402 				NULL, NULL,
10403 				MCLBYTES,
10404 				1,
10405 				BUS_SPACE_MAXSIZE_32BIT,
10406 				0,
10407 				NULL, NULL,
10408 				&dma->rxbuf_dtag);
10409 	if (error) {
10410 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10411 		goto fail0;
10412 	}
10413 	error = bus_dma_tag_create(dma->parent_dtag,
10414 				1,
10415 				0,
10416 				BUS_SPACE_MAXADDR,
10417 				BUS_SPACE_MAXADDR,
10418 				NULL, NULL,
10419 				MCLBYTES,
10420 				1,
10421 				BUS_SPACE_MAXSIZE_32BIT,
10422 				0,
10423 				NULL, NULL,
10424 				&dma->txbuf_dtag);
10425 	if (error) {
10426 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10427 		goto fail1;
10428 	}
10429 
10430 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10431 	if (!dma->wme[WME_AC_BK])
10432 		goto fail2;
10433 
10434 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10435 	if (!dma->wme[WME_AC_BE])
10436 		goto fail3;
10437 
10438 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10439 	if (!dma->wme[WME_AC_VI])
10440 		goto fail4;
10441 
10442 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10443 	if (!dma->wme[WME_AC_VO])
10444 		goto fail5;
10445 
10446 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10447 	if (!dma->mcast)
10448 		goto fail6;
10449 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10450 	if (!dma->rx)
10451 		goto fail7;
10452 
10453 	return (error);
10454 
10455 fail7:	bwn_dma_ringfree(&dma->mcast);
10456 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10457 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10458 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10459 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10460 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10461 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10462 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10463 	return (error);
10464 }
10465 
10466 static struct bwn_dma_ring *
10467 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10468     uint16_t cookie, int *slot)
10469 {
10470 	struct bwn_dma *dma = &mac->mac_method.dma;
10471 	struct bwn_dma_ring *dr;
10472 	struct bwn_softc *sc = mac->mac_sc;
10473 
10474 	BWN_ASSERT_LOCKED(mac->mac_sc);
10475 
10476 	switch (cookie & 0xf000) {
10477 	case 0x1000:
10478 		dr = dma->wme[WME_AC_BK];
10479 		break;
10480 	case 0x2000:
10481 		dr = dma->wme[WME_AC_BE];
10482 		break;
10483 	case 0x3000:
10484 		dr = dma->wme[WME_AC_VI];
10485 		break;
10486 	case 0x4000:
10487 		dr = dma->wme[WME_AC_VO];
10488 		break;
10489 	case 0x5000:
10490 		dr = dma->mcast;
10491 		break;
10492 	default:
10493 		dr = NULL;
10494 		KASSERT(0 == 1,
10495 		    ("invalid cookie value %d", cookie & 0xf000));
10496 	}
10497 	*slot = (cookie & 0x0fff);
10498 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10499 		/*
10500 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10501 		 * that it occurs events which have same H/W sequence numbers.
10502 		 * When it's occurred just prints a WARNING msgs and ignores.
10503 		 */
10504 		KASSERT(status->seq == dma->lastseq,
10505 		    ("%s:%d: fail", __func__, __LINE__));
10506 		device_printf(sc->sc_dev,
10507 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10508 		    dr->dr_numslots);
10509 		return (NULL);
10510 	}
10511 	dma->lastseq = status->seq;
10512 	return (dr);
10513 }
10514 
10515 static void
10516 bwn_dma_stop(struct bwn_mac *mac)
10517 {
10518 	struct bwn_dma *dma;
10519 
10520 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10521 		return;
10522 	dma = &mac->mac_method.dma;
10523 
10524 	bwn_dma_ringstop(&dma->rx);
10525 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10526 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10527 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10528 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10529 	bwn_dma_ringstop(&dma->mcast);
10530 }
10531 
10532 static void
10533 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10534 {
10535 
10536 	if (dr == NULL)
10537 		return;
10538 
10539 	bwn_dma_cleanup(*dr);
10540 }
10541 
10542 static void
10543 bwn_pio_stop(struct bwn_mac *mac)
10544 {
10545 	struct bwn_pio *pio;
10546 
10547 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10548 		return;
10549 	pio = &mac->mac_method.pio;
10550 
10551 	bwn_destroy_queue_tx(&pio->mcast);
10552 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10553 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10554 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10555 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10556 }
10557 
10558 static void
10559 bwn_led_attach(struct bwn_mac *mac)
10560 {
10561 	struct bwn_softc *sc = mac->mac_sc;
10562 	const uint8_t *led_act = NULL;
10563 	uint16_t val[BWN_LED_MAX];
10564 	int i;
10565 
10566 	sc->sc_led_idle = (2350 * hz) / 1000;
10567 	sc->sc_led_blink = 1;
10568 
10569 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10570 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10571 		    bwn_vendor_led_act[i].vid) {
10572 			led_act = bwn_vendor_led_act[i].led_act;
10573 			break;
10574 		}
10575 	}
10576 	if (led_act == NULL)
10577 		led_act = bwn_default_led_act;
10578 
10579 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10580 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10581 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10582 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10583 
10584 	for (i = 0; i < BWN_LED_MAX; ++i) {
10585 		struct bwn_led *led = &sc->sc_leds[i];
10586 
10587 		if (val[i] == 0xff) {
10588 			led->led_act = led_act[i];
10589 		} else {
10590 			if (val[i] & BWN_LED_ACT_LOW)
10591 				led->led_flags |= BWN_LED_F_ACTLOW;
10592 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10593 		}
10594 		led->led_mask = (1 << i);
10595 
10596 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10597 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10598 		    led->led_act == BWN_LED_ACT_BLINK) {
10599 			led->led_flags |= BWN_LED_F_BLINK;
10600 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10601 				led->led_flags |= BWN_LED_F_POLLABLE;
10602 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10603 				led->led_flags |= BWN_LED_F_SLOW;
10604 
10605 			if (sc->sc_blink_led == NULL) {
10606 				sc->sc_blink_led = led;
10607 				if (led->led_flags & BWN_LED_F_SLOW)
10608 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10609 			}
10610 		}
10611 
10612 		DPRINTF(sc, BWN_DEBUG_LED,
10613 		    "%dth led, act %d, lowact %d\n", i,
10614 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10615 	}
10616 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10617 }
10618 
10619 static __inline uint16_t
10620 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10621 {
10622 
10623 	if (led->led_flags & BWN_LED_F_ACTLOW)
10624 		on = !on;
10625 	if (on)
10626 		val |= led->led_mask;
10627 	else
10628 		val &= ~led->led_mask;
10629 	return val;
10630 }
10631 
10632 static void
10633 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10634 {
10635 	struct bwn_softc *sc = mac->mac_sc;
10636 	struct ifnet *ifp = sc->sc_ifp;
10637 	struct ieee80211com *ic = ifp->if_l2com;
10638 	uint16_t val;
10639 	int i;
10640 
10641 	if (nstate == IEEE80211_S_INIT) {
10642 		callout_stop(&sc->sc_led_blink_ch);
10643 		sc->sc_led_blinking = 0;
10644 	}
10645 
10646 	if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
10647 		return;
10648 
10649 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10650 	for (i = 0; i < BWN_LED_MAX; ++i) {
10651 		struct bwn_led *led = &sc->sc_leds[i];
10652 		int on;
10653 
10654 		if (led->led_act == BWN_LED_ACT_UNKN ||
10655 		    led->led_act == BWN_LED_ACT_NULL)
10656 			continue;
10657 
10658 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10659 		    nstate != IEEE80211_S_INIT)
10660 			continue;
10661 
10662 		switch (led->led_act) {
10663 		case BWN_LED_ACT_ON:    /* Always on */
10664 			on = 1;
10665 			break;
10666 		case BWN_LED_ACT_OFF:   /* Always off */
10667 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10668 			on = 0;
10669 			break;
10670 		default:
10671 			on = 1;
10672 			switch (nstate) {
10673 			case IEEE80211_S_INIT:
10674 				on = 0;
10675 				break;
10676 			case IEEE80211_S_RUN:
10677 				if (led->led_act == BWN_LED_ACT_11G &&
10678 				    ic->ic_curmode != IEEE80211_MODE_11G)
10679 					on = 0;
10680 				break;
10681 			default:
10682 				if (led->led_act == BWN_LED_ACT_ASSOC)
10683 					on = 0;
10684 				break;
10685 			}
10686 			break;
10687 		}
10688 
10689 		val = bwn_led_onoff(led, val, on);
10690 	}
10691 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10692 }
10693 
10694 static void
10695 bwn_led_event(struct bwn_mac *mac, int event)
10696 {
10697 	struct bwn_softc *sc = mac->mac_sc;
10698 	struct bwn_led *led = sc->sc_blink_led;
10699 	int rate;
10700 
10701 	if (event == BWN_LED_EVENT_POLL) {
10702 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10703 			return;
10704 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10705 			return;
10706 	}
10707 
10708 	sc->sc_led_ticks = ticks;
10709 	if (sc->sc_led_blinking)
10710 		return;
10711 
10712 	switch (event) {
10713 	case BWN_LED_EVENT_RX:
10714 		rate = sc->sc_rx_rate;
10715 		break;
10716 	case BWN_LED_EVENT_TX:
10717 		rate = sc->sc_tx_rate;
10718 		break;
10719 	case BWN_LED_EVENT_POLL:
10720 		rate = 0;
10721 		break;
10722 	default:
10723 		panic("unknown LED event %d\n", event);
10724 		break;
10725 	}
10726 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10727 	    bwn_led_duration[rate].off_dur);
10728 }
10729 
10730 static void
10731 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10732 {
10733 	struct bwn_softc *sc = mac->mac_sc;
10734 	struct bwn_led *led = sc->sc_blink_led;
10735 	uint16_t val;
10736 
10737 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10738 	val = bwn_led_onoff(led, val, 1);
10739 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10740 
10741 	if (led->led_flags & BWN_LED_F_SLOW) {
10742 		BWN_LED_SLOWDOWN(on_dur);
10743 		BWN_LED_SLOWDOWN(off_dur);
10744 	}
10745 
10746 	sc->sc_led_blinking = 1;
10747 	sc->sc_led_blink_offdur = off_dur;
10748 
10749 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10750 }
10751 
10752 static void
10753 bwn_led_blink_next(void *arg)
10754 {
10755 	struct bwn_mac *mac = arg;
10756 	struct bwn_softc *sc = mac->mac_sc;
10757 	uint16_t val;
10758 
10759 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10760 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10761 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10762 
10763 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10764 	    bwn_led_blink_end, mac);
10765 }
10766 
10767 static void
10768 bwn_led_blink_end(void *arg)
10769 {
10770 	struct bwn_mac *mac = arg;
10771 	struct bwn_softc *sc = mac->mac_sc;
10772 
10773 	sc->sc_led_blinking = 0;
10774 }
10775 
10776 static int
10777 bwn_suspend(device_t dev)
10778 {
10779 	struct bwn_softc *sc = device_get_softc(dev);
10780 
10781 	bwn_stop(sc, 1);
10782 	return (0);
10783 }
10784 
10785 static int
10786 bwn_resume(device_t dev)
10787 {
10788 	struct bwn_softc *sc = device_get_softc(dev);
10789 	struct ifnet *ifp = sc->sc_ifp;
10790 
10791 	if (ifp->if_flags & IFF_UP)
10792 		bwn_init(sc);
10793 	return (0);
10794 }
10795 
10796 static void
10797 bwn_rfswitch(void *arg)
10798 {
10799 	struct bwn_softc *sc = arg;
10800 	struct bwn_mac *mac = sc->sc_curmac;
10801 	int cur = 0, prev = 0;
10802 
10803 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10804 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10805 
10806 	if (mac->mac_phy.rf_rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10807 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10808 			& BWN_RF_HWENABLED_HI_MASK))
10809 			cur = 1;
10810 	} else {
10811 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10812 		    & BWN_RF_HWENABLED_LO_MASK)
10813 			cur = 1;
10814 	}
10815 
10816 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10817 		prev = 1;
10818 
10819 	if (cur != prev) {
10820 		if (cur)
10821 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10822 		else
10823 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10824 
10825 		device_printf(sc->sc_dev,
10826 		    "status of RF switch is changed to %s\n",
10827 		    cur ? "ON" : "OFF");
10828 		if (cur != mac->mac_phy.rf_on) {
10829 			if (cur)
10830 				bwn_rf_turnon(mac);
10831 			else
10832 				bwn_rf_turnoff(mac);
10833 		}
10834 	}
10835 
10836 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10837 }
10838 
10839 static void
10840 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10841 {
10842 	struct bwn_phy *phy = &mac->mac_phy;
10843 	struct bwn_phy_lp *plp = &phy->phy_lp;
10844 
10845 	plp->plp_antenna = BWN_ANT_DEFAULT;
10846 }
10847 
10848 static int
10849 bwn_phy_lp_init(struct bwn_mac *mac)
10850 {
10851 	static const struct bwn_stxtable tables[] = {
10852 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10853 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10854 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10855 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10856 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10857 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10858 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10859 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10860 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10861 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10862 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10863 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10864 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10865 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10866 		{ 2, 11, 0x40, 0, 0x0f }
10867 	};
10868 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10869 	struct bwn_softc *sc = mac->mac_sc;
10870 	const struct bwn_stxtable *st;
10871 	struct ifnet *ifp = sc->sc_ifp;
10872 	struct ieee80211com *ic = ifp->if_l2com;
10873 	int i, error;
10874 	uint16_t tmp;
10875 
10876 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10877 	bwn_phy_lp_bbinit(mac);
10878 
10879 	/* initialize RF */
10880 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10881 	DELAY(1);
10882 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10883 	DELAY(1);
10884 
10885 	if (mac->mac_phy.rf_ver == 0x2062)
10886 		bwn_phy_lp_b2062_init(mac);
10887 	else {
10888 		bwn_phy_lp_b2063_init(mac);
10889 
10890 		/* synchronize stx table. */
10891 		for (i = 0; i < N(tables); i++) {
10892 			st = &tables[i];
10893 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10894 			tmp >>= st->st_rfshift;
10895 			tmp <<= st->st_physhift;
10896 			BWN_PHY_SETMASK(mac,
10897 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10898 			    ~(st->st_mask << st->st_physhift), tmp);
10899 		}
10900 
10901 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10902 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10903 	}
10904 
10905 	/* calibrate RC */
10906 	if (mac->mac_phy.rev >= 2)
10907 		bwn_phy_lp_rxcal_r2(mac);
10908 	else if (!plp->plp_rccap) {
10909 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10910 			bwn_phy_lp_rccal_r12(mac);
10911 	} else
10912 		bwn_phy_lp_set_rccap(mac);
10913 
10914 	error = bwn_phy_lp_switch_channel(mac, 7);
10915 	if (error)
10916 		device_printf(sc->sc_dev,
10917 		    "failed to change channel 7 (%d)\n", error);
10918 	bwn_phy_lp_txpctl_init(mac);
10919 	bwn_phy_lp_calib(mac);
10920 	return (0);
10921 }
10922 
10923 static uint16_t
10924 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10925 {
10926 
10927 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10928 	return (BWN_READ_2(mac, BWN_PHYDATA));
10929 }
10930 
10931 static void
10932 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10933 {
10934 
10935 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10936 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10937 }
10938 
10939 static void
10940 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10941     uint16_t set)
10942 {
10943 
10944 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10945 	BWN_WRITE_2(mac, BWN_PHYDATA,
10946 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10947 }
10948 
10949 static uint16_t
10950 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10951 {
10952 
10953 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10954 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10955 		reg |= 0x100;
10956 	if (mac->mac_phy.rev >= 2)
10957 		reg |= 0x200;
10958 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10959 	return BWN_READ_2(mac, BWN_RFDATALO);
10960 }
10961 
10962 static void
10963 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10964 {
10965 
10966 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10967 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10968 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10969 }
10970 
10971 static void
10972 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10973 {
10974 
10975 	if (on) {
10976 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10977 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10978 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10979 		return;
10980 	}
10981 
10982 	if (mac->mac_phy.rev >= 2) {
10983 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10984 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10985 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10986 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10987 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10988 		return;
10989 	}
10990 
10991 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10992 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10993 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10994 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10995 }
10996 
10997 static int
10998 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10999 {
11000 	struct bwn_phy *phy = &mac->mac_phy;
11001 	struct bwn_phy_lp *plp = &phy->phy_lp;
11002 	int error;
11003 
11004 	if (phy->rf_ver == 0x2063) {
11005 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
11006 		if (error)
11007 			return (error);
11008 	} else {
11009 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
11010 		if (error)
11011 			return (error);
11012 		bwn_phy_lp_set_anafilter(mac, chan);
11013 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
11014 	}
11015 
11016 	plp->plp_chan = chan;
11017 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
11018 	return (0);
11019 }
11020 
11021 static uint32_t
11022 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
11023 {
11024 	struct bwn_softc *sc = mac->mac_sc;
11025 	struct ifnet *ifp = sc->sc_ifp;
11026 	struct ieee80211com *ic = ifp->if_l2com;
11027 
11028 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
11029 }
11030 
11031 static void
11032 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
11033 {
11034 	struct bwn_phy *phy = &mac->mac_phy;
11035 	struct bwn_phy_lp *plp = &phy->phy_lp;
11036 
11037 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
11038 		return;
11039 
11040 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
11041 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
11042 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
11043 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
11044 	plp->plp_antenna = antenna;
11045 }
11046 
11047 static void
11048 bwn_phy_lp_task_60s(struct bwn_mac *mac)
11049 {
11050 
11051 	bwn_phy_lp_calib(mac);
11052 }
11053 
11054 static void
11055 bwn_phy_lp_readsprom(struct bwn_mac *mac)
11056 {
11057 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11058 	struct bwn_softc *sc = mac->mac_sc;
11059 	struct ifnet *ifp = sc->sc_ifp;
11060 	struct ieee80211com *ic = ifp->if_l2com;
11061 
11062 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11063 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
11064 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
11065 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
11066 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
11067 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
11068 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
11069 		return;
11070 	}
11071 
11072 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
11073 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
11074 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
11075 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
11076 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
11077 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
11078 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
11079 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
11080 }
11081 
11082 static void
11083 bwn_phy_lp_bbinit(struct bwn_mac *mac)
11084 {
11085 
11086 	bwn_phy_lp_tblinit(mac);
11087 	if (mac->mac_phy.rev >= 2)
11088 		bwn_phy_lp_bbinit_r2(mac);
11089 	else
11090 		bwn_phy_lp_bbinit_r01(mac);
11091 }
11092 
11093 static void
11094 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
11095 {
11096 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
11097 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
11098 	struct bwn_softc *sc = mac->mac_sc;
11099 	struct ifnet *ifp = sc->sc_ifp;
11100 	struct ieee80211com *ic = ifp->if_l2com;
11101 
11102 	bwn_phy_lp_set_txgain(mac,
11103 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
11104 	bwn_phy_lp_set_bbmult(mac, 150);
11105 }
11106 
11107 static void
11108 bwn_phy_lp_calib(struct bwn_mac *mac)
11109 {
11110 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11111 	struct bwn_softc *sc = mac->mac_sc;
11112 	struct ifnet *ifp = sc->sc_ifp;
11113 	struct ieee80211com *ic = ifp->if_l2com;
11114 	const struct bwn_rxcompco *rc = NULL;
11115 	struct bwn_txgain ogain;
11116 	int i, omode, oafeovr, orf, obbmult;
11117 	uint8_t mode, fc = 0;
11118 
11119 	if (plp->plp_chanfullcal != plp->plp_chan) {
11120 		plp->plp_chanfullcal = plp->plp_chan;
11121 		fc = 1;
11122 	}
11123 
11124 	bwn_mac_suspend(mac);
11125 
11126 	/* BlueTooth Coexistance Override */
11127 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
11128 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
11129 
11130 	if (mac->mac_phy.rev >= 2)
11131 		bwn_phy_lp_digflt_save(mac);
11132 	bwn_phy_lp_get_txpctlmode(mac);
11133 	mode = plp->plp_txpctlmode;
11134 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11135 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
11136 		bwn_phy_lp_bugfix(mac);
11137 	if (mac->mac_phy.rev >= 2 && fc == 1) {
11138 		bwn_phy_lp_get_txpctlmode(mac);
11139 		omode = plp->plp_txpctlmode;
11140 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
11141 		if (oafeovr)
11142 			ogain = bwn_phy_lp_get_txgain(mac);
11143 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11144 		obbmult = bwn_phy_lp_get_bbmult(mac);
11145 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11146 		if (oafeovr)
11147 			bwn_phy_lp_set_txgain(mac, &ogain);
11148 		bwn_phy_lp_set_bbmult(mac, obbmult);
11149 		bwn_phy_lp_set_txpctlmode(mac, omode);
11150 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11151 	}
11152 	bwn_phy_lp_set_txpctlmode(mac, mode);
11153 	if (mac->mac_phy.rev >= 2)
11154 		bwn_phy_lp_digflt_restore(mac);
11155 
11156 	/* do RX IQ Calculation; assumes that noise is true. */
11157 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11158 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11159 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11160 				rc = &bwn_rxcompco_5354[i];
11161 		}
11162 	} else if (mac->mac_phy.rev >= 2)
11163 		rc = &bwn_rxcompco_r2;
11164 	else {
11165 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11166 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11167 				rc = &bwn_rxcompco_r12[i];
11168 		}
11169 	}
11170 	if (rc == NULL)
11171 		goto fail;
11172 
11173 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11174 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11175 
11176 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11177 
11178 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11179 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11180 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11181 	} else {
11182 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11183 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11184 	}
11185 
11186 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11187 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11188 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11189 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11190 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11191 	bwn_phy_lp_set_deaf(mac, 0);
11192 	/* XXX no checking return value? */
11193 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11194 	bwn_phy_lp_clear_deaf(mac, 0);
11195 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11196 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11197 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11198 
11199 	/* disable RX GAIN override. */
11200 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11201 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11202 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11203 	if (mac->mac_phy.rev >= 2) {
11204 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11205 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11206 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11207 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11208 		}
11209 	} else {
11210 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11211 	}
11212 
11213 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11214 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11215 fail:
11216 	bwn_mac_enable(mac);
11217 }
11218 
11219 static void
11220 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11221 {
11222 
11223 	if (on) {
11224 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11225 		return;
11226 	}
11227 
11228 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11229 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11230 }
11231 
11232 static int
11233 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11234 {
11235 	static const struct bwn_b206x_chan *bc = NULL;
11236 	struct bwn_softc *sc = mac->mac_sc;
11237 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11238 	    tmp[6];
11239 	uint16_t old, scale, tmp16;
11240 	int i, div;
11241 
11242 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11243 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11244 			bc = &bwn_b2063_chantable[i];
11245 			break;
11246 		}
11247 	}
11248 	if (bc == NULL)
11249 		return (EINVAL);
11250 
11251 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11252 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11253 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11254 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11255 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11256 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11257 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11258 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11259 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11260 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11261 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11262 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11263 
11264 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11265 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11266 
11267 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11268 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11269 	freqref = freqxtal * 3;
11270 	div = (freqxtal <= 26000000 ? 1 : 2);
11271 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11272 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11273 		999999) / 1000000) + 1;
11274 
11275 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11276 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11277 	    0xfff8, timeout >> 2);
11278 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11279 	    0xff9f,timeout << 5);
11280 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11281 
11282 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11283 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11284 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11285 
11286 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11287 	    (timeoutref + 1)) - 1;
11288 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11289 	    0xf0, count >> 8);
11290 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11291 
11292 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11293 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11294 	while (tmp[1] >= freqref) {
11295 		tmp[0]++;
11296 		tmp[1] -= freqref;
11297 	}
11298 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11299 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11300 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11301 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11302 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11303 
11304 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11305 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11306 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11307 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11308 
11309 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11310 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11311 
11312 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11313 		scale = 1;
11314 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11315 	} else {
11316 		scale = 0;
11317 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11318 	}
11319 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11320 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11321 
11322 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11323 	    (scale + 1);
11324 	if (tmp[5] > 150)
11325 		tmp[5] = 0;
11326 
11327 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11328 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11329 
11330 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11331 	if (freqxtal > 26000000)
11332 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11333 	else
11334 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11335 
11336 	if (val[0] == 45)
11337 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11338 	else
11339 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11340 
11341 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11342 	DELAY(1);
11343 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11344 
11345 	/* VCO Calibration */
11346 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11347 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11348 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11349 	DELAY(1);
11350 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11351 	DELAY(1);
11352 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11353 	DELAY(1);
11354 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11355 	DELAY(300);
11356 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11357 
11358 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11359 	return (0);
11360 }
11361 
11362 static int
11363 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11364 {
11365 	struct bwn_softc *sc = mac->mac_sc;
11366 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11367 	const struct bwn_b206x_chan *bc = NULL;
11368 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11369 	uint32_t tmp[9];
11370 	int i;
11371 
11372 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11373 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11374 			bc = &bwn_b2062_chantable[i];
11375 			break;
11376 		}
11377 	}
11378 
11379 	if (bc == NULL)
11380 		return (EINVAL);
11381 
11382 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11383 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11384 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11385 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11386 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11387 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11388 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11389 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11390 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11391 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11392 
11393 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11394 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11395 	bwn_phy_lp_b2062_reset_pllbias(mac);
11396 	tmp[0] = freqxtal / 1000;
11397 	tmp[1] = plp->plp_div * 1000;
11398 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11399 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11400 		tmp[2] *= 2;
11401 	tmp[3] = 48 * tmp[0];
11402 	tmp[5] = tmp[2] / tmp[3];
11403 	tmp[6] = tmp[2] % tmp[3];
11404 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11405 	tmp[4] = tmp[6] * 0x100;
11406 	tmp[5] = tmp[4] / tmp[3];
11407 	tmp[6] = tmp[4] % tmp[3];
11408 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11409 	tmp[4] = tmp[6] * 0x100;
11410 	tmp[5] = tmp[4] / tmp[3];
11411 	tmp[6] = tmp[4] % tmp[3];
11412 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11413 	tmp[4] = tmp[6] * 0x100;
11414 	tmp[5] = tmp[4] / tmp[3];
11415 	tmp[6] = tmp[4] % tmp[3];
11416 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11417 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11418 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11419 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11420 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11421 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11422 
11423 	bwn_phy_lp_b2062_vco_calib(mac);
11424 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11425 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11426 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11427 		bwn_phy_lp_b2062_reset_pllbias(mac);
11428 		bwn_phy_lp_b2062_vco_calib(mac);
11429 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11430 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11431 			return (EIO);
11432 		}
11433 	}
11434 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11435 	return (0);
11436 }
11437 
11438 static void
11439 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11440 {
11441 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11442 	uint16_t tmp = (channel == 14);
11443 
11444 	if (mac->mac_phy.rev < 2) {
11445 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11446 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11447 			bwn_phy_lp_set_rccap(mac);
11448 		return;
11449 	}
11450 
11451 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11452 }
11453 
11454 static void
11455 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11456 {
11457 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11458 	struct bwn_softc *sc = mac->mac_sc;
11459 	struct ifnet *ifp = sc->sc_ifp;
11460 	struct ieee80211com *ic = ifp->if_l2com;
11461 	uint16_t iso, tmp[3];
11462 
11463 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11464 
11465 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11466 		iso = plp->plp_txisoband_m;
11467 	else if (freq <= 5320)
11468 		iso = plp->plp_txisoband_l;
11469 	else if (freq <= 5700)
11470 		iso = plp->plp_txisoband_m;
11471 	else
11472 		iso = plp->plp_txisoband_h;
11473 
11474 	tmp[0] = ((iso - 26) / 12) << 12;
11475 	tmp[1] = tmp[0] + 0x1000;
11476 	tmp[2] = tmp[0] + 0x2000;
11477 
11478 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11479 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11480 }
11481 
11482 static void
11483 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11484 {
11485 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11486 	int i;
11487 	static const uint16_t addr[] = {
11488 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11489 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11490 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11491 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11492 		BWN_PHY_OFDM(0xcf),
11493 	};
11494 	static const uint16_t val[] = {
11495 		0xde5e, 0xe832, 0xe331, 0x4d26,
11496 		0x0026, 0x1420, 0x0020, 0xfe08,
11497 		0x0008,
11498 	};
11499 
11500 	for (i = 0; i < N(addr); i++) {
11501 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11502 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11503 	}
11504 }
11505 
11506 static void
11507 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11508 {
11509 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11510 	struct bwn_softc *sc = mac->mac_sc;
11511 	uint16_t ctl;
11512 
11513 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11514 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11515 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11516 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11517 		break;
11518 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11519 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11520 		break;
11521 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11522 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11523 		break;
11524 	default:
11525 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11526 		device_printf(sc->sc_dev, "unknown command mode\n");
11527 		break;
11528 	}
11529 }
11530 
11531 static void
11532 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11533 {
11534 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11535 	uint16_t ctl;
11536 	uint8_t old;
11537 
11538 	bwn_phy_lp_get_txpctlmode(mac);
11539 	old = plp->plp_txpctlmode;
11540 	if (old == mode)
11541 		return;
11542 	plp->plp_txpctlmode = mode;
11543 
11544 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11545 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11546 		    plp->plp_tssiidx);
11547 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11548 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11549 
11550 		/* disable TX GAIN override */
11551 		if (mac->mac_phy.rev < 2)
11552 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11553 		else {
11554 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11555 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11556 		}
11557 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11558 
11559 		plp->plp_txpwridx = -1;
11560 	}
11561 	if (mac->mac_phy.rev >= 2) {
11562 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11563 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11564 		else
11565 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11566 	}
11567 
11568 	/* writes TX Power Control mode */
11569 	switch (plp->plp_txpctlmode) {
11570 	case BWN_PHYLP_TXPCTL_OFF:
11571 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11572 		break;
11573 	case BWN_PHYLP_TXPCTL_ON_HW:
11574 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11575 		break;
11576 	case BWN_PHYLP_TXPCTL_ON_SW:
11577 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11578 		break;
11579 	default:
11580 		ctl = 0;
11581 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11582 	}
11583 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11584 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11585 }
11586 
11587 static void
11588 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11589 {
11590 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11591 	struct bwn_softc *sc = mac->mac_sc;
11592 	const unsigned int size = 256;
11593 	struct bwn_txgain tg;
11594 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11595 	uint16_t tssinpt, tssiidx, value[2];
11596 	uint8_t mode;
11597 	int8_t txpwridx;
11598 
11599 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11600 	    M_NOWAIT | M_ZERO);
11601 	if (tabs == NULL) {
11602 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11603 		return;
11604 	}
11605 
11606 	bwn_phy_lp_get_txpctlmode(mac);
11607 	mode = plp->plp_txpctlmode;
11608 	txpwridx = plp->plp_txpwridx;
11609 	tssinpt = plp->plp_tssinpt;
11610 	tssiidx = plp->plp_tssiidx;
11611 
11612 	bwn_tab_read_multi(mac,
11613 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11614 	    BWN_TAB_4(7, 0x140), size, tabs);
11615 
11616 	bwn_phy_lp_tblinit(mac);
11617 	bwn_phy_lp_bbinit(mac);
11618 	bwn_phy_lp_txpctl_init(mac);
11619 	bwn_phy_lp_rf_onoff(mac, 1);
11620 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11621 
11622 	bwn_tab_write_multi(mac,
11623 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11624 	    BWN_TAB_4(7, 0x140), size, tabs);
11625 
11626 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11627 	plp->plp_tssinpt = tssinpt;
11628 	plp->plp_tssiidx = tssiidx;
11629 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11630 	if (txpwridx != -1) {
11631 		/* set TX power by index */
11632 		plp->plp_txpwridx = txpwridx;
11633 		bwn_phy_lp_get_txpctlmode(mac);
11634 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11635 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11636 		if (mac->mac_phy.rev >= 2) {
11637 			rxcomp = bwn_tab_read(mac,
11638 			    BWN_TAB_4(7, txpwridx + 320));
11639 			txgain = bwn_tab_read(mac,
11640 			    BWN_TAB_4(7, txpwridx + 192));
11641 			tg.tg_pad = (txgain >> 16) & 0xff;
11642 			tg.tg_gm = txgain & 0xff;
11643 			tg.tg_pga = (txgain >> 8) & 0xff;
11644 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11645 			bwn_phy_lp_set_txgain(mac, &tg);
11646 		} else {
11647 			rxcomp = bwn_tab_read(mac,
11648 			    BWN_TAB_4(10, txpwridx + 320));
11649 			txgain = bwn_tab_read(mac,
11650 			    BWN_TAB_4(10, txpwridx + 192));
11651 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11652 			    0xf800, (txgain >> 4) & 0x7fff);
11653 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11654 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11655 		}
11656 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11657 
11658 		/* set TX IQCC */
11659 		value[0] = (rxcomp >> 10) & 0x3ff;
11660 		value[1] = rxcomp & 0x3ff;
11661 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11662 
11663 		coeff = bwn_tab_read(mac,
11664 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11665 		    BWN_TAB_4(10, txpwridx + 448));
11666 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11667 		if (mac->mac_phy.rev >= 2) {
11668 			rfpwr = bwn_tab_read(mac,
11669 			    BWN_TAB_4(7, txpwridx + 576));
11670 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11671 			    rfpwr & 0xffff);
11672 		}
11673 		bwn_phy_lp_set_txgain_override(mac);
11674 	}
11675 	if (plp->plp_rccap)
11676 		bwn_phy_lp_set_rccap(mac);
11677 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11678 	bwn_phy_lp_set_txpctlmode(mac, mode);
11679 	free(tabs, M_DEVBUF);
11680 }
11681 
11682 static void
11683 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11684 {
11685 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11686 	int i;
11687 	static const uint16_t addr[] = {
11688 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11689 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11690 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11691 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11692 		BWN_PHY_OFDM(0xcf),
11693 	};
11694 
11695 	for (i = 0; i < N(addr); i++)
11696 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11697 }
11698 
11699 static void
11700 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11701 {
11702 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11703 
11704 	if (mac->mac_phy.rev < 2) {
11705 		bwn_phy_lp_tblinit_r01(mac);
11706 		bwn_phy_lp_tblinit_txgain(mac);
11707 		bwn_phy_lp_set_gaintbl(mac, freq);
11708 		return;
11709 	}
11710 
11711 	bwn_phy_lp_tblinit_r2(mac);
11712 	bwn_phy_lp_tblinit_txgain(mac);
11713 }
11714 
11715 struct bwn_wpair {
11716 	uint16_t		reg;
11717 	uint16_t		value;
11718 };
11719 
11720 struct bwn_smpair {
11721 	uint16_t		offset;
11722 	uint16_t		mask;
11723 	uint16_t		set;
11724 };
11725 
11726 static void
11727 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11728 {
11729 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11730 	struct bwn_softc *sc = mac->mac_sc;
11731 	struct ifnet *ifp = sc->sc_ifp;
11732 	struct ieee80211com *ic = ifp->if_l2com;
11733 	static const struct bwn_wpair v1[] = {
11734 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11735 		{ BWN_PHY_AFE_CTL, 0x8800 },
11736 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11737 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11738 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11739 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11740 		{ BWN_PHY_OFDM(0xf9), 0 },
11741 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11742 	};
11743 	static const struct bwn_smpair v2[] = {
11744 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11745 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11746 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11747 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11748 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11749 	};
11750 	static const struct bwn_smpair v3[] = {
11751 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11752 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11753 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11754 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11755 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11756 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11757 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11758 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11759 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11760 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11761 
11762 	};
11763 	int i;
11764 
11765 	for (i = 0; i < N(v1); i++)
11766 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11767 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11768 	for (i = 0; i < N(v2); i++)
11769 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11770 
11771 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11772 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11773 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11774 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11775 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11776 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11777 	} else {
11778 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11779 	}
11780 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11781 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11782 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11783 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11784 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11785 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11786 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11787 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11788 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11789 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11790 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11791 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11792 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11793 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11794 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11795 	} else {
11796 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11797 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11798 	}
11799 	for (i = 0; i < N(v3); i++)
11800 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11801 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11802 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11803 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11804 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11805 	}
11806 
11807 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11808 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11809 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11810 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11811 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11812 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11813 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11814 	} else
11815 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11816 
11817 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11818 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11819 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11820 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11821 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11822 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11823 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11824 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11825 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11826 
11827 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11828 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11829 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11830 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11831 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11832 	}
11833 
11834 	bwn_phy_lp_digflt_save(mac);
11835 }
11836 
11837 static void
11838 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11839 {
11840 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11841 	struct bwn_softc *sc = mac->mac_sc;
11842 	struct ifnet *ifp = sc->sc_ifp;
11843 	struct ieee80211com *ic = ifp->if_l2com;
11844 	static const struct bwn_smpair v1[] = {
11845 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11846 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11847 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11848 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11849 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11850 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11851 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11852 	};
11853 	static const struct bwn_smpair v2[] = {
11854 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11855 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11856 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11857 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11858 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11859 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11860 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11861 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11862 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11863 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11864 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11865 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11866 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11867 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11868 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11869 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11870 	};
11871 	static const struct bwn_smpair v3[] = {
11872 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11873 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11874 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11875 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11876 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11877 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11878 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11879 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11880 	};
11881 	static const struct bwn_smpair v4[] = {
11882 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11883 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11884 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11885 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11886 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11887 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11888 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11889 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11890 	};
11891 	static const struct bwn_smpair v5[] = {
11892 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11893 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11894 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11895 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11896 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11897 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11898 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11899 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11900 	};
11901 	int i;
11902 	uint16_t tmp, tmp2;
11903 
11904 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11905 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11906 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11907 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11908 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11909 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11910 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11911 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11912 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11913 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11914 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11915 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11916 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11917 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11918 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11919 	for (i = 0; i < N(v1); i++)
11920 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11921 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11922 	    0xff00, plp->plp_rxpwroffset);
11923 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11924 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11925 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11926 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11927 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11928 		if (mac->mac_phy.rev == 0)
11929 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11930 			    0xffcf, 0x0010);
11931 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11932 	} else {
11933 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11934 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11935 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11936 	}
11937 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11938 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11939 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11940 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11941 	else
11942 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11943 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11944 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11945 	    0xfff9, (plp->plp_bxarch << 1));
11946 	if (mac->mac_phy.rev == 1 &&
11947 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11948 		for (i = 0; i < N(v2); i++)
11949 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11950 			    v2[i].set);
11951 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11952 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11953 	    ((mac->mac_phy.rev == 0) &&
11954 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11955 		for (i = 0; i < N(v3); i++)
11956 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11957 			    v3[i].set);
11958 	} else if (mac->mac_phy.rev == 1 ||
11959 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11960 		for (i = 0; i < N(v4); i++)
11961 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11962 			    v4[i].set);
11963 	} else {
11964 		for (i = 0; i < N(v5); i++)
11965 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11966 			    v5[i].set);
11967 	}
11968 	if (mac->mac_phy.rev == 1 &&
11969 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11970 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11971 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11972 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11973 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11974 	}
11975 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11976 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11977 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11978 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11979 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11980 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11981 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11982 	}
11983 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11984 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11985 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11986 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11987 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11988 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11989 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11990 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11991 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11992 	} else {
11993 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11994 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11995 	}
11996 	if (mac->mac_phy.rev == 1) {
11997 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11998 		tmp2 = (tmp & 0x03e0) >> 5;
11999 		tmp2 |= tmp2 << 5;
12000 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
12001 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
12002 		tmp2 = (tmp & 0x1f00) >> 8;
12003 		tmp2 |= tmp2 << 5;
12004 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
12005 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
12006 		tmp2 = tmp & 0x00ff;
12007 		tmp2 |= tmp << 8;
12008 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
12009 	}
12010 }
12011 
12012 struct bwn_b2062_freq {
12013 	uint16_t		freq;
12014 	uint8_t			value[6];
12015 };
12016 
12017 static void
12018 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
12019 {
12020 #define	CALC_CTL7(freq, div)						\
12021 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
12022 #define	CALC_CTL18(freq, div)						\
12023 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
12024 #define	CALC_CTL19(freq, div)						\
12025 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
12026 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12027 	struct bwn_softc *sc = mac->mac_sc;
12028 	struct ifnet *ifp = sc->sc_ifp;
12029 	struct ieee80211com *ic = ifp->if_l2com;
12030 	static const struct bwn_b2062_freq freqdata_tab[] = {
12031 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
12032 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
12033 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
12034 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
12035 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
12036 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
12037 	};
12038 	static const struct bwn_wpair v1[] = {
12039 		{ BWN_B2062_N_TXCTL3, 0 },
12040 		{ BWN_B2062_N_TXCTL4, 0 },
12041 		{ BWN_B2062_N_TXCTL5, 0 },
12042 		{ BWN_B2062_N_TXCTL6, 0 },
12043 		{ BWN_B2062_N_PDNCTL0, 0x40 },
12044 		{ BWN_B2062_N_PDNCTL0, 0 },
12045 		{ BWN_B2062_N_CALIB_TS, 0x10 },
12046 		{ BWN_B2062_N_CALIB_TS, 0 }
12047 	};
12048 	const struct bwn_b2062_freq *f = NULL;
12049 	uint32_t xtalfreq, ref;
12050 	unsigned int i;
12051 
12052 	bwn_phy_lp_b2062_tblinit(mac);
12053 
12054 	for (i = 0; i < N(v1); i++)
12055 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12056 	if (mac->mac_phy.rev > 0)
12057 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
12058 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
12059 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12060 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
12061 	else
12062 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
12063 
12064 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
12065 	    ("%s:%d: fail", __func__, __LINE__));
12066 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12067 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
12068 
12069 	if (xtalfreq <= 30000000) {
12070 		plp->plp_div = 1;
12071 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
12072 	} else {
12073 		plp->plp_div = 2;
12074 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
12075 	}
12076 
12077 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
12078 	    CALC_CTL7(xtalfreq, plp->plp_div));
12079 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
12080 	    CALC_CTL18(xtalfreq, plp->plp_div));
12081 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
12082 	    CALC_CTL19(xtalfreq, plp->plp_div));
12083 
12084 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
12085 	ref &= 0xffff;
12086 	for (i = 0; i < N(freqdata_tab); i++) {
12087 		if (ref < freqdata_tab[i].freq) {
12088 			f = &freqdata_tab[i];
12089 			break;
12090 		}
12091 	}
12092 	if (f == NULL)
12093 		f = &freqdata_tab[N(freqdata_tab) - 1];
12094 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
12095 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
12096 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
12097 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
12098 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
12099 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
12100 #undef CALC_CTL7
12101 #undef CALC_CTL18
12102 #undef CALC_CTL19
12103 }
12104 
12105 static void
12106 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
12107 {
12108 
12109 	bwn_phy_lp_b2063_tblinit(mac);
12110 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
12111 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
12112 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
12113 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
12114 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
12115 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
12116 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
12117 	if (mac->mac_phy.rev == 2) {
12118 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
12119 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
12120 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
12121 	} else {
12122 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
12123 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
12124 	}
12125 }
12126 
12127 static void
12128 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
12129 {
12130 	struct bwn_softc *sc = mac->mac_sc;
12131 	static const struct bwn_wpair v1[] = {
12132 		{ BWN_B2063_RX_BB_SP8, 0x0 },
12133 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12134 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12135 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
12136 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
12137 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
12138 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
12139 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
12140 	};
12141 	static const struct bwn_wpair v2[] = {
12142 		{ BWN_B2063_TX_BB_SP3, 0x0 },
12143 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
12144 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
12145 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
12146 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
12147 	};
12148 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12149 	int i;
12150 	uint8_t tmp;
12151 
12152 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12153 
12154 	for (i = 0; i < 2; i++)
12155 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12156 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12157 	for (i = 2; i < N(v1); i++)
12158 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12159 	for (i = 0; i < 10000; i++) {
12160 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12161 			break;
12162 		DELAY(1000);
12163 	}
12164 
12165 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12166 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12167 
12168 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12169 
12170 	for (i = 0; i < N(v2); i++)
12171 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12172 	if (freqxtal == 24000000) {
12173 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12174 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12175 	} else {
12176 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12177 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12178 	}
12179 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12180 	for (i = 0; i < 10000; i++) {
12181 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12182 			break;
12183 		DELAY(1000);
12184 	}
12185 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12186 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12187 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12188 }
12189 
12190 static void
12191 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12192 {
12193 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12194 	struct bwn_softc *sc = mac->mac_sc;
12195 	struct bwn_phy_lp_iq_est ie;
12196 	struct bwn_txgain tx_gains;
12197 	static const uint32_t pwrtbl[21] = {
12198 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12199 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12200 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12201 		0x0004c, 0x0002c, 0x0001a,
12202 	};
12203 	uint32_t npwr, ipwr, sqpwr, tmp;
12204 	int loopback, i, j, sum, error;
12205 	uint16_t save[7];
12206 	uint8_t txo, bbmult, txpctlmode;
12207 
12208 	error = bwn_phy_lp_switch_channel(mac, 7);
12209 	if (error)
12210 		device_printf(sc->sc_dev,
12211 		    "failed to change channel to 7 (%d)\n", error);
12212 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12213 	bbmult = bwn_phy_lp_get_bbmult(mac);
12214 	if (txo)
12215 		tx_gains = bwn_phy_lp_get_txgain(mac);
12216 
12217 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12218 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12219 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12220 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12221 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12222 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12223 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12224 
12225 	bwn_phy_lp_get_txpctlmode(mac);
12226 	txpctlmode = plp->plp_txpctlmode;
12227 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12228 
12229 	/* disable CRS */
12230 	bwn_phy_lp_set_deaf(mac, 1);
12231 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12232 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12233 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12234 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12235 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12236 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12237 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12238 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12239 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12240 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12241 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12242 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12243 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12244 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12245 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12246 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12247 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12248 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12249 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12250 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12251 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12252 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12253 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12254 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12255 
12256 	loopback = bwn_phy_lp_loopback(mac);
12257 	if (loopback == -1)
12258 		goto done;
12259 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12260 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12261 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12262 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12263 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12264 
12265 	tmp = 0;
12266 	memset(&ie, 0, sizeof(ie));
12267 	for (i = 128; i <= 159; i++) {
12268 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12269 		sum = 0;
12270 		for (j = 5; j <= 25; j++) {
12271 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12272 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12273 				goto done;
12274 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12275 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12276 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12277 			    12);
12278 			sum += ((ipwr - npwr) * (ipwr - npwr));
12279 			if ((i == 128) || (sum < tmp)) {
12280 				plp->plp_rccap = i;
12281 				tmp = sum;
12282 			}
12283 		}
12284 	}
12285 	bwn_phy_lp_ddfs_turnoff(mac);
12286 done:
12287 	/* restore CRS */
12288 	bwn_phy_lp_clear_deaf(mac, 1);
12289 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12290 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12291 
12292 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12293 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12294 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12295 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12296 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12297 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12298 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12299 
12300 	bwn_phy_lp_set_bbmult(mac, bbmult);
12301 	if (txo)
12302 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12303 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12304 	if (plp->plp_rccap)
12305 		bwn_phy_lp_set_rccap(mac);
12306 }
12307 
12308 static void
12309 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12310 {
12311 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12312 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12313 
12314 	if (mac->mac_phy.rev == 1)
12315 		rc_cap = MIN(rc_cap + 5, 15);
12316 
12317 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12318 	    MAX(plp->plp_rccap - 4, 0x80));
12319 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12320 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12321 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12322 }
12323 
12324 static uint32_t
12325 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12326 {
12327 	uint32_t i, q, r;
12328 
12329 	if (div == 0)
12330 		return (0);
12331 
12332 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12333 		q <<= 1;
12334 		if (r << 1 >= div) {
12335 			q++;
12336 			r = (r << 1) - div;
12337 		}
12338 	}
12339 	if (r << 1 >= div)
12340 		q++;
12341 	return (q);
12342 }
12343 
12344 static void
12345 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12346 {
12347 	struct bwn_softc *sc = mac->mac_sc;
12348 
12349 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12350 	DELAY(20);
12351 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12352 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12353 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12354 	} else {
12355 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12356 	}
12357 	DELAY(5);
12358 }
12359 
12360 static void
12361 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12362 {
12363 
12364 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12365 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12366 	DELAY(200);
12367 }
12368 
12369 static void
12370 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12371 {
12372 #define	FLAG_A	0x01
12373 #define	FLAG_G	0x02
12374 	struct bwn_softc *sc = mac->mac_sc;
12375 	struct ifnet *ifp = sc->sc_ifp;
12376 	struct ieee80211com *ic = ifp->if_l2com;
12377 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12378 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12379 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12380 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12381 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12382 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12383 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12384 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12385 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12386 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12387 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12388 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12389 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12390 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12391 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12392 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12393 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12394 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12395 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12396 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12397 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12398 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12399 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12400 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12401 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12402 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12403 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12404 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12405 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12406 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12407 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12408 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12409 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12410 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12411 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12412 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12413 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12414 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12415 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12416 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12417 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12418 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12419 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12420 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12421 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12422 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12423 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12424 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12425 	};
12426 	const struct bwn_b206x_rfinit_entry *br;
12427 	unsigned int i;
12428 
12429 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12430 		br = &bwn_b2062_init_tab[i];
12431 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12432 			if (br->br_flags & FLAG_G)
12433 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12434 		} else {
12435 			if (br->br_flags & FLAG_A)
12436 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12437 		}
12438 	}
12439 #undef FLAG_A
12440 #undef FLAG_B
12441 }
12442 
12443 static void
12444 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12445 {
12446 #define	FLAG_A	0x01
12447 #define	FLAG_G	0x02
12448 	struct bwn_softc *sc = mac->mac_sc;
12449 	struct ifnet *ifp = sc->sc_ifp;
12450 	struct ieee80211com *ic = ifp->if_l2com;
12451 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12452 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12453 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12454 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12455 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12456 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12457 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12458 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12459 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12460 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12461 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12462 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12463 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12464 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12465 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12466 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12467 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12468 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12469 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12470 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12471 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12472 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12473 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12474 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12475 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12476 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12477 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12478 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12479 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12480 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12481 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12482 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12483 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12484 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12485 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12486 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12487 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12488 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12489 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12490 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12491 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12492 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12493 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12494 	};
12495 	const struct bwn_b206x_rfinit_entry *br;
12496 	unsigned int i;
12497 
12498 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12499 		br = &bwn_b2063_init_tab[i];
12500 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12501 			if (br->br_flags & FLAG_G)
12502 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12503 		} else {
12504 			if (br->br_flags & FLAG_A)
12505 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12506 		}
12507 	}
12508 #undef FLAG_A
12509 #undef FLAG_B
12510 }
12511 
12512 static void
12513 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12514     int count, void *_data)
12515 {
12516 	unsigned int i;
12517 	uint32_t offset, type;
12518 	uint8_t *data = _data;
12519 
12520 	type = BWN_TAB_GETTYPE(typenoffset);
12521 	offset = BWN_TAB_GETOFFSET(typenoffset);
12522 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12523 
12524 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12525 
12526 	for (i = 0; i < count; i++) {
12527 		switch (type) {
12528 		case BWN_TAB_8BIT:
12529 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12530 			data++;
12531 			break;
12532 		case BWN_TAB_16BIT:
12533 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12534 			    BWN_PHY_TABLEDATALO);
12535 			data += 2;
12536 			break;
12537 		case BWN_TAB_32BIT:
12538 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12539 			    BWN_PHY_TABLEDATAHI);
12540 			*((uint32_t *)data) <<= 16;
12541 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12542 			    BWN_PHY_TABLEDATALO);
12543 			data += 4;
12544 			break;
12545 		default:
12546 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12547 		}
12548 	}
12549 }
12550 
12551 static void
12552 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12553     int count, const void *_data)
12554 {
12555 	uint32_t offset, type, value;
12556 	const uint8_t *data = _data;
12557 	unsigned int i;
12558 
12559 	type = BWN_TAB_GETTYPE(typenoffset);
12560 	offset = BWN_TAB_GETOFFSET(typenoffset);
12561 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12562 
12563 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12564 
12565 	for (i = 0; i < count; i++) {
12566 		switch (type) {
12567 		case BWN_TAB_8BIT:
12568 			value = *data;
12569 			data++;
12570 			KASSERT(!(value & ~0xff),
12571 			    ("%s:%d: fail", __func__, __LINE__));
12572 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12573 			break;
12574 		case BWN_TAB_16BIT:
12575 			value = *((const uint16_t *)data);
12576 			data += 2;
12577 			KASSERT(!(value & ~0xffff),
12578 			    ("%s:%d: fail", __func__, __LINE__));
12579 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12580 			break;
12581 		case BWN_TAB_32BIT:
12582 			value = *((const uint32_t *)data);
12583 			data += 4;
12584 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12585 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12586 			break;
12587 		default:
12588 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12589 		}
12590 	}
12591 }
12592 
12593 static struct bwn_txgain
12594 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12595 {
12596 	struct bwn_txgain tg;
12597 	uint16_t tmp;
12598 
12599 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12600 	if (mac->mac_phy.rev < 2) {
12601 		tmp = BWN_PHY_READ(mac,
12602 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12603 		tg.tg_gm = tmp & 0x0007;
12604 		tg.tg_pga = (tmp & 0x0078) >> 3;
12605 		tg.tg_pad = (tmp & 0x780) >> 7;
12606 		return (tg);
12607 	}
12608 
12609 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12610 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12611 	tg.tg_gm = tmp & 0xff;
12612 	tg.tg_pga = (tmp >> 8) & 0xff;
12613 	return (tg);
12614 }
12615 
12616 static uint8_t
12617 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12618 {
12619 
12620 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12621 }
12622 
12623 static void
12624 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12625 {
12626 	uint16_t pa;
12627 
12628 	if (mac->mac_phy.rev < 2) {
12629 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12630 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12631 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12632 		bwn_phy_lp_set_txgain_override(mac);
12633 		return;
12634 	}
12635 
12636 	pa = bwn_phy_lp_get_pa_gain(mac);
12637 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12638 	    (tg->tg_pga << 8) | tg->tg_gm);
12639 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12640 	    tg->tg_pad | (pa << 6));
12641 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12642 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12643 	    tg->tg_pad | (pa << 8));
12644 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12645 	bwn_phy_lp_set_txgain_override(mac);
12646 }
12647 
12648 static void
12649 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12650 {
12651 
12652 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12653 }
12654 
12655 static void
12656 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12657 {
12658 	uint16_t trsw = (tx << 1) | rx;
12659 
12660 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12661 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12662 }
12663 
12664 static void
12665 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12666 {
12667 	struct bwn_softc *sc = mac->mac_sc;
12668 	struct ifnet *ifp = sc->sc_ifp;
12669 	struct ieee80211com *ic = ifp->if_l2com;
12670 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12671 
12672 	if (mac->mac_phy.rev < 2) {
12673 		trsw = gain & 0x1;
12674 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12675 		ext_lna = (gain & 2) >> 1;
12676 
12677 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12678 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12679 		    0xfbff, ext_lna << 10);
12680 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12681 		    0xf7ff, ext_lna << 11);
12682 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12683 	} else {
12684 		low_gain = gain & 0xffff;
12685 		high_gain = (gain >> 16) & 0xf;
12686 		ext_lna = (gain >> 21) & 0x1;
12687 		trsw = ~(gain >> 20) & 0x1;
12688 
12689 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12690 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12691 		    0xfdff, ext_lna << 9);
12692 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12693 		    0xfbff, ext_lna << 10);
12694 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12695 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12696 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12697 			tmp = (gain >> 2) & 0x3;
12698 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12699 			    0xe7ff, tmp<<11);
12700 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12701 			    tmp << 3);
12702 		}
12703 	}
12704 
12705 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12706 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12707 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12708 	if (mac->mac_phy.rev >= 2) {
12709 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12710 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12711 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12712 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12713 		}
12714 		return;
12715 	}
12716 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12717 }
12718 
12719 static void
12720 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12721 {
12722 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12723 
12724 	if (user)
12725 		plp->plp_crsusr_off = 1;
12726 	else
12727 		plp->plp_crssys_off = 1;
12728 
12729 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12730 }
12731 
12732 static void
12733 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12734 {
12735 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12736 	struct bwn_softc *sc = mac->mac_sc;
12737 	struct ifnet *ifp = sc->sc_ifp;
12738 	struct ieee80211com *ic = ifp->if_l2com;
12739 
12740 	if (user)
12741 		plp->plp_crsusr_off = 0;
12742 	else
12743 		plp->plp_crssys_off = 0;
12744 
12745 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12746 		return;
12747 
12748 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12749 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12750 	else
12751 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12752 }
12753 
12754 static unsigned int
12755 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12756 {
12757 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12758 	static uint8_t sqrt_table[256] = {
12759 		10, 14, 17, 20, 22, 24, 26, 28,
12760 		30, 31, 33, 34, 36, 37, 38, 40,
12761 		41, 42, 43, 44, 45, 46, 47, 48,
12762 		50, 50, 51, 52, 53, 54, 55, 56,
12763 		57, 58, 59, 60, 60, 61, 62, 63,
12764 		64, 64, 65, 66, 67, 67, 68, 69,
12765 		70, 70, 71, 72, 72, 73, 74, 74,
12766 		75, 76, 76, 77, 78, 78, 79, 80,
12767 		80, 81, 81, 82, 83, 83, 84, 84,
12768 		85, 86, 86, 87, 87, 88, 88, 89,
12769 		90, 90, 91, 91, 92, 92, 93, 93,
12770 		94, 94, 95, 95, 96, 96, 97, 97,
12771 		98, 98, 99, 100, 100, 100, 101, 101,
12772 		102, 102, 103, 103, 104, 104, 105, 105,
12773 		106, 106, 107, 107, 108, 108, 109, 109,
12774 		110, 110, 110, 111, 111, 112, 112, 113,
12775 		113, 114, 114, 114, 115, 115, 116, 116,
12776 		117, 117, 117, 118, 118, 119, 119, 120,
12777 		120, 120, 121, 121, 122, 122, 122, 123,
12778 		123, 124, 124, 124, 125, 125, 126, 126,
12779 		126, 127, 127, 128, 128, 128, 129, 129,
12780 		130, 130, 130, 131, 131, 131, 132, 132,
12781 		133, 133, 133, 134, 134, 134, 135, 135,
12782 		136, 136, 136, 137, 137, 137, 138, 138,
12783 		138, 139, 139, 140, 140, 140, 141, 141,
12784 		141, 142, 142, 142, 143, 143, 143, 144,
12785 		144, 144, 145, 145, 145, 146, 146, 146,
12786 		147, 147, 147, 148, 148, 148, 149, 149,
12787 		150, 150, 150, 150, 151, 151, 151, 152,
12788 		152, 152, 153, 153, 153, 154, 154, 154,
12789 		155, 155, 155, 156, 156, 156, 157, 157,
12790 		157, 158, 158, 158, 159, 159, 159, 160
12791 	};
12792 
12793 	if (x == 0)
12794 		return (0);
12795 	if (x >= 256) {
12796 		unsigned int tmp;
12797 
12798 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12799 			/* do nothing */ ;
12800 		return (tmp);
12801 	}
12802 	return (sqrt_table[x - 1] / 10);
12803 }
12804 
12805 static int
12806 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12807 {
12808 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12809 	int _t;								\
12810 	_t = _x - 20;							\
12811 	if (_t >= 0) {							\
12812 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12813 	} else {							\
12814 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12815 	}								\
12816 } while (0)
12817 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12818 	int _t;								\
12819 	_t = _x - 11;							\
12820 	if (_t >= 0)							\
12821 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12822 	else								\
12823 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12824 } while (0)
12825 	struct bwn_phy_lp_iq_est ie;
12826 	uint16_t v0, v1;
12827 	int tmp[2], ret;
12828 
12829 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12830 	v0 = v1 >> 8;
12831 	v1 |= 0xff;
12832 
12833 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12834 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12835 
12836 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12837 	if (ret == 0)
12838 		goto done;
12839 
12840 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12841 		ret = 0;
12842 		goto done;
12843 	}
12844 
12845 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12846 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12847 
12848 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12849 	v0 = tmp[0] >> 3;
12850 	v1 = tmp[1] >> 4;
12851 done:
12852 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12853 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12854 	return ret;
12855 #undef CALC_COEFF
12856 #undef CALC_COEFF2
12857 }
12858 
12859 static void
12860 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12861 {
12862 	static const uint16_t noisescale[] = {
12863 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12864 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12865 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12866 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12867 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12868 	};
12869 	static const uint16_t crsgainnft[] = {
12870 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12871 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12872 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12873 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12874 		0x013d,
12875 	};
12876 	static const uint16_t filterctl[] = {
12877 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12878 		0xff53, 0x0127,
12879 	};
12880 	static const uint32_t psctl[] = {
12881 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12882 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12883 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12884 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12885 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12886 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12887 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12888 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12889 	};
12890 	static const uint16_t ofdmcckgain_r0[] = {
12891 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12892 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12893 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12894 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12895 		0x755d,
12896 	};
12897 	static const uint16_t ofdmcckgain_r1[] = {
12898 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12899 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12900 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12901 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12902 		0x755d,
12903 	};
12904 	static const uint16_t gaindelta[] = {
12905 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12906 		0x0000,
12907 	};
12908 	static const uint32_t txpwrctl[] = {
12909 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12910 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12911 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12912 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12913 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12914 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12915 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12916 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12917 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12918 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12919 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12920 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12921 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12922 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12923 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12924 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12925 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12926 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12927 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12931 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12932 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12933 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12934 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12935 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12936 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12937 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12938 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12939 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12940 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12941 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12942 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12946 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12947 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12948 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12949 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12950 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12951 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12952 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12953 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12954 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12955 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12956 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12957 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12958 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12959 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12960 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12961 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12962 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12963 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12964 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12965 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12966 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12967 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12968 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12969 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12970 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12971 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12972 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12973 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12974 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12975 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12976 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12977 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12978 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12979 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12980 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12981 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12982 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12983 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12984 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12985 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12986 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12987 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12988 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12989 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12990 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12991 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12992 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12993 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12994 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12995 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12996 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12997 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12998 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12999 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
13000 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
13001 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
13002 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
13003 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
13004 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
13005 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
13006 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
13007 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
13008 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
13009 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
13010 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
13011 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
13012 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
13013 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
13014 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
13015 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
13016 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
13017 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
13018 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
13019 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
13020 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
13021 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
13022 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
13023 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
13024 		0x00000702,
13025 	};
13026 
13027 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13028 
13029 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13030 	    bwn_tab_sigsq_tbl);
13031 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13032 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
13033 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
13034 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
13035 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13036 	    bwn_tab_pllfrac_tbl);
13037 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13038 	    bwn_tabl_iqlocal_tbl);
13039 	if (mac->mac_phy.rev == 0) {
13040 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
13041 		    ofdmcckgain_r0);
13042 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
13043 		    ofdmcckgain_r0);
13044 	} else {
13045 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
13046 		    ofdmcckgain_r1);
13047 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
13048 		    ofdmcckgain_r1);
13049 	}
13050 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
13051 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
13052 }
13053 
13054 static void
13055 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
13056 {
13057 	struct bwn_softc *sc = mac->mac_sc;
13058 	int i;
13059 	static const uint16_t noisescale[] = {
13060 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13061 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13062 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13063 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13064 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13065 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
13066 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
13067 	};
13068 	static const uint32_t filterctl[] = {
13069 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
13070 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
13071 	};
13072 	static const uint32_t psctl[] = {
13073 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
13074 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
13075 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
13076 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
13077 	};
13078 	static const uint32_t gainidx[] = {
13079 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13080 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13081 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13082 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
13083 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
13084 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
13085 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
13086 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
13087 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
13088 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
13089 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
13090 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
13091 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
13092 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
13093 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
13094 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13095 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13096 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13097 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
13098 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
13099 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
13100 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
13101 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
13102 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
13103 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
13104 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
13105 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
13106 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
13107 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
13108 		0x0000001a, 0x64ca55ad, 0x0000001a
13109 	};
13110 	static const uint16_t auxgainidx[] = {
13111 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13112 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
13113 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
13114 		0x0004, 0x0016
13115 	};
13116 	static const uint16_t swctl[] = {
13117 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13118 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13119 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13120 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
13121 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13122 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
13123 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
13124 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
13125 	};
13126 	static const uint8_t hf[] = {
13127 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
13128 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
13129 	};
13130 	static const uint32_t gainval[] = {
13131 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13132 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13133 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13134 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13135 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13136 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13137 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13138 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13139 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13140 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13141 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13142 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13143 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
13144 		0x000000f1, 0x00000000, 0x00000000
13145 	};
13146 	static const uint16_t gain[] = {
13147 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
13148 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
13149 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
13150 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
13151 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13152 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13153 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13154 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13155 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13156 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13157 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13158 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13159 	};
13160 	static const uint32_t papdeps[] = {
13161 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13162 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13163 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13164 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13165 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13166 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13167 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13168 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13169 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13170 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13171 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13172 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13173 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13174 	};
13175 	static const uint32_t papdmult[] = {
13176 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13177 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13178 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13179 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13180 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13181 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13182 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13183 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13184 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13185 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13186 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13187 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13188 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13189 	};
13190 	static const uint32_t gainidx_a0[] = {
13191 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13192 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13193 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13194 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13195 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13196 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13197 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13198 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13199 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13200 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13201 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13202 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13203 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13204 	};
13205 	static const uint16_t auxgainidx_a0[] = {
13206 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13207 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13208 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13209 		0x0002, 0x0014
13210 	};
13211 	static const uint32_t gainval_a0[] = {
13212 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13213 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13214 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13215 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13216 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13217 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13218 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13219 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13220 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13221 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13222 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13223 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13224 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13225 		0x000000f7, 0x00000000, 0x00000000
13226 	};
13227 	static const uint16_t gain_a0[] = {
13228 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13229 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13230 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13231 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13232 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13233 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13234 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13235 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13236 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13237 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13238 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13239 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13240 	};
13241 
13242 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13243 
13244 	for (i = 0; i < 704; i++)
13245 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13246 
13247 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13248 	    bwn_tab_sigsq_tbl);
13249 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13250 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13251 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13252 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13253 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13254 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13255 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13256 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13257 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13258 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13259 	    bwn_tab_pllfrac_tbl);
13260 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13261 	    bwn_tabl_iqlocal_tbl);
13262 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13263 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13264 
13265 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13266 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13267 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13268 		    gainidx_a0);
13269 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13270 		    auxgainidx_a0);
13271 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13272 		    gainval_a0);
13273 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13274 	}
13275 }
13276 
13277 static void
13278 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13279 {
13280 	struct bwn_softc *sc = mac->mac_sc;
13281 	struct ifnet *ifp = sc->sc_ifp;
13282 	struct ieee80211com *ic = ifp->if_l2com;
13283 	static struct bwn_txgain_entry txgain_r2[] = {
13284 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13285 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13286 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13287 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13288 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13289 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13290 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13291 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13292 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13293 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13294 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13295 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13296 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13297 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13298 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13299 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13300 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13301 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13302 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13303 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13304 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13305 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13306 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13307 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13308 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13309 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13310 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13311 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13312 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13313 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13314 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13315 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13316 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13317 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13318 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13319 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13320 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13321 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13322 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13323 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13324 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13325 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13326 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13327 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13328 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13329 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13330 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13331 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13332 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13333 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13334 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13335 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13336 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13337 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13338 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13339 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13340 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13341 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13342 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13343 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13344 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13345 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13346 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13347 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13348 	};
13349 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13350 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13351 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13352 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13353 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13354 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13355 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13356 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13357 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13358 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13359 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13360 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13361 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13362 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13363 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13364 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13365 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13366 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13367 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13368 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13369 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13370 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13371 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13372 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13373 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13374 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13375 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13376 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13377 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13378 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13379 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13380 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13381 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13382 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13383 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13384 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13385 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13386 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13387 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13388 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13389 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13390 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13391 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13392 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13393 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13394 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13395 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13396 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13397 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13398 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13399 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13400 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13401 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13402 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13403 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13404 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13405 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13406 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13407 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13408 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13409 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13410 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13411 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13412 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13413 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13414 	};
13415 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13416 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13417 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13418 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13419 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13420 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13421 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13422 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13423 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13424 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13425 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13426 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13427 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13428 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13429 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13430 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13431 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13432 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13433 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13434 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13435 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13436 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13437 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13438 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13439 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13440 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13441 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13442 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13443 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13444 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13445 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13446 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13447 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13448 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13449 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13450 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13451 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13452 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13453 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13454 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13455 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13456 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13457 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13458 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13459 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13460 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13461 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13462 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13463 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13464 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13465 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13466 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13467 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13468 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13469 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13470 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13471 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13472 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13473 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13474 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13475 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13476 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13477 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13478 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13479 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13480 	};
13481 	static struct bwn_txgain_entry txgain_r0[] = {
13482 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13483 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13484 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13485 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13486 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13487 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13488 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13489 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13490 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13491 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13492 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13493 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13494 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13495 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13496 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13497 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13498 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13499 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13500 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13501 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13502 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13503 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13504 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13505 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13506 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13507 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13508 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13509 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13510 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13511 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13512 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13513 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13514 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13515 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13516 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13517 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13518 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13519 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13520 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13521 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13522 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13523 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13524 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13525 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13526 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13527 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13528 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13529 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13530 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13531 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13532 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13533 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13534 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13535 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13536 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13537 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13538 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13539 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13540 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13541 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13542 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13543 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13544 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13545 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13546 	};
13547 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13548 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13549 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13550 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13551 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13552 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13553 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13554 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13555 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13556 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13557 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13558 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13559 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13560 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13561 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13562 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13563 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13564 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13565 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13566 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13567 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13568 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13569 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13570 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13571 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13572 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13573 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13574 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13575 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13576 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13577 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13578 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13579 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13580 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13581 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13582 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13583 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13584 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13585 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13586 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13587 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13588 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13589 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13590 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13591 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13592 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13593 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13594 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13595 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13596 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13597 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13598 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13599 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13600 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13601 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13602 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13603 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13604 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13605 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13606 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13607 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13608 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13609 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13610 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13611 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13612 	};
13613 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13614 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13615 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13616 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13617 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13618 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13619 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13620 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13621 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13622 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13623 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13624 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13625 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13626 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13627 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13628 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13629 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13630 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13631 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13632 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13633 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13634 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13635 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13636 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13637 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13638 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13639 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13640 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13641 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13642 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13643 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13644 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13645 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13646 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13647 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13648 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13649 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13650 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13651 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13652 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13653 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13654 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13655 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13656 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13657 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13658 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13659 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13660 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13661 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13662 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13663 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13664 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13665 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13666 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13667 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13668 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13669 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13670 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13671 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13672 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13673 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13674 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13675 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13676 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13677 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13678 	};
13679 	static struct bwn_txgain_entry txgain_r1[] = {
13680 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13681 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13682 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13683 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13684 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13685 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13686 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13687 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13688 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13689 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13690 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13691 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13692 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13693 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13694 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13695 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13696 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13697 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13698 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13699 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13700 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13701 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13702 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13703 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13704 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13705 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13706 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13707 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13708 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13709 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13710 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13711 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13712 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13713 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13714 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13715 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13716 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13717 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13718 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13719 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13720 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13721 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13722 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13723 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13724 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13725 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13726 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13727 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13728 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13729 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13730 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13731 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13732 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13733 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13734 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13735 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13736 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13737 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13738 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13739 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13740 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13741 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13742 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13743 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13744 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13745 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13746 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13747 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13748 		{ 7, 11, 6, 0, 71 }
13749 	};
13750 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13751 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13752 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13753 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13754 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13755 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13756 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13757 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13758 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13759 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13760 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13761 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13762 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13763 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13764 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13765 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13766 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13767 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13768 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13769 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13770 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13771 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13772 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13773 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13774 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13775 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13776 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13777 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13778 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13779 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13780 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13781 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13782 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13783 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13784 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13785 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13786 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13787 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13788 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13789 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13790 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13791 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13792 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13793 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13794 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13795 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13796 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13797 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13798 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13799 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13800 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13801 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13802 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13803 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13804 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13805 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13806 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13807 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13808 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13809 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13810 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13811 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13812 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13813 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13814 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13815 	};
13816 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13817 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13818 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13819 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13820 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13821 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13822 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13823 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13824 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13825 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13826 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13827 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13828 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13829 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13830 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13831 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13832 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13833 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13834 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13835 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13836 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13837 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13838 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13839 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13840 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13841 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13842 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13843 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13844 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13845 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13846 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13847 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13848 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13849 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13850 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13851 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13852 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13853 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13854 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13855 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13856 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13857 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13858 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13859 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13860 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13861 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13862 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13863 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13864 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13865 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13866 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13867 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13868 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13869 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13870 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13871 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13872 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13873 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13874 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13875 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13876 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13877 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13878 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13879 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13880 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13881 	};
13882 
13883 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13884 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13885 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13886 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13887 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13888 			    txgain_2ghz_r2);
13889 		else
13890 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13891 			    txgain_5ghz_r2);
13892 		return;
13893 	}
13894 
13895 	if (mac->mac_phy.rev == 0) {
13896 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13897 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13898 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13899 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13900 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13901 			    txgain_2ghz_r0);
13902 		else
13903 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13904 			    txgain_5ghz_r0);
13905 		return;
13906 	}
13907 
13908 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13909 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13910 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13911 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13912 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13913 	else
13914 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13915 }
13916 
13917 static void
13918 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13919 {
13920 	uint32_t offset, type;
13921 
13922 	type = BWN_TAB_GETTYPE(typeoffset);
13923 	offset = BWN_TAB_GETOFFSET(typeoffset);
13924 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13925 
13926 	switch (type) {
13927 	case BWN_TAB_8BIT:
13928 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13929 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13930 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13931 		break;
13932 	case BWN_TAB_16BIT:
13933 		KASSERT(!(value & ~0xffff),
13934 		    ("%s:%d: fail", __func__, __LINE__));
13935 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13936 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13937 		break;
13938 	case BWN_TAB_32BIT:
13939 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13940 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13941 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13942 		break;
13943 	default:
13944 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13945 	}
13946 }
13947 
13948 static int
13949 bwn_phy_lp_loopback(struct bwn_mac *mac)
13950 {
13951 	struct bwn_phy_lp_iq_est ie;
13952 	int i, index = -1;
13953 	uint32_t tmp;
13954 
13955 	memset(&ie, 0, sizeof(ie));
13956 
13957 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13958 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13959 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13960 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13961 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13962 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13963 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13964 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13965 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13966 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13967 	for (i = 0; i < 32; i++) {
13968 		bwn_phy_lp_set_rxgain_idx(mac, i);
13969 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13970 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13971 			continue;
13972 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13973 		if ((tmp > 4000) && (tmp < 10000)) {
13974 			index = i;
13975 			break;
13976 		}
13977 	}
13978 	bwn_phy_lp_ddfs_turnoff(mac);
13979 	return (index);
13980 }
13981 
13982 static void
13983 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13984 {
13985 
13986 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13987 }
13988 
13989 static void
13990 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13991     int incr1, int incr2, int scale_idx)
13992 {
13993 
13994 	bwn_phy_lp_ddfs_turnoff(mac);
13995 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13996 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13997 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13998 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13999 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
14000 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
14001 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
14002 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
14003 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
14004 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
14005 }
14006 
14007 static uint8_t
14008 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
14009     struct bwn_phy_lp_iq_est *ie)
14010 {
14011 	int i;
14012 
14013 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
14014 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
14015 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
14016 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
14017 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
14018 
14019 	for (i = 0; i < 500; i++) {
14020 		if (!(BWN_PHY_READ(mac,
14021 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
14022 			break;
14023 		DELAY(1000);
14024 	}
14025 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
14026 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14027 		return 0;
14028 	}
14029 
14030 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
14031 	ie->ie_iqprod <<= 16;
14032 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
14033 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
14034 	ie->ie_ipwr <<= 16;
14035 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
14036 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
14037 	ie->ie_qpwr <<= 16;
14038 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
14039 
14040 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
14041 	return 1;
14042 }
14043 
14044 static uint32_t
14045 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
14046 {
14047 	uint32_t offset, type, value;
14048 
14049 	type = BWN_TAB_GETTYPE(typeoffset);
14050 	offset = BWN_TAB_GETOFFSET(typeoffset);
14051 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
14052 
14053 	switch (type) {
14054 	case BWN_TAB_8BIT:
14055 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14056 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
14057 		break;
14058 	case BWN_TAB_16BIT:
14059 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14060 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14061 		break;
14062 	case BWN_TAB_32BIT:
14063 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
14064 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
14065 		value <<= 16;
14066 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
14067 		break;
14068 	default:
14069 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
14070 		value = 0;
14071 	}
14072 
14073 	return (value);
14074 }
14075 
14076 static void
14077 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
14078 {
14079 
14080 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
14081 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
14082 }
14083 
14084 static void
14085 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
14086 {
14087 	uint16_t ctl;
14088 
14089 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
14090 	ctl |= dac << 7;
14091 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
14092 }
14093 
14094 static void
14095 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
14096 {
14097 
14098 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
14099 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
14100 }
14101 
14102 static void
14103 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
14104 {
14105 
14106 	if (mac->mac_phy.rev < 2)
14107 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
14108 	else {
14109 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
14110 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
14111 	}
14112 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
14113 }
14114 
14115 static uint16_t
14116 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
14117 {
14118 
14119 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
14120 }
14121 
14122 static uint8_t
14123 bwn_nbits(int32_t val)
14124 {
14125 	uint32_t tmp;
14126 	uint8_t nbits = 0;
14127 
14128 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
14129 		nbits++;
14130 	return (nbits);
14131 }
14132 
14133 static void
14134 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
14135     struct bwn_txgain_entry *table)
14136 {
14137 	int i;
14138 
14139 	for (i = offset; i < count; i++)
14140 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
14141 }
14142 
14143 static void
14144 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
14145     struct bwn_txgain_entry data)
14146 {
14147 
14148 	if (mac->mac_phy.rev >= 2)
14149 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
14150 	else
14151 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
14152 }
14153 
14154 static void
14155 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14156     struct bwn_txgain_entry te)
14157 {
14158 	struct bwn_softc *sc = mac->mac_sc;
14159 	struct ifnet *ifp = sc->sc_ifp;
14160 	struct ieee80211com *ic = ifp->if_l2com;
14161 	uint32_t tmp;
14162 
14163 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14164 
14165 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14166 	if (mac->mac_phy.rev >= 3) {
14167 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14168 		    (0x10 << 24) : (0x70 << 24));
14169 	} else {
14170 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14171 		    (0x14 << 24) : (0x7f << 24));
14172 	}
14173 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14174 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14175 	    te.te_bbmult << 20 | te.te_dac << 28);
14176 }
14177 
14178 static void
14179 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14180     struct bwn_txgain_entry te)
14181 {
14182 
14183 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14184 
14185 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14186 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14187 	    te.te_dac);
14188 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14189 }
14190 
14191 static void
14192 bwn_sysctl_node(struct bwn_softc *sc)
14193 {
14194 	device_t dev = sc->sc_dev;
14195 	struct bwn_mac *mac;
14196 	struct bwn_stats *stats;
14197 
14198 	/* XXX assume that count of MAC is only 1. */
14199 
14200 	if ((mac = sc->sc_curmac) == NULL)
14201 		return;
14202 	stats = &mac->mac_stats;
14203 
14204 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14205 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14206 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14207 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14208 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14209 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14210 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14211 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14212 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14213 
14214 #ifdef BWN_DEBUG
14215 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14216 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14217 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14218 #endif
14219 }
14220 
14221 static device_method_t bwn_methods[] = {
14222 	/* Device interface */
14223 	DEVMETHOD(device_probe,		bwn_probe),
14224 	DEVMETHOD(device_attach,	bwn_attach),
14225 	DEVMETHOD(device_detach,	bwn_detach),
14226 	DEVMETHOD(device_suspend,	bwn_suspend),
14227 	DEVMETHOD(device_resume,	bwn_resume),
14228 	KOBJMETHOD_END
14229 };
14230 static driver_t bwn_driver = {
14231 	"bwn",
14232 	bwn_methods,
14233 	sizeof(struct bwn_softc)
14234 };
14235 static devclass_t bwn_devclass;
14236 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14237 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14238 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14239 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14240 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14241